1 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
4 /* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 1, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #if defined (HAVE_UNISTD_H)
26 # include <sys/types.h>
32 #include "../bashtypes.h"
36 #include "../posixstat.h"
37 #include "../filecntl.h"
39 #include "../bashansi.h"
42 #define DOCFILE "builtins.texi"
44 static char *xmalloc (), *xrealloc ();
46 #if !defined (__STDC__) && !defined (strcpy)
47 extern char *strcpy ();
48 #endif /* !__STDC__ && !strcpy */
50 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
51 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
53 /* Flag values that builtins can have. */
54 #define BUILTIN_FLAG_SPECIAL 0x01
55 #define BUILTIN_FLAG_ASSIGNMENT 0x02
57 /* If this stream descriptor is non-zero, then write
58 texinfo documentation to it. */
59 FILE *documentation_file = (FILE *)NULL;
61 /* Non-zero means to only produce documentation. */
62 int only_documentation = 0;
64 /* Non-zero means to not do any productions. */
65 int inhibit_production = 0;
67 #if !defined (OLDCODE)
68 int no_long_document = 0;
71 /* The name of a directory to precede the filename when reporting
73 char *error_directory = (char *)NULL;
75 /* The name of the structure file. */
76 char *struct_filename = (char *)NULL;
78 /* The name of the external declaration file. */
79 char *extern_filename = (char *)NULL;
81 /* Here is a structure for manipulating arrays of data. */
83 int size; /* Number of slots allocated to array. */
84 int sindex; /* Current location in array. */
85 int width; /* Size of each element. */
86 int growth_rate; /* How fast to grow. */
87 char **array; /* The array itself. */
90 /* Here is a structure defining a single BUILTIN. */
92 char *name; /* The name of this builtin. */
93 char *function; /* The name of the function to call. */
94 char *shortdoc; /* The short documentation for this builtin. */
95 char *docname; /* Possible name for documentation string. */
96 ARRAY *longdoc; /* The long documentation for this builtin. */
97 ARRAY *dependencies; /* Null terminated array of #define names. */
98 int flags; /* Flags for this builtin. */
101 /* Here is a structure which defines a DEF file. */
103 char *filename; /* The name of the input def file. */
104 ARRAY *lines; /* The contents of the file. */
105 int line_number; /* The current line number. */
106 char *production; /* The name of the production file. */
107 FILE *output; /* Open file stream for PRODUCTION. */
108 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
111 /* The array of all builtins encountered during execution of this code. */
112 ARRAY *saved_builtins = (ARRAY *)NULL;
114 /* The Posix.2 so-called `special' builtins. */
115 char *special_builtins[] =
117 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
118 "export", "readonly", "return", "set", "shift", "trap", "unset",
122 /* The builtin commands that take assignment statements as arguments. */
123 char *assignment_builtins[] =
125 "alias", "declare", "export", "local", "readonly", "typeset",
129 /* Forward declarations. */
130 static int is_special_builtin ();
131 static int is_assignment_builtin ();
133 void extract_info ();
138 void write_file_headers ();
139 void write_file_footers ();
140 void write_ifdefs ();
141 void write_endifs ();
142 void write_documentation ();
143 void write_longdocs ();
144 void write_builtins ();
147 void add_documentation ();
149 void must_be_building ();
150 void remove_trailing_whitespace ();
152 /* For each file mentioned on the command line, process it and
153 write the information to STRUCTFILE and EXTERNFILE, while
154 creating the production file if neccessary. */
161 FILE *structfile, *externfile;
162 char *documentation_filename, *temp_struct_filename;
164 structfile = externfile = (FILE *)NULL;
165 documentation_filename = DOCFILE;
166 temp_struct_filename = (char *)NULL;
168 while (arg_index < argc && argv[arg_index][0] == '-')
170 char *arg = argv[arg_index++];
172 if (strcmp (arg, "-externfile") == 0)
173 extern_filename = argv[arg_index++];
174 else if (strcmp (arg, "-structfile") == 0)
175 struct_filename = argv[arg_index++];
176 else if (strcmp (arg, "-noproduction") == 0)
177 inhibit_production = 1;
178 else if (strcmp (arg, "-document") == 0)
179 documentation_file = fopen (documentation_filename, "w");
180 else if (strcmp (arg, "-D") == 0)
185 free (error_directory);
187 error_directory = xmalloc (2 + strlen (argv[arg_index]));
188 strcpy (error_directory, argv[arg_index]);
189 len = strlen (error_directory);
191 if (len && error_directory[len - 1] != '/')
192 strcat (error_directory, "/");
196 else if (strcmp (arg, "-documentonly") == 0)
198 only_documentation = 1;
199 documentation_file = fopen (documentation_filename, "w");
201 #if !defined (OLDCODE)
202 else if (strcmp (arg, "-nodocument") == 0)
203 no_long_document = 1;
204 #endif /* !OLDCODE */
207 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
212 /* If there are no files to process, just quit now. */
213 if (arg_index == argc)
216 if (!only_documentation)
218 /* Open the files. */
221 temp_struct_filename = xmalloc (15);
222 sprintf (temp_struct_filename, "mk-%d", (int) getpid ());
223 structfile = fopen (temp_struct_filename, "w");
226 file_error (temp_struct_filename);
231 externfile = fopen (extern_filename, "w");
234 file_error (extern_filename);
237 /* Write out the headers. */
238 write_file_headers (structfile, externfile);
241 if (documentation_file)
243 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
245 fprintf (documentation_file, "@ftable @asis\n");
248 /* Process the .def files. */
249 while (arg_index < argc)
253 arg = argv[arg_index++];
255 extract_info (arg, structfile, externfile);
258 /* Close the files. */
259 if (!only_documentation)
261 /* Write the footers. */
262 write_file_footers (structfile, externfile);
266 write_longdocs (structfile, saved_builtins);
268 link (temp_struct_filename, struct_filename);
269 unlink (temp_struct_filename);
276 if (documentation_file)
278 fprintf (documentation_file, "@end ftable\n");
279 fclose (documentation_file);
285 /* **************************************************************** */
287 /* Array Functions and Manipulators */
289 /* **************************************************************** */
291 /* Make a new array, and return a pointer to it. The array will
292 contain elements of size WIDTH, and is initialized to no elements. */
299 array = (ARRAY *)xmalloc (sizeof (ARRAY));
302 array->width = width;
304 /* Default to increasing size in units of 20. */
305 array->growth_rate = 20;
307 array->array = (char **)NULL;
312 /* Copy the array of strings in ARRAY. */
314 copy_string_array (array)
321 return (ARRAY *)NULL;
323 copy = array_create (sizeof (char *));
325 copy->size = array->size;
326 copy->sindex = array->sindex;
327 copy->width = array->width;
329 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
331 for (i = 0; i < array->sindex; i++)
332 copy->array[i] = savestring (array->array[i]);
334 copy->array[i] = (char *)NULL;
339 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
341 array_add (element, array)
345 if (array->sindex + 2 > array->size)
346 array->array = (char **)xrealloc
347 (array->array, (array->size += array->growth_rate) * array->width);
349 #if defined (HAVE_BCOPY)
350 bcopy (&element, (char *) &(array->array[array->sindex]), array->width);
352 bzero ((char *) &(array->array[array->sindex]), array->width);
354 array->array[array->sindex++] = element;
355 array->array[array->sindex] = (char *)NULL;
356 #endif /* !HAVE_BCOPY */
359 /* Free an allocated array and data pointer. */
370 /* **************************************************************** */
372 /* Processing a DEF File */
374 /* **************************************************************** */
376 /* The definition of a function. */
377 typedef int Function ();
379 /* Structure handles processor directives. */
386 builtin_handler (), function_handler (), short_doc_handler (),
387 comment_handler (), depends_on_handler (), produces_handler (),
388 end_handler (), docname_handler ();
390 HANDLER_ENTRY handlers[] = {
391 { "BUILTIN", builtin_handler },
392 { "DOCNAME", docname_handler },
393 { "FUNCTION", function_handler },
394 { "SHORT_DOC", short_doc_handler },
395 { "$", comment_handler },
396 { "COMMENT", comment_handler },
397 { "DEPENDS_ON", depends_on_handler },
398 { "PRODUCES", produces_handler },
399 { "END", end_handler },
400 { (char *)NULL, (Function *)NULL }
403 /* Return the entry in the table of handlers for NAME. */
405 find_directive (directive)
410 for (i = 0; handlers[i].directive; i++)
411 if (strcmp (handlers[i].directive, directive) == 0)
412 return (&handlers[i]);
414 return ((HANDLER_ENTRY *)NULL);
417 /* Non-zero indicates that a $BUILTIN has been seen, but not
418 the corresponding $END. */
419 static int building_builtin = 0;
421 /* Non-zero means to output cpp line and file information before
422 printing the current line to the production file. */
423 int output_cpp_line_info = 0;
425 /* The main function of this program. Read FILENAME and act on what is
426 found. Lines not starting with a dollar sign are copied to the
427 $PRODUCES target, if one is present. Lines starting with a dollar sign
428 are directives to this program, specifying the name of the builtin, the
429 function to call, the short documentation and the long documentation
430 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
431 target. After the file has been processed, write out the names of
432 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
433 is ignored, as is "$$ comment text". */
435 extract_info (filename, structfile, externfile)
437 FILE *structfile, *externfile;
446 if (stat (filename, &finfo) == -1)
447 file_error (filename);
449 fd = open (filename, O_RDONLY, 0666);
452 file_error (filename);
454 file_size = (size_t)finfo.st_size;
455 buffer = xmalloc (1 + file_size);
457 if ((nr = read (fd, buffer, file_size)) < 0)
458 file_error (filename);
464 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
468 /* Create and fill in the initial structure describing this file. */
469 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
470 defs->filename = filename;
471 defs->lines = array_create (sizeof (char *));
472 defs->line_number = 0;
473 defs->production = (char *)NULL;
474 defs->output = (FILE *)NULL;
475 defs->builtins = (ARRAY *)NULL;
477 /* Build the array of lines. */
479 while (i < file_size)
481 array_add (&buffer[i], defs->lines);
483 while (buffer[i] != '\n' && i < file_size)
488 /* Begin processing the input file. We don't write any output
489 until we have a file to write output to. */
490 output_cpp_line_info = 1;
492 /* Process each line in the array. */
493 for (i = 0; line = defs->lines->array[i]; i++)
495 defs->line_number = i;
501 HANDLER_ENTRY *handler;
503 /* Isolate the directive. */
504 for (j = 0; line[j] && !whitespace (line[j]); j++);
506 directive = xmalloc (j);
507 strncpy (directive, line + 1, j - 1);
508 directive[j -1] = '\0';
510 /* Get the function handler and call it. */
511 handler = find_directive (directive);
515 line_error (defs, "Unknown directive `%s'", directive);
521 /* Advance to the first non-whitespace character. */
522 while (whitespace (line[j]))
525 /* Call the directive handler with the FILE, and ARGS. */
526 (*(handler->function)) (directive, defs, line + j);
532 if (building_builtin)
533 add_documentation (defs, line);
534 else if (defs->output)
536 if (output_cpp_line_info)
538 /* If we're handed an absolute pathname, don't prepend
539 the directory name. */
540 if (defs->filename[0] == '/')
541 fprintf (defs->output, "#line %d \"%s\"\n",
542 defs->line_number + 1, defs->filename);
544 fprintf (defs->output, "#line %d \"%s%s\"\n",
545 defs->line_number + 1,
546 error_directory ? error_directory : "./",
548 output_cpp_line_info = 0;
551 fprintf (defs->output, "%s\n", line);
556 /* Close the production file. */
558 fclose (defs->output);
560 /* The file has been processed. Write the accumulated builtins to
561 the builtins.c file, and write the extern definitions to the
563 write_builtins (defs, structfile, externfile);
569 #define free_safely(x) if (x) free (x)
572 free_builtin (builtin)
573 BUILTIN_DESC *builtin;
577 free_safely (builtin->name);
578 free_safely (builtin->function);
579 free_safely (builtin->shortdoc);
580 free_safely (builtin->docname);
582 if (builtin->longdoc)
583 array_free (builtin->longdoc);
585 if (builtin->dependencies)
587 for (i = 0; builtin->dependencies->array[i]; i++)
588 free (builtin->dependencies->array[i]);
589 array_free (builtin->dependencies);
593 /* Free all of the memory allocated to a DEF_FILE. */
599 register BUILTIN_DESC *builtin;
601 if (defs->production)
602 free (defs->production);
605 array_free (defs->lines);
609 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
611 free_builtin (builtin);
614 array_free (defs->builtins);
619 /* **************************************************************** */
621 /* The Handler Functions Themselves */
623 /* **************************************************************** */
625 /* Strip surrounding whitespace from STRING, and
626 return a pointer to the start of it. */
628 strip_whitespace (string)
631 while (whitespace (*string))
634 remove_trailing_whitespace (string);
638 /* Remove only the trailing whitespace from STRING. */
640 remove_trailing_whitespace (string)
645 i = strlen (string) - 1;
647 while (i > 0 && whitespace (string[i]))
653 /* Ensure that there is a argument in STRING and return it.
654 FOR_WHOM is the name of the directive which needs the argument.
655 DEFS is the DEF_FILE in which the directive is found.
656 If there is no argument, produce an error. */
658 get_arg (for_whom, defs, string)
659 char *for_whom, *string;
664 new = strip_whitespace (string);
667 line_error (defs, "%s requires an argument", for_whom);
669 return (savestring (new));
672 /* Error if not building a builtin. */
674 must_be_building (directive, defs)
678 if (!building_builtin)
679 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
682 /* Return the current builtin. */
684 current_builtin (directive, defs)
688 must_be_building (directive, defs);
690 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
692 return ((BUILTIN_DESC *)NULL);
695 /* Add LINE to the long documentation for the current builtin.
696 Ignore blank lines until the first non-blank line has been seen. */
698 add_documentation (defs, line)
702 register BUILTIN_DESC *builtin;
704 builtin = current_builtin ("(implied LONGDOC)", defs);
706 remove_trailing_whitespace (line);
708 if (!*line && !builtin->longdoc)
711 if (!builtin->longdoc)
712 builtin->longdoc = array_create (sizeof (char *));
714 array_add (line, builtin->longdoc);
717 /* How to handle the $BUILTIN directive. */
719 builtin_handler (self, defs, arg)
726 /* If we are already building a builtin, we cannot start a new one. */
727 if (building_builtin)
729 line_error (defs, "%s found before $END", self);
733 output_cpp_line_info++;
735 /* Get the name of this builtin, and stick it in the array. */
736 name = get_arg (self, defs, arg);
738 /* If this is the first builtin, create the array to hold them. */
740 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
742 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
744 new->function = (char *)NULL;
745 new->shortdoc = (char *)NULL;
746 new->docname = (char *)NULL;
747 new->longdoc = (ARRAY *)NULL;
748 new->dependencies = (ARRAY *)NULL;
751 if (is_special_builtin (name))
752 new->flags |= BUILTIN_FLAG_SPECIAL;
753 if (is_assignment_builtin (name))
754 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
756 array_add ((char *)new, defs->builtins);
757 building_builtin = 1;
762 /* How to handle the $FUNCTION directive. */
764 function_handler (self, defs, arg)
768 register BUILTIN_DESC *builtin;
770 builtin = current_builtin (self, defs);
774 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
777 if (builtin->function)
778 line_error (defs, "%s already has a function (%s)",
779 builtin->name, builtin->function);
781 builtin->function = get_arg (self, defs, arg);
786 /* How to handle the $DOCNAME directive. */
788 docname_handler (self, defs, arg)
792 register BUILTIN_DESC *builtin;
794 builtin = current_builtin (self, defs);
796 if (builtin->docname)
797 line_error (defs, "%s already had a docname (%s)",
798 builtin->name, builtin->docname);
800 builtin->docname = get_arg (self, defs, arg);
805 /* How to handle the $SHORT_DOC directive. */
807 short_doc_handler (self, defs, arg)
811 register BUILTIN_DESC *builtin;
813 builtin = current_builtin (self, defs);
815 if (builtin->shortdoc)
816 line_error (defs, "%s already has short documentation (%s)",
817 builtin->name, builtin->shortdoc);
819 builtin->shortdoc = get_arg (self, defs, arg);
824 /* How to handle the $COMMENT directive. */
826 comment_handler (self, defs)
833 /* How to handle the $DEPENDS_ON directive. */
835 depends_on_handler (self, defs, arg)
839 register BUILTIN_DESC *builtin;
842 builtin = current_builtin (self, defs);
843 dependent = get_arg (self, defs, arg);
845 if (!builtin->dependencies)
846 builtin->dependencies = array_create (sizeof (char *));
848 array_add (dependent, builtin->dependencies);
853 /* How to handle the $PRODUCES directive. */
855 produces_handler (self, defs, arg)
859 /* If just hacking documentation, don't change any of the production
861 if (only_documentation)
864 output_cpp_line_info++;
866 if (defs->production)
867 line_error (defs, "%s already has a %s definition", defs->filename, self);
870 defs->production = get_arg (self, defs, arg);
872 if (inhibit_production)
875 defs->output = fopen (defs->production, "w");
878 file_error (defs->production);
880 fprintf (defs->output, "/* %s, created from %s. */\n",
881 defs->production, defs->filename);
886 /* How to handle the $END directive. */
888 end_handler (self, defs, arg)
892 must_be_building (self, defs);
893 building_builtin = 0;
897 /* **************************************************************** */
899 /* Error Handling Functions */
901 /* **************************************************************** */
903 /* Produce an error for DEFS with FORMAT and ARGS. */
905 line_error (defs, format, arg1, arg2)
907 char *format, *arg1, *arg2;
909 if (defs->filename[0] != '/')
910 fprintf (stderr, "%s", error_directory ? error_directory : "./");
911 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
912 fprintf (stderr, format, arg1, arg2);
913 fprintf (stderr, "\n");
917 /* Print error message for FILENAME. */
919 file_error (filename)
926 /* **************************************************************** */
928 /* xmalloc and xrealloc () */
930 /* **************************************************************** */
932 static void memory_error_and_abort ();
938 char *temp = (char *)malloc (bytes);
941 memory_error_and_abort ();
946 xrealloc (pointer, bytes)
953 temp = (char *)malloc (bytes);
955 temp = (char *)realloc (pointer, bytes);
958 memory_error_and_abort ();
964 memory_error_and_abort ()
966 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
970 /* **************************************************************** */
972 /* Creating the Struct and Extern Files */
974 /* **************************************************************** */
976 /* Return a pointer to a newly allocated builtin which is
977 an exact copy of BUILTIN. */
979 copy_builtin (builtin)
980 BUILTIN_DESC *builtin;
984 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
986 new->name = savestring (builtin->name);
987 new->shortdoc = savestring (builtin->shortdoc);
988 new->longdoc = copy_string_array (builtin->longdoc);
989 new->dependencies = copy_string_array (builtin->dependencies);
992 builtin->function ? savestring (builtin->function) : (char *)NULL;
994 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
999 /* How to save away a builtin. */
1001 save_builtin (builtin)
1002 BUILTIN_DESC *builtin;
1004 BUILTIN_DESC *newbuiltin;
1006 newbuiltin = copy_builtin (builtin);
1008 /* If this is the first builtin to be saved, create the array
1010 if (!saved_builtins)
1011 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1013 array_add ((char *)newbuiltin, saved_builtins);
1016 /* Flags that mean something to write_documentation (). */
1017 #define STRING_ARRAY 1
1020 char *structfile_header[] = {
1021 "/* builtins.c -- the built in shell commands. */",
1023 "/* This file is manufactured by ./mkbuiltins, and should not be",
1024 " edited by hand. See the source to mkbuiltins for details. */",
1026 "/* Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.",
1028 " This file is part of GNU Bash, the Bourne Again SHell.",
1030 " Bash is free software; you can redistribute it and/or modify it",
1031 " under the terms of the GNU General Public License as published by",
1032 " the Free Software Foundation; either version 1, or (at your option)",
1033 " any later version.",
1035 " Bash is distributed in the hope that it will be useful, but WITHOUT",
1036 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1037 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public",
1038 " License for more details.",
1040 " You should have received a copy of the GNU General Public License",
1041 " along with Bash; see the file COPYING. If not, write to the Free",
1042 " Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
1044 "/* The list of shell builtins. Each element is name, function, flags,",
1045 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1046 " of help lines. The function takes a WORD_LIST *; the first word in the",
1047 " list is the first arg to the command. The list has already had word",
1048 " expansion performed.",
1050 " Functions which need to look at only the simple commands (e.g.",
1051 " the enable_builtin ()), should ignore entries where",
1052 " (array[i].function == (Function *)NULL). Such entries are for",
1053 " the list of shell reserved control structures, like `if' and `while'.",
1054 " The end of the list is denoted with a NULL name field. */",
1056 "#include \"../builtins.h\"",
1060 char *structfile_footer[] = {
1061 " { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
1064 "struct builtin *shell_builtins = static_shell_builtins;",
1065 "struct builtin *current_builtin;",
1067 "int num_shell_builtins =",
1068 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1072 /* Write out any neccessary opening information for
1073 STRUCTFILE and EXTERNFILE. */
1075 write_file_headers (structfile, externfile)
1076 FILE *structfile, *externfile;
1082 for (i = 0; structfile_header[i]; i++)
1083 fprintf (structfile, "%s\n", structfile_header[i]);
1085 fprintf (structfile, "#include \"%s\"\n",
1086 extern_filename ? extern_filename : "builtext.h");
1087 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1091 fprintf (externfile,
1092 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1093 extern_filename ? extern_filename : "builtext.h");
1096 /* Write out any necessary closing information for
1097 STRUCTFILE and EXTERNFILE. */
1099 write_file_footers (structfile, externfile)
1100 FILE *structfile, *externfile;
1104 /* Write out the footers. */
1107 for (i = 0; structfile_footer[i]; i++)
1108 fprintf (structfile, "%s\n", structfile_footer[i]);
1112 /* Write out the information accumulated in DEFS to
1113 STRUCTFILE and EXTERNFILE. */
1115 write_builtins (defs, structfile, externfile)
1117 FILE *structfile, *externfile;
1121 /* Write out the information. */
1124 register BUILTIN_DESC *builtin;
1126 for (i = 0; i < defs->builtins->sindex; i++)
1128 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1130 /* Write out any #ifdefs that may be there. */
1131 if (!only_documentation)
1133 if (builtin->dependencies)
1135 write_ifdefs (externfile, builtin->dependencies->array);
1136 write_ifdefs (structfile, builtin->dependencies->array);
1139 /* Write the extern definition. */
1142 if (builtin->function)
1143 fprintf (externfile, "extern int %s ();\n",
1146 fprintf (externfile, "extern char *%s_doc[];\n",
1147 builtin->docname ?builtin->docname : builtin->name);
1150 /* Write the structure definition. */
1153 fprintf (structfile, " { \"%s\", ", builtin->name);
1155 if (builtin->function)
1156 fprintf (structfile, "%s, ", builtin->function);
1158 fprintf (structfile, "(Function *)0x0, ");
1160 fprintf (structfile, "%s%s%s, %s_doc,\n",
1161 "BUILTIN_ENABLED | STATIC_BUILTIN",
1162 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1163 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1164 builtin->docname ? builtin->docname : builtin->name);
1167 (structfile, " \"%s\", (char *)NULL },\n",
1168 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1170 /* Save away this builtin for later writing of the
1171 long documentation strings. */
1172 save_builtin (builtin);
1175 /* Write out the matching #endif, if neccessary. */
1176 if (builtin->dependencies)
1179 write_endifs (externfile, builtin->dependencies->array);
1182 write_endifs (structfile, builtin->dependencies->array);
1186 if (documentation_file)
1188 fprintf (documentation_file, "@item %s\n", builtin->name);
1190 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1196 /* Write out the long documentation strings in BUILTINS to STREAM. */
1198 write_longdocs (stream, builtins)
1203 register BUILTIN_DESC *builtin;
1205 for (i = 0; i < builtins->sindex; i++)
1207 builtin = (BUILTIN_DESC *)builtins->array[i];
1209 if (builtin->dependencies)
1210 write_ifdefs (stream, builtin->dependencies->array);
1212 /* Write the long documentation strings. */
1213 fprintf (stream, "char *%s_doc[] =",
1214 builtin->docname ? builtin->docname : builtin->name);
1215 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1217 if (builtin->dependencies)
1218 write_endifs (stream, builtin->dependencies->array);
1223 /* Write an #ifdef string saying what needs to be defined (or not defined)
1224 in order to allow compilation of the code that will follow.
1225 STREAM is the stream to write the information to,
1226 DEFINES is a null terminated array of define names.
1227 If a define is preceded by an `!', then the sense of the test is
1230 write_ifdefs (stream, defines)
1239 fprintf (stream, "#if ");
1241 for (i = 0; defines[i]; i++)
1243 char *def = defines[i];
1246 fprintf (stream, "!defined (%s)", def + 1);
1248 fprintf (stream, "defined (%s)", def);
1251 fprintf (stream, " && ");
1253 fprintf (stream, "\n");
1256 /* Write an #endif string saying what defines controlled the compilation
1257 of the immediately preceding code.
1258 STREAM is the stream to write the information to.
1259 DEFINES is a null terminated array of define names. */
1261 write_endifs (stream, defines)
1270 fprintf (stream, "#endif /* ");
1272 for (i = 0; defines[i]; i++)
1274 fprintf (stream, "%s", defines[i]);
1277 fprintf (stream, " && ");
1280 fprintf (stream, " */\n");
1283 /* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
1284 and quoting special characters in the string. */
1286 write_documentation (stream, documentation, indentation, flags)
1288 char **documentation;
1289 int indentation, flags;
1292 register char *line;
1293 int string_array, texinfo;
1298 string_array = flags & STRING_ARRAY;
1300 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
1302 #if !defined (OLDCODE)
1303 /* XXX -- clean me up; for experiment only */
1304 if (no_long_document)
1305 goto end_of_document;
1306 #endif /* !OLDCODE */
1308 for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1310 /* Allow #ifdef's to be written out verbatim. */
1314 fprintf (stream, "%s\n", line);
1319 fprintf (stream, " \"");
1322 for (j = 0; j < indentation; j++)
1323 fprintf (stream, " ");
1327 for (j = 0; line[j]; j++)
1333 fprintf (stream, "\\%c", line[j]);
1337 fprintf (stream, "%c", line[j]);
1341 fprintf (stream, "\",\n");
1345 for (j = 0; line[j]; j++)
1352 fprintf (stream, "@%c", line[j]);
1356 fprintf (stream, "%c", line[j]);
1359 fprintf (stream, "\n");
1362 fprintf (stream, "%s\n", line);
1365 #if !defined (OLDCODE)
1367 #endif /* !OLDCODE */
1370 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1374 _find_in_table (name, name_table)
1375 char *name, *name_table[];
1379 for (i = 0; name_table[i]; i++)
1380 if (strcmp (name, name_table[i]) == 0)
1386 is_special_builtin (name)
1389 return (_find_in_table (name, special_builtins));
1393 is_assignment_builtin (name)
1396 return (_find_in_table (name, assignment_builtins));