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)
28 #include "../bashtypes.h"
30 #include "../posixstat.h"
31 #include "../filecntl.h"
33 #if defined (HAVE_UNISTD_H)
35 #endif /* HAVE_UNISTD_H */
37 #include "../bashansi.h"
40 #define DOCFILE "builtins.texi"
42 static char *xmalloc (), *xrealloc ();
44 #if !defined (__STDC__) && !defined (strcpy)
45 extern char *strcpy ();
46 #endif /* !__STDC__ && !strcpy */
48 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
49 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
51 /* Flag values that builtins can have. */
52 #define BUILTIN_FLAG_SPECIAL 0x01
53 #define BUILTIN_FLAG_ASSIGNMENT 0x02
55 /* If this stream descriptor is non-zero, then write
56 texinfo documentation to it. */
57 FILE *documentation_file = (FILE *)NULL;
59 /* Non-zero means to only produce documentation. */
60 int only_documentation = 0;
62 /* Non-zero means to not do any productions. */
63 int inhibit_production = 0;
65 #if !defined (OLDCODE)
66 int no_long_document = 0;
69 /* The name of a directory to precede the filename when reporting
71 char *error_directory = (char *)NULL;
73 /* The name of the structure file. */
74 char *struct_filename = (char *)NULL;
76 /* The name of the external declaration file. */
77 char *extern_filename = (char *)NULL;
79 /* Here is a structure for manipulating arrays of data. */
81 int size; /* Number of slots allocated to array. */
82 int sindex; /* Current location in array. */
83 int width; /* Size of each element. */
84 int growth_rate; /* How fast to grow. */
85 char **array; /* The array itself. */
88 /* Here is a structure defining a single BUILTIN. */
90 char *name; /* The name of this builtin. */
91 char *function; /* The name of the function to call. */
92 char *shortdoc; /* The short documentation for this builtin. */
93 char *docname; /* Possible name for documentation string. */
94 ARRAY *longdoc; /* The long documentation for this builtin. */
95 ARRAY *dependencies; /* Null terminated array of #define names. */
96 int flags; /* Flags for this builtin. */
99 /* Here is a structure which defines a DEF file. */
101 char *filename; /* The name of the input def file. */
102 ARRAY *lines; /* The contents of the file. */
103 int line_number; /* The current line number. */
104 char *production; /* The name of the production file. */
105 FILE *output; /* Open file stream for PRODUCTION. */
106 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
109 /* The array of all builtins encountered during execution of this code. */
110 ARRAY *saved_builtins = (ARRAY *)NULL;
112 /* The Posix.2 so-called `special' builtins. */
113 char *special_builtins[] =
115 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
116 "export", "readonly", "return", "set", "shift", "trap", "unset",
120 /* The builtin commands that take assignment statements as arguments. */
121 char *assignment_builtins[] =
123 "alias", "declare", "export", "local", "readonly", "typeset",
127 /* Forward declarations. */
128 static int is_special_builtin ();
129 static int is_assignment_builtin ();
131 void extract_info ();
136 void write_file_headers ();
137 void write_file_footers ();
138 void write_ifdefs ();
139 void write_endifs ();
140 void write_documentation ();
141 void write_longdocs ();
142 void write_builtins ();
145 void add_documentation ();
147 void must_be_building ();
148 void remove_trailing_whitespace ();
150 /* For each file mentioned on the command line, process it and
151 write the information to STRUCTFILE and EXTERNFILE, while
152 creating the production file if neccessary. */
159 FILE *structfile, *externfile;
160 char *documentation_filename, *temp_struct_filename;
162 structfile = externfile = (FILE *)NULL;
163 documentation_filename = DOCFILE;
164 temp_struct_filename = (char *)NULL;
166 while (arg_index < argc && argv[arg_index][0] == '-')
168 char *arg = argv[arg_index++];
170 if (strcmp (arg, "-externfile") == 0)
171 extern_filename = argv[arg_index++];
172 else if (strcmp (arg, "-structfile") == 0)
173 struct_filename = argv[arg_index++];
174 else if (strcmp (arg, "-noproduction") == 0)
175 inhibit_production = 1;
176 else if (strcmp (arg, "-document") == 0)
177 documentation_file = fopen (documentation_filename, "w");
178 else if (strcmp (arg, "-D") == 0)
183 free (error_directory);
185 error_directory = xmalloc (2 + strlen (argv[arg_index]));
186 strcpy (error_directory, argv[arg_index]);
187 len = strlen (error_directory);
189 if (len && error_directory[len - 1] != '/')
190 strcat (error_directory, "/");
194 else if (strcmp (arg, "-documentonly") == 0)
196 only_documentation = 1;
197 documentation_file = fopen (documentation_filename, "w");
199 #if !defined (OLDCODE)
200 else if (strcmp (arg, "-nodocument") == 0)
201 no_long_document = 1;
202 #endif /* !OLDCODE */
205 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
210 /* If there are no files to process, just quit now. */
211 if (arg_index == argc)
214 if (!only_documentation)
216 /* Open the files. */
219 temp_struct_filename = xmalloc (15);
220 sprintf (temp_struct_filename, "mk-%d", (int) getpid ());
221 structfile = fopen (temp_struct_filename, "w");
224 file_error (temp_struct_filename);
229 externfile = fopen (extern_filename, "w");
232 file_error (extern_filename);
235 /* Write out the headers. */
236 write_file_headers (structfile, externfile);
239 if (documentation_file)
241 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
243 fprintf (documentation_file, "@ftable @asis\n");
246 /* Process the .def files. */
247 while (arg_index < argc)
251 arg = argv[arg_index++];
253 extract_info (arg, structfile, externfile);
256 /* Close the files. */
257 if (!only_documentation)
259 /* Write the footers. */
260 write_file_footers (structfile, externfile);
264 write_longdocs (structfile, saved_builtins);
266 link (temp_struct_filename, struct_filename);
267 unlink (temp_struct_filename);
274 if (documentation_file)
276 fprintf (documentation_file, "@end ftable\n");
277 fclose (documentation_file);
283 /* **************************************************************** */
285 /* Array Functions and Manipulators */
287 /* **************************************************************** */
289 /* Make a new array, and return a pointer to it. The array will
290 contain elements of size WIDTH, and is initialized to no elements. */
297 array = (ARRAY *)xmalloc (sizeof (ARRAY));
300 array->width = width;
302 /* Default to increasing size in units of 20. */
303 array->growth_rate = 20;
305 array->array = (char **)NULL;
310 /* Copy the array of strings in ARRAY. */
312 copy_string_array (array)
319 return (ARRAY *)NULL;
321 copy = array_create (sizeof (char *));
323 copy->size = array->size;
324 copy->sindex = array->sindex;
325 copy->width = array->width;
327 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
329 for (i = 0; i < array->sindex; i++)
330 copy->array[i] = savestring (array->array[i]);
332 copy->array[i] = (char *)NULL;
337 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
339 array_add (element, array)
343 if (array->sindex + 2 > array->size)
344 array->array = (char **)xrealloc
345 (array->array, (array->size += array->growth_rate) * array->width);
347 #if defined (HAVE_BCOPY)
348 bcopy (&element, (char *) &(array->array[array->sindex]), array->width);
350 bzero ((char *) &(array->array[array->sindex]), array->width);
352 array->array[array->sindex++] = element;
353 array->array[array->sindex] = (char *)NULL;
354 #endif /* !HAVE_BCOPY */
357 /* Free an allocated array and data pointer. */
368 /* **************************************************************** */
370 /* Processing a DEF File */
372 /* **************************************************************** */
374 /* The definition of a function. */
375 typedef int Function ();
377 /* Structure handles processor directives. */
384 builtin_handler (), function_handler (), short_doc_handler (),
385 comment_handler (), depends_on_handler (), produces_handler (),
386 end_handler (), docname_handler ();
388 HANDLER_ENTRY handlers[] = {
389 { "BUILTIN", builtin_handler },
390 { "DOCNAME", docname_handler },
391 { "FUNCTION", function_handler },
392 { "SHORT_DOC", short_doc_handler },
393 { "$", comment_handler },
394 { "COMMENT", comment_handler },
395 { "DEPENDS_ON", depends_on_handler },
396 { "PRODUCES", produces_handler },
397 { "END", end_handler },
398 { (char *)NULL, (Function *)NULL }
401 /* Return the entry in the table of handlers for NAME. */
403 find_directive (directive)
408 for (i = 0; handlers[i].directive; i++)
409 if (strcmp (handlers[i].directive, directive) == 0)
410 return (&handlers[i]);
412 return ((HANDLER_ENTRY *)NULL);
415 /* Non-zero indicates that a $BUILTIN has been seen, but not
416 the corresponding $END. */
417 static int building_builtin = 0;
419 /* Non-zero means to output cpp line and file information before
420 printing the current line to the production file. */
421 int output_cpp_line_info = 0;
423 /* The main function of this program. Read FILENAME and act on what is
424 found. Lines not starting with a dollar sign are copied to the
425 $PRODUCES target, if one is present. Lines starting with a dollar sign
426 are directives to this program, specifying the name of the builtin, the
427 function to call, the short documentation and the long documentation
428 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
429 target. After the file has been processed, write out the names of
430 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
431 is ignored, as is "$$ comment text". */
433 extract_info (filename, structfile, externfile)
435 FILE *structfile, *externfile;
443 if (stat (filename, &finfo) == -1)
444 file_error (filename);
446 fd = open (filename, O_RDONLY, 0666);
449 file_error (filename);
451 buffer = xmalloc (1 + (int)finfo.st_size);
453 if (read (fd, buffer, finfo.st_size) != finfo.st_size)
454 file_error (filename);
458 /* Create and fill in the initial structure describing this file. */
459 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
460 defs->filename = filename;
461 defs->lines = array_create (sizeof (char *));
462 defs->line_number = 0;
463 defs->production = (char *)NULL;
464 defs->output = (FILE *)NULL;
465 defs->builtins = (ARRAY *)NULL;
467 /* Build the array of lines. */
469 while (i < finfo.st_size)
471 array_add (&buffer[i], defs->lines);
473 while (buffer[i] != '\n' && i < finfo.st_size)
478 /* Begin processing the input file. We don't write any output
479 until we have a file to write output to. */
480 output_cpp_line_info = 1;
482 /* Process each line in the array. */
483 for (i = 0; line = defs->lines->array[i]; i++)
485 defs->line_number = i;
491 HANDLER_ENTRY *handler;
493 /* Isolate the directive. */
494 for (j = 0; line[j] && !whitespace (line[j]); j++);
496 directive = xmalloc (j);
497 strncpy (directive, line + 1, j - 1);
498 directive[j -1] = '\0';
500 /* Get the function handler and call it. */
501 handler = find_directive (directive);
505 line_error (defs, "Unknown directive `%s'", directive);
511 /* Advance to the first non-whitespace character. */
512 while (whitespace (line[j]))
515 /* Call the directive handler with the FILE, and ARGS. */
516 (*(handler->function)) (directive, defs, line + j);
522 if (building_builtin)
523 add_documentation (defs, line);
524 else if (defs->output)
526 if (output_cpp_line_info)
528 /* If we're handed an absolute pathname, don't prepend
529 the directory name. */
530 if (defs->filename[0] == '/')
531 fprintf (defs->output, "#line %d \"%s\"\n",
532 defs->line_number + 1, defs->filename);
534 fprintf (defs->output, "#line %d \"%s%s\"\n",
535 defs->line_number + 1,
536 error_directory ? error_directory : "./",
538 output_cpp_line_info = 0;
541 fprintf (defs->output, "%s\n", line);
546 /* Close the production file. */
548 fclose (defs->output);
550 /* The file has been processed. Write the accumulated builtins to
551 the builtins.c file, and write the extern definitions to the
553 write_builtins (defs, structfile, externfile);
559 #define free_safely(x) if (x) free (x)
562 free_builtin (builtin)
563 BUILTIN_DESC *builtin;
567 free_safely (builtin->name);
568 free_safely (builtin->function);
569 free_safely (builtin->shortdoc);
570 free_safely (builtin->docname);
572 if (builtin->longdoc)
573 array_free (builtin->longdoc);
575 if (builtin->dependencies)
577 for (i = 0; builtin->dependencies->array[i]; i++)
578 free (builtin->dependencies->array[i]);
579 array_free (builtin->dependencies);
583 /* Free all of the memory allocated to a DEF_FILE. */
589 register BUILTIN_DESC *builtin;
591 if (defs->production)
592 free (defs->production);
595 array_free (defs->lines);
599 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
601 free_builtin (builtin);
604 array_free (defs->builtins);
609 /* **************************************************************** */
611 /* The Handler Functions Themselves */
613 /* **************************************************************** */
615 /* Strip surrounding whitespace from STRING, and
616 return a pointer to the start of it. */
618 strip_whitespace (string)
621 while (whitespace (*string))
624 remove_trailing_whitespace (string);
628 /* Remove only the trailing whitespace from STRING. */
630 remove_trailing_whitespace (string)
635 i = strlen (string) - 1;
637 while (i > 0 && whitespace (string[i]))
643 /* Ensure that there is a argument in STRING and return it.
644 FOR_WHOM is the name of the directive which needs the argument.
645 DEFS is the DEF_FILE in which the directive is found.
646 If there is no argument, produce an error. */
648 get_arg (for_whom, defs, string)
649 char *for_whom, *string;
654 new = strip_whitespace (string);
657 line_error (defs, "%s requires an argument", for_whom);
659 return (savestring (new));
662 /* Error if not building a builtin. */
664 must_be_building (directive, defs)
668 if (!building_builtin)
669 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
672 /* Return the current builtin. */
674 current_builtin (directive, defs)
678 must_be_building (directive, defs);
679 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
682 /* Add LINE to the long documentation for the current builtin.
683 Ignore blank lines until the first non-blank line has been seen. */
685 add_documentation (defs, line)
689 register BUILTIN_DESC *builtin;
691 builtin = current_builtin ("(implied LONGDOC)", defs);
693 remove_trailing_whitespace (line);
695 if (!*line && !builtin->longdoc)
698 if (!builtin->longdoc)
699 builtin->longdoc = array_create (sizeof (char *));
701 array_add (line, builtin->longdoc);
704 /* How to handle the $BUILTIN directive. */
706 builtin_handler (self, defs, arg)
713 /* If we are already building a builtin, we cannot start a new one. */
714 if (building_builtin)
716 line_error (defs, "%s found before $END", self);
720 output_cpp_line_info++;
722 /* Get the name of this builtin, and stick it in the array. */
723 name = get_arg (self, defs, arg);
725 /* If this is the first builtin, create the array to hold them. */
727 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
729 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
731 new->function = (char *)NULL;
732 new->shortdoc = (char *)NULL;
733 new->docname = (char *)NULL;
734 new->longdoc = (ARRAY *)NULL;
735 new->dependencies = (ARRAY *)NULL;
738 if (is_special_builtin (name))
739 new->flags |= BUILTIN_FLAG_SPECIAL;
740 if (is_assignment_builtin (name))
741 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
743 array_add ((char *)new, defs->builtins);
744 building_builtin = 1;
749 /* How to handle the $FUNCTION directive. */
751 function_handler (self, defs, arg)
755 register BUILTIN_DESC *builtin;
757 builtin = current_builtin (self, defs);
759 if (builtin->function)
760 line_error (defs, "%s already has a function (%s)",
761 builtin->name, builtin->function);
763 builtin->function = get_arg (self, defs, arg);
768 /* How to handle the $DOCNAME directive. */
770 docname_handler (self, defs, arg)
774 register BUILTIN_DESC *builtin;
776 builtin = current_builtin (self, defs);
778 if (builtin->docname)
779 line_error (defs, "%s already had a docname (%s)",
780 builtin->name, builtin->docname);
782 builtin->docname = get_arg (self, defs, arg);
787 /* How to handle the $SHORT_DOC directive. */
789 short_doc_handler (self, defs, arg)
793 register BUILTIN_DESC *builtin;
795 builtin = current_builtin (self, defs);
797 if (builtin->shortdoc)
798 line_error (defs, "%s already has short documentation (%s)",
799 builtin->name, builtin->shortdoc);
801 builtin->shortdoc = get_arg (self, defs, arg);
806 /* How to handle the $COMMENT directive. */
808 comment_handler (self, defs)
815 /* How to handle the $DEPENDS_ON directive. */
817 depends_on_handler (self, defs, arg)
821 register BUILTIN_DESC *builtin;
824 builtin = current_builtin (self, defs);
825 dependent = get_arg (self, defs, arg);
827 if (!builtin->dependencies)
828 builtin->dependencies = array_create (sizeof (char *));
830 array_add (dependent, builtin->dependencies);
835 /* How to handle the $PRODUCES directive. */
837 produces_handler (self, defs, arg)
841 /* If just hacking documentation, don't change any of the production
843 if (only_documentation)
846 output_cpp_line_info++;
848 if (defs->production)
849 line_error (defs, "%s already has a %s definition", defs->filename, self);
852 defs->production = get_arg (self, defs, arg);
854 if (inhibit_production)
857 defs->output = fopen (defs->production, "w");
860 file_error (defs->production);
862 fprintf (defs->output, "/* %s, created from %s. */\n",
863 defs->production, defs->filename);
868 /* How to handle the $END directive. */
870 end_handler (self, defs, arg)
874 must_be_building (self, defs);
875 building_builtin = 0;
879 /* **************************************************************** */
881 /* Error Handling Functions */
883 /* **************************************************************** */
885 /* Produce an error for DEFS with FORMAT and ARGS. */
887 line_error (defs, format, arg1, arg2)
889 char *format, *arg1, *arg2;
891 if (defs->filename[0] != '/')
892 fprintf (stderr, "%s", error_directory ? error_directory : "./");
893 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
894 fprintf (stderr, format, arg1, arg2);
895 fprintf (stderr, "\n");
899 /* Print error message for FILENAME. */
901 file_error (filename)
908 /* **************************************************************** */
910 /* xmalloc and xrealloc () */
912 /* **************************************************************** */
914 static void memory_error_and_abort ();
920 char *temp = (char *)malloc (bytes);
923 memory_error_and_abort ();
928 xrealloc (pointer, bytes)
935 temp = (char *)malloc (bytes);
937 temp = (char *)realloc (pointer, bytes);
940 memory_error_and_abort ();
946 memory_error_and_abort ()
948 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
952 /* **************************************************************** */
954 /* Creating the Struct and Extern Files */
956 /* **************************************************************** */
958 /* Return a pointer to a newly allocated builtin which is
959 an exact copy of BUILTIN. */
961 copy_builtin (builtin)
962 BUILTIN_DESC *builtin;
966 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
968 new->name = savestring (builtin->name);
969 new->shortdoc = savestring (builtin->shortdoc);
970 new->longdoc = copy_string_array (builtin->longdoc);
971 new->dependencies = copy_string_array (builtin->dependencies);
974 builtin->function ? savestring (builtin->function) : (char *)NULL;
976 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
981 /* How to save away a builtin. */
983 save_builtin (builtin)
984 BUILTIN_DESC *builtin;
986 BUILTIN_DESC *newbuiltin;
988 newbuiltin = copy_builtin (builtin);
990 /* If this is the first builtin to be saved, create the array
993 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
995 array_add ((char *)newbuiltin, saved_builtins);
998 /* Flags that mean something to write_documentation (). */
999 #define STRING_ARRAY 1
1002 char *structfile_header[] = {
1003 "/* builtins.c -- the built in shell commands. */",
1005 "/* This file is manufactured by ./mkbuiltins, and should not be",
1006 " edited by hand. See the source to mkbuiltins for details. */",
1008 "/* Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.",
1010 " This file is part of GNU Bash, the Bourne Again SHell.",
1012 " Bash is free software; you can redistribute it and/or modify it",
1013 " under the terms of the GNU General Public License as published by",
1014 " the Free Software Foundation; either version 1, or (at your option)",
1015 " any later version.",
1017 " Bash is distributed in the hope that it will be useful, but WITHOUT",
1018 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1019 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public",
1020 " License for more details.",
1022 " You should have received a copy of the GNU General Public License",
1023 " along with Bash; see the file COPYING. If not, write to the Free",
1024 " Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
1026 "/* The list of shell builtins. Each element is name, function, flags,",
1027 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1028 " of help lines. The function takes a WORD_LIST *; the first word in the",
1029 " list is the first arg to the command. The list has already had word",
1030 " expansion performed.",
1032 " Functions which need to look at only the simple commands (e.g.",
1033 " the enable_builtin ()), should ignore entries where",
1034 " (array[i].function == (Function *)NULL). Such entries are for",
1035 " the list of shell reserved control structures, like `if' and `while'.",
1036 " The end of the list is denoted with a NULL name field. */",
1038 "#include \"../builtins.h\"",
1042 char *structfile_footer[] = {
1043 " { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
1046 "struct builtin *shell_builtins = static_shell_builtins;",
1047 "struct builtin *current_builtin;",
1049 "int num_shell_builtins =",
1050 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1054 /* Write out any neccessary opening information for
1055 STRUCTFILE and EXTERNFILE. */
1057 write_file_headers (structfile, externfile)
1058 FILE *structfile, *externfile;
1064 for (i = 0; structfile_header[i]; i++)
1065 fprintf (structfile, "%s\n", structfile_header[i]);
1067 fprintf (structfile, "#include \"%s\"\n",
1068 extern_filename ? extern_filename : "builtext.h");
1069 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1073 fprintf (externfile,
1074 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1075 extern_filename ? extern_filename : "builtext.h");
1078 /* Write out any necessary closing information for
1079 STRUCTFILE and EXTERNFILE. */
1081 write_file_footers (structfile, externfile)
1082 FILE *structfile, *externfile;
1086 /* Write out the footers. */
1089 for (i = 0; structfile_footer[i]; i++)
1090 fprintf (structfile, "%s\n", structfile_footer[i]);
1094 /* Write out the information accumulated in DEFS to
1095 STRUCTFILE and EXTERNFILE. */
1097 write_builtins (defs, structfile, externfile)
1099 FILE *structfile, *externfile;
1103 /* Write out the information. */
1106 register BUILTIN_DESC *builtin;
1108 for (i = 0; i < defs->builtins->sindex; i++)
1110 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1112 /* Write out any #ifdefs that may be there. */
1113 if (!only_documentation)
1115 if (builtin->dependencies)
1117 write_ifdefs (externfile, builtin->dependencies->array);
1118 write_ifdefs (structfile, builtin->dependencies->array);
1121 /* Write the extern definition. */
1124 if (builtin->function)
1125 fprintf (externfile, "extern int %s ();\n",
1128 fprintf (externfile, "extern char *%s_doc[];\n",
1129 builtin->docname ?builtin->docname : builtin->name);
1132 /* Write the structure definition. */
1135 fprintf (structfile, " { \"%s\", ", builtin->name);
1137 if (builtin->function)
1138 fprintf (structfile, "%s, ", builtin->function);
1140 fprintf (structfile, "(Function *)0x0, ");
1142 fprintf (structfile, "%s%s%s, %s_doc,\n",
1143 "BUILTIN_ENABLED | STATIC_BUILTIN",
1144 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1145 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1146 builtin->docname ? builtin->docname : builtin->name);
1149 (structfile, " \"%s\", (char *)NULL },\n",
1150 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1152 /* Save away this builtin for later writing of the
1153 long documentation strings. */
1154 save_builtin (builtin);
1157 /* Write out the matching #endif, if neccessary. */
1158 if (builtin->dependencies)
1161 write_endifs (externfile, builtin->dependencies->array);
1164 write_endifs (structfile, builtin->dependencies->array);
1168 if (documentation_file)
1170 fprintf (documentation_file, "@item %s\n", builtin->name);
1172 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1178 /* Write out the long documentation strings in BUILTINS to STREAM. */
1180 write_longdocs (stream, builtins)
1185 register BUILTIN_DESC *builtin;
1187 for (i = 0; i < builtins->sindex; i++)
1189 builtin = (BUILTIN_DESC *)builtins->array[i];
1191 if (builtin->dependencies)
1192 write_ifdefs (stream, builtin->dependencies->array);
1194 /* Write the long documentation strings. */
1195 fprintf (stream, "char *%s_doc[] =",
1196 builtin->docname ? builtin->docname : builtin->name);
1197 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1199 if (builtin->dependencies)
1200 write_endifs (stream, builtin->dependencies->array);
1205 /* Write an #ifdef string saying what needs to be defined (or not defined)
1206 in order to allow compilation of the code that will follow.
1207 STREAM is the stream to write the information to,
1208 DEFINES is a null terminated array of define names.
1209 If a define is preceded by an `!', then the sense of the test is
1212 write_ifdefs (stream, defines)
1221 fprintf (stream, "#if ");
1223 for (i = 0; defines[i]; i++)
1225 char *def = defines[i];
1228 fprintf (stream, "!defined (%s)", def + 1);
1230 fprintf (stream, "defined (%s)", def);
1233 fprintf (stream, " && ");
1235 fprintf (stream, "\n");
1238 /* Write an #endif string saying what defines controlled the compilation
1239 of the immediately preceding code.
1240 STREAM is the stream to write the information to.
1241 DEFINES is a null terminated array of define names. */
1243 write_endifs (stream, defines)
1252 fprintf (stream, "#endif /* ");
1254 for (i = 0; defines[i]; i++)
1256 fprintf (stream, "%s", defines[i]);
1259 fprintf (stream, " && ");
1262 fprintf (stream, " */\n");
1265 /* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
1266 and quoting special characters in the string. */
1268 write_documentation (stream, documentation, indentation, flags)
1270 char **documentation;
1271 int indentation, flags;
1274 register char *line;
1275 int string_array, texinfo;
1280 string_array = flags & STRING_ARRAY;
1282 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
1284 #if !defined (OLDCODE)
1285 /* XXX -- clean me up; for experiment only */
1286 if (no_long_document)
1287 goto end_of_document;
1288 #endif /* !OLDCODE */
1290 for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1292 /* Allow #ifdef's to be written out verbatim. */
1296 fprintf (stream, "%s\n", line);
1301 fprintf (stream, " \"");
1304 for (j = 0; j < indentation; j++)
1305 fprintf (stream, " ");
1309 for (j = 0; line[j]; j++)
1315 fprintf (stream, "\\%c", line[j]);
1319 fprintf (stream, "%c", line[j]);
1323 fprintf (stream, "\",\n");
1327 for (j = 0; line[j]; j++)
1334 fprintf (stream, "@%c", line[j]);
1338 fprintf (stream, "%c", line[j]);
1341 fprintf (stream, "\n");
1344 fprintf (stream, "%s\n", line);
1347 #if !defined (OLDCODE)
1349 #endif /* !OLDCODE */
1352 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1356 _find_in_table (name, name_table)
1357 char *name, *name_table[];
1361 for (i = 0; name_table[i]; i++)
1362 if (strcmp (name, name_table[i]) == 0)
1368 is_special_builtin (name)
1371 return (_find_in_table (name, special_builtins));
1375 is_assignment_builtin (name)
1378 return (_find_in_table (name, assignment_builtins));