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 "../bashansi.h"
29 #include "../config.h"
31 #include <sys/types.h>
34 #include "../filecntl.h"
36 #if defined (HAVE_UNISTD_H)
38 #endif /* HAVE_UNISTD_H */
40 #if defined (HAVE_STRING_H)
42 #else /* !HAVE_STRING_H */
44 #endif /* !HAVE_STRING_H */
46 #define DOCFILE "builtins.texi"
48 static char *xmalloc (), *xrealloc ();
50 #if !defined (__STDC__) && !defined (strcpy)
51 extern char *strcpy ();
52 #endif /* !__STDC__ && !strcpy */
54 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
55 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
57 /* Flag values that builtins can have. */
58 #define BUILTIN_FLAG_SPECIAL 0x01
59 #define BUILTIN_FLAG_ASSIGNMENT 0x02
61 /* If this stream descriptor is non-zero, then write
62 texinfo documentation to it. */
63 FILE *documentation_file = (FILE *)NULL;
65 /* Non-zero means to only produce documentation. */
66 int only_documentation = 0;
68 /* Non-zero means to not do any productions. */
69 int inhibit_production = 0;
71 #if !defined (OLDCODE)
72 int no_long_document = 0;
75 /* The name of a directory to precede the filename when reporting
77 char *error_directory = (char *)NULL;
79 /* The name of the structure file. */
80 char *struct_filename = (char *)NULL;
82 /* The name of the external declaration file. */
83 char *extern_filename = (char *)NULL;
85 /* Here is a structure for manipulating arrays of data. */
87 int size; /* Number of slots allocated to array. */
88 int sindex; /* Current location in array. */
89 int width; /* Size of each element. */
90 int growth_rate; /* How fast to grow. */
91 char **array; /* The array itself. */
94 /* Here is a structure defining a single BUILTIN. */
96 char *name; /* The name of this builtin. */
97 char *function; /* The name of the function to call. */
98 char *shortdoc; /* The short documentation for this builtin. */
99 char *docname; /* Possible name for documentation string. */
100 ARRAY *longdoc; /* The long documentation for this builtin. */
101 ARRAY *dependencies; /* Null terminated array of #define names. */
102 int flags; /* Flags for this builtin. */
105 /* Here is a structure which defines a DEF file. */
107 char *filename; /* The name of the input def file. */
108 ARRAY *lines; /* The contents of the file. */
109 int line_number; /* The current line number. */
110 char *production; /* The name of the production file. */
111 FILE *output; /* Open file stream for PRODUCTION. */
112 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
115 /* The array of all builtins encountered during execution of this code. */
116 ARRAY *saved_builtins = (ARRAY *)NULL;
118 /* The Posix.2 so-called `special' builtins. */
119 char *special_builtins[] =
121 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
122 "export", "readonly", "return", "set", "shift", "trap", "unset",
126 /* The builtin commands that take assignment statements as arguments. */
127 char *assignment_builtins[] =
129 "alias", "declare", "export", "local", "readonly", "typeset",
133 /* Forward declarations. */
134 static int is_special_builtin ();
135 static int is_assignment_builtin ();
137 void extract_info ();
142 void write_file_headers ();
143 void write_file_footers ();
144 void write_ifdefs ();
145 void write_endifs ();
146 void write_documentation ();
147 void write_longdocs ();
148 void write_builtins ();
151 void add_documentation ();
153 void must_be_building ();
154 void remove_trailing_whitespace ();
156 /* For each file mentioned on the command line, process it and
157 write the information to STRUCTFILE and EXTERNFILE, while
158 creating the production file if neccessary. */
165 FILE *structfile, *externfile;
166 char *documentation_filename, *temp_struct_filename;
168 structfile = externfile = (FILE *)NULL;
169 documentation_filename = DOCFILE;
170 temp_struct_filename = (char *)NULL;
172 while (arg_index < argc && argv[arg_index][0] == '-')
174 char *arg = argv[arg_index++];
176 if (strcmp (arg, "-externfile") == 0)
177 extern_filename = argv[arg_index++];
178 else if (strcmp (arg, "-structfile") == 0)
179 struct_filename = argv[arg_index++];
180 else if (strcmp (arg, "-noproduction") == 0)
181 inhibit_production = 1;
182 else if (strcmp (arg, "-document") == 0)
183 documentation_file = fopen (documentation_filename, "w");
184 else if (strcmp (arg, "-D") == 0)
189 free (error_directory);
191 error_directory = xmalloc (2 + strlen (argv[arg_index]));
192 strcpy (error_directory, argv[arg_index]);
193 len = strlen (error_directory);
195 if (len && error_directory[len - 1] != '/')
196 strcat (error_directory, "/");
200 else if (strcmp (arg, "-documentonly") == 0)
202 only_documentation = 1;
203 documentation_file = fopen (documentation_filename, "w");
205 #if !defined (OLDCODE)
206 else if (strcmp (arg, "-nodocument") == 0)
207 no_long_document = 1;
208 #endif /* !OLDCODE */
211 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
216 /* If there are no files to process, just quit now. */
217 if (arg_index == argc)
220 if (!only_documentation)
222 /* Open the files. */
225 temp_struct_filename = xmalloc (15);
226 sprintf (temp_struct_filename, "mk-%d", (int) getpid ());
227 structfile = fopen (temp_struct_filename, "w");
230 file_error (temp_struct_filename);
235 externfile = fopen (extern_filename, "w");
238 file_error (extern_filename);
241 /* Write out the headers. */
242 write_file_headers (structfile, externfile);
245 if (documentation_file)
247 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
249 fprintf (documentation_file, "@ftable @asis\n");
252 /* Process the .def files. */
253 while (arg_index < argc)
257 arg = argv[arg_index++];
259 extract_info (arg, structfile, externfile);
262 /* Close the files. */
263 if (!only_documentation)
265 /* Write the footers. */
266 write_file_footers (structfile, externfile);
270 write_longdocs (structfile, saved_builtins);
272 link (temp_struct_filename, struct_filename);
273 unlink (temp_struct_filename);
280 if (documentation_file)
282 fprintf (documentation_file, "@end ftable\n");
283 fclose (documentation_file);
289 /* **************************************************************** */
291 /* Array Functions and Manipulators */
293 /* **************************************************************** */
295 /* Make a new array, and return a pointer to it. The array will
296 contain elements of size WIDTH, and is initialized to no elements. */
303 array = (ARRAY *)xmalloc (sizeof (ARRAY));
306 array->width = width;
308 /* Default to increasing size in units of 20. */
309 array->growth_rate = 20;
311 array->array = (char **)NULL;
316 /* Copy the array of strings in ARRAY. */
318 copy_string_array (array)
325 return (ARRAY *)NULL;
327 copy = array_create (sizeof (char *));
329 copy->size = array->size;
330 copy->sindex = array->sindex;
331 copy->width = array->width;
333 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
335 for (i = 0; i < array->sindex; i++)
336 copy->array[i] = savestring (array->array[i]);
338 copy->array[i] = (char *)NULL;
343 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
345 array_add (element, array)
349 if (array->sindex + 2 > array->size)
350 array->array = (char **)xrealloc
351 (array->array, (array->size += array->growth_rate) * array->width);
353 #if defined (HAVE_BCOPY)
354 bcopy (&element, &(array->array[array->sindex]), array->width);
356 bzero (&(array->array[array->sindex]), array->width);
358 array->array[array->sindex++] = element;
359 array->array[array->sindex] = (char *)NULL;
360 #endif /* !HAVE_BCOPY */
363 /* Free an allocated array and data pointer. */
374 /* **************************************************************** */
376 /* Processing a DEF File */
378 /* **************************************************************** */
380 /* The definition of a function. */
381 typedef int Function ();
383 /* Structure handles processor directives. */
390 builtin_handler (), function_handler (), short_doc_handler (),
391 comment_handler (), depends_on_handler (), produces_handler (),
392 end_handler (), docname_handler ();
394 HANDLER_ENTRY handlers[] = {
395 { "BUILTIN", builtin_handler },
396 { "DOCNAME", docname_handler },
397 { "FUNCTION", function_handler },
398 { "SHORT_DOC", short_doc_handler },
399 { "$", comment_handler },
400 { "COMMENT", comment_handler },
401 { "DEPENDS_ON", depends_on_handler },
402 { "PRODUCES", produces_handler },
403 { "END", end_handler },
404 { (char *)NULL, (Function *)NULL }
407 /* Return the entry in the table of handlers for NAME. */
409 find_directive (directive)
414 for (i = 0; handlers[i].directive; i++)
415 if (strcmp (handlers[i].directive, directive) == 0)
416 return (&handlers[i]);
418 return ((HANDLER_ENTRY *)NULL);
421 /* Non-zero indicates that a $BUILTIN has been seen, but not
422 the corresponding $END. */
423 static int building_builtin = 0;
425 /* Non-zero means to output cpp line and file information before
426 printing the current line to the production file. */
427 int output_cpp_line_info = 0;
429 /* The main function of this program. Read FILENAME and act on what is
430 found. Lines not starting with a dollar sign are copied to the
431 $PRODUCES target, if one is present. Lines starting with a dollar sign
432 are directives to this program, specifying the name of the builtin, the
433 function to call, the short documentation and the long documentation
434 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
435 target. After the file has been processed, write out the names of
436 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
437 is ignored, as is "$$ comment text". */
439 extract_info (filename, structfile, externfile)
441 FILE *structfile, *externfile;
449 if (stat (filename, &finfo) == -1)
450 file_error (filename);
452 fd = open (filename, O_RDONLY, 0666);
455 file_error (filename);
457 buffer = xmalloc (1 + (int)finfo.st_size);
459 if (read (fd, buffer, finfo.st_size) != finfo.st_size)
460 file_error (filename);
464 /* Create and fill in the initial structure describing this file. */
465 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
466 defs->filename = filename;
467 defs->lines = array_create (sizeof (char *));
468 defs->line_number = 0;
469 defs->production = (char *)NULL;
470 defs->output = (FILE *)NULL;
471 defs->builtins = (ARRAY *)NULL;
473 /* Build the array of lines. */
475 while (i < finfo.st_size)
477 array_add (&buffer[i], defs->lines);
479 while (buffer[i] != '\n' && i < finfo.st_size)
484 /* Begin processing the input file. We don't write any output
485 until we have a file to write output to. */
486 output_cpp_line_info = 1;
488 /* Process each line in the array. */
489 for (i = 0; line = defs->lines->array[i]; i++)
491 defs->line_number = i;
497 HANDLER_ENTRY *handler;
499 /* Isolate the directive. */
500 for (j = 0; line[j] && !whitespace (line[j]); j++);
502 directive = xmalloc (j);
503 strncpy (directive, line + 1, j - 1);
504 directive[j -1] = '\0';
506 /* Get the function handler and call it. */
507 handler = find_directive (directive);
511 line_error (defs, "Unknown directive `%s'", directive);
517 /* Advance to the first non-whitespace character. */
518 while (whitespace (line[j]))
521 /* Call the directive handler with the FILE, and ARGS. */
522 (*(handler->function)) (directive, defs, line + j);
528 if (building_builtin)
529 add_documentation (defs, line);
530 else if (defs->output)
532 if (output_cpp_line_info)
534 /* If we're handed an absolute pathname, don't prepend
535 the directory name. */
536 if (defs->filename[0] == '/')
537 fprintf (defs->output, "#line %d \"%s\"\n",
538 defs->line_number + 1, defs->filename);
540 fprintf (defs->output, "#line %d \"%s%s\"\n",
541 defs->line_number + 1,
542 error_directory ? error_directory : "./",
544 output_cpp_line_info = 0;
547 fprintf (defs->output, "%s\n", line);
552 /* Close the production file. */
554 fclose (defs->output);
556 /* The file has been processed. Write the accumulated builtins to
557 the builtins.c file, and write the extern definitions to the
559 write_builtins (defs, structfile, externfile);
565 #define free_safely(x) if (x) free (x)
568 free_builtin (builtin)
569 BUILTIN_DESC *builtin;
573 free_safely (builtin->name);
574 free_safely (builtin->function);
575 free_safely (builtin->shortdoc);
576 free_safely (builtin->docname);
578 if (builtin->longdoc)
579 array_free (builtin->longdoc);
581 if (builtin->dependencies)
583 for (i = 0; builtin->dependencies->array[i]; i++)
584 free (builtin->dependencies->array[i]);
585 array_free (builtin->dependencies);
589 /* Free all of the memory allocated to a DEF_FILE. */
595 register BUILTIN_DESC *builtin;
597 if (defs->production)
598 free (defs->production);
601 array_free (defs->lines);
605 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
607 free_builtin (builtin);
610 array_free (defs->builtins);
615 /* **************************************************************** */
617 /* The Handler Functions Themselves */
619 /* **************************************************************** */
621 /* Strip surrounding whitespace from STRING, and
622 return a pointer to the start of it. */
624 strip_whitespace (string)
627 while (whitespace (*string))
630 remove_trailing_whitespace (string);
634 /* Remove only the trailing whitespace from STRING. */
636 remove_trailing_whitespace (string)
641 i = strlen (string) - 1;
643 while (i > 0 && whitespace (string[i]))
649 /* Ensure that there is a argument in STRING and return it.
650 FOR_WHOM is the name of the directive which needs the argument.
651 DEFS is the DEF_FILE in which the directive is found.
652 If there is no argument, produce an error. */
654 get_arg (for_whom, defs, string)
655 char *for_whom, *string;
660 new = strip_whitespace (string);
663 line_error (defs, "%s requires an argument", for_whom);
665 return (savestring (new));
668 /* Error if not building a builtin. */
670 must_be_building (directive, defs)
674 if (!building_builtin)
675 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
678 /* Return the current builtin. */
680 current_builtin (directive, defs)
684 must_be_building (directive, defs);
685 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
688 /* Add LINE to the long documentation for the current builtin.
689 Ignore blank lines until the first non-blank line has been seen. */
691 add_documentation (defs, line)
695 register BUILTIN_DESC *builtin;
697 builtin = current_builtin ("(implied LONGDOC)", defs);
699 remove_trailing_whitespace (line);
701 if (!*line && !builtin->longdoc)
704 if (!builtin->longdoc)
705 builtin->longdoc = array_create (sizeof (char *));
707 array_add (line, builtin->longdoc);
710 /* How to handle the $BUILTIN directive. */
712 builtin_handler (self, defs, arg)
719 /* If we are already building a builtin, we cannot start a new one. */
720 if (building_builtin)
722 line_error (defs, "%s found before $END", self);
726 output_cpp_line_info++;
728 /* Get the name of this builtin, and stick it in the array. */
729 name = get_arg (self, defs, arg);
731 /* If this is the first builtin, create the array to hold them. */
733 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
735 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
737 new->function = (char *)NULL;
738 new->shortdoc = (char *)NULL;
739 new->docname = (char *)NULL;
740 new->longdoc = (ARRAY *)NULL;
741 new->dependencies = (ARRAY *)NULL;
744 if (is_special_builtin (name))
745 new->flags |= BUILTIN_FLAG_SPECIAL;
746 if (is_assignment_builtin (name))
747 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
749 array_add ((char *)new, defs->builtins);
750 building_builtin = 1;
755 /* How to handle the $FUNCTION directive. */
757 function_handler (self, defs, arg)
761 register BUILTIN_DESC *builtin;
763 builtin = current_builtin (self, defs);
765 if (builtin->function)
766 line_error (defs, "%s already has a function (%s)",
767 builtin->name, builtin->function);
769 builtin->function = get_arg (self, defs, arg);
774 /* How to handle the $DOCNAME directive. */
776 docname_handler (self, defs, arg)
780 register BUILTIN_DESC *builtin;
782 builtin = current_builtin (self, defs);
784 if (builtin->docname)
785 line_error (defs, "%s already had a docname (%s)",
786 builtin->name, builtin->docname);
788 builtin->docname = get_arg (self, defs, arg);
793 /* How to handle the $SHORT_DOC directive. */
795 short_doc_handler (self, defs, arg)
799 register BUILTIN_DESC *builtin;
801 builtin = current_builtin (self, defs);
803 if (builtin->shortdoc)
804 line_error (defs, "%s already has short documentation (%s)",
805 builtin->name, builtin->shortdoc);
807 builtin->shortdoc = get_arg (self, defs, arg);
812 /* How to handle the $COMMENT directive. */
814 comment_handler (self, defs)
821 /* How to handle the $DEPENDS_ON directive. */
823 depends_on_handler (self, defs, arg)
827 register BUILTIN_DESC *builtin;
830 builtin = current_builtin (self, defs);
831 dependent = get_arg (self, defs, arg);
833 if (!builtin->dependencies)
834 builtin->dependencies = array_create (sizeof (char *));
836 array_add (dependent, builtin->dependencies);
841 /* How to handle the $PRODUCES directive. */
843 produces_handler (self, defs, arg)
847 /* If just hacking documentation, don't change any of the production
849 if (only_documentation)
852 output_cpp_line_info++;
854 if (defs->production)
855 line_error (defs, "%s already has a %s definition", defs->filename, self);
858 defs->production = get_arg (self, defs, arg);
860 if (inhibit_production)
863 defs->output = fopen (defs->production, "w");
866 file_error (defs->production);
868 fprintf (defs->output, "/* %s, created from %s. */\n",
869 defs->production, defs->filename);
874 /* How to handle the $END directive. */
876 end_handler (self, defs, arg)
880 must_be_building (self, defs);
881 building_builtin = 0;
885 /* **************************************************************** */
887 /* Error Handling Functions */
889 /* **************************************************************** */
891 /* Produce an error for DEFS with FORMAT and ARGS. */
893 line_error (defs, format, arg1, arg2)
895 char *format, *arg1, *arg2;
897 if (defs->filename[0] != '/')
898 fprintf (stderr, "%s", error_directory ? error_directory : "./");
899 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
900 fprintf (stderr, format, arg1, arg2);
901 fprintf (stderr, "\n");
905 /* Print error message for FILENAME. */
907 file_error (filename)
914 /* **************************************************************** */
916 /* xmalloc and xrealloc () */
918 /* **************************************************************** */
920 static void memory_error_and_abort ();
926 char *temp = (char *)malloc (bytes);
929 memory_error_and_abort ();
934 xrealloc (pointer, bytes)
941 temp = (char *)malloc (bytes);
943 temp = (char *)realloc (pointer, bytes);
946 memory_error_and_abort ();
952 memory_error_and_abort ()
954 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
958 /* **************************************************************** */
960 /* Creating the Struct and Extern Files */
962 /* **************************************************************** */
964 /* Return a pointer to a newly allocated builtin which is
965 an exact copy of BUILTIN. */
967 copy_builtin (builtin)
968 BUILTIN_DESC *builtin;
972 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
974 new->name = savestring (builtin->name);
975 new->shortdoc = savestring (builtin->shortdoc);
976 new->longdoc = copy_string_array (builtin->longdoc);
977 new->dependencies = copy_string_array (builtin->dependencies);
980 builtin->function ? savestring (builtin->function) : (char *)NULL;
982 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
987 /* How to save away a builtin. */
989 save_builtin (builtin)
990 BUILTIN_DESC *builtin;
992 BUILTIN_DESC *newbuiltin;
994 newbuiltin = copy_builtin (builtin);
996 /* If this is the first builtin to be saved, create the array
999 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1001 array_add ((char *)newbuiltin, saved_builtins);
1004 /* Flags that mean something to write_documentation (). */
1005 #define STRING_ARRAY 1
1008 char *structfile_header[] = {
1009 "/* builtins.c -- the built in shell commands. */",
1011 "/* This file is manufactured by ./mkbuiltins, and should not be",
1012 " edited by hand. See the source to mkbuiltins for details. */",
1014 "/* Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.",
1016 " This file is part of GNU Bash, the Bourne Again SHell.",
1018 " Bash is free software; you can redistribute it and/or modify it",
1019 " under the terms of the GNU General Public License as published by",
1020 " the Free Software Foundation; either version 1, or (at your option)",
1021 " any later version.",
1023 " Bash is distributed in the hope that it will be useful, but WITHOUT",
1024 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1025 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public",
1026 " License for more details.",
1028 " You should have received a copy of the GNU General Public License",
1029 " along with Bash; see the file COPYING. If not, write to the Free",
1030 " Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
1032 "/* The list of shell builtins. Each element is name, function, flags,",
1033 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1034 " of help lines. The function takes a WORD_LIST *; the first word in the",
1035 " list is the first arg to the command. The list has already had word",
1036 " expansion performed.",
1038 " Functions which need to look at only the simple commands (e.g.",
1039 " the enable_builtin ()), should ignore entries where",
1040 " (array[i].function == (Function *)NULL). Such entries are for",
1041 " the list of shell reserved control structures, like `if' and `while'.",
1042 " The end of the list is denoted with a NULL name field. */",
1044 "#include \"../builtins.h\"",
1048 char *structfile_footer[] = {
1049 " { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
1052 "struct builtin *shell_builtins = static_shell_builtins;",
1053 "struct builtin *current_builtin;",
1055 "int num_shell_builtins =",
1056 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1060 /* Write out any neccessary opening information for
1061 STRUCTFILE and EXTERNFILE. */
1063 write_file_headers (structfile, externfile)
1064 FILE *structfile, *externfile;
1070 for (i = 0; structfile_header[i]; i++)
1071 fprintf (structfile, "%s\n", structfile_header[i]);
1073 fprintf (structfile, "#include \"%s\"\n",
1074 extern_filename ? extern_filename : "builtext.h");
1075 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1079 fprintf (externfile,
1080 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1081 extern_filename ? extern_filename : "builtext.h");
1084 /* Write out any necessary closing information for
1085 STRUCTFILE and EXTERNFILE. */
1087 write_file_footers (structfile, externfile)
1088 FILE *structfile, *externfile;
1092 /* Write out the footers. */
1095 for (i = 0; structfile_footer[i]; i++)
1096 fprintf (structfile, "%s\n", structfile_footer[i]);
1100 /* Write out the information accumulated in DEFS to
1101 STRUCTFILE and EXTERNFILE. */
1103 write_builtins (defs, structfile, externfile)
1105 FILE *structfile, *externfile;
1109 /* Write out the information. */
1112 register BUILTIN_DESC *builtin;
1114 for (i = 0; i < defs->builtins->sindex; i++)
1116 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1118 /* Write out any #ifdefs that may be there. */
1119 if (!only_documentation)
1121 if (builtin->dependencies)
1123 write_ifdefs (externfile, builtin->dependencies->array);
1124 write_ifdefs (structfile, builtin->dependencies->array);
1127 /* Write the extern definition. */
1130 if (builtin->function)
1131 fprintf (externfile, "extern int %s ();\n",
1134 fprintf (externfile, "extern char *%s_doc[];\n",
1135 builtin->docname ?builtin->docname : builtin->name);
1138 /* Write the structure definition. */
1141 fprintf (structfile, " { \"%s\", ", builtin->name);
1143 if (builtin->function)
1144 fprintf (structfile, "%s, ", builtin->function);
1146 fprintf (structfile, "(Function *)0x0, ");
1148 fprintf (structfile, "%s%s%s, %s_doc,\n",
1149 "BUILTIN_ENABLED | STATIC_BUILTIN",
1150 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1151 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1152 builtin->docname ? builtin->docname : builtin->name);
1155 (structfile, " \"%s\", (char *)NULL },\n",
1156 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1158 /* Save away this builtin for later writing of the
1159 long documentation strings. */
1160 save_builtin (builtin);
1163 /* Write out the matching #endif, if neccessary. */
1164 if (builtin->dependencies)
1167 write_endifs (externfile, builtin->dependencies->array);
1170 write_endifs (structfile, builtin->dependencies->array);
1174 if (documentation_file)
1176 fprintf (documentation_file, "@item %s\n", builtin->name);
1178 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1184 /* Write out the long documentation strings in BUILTINS to STREAM. */
1186 write_longdocs (stream, builtins)
1191 register BUILTIN_DESC *builtin;
1193 for (i = 0; i < builtins->sindex; i++)
1195 builtin = (BUILTIN_DESC *)builtins->array[i];
1197 if (builtin->dependencies)
1198 write_ifdefs (stream, builtin->dependencies->array);
1200 /* Write the long documentation strings. */
1201 fprintf (stream, "char *%s_doc[] =",
1202 builtin->docname ? builtin->docname : builtin->name);
1203 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1205 if (builtin->dependencies)
1206 write_endifs (stream, builtin->dependencies->array);
1211 /* Write an #ifdef string saying what needs to be defined (or not defined)
1212 in order to allow compilation of the code that will follow.
1213 STREAM is the stream to write the information to,
1214 DEFINES is a null terminated array of define names.
1215 If a define is preceded by an `!', then the sense of the test is
1218 write_ifdefs (stream, defines)
1227 fprintf (stream, "#if ");
1229 for (i = 0; defines[i]; i++)
1231 char *def = defines[i];
1234 fprintf (stream, "!defined (%s)", def + 1);
1236 fprintf (stream, "defined (%s)", def);
1239 fprintf (stream, " && ");
1241 fprintf (stream, "\n");
1244 /* Write an #endif string saying what defines controlled the compilation
1245 of the immediately preceding code.
1246 STREAM is the stream to write the information to.
1247 DEFINES is a null terminated array of define names. */
1249 write_endifs (stream, defines)
1258 fprintf (stream, "#endif /* ");
1260 for (i = 0; defines[i]; i++)
1262 fprintf (stream, "%s", defines[i]);
1265 fprintf (stream, " && ");
1268 fprintf (stream, " */\n");
1271 /* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
1272 and quoting special characters in the string. */
1274 write_documentation (stream, documentation, indentation, flags)
1276 char **documentation;
1277 int indentation, flags;
1280 register char *line;
1281 int string_array, texinfo;
1286 string_array = flags & STRING_ARRAY;
1288 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
1290 #if !defined (OLDCODE)
1291 /* XXX -- clean me up; for experiment only */
1292 if (no_long_document)
1293 goto end_of_document;
1294 #endif /* !OLDCODE */
1296 for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1298 /* Allow #ifdef's to be written out verbatim. */
1302 fprintf (stream, "%s\n", line);
1307 fprintf (stream, " \"");
1310 for (j = 0; j < indentation; j++)
1311 fprintf (stream, " ");
1315 for (j = 0; line[j]; j++)
1321 fprintf (stream, "\\%c", line[j]);
1325 fprintf (stream, "%c", line[j]);
1329 fprintf (stream, "\",\n");
1333 for (j = 0; line[j]; j++)
1340 fprintf (stream, "@%c", line[j]);
1344 fprintf (stream, "%c", line[j]);
1347 fprintf (stream, "\n");
1350 fprintf (stream, "%s\n", line);
1353 #if !defined (OLDCODE)
1355 #endif /* !OLDCODE */
1358 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1362 _find_in_table (name, name_table)
1363 char *name, *name_table[];
1367 for (i = 0; name_table[i]; i++)
1368 if (strcmp (name, name_table[i]) == 0)
1374 is_special_builtin (name)
1377 return (_find_in_table (name, special_builtins));
1381 is_assignment_builtin (name)
1384 return (_find_in_table (name, assignment_builtins));