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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
24 #if defined (HAVE_UNISTD_H)
26 # include <sys/types.h>
32 #include "../bashtypes.h"
36 #include "posixstat.h"
39 #include "../bashansi.h"
44 #define DOCFILE "builtins.texi"
46 static char *xmalloc (), *xrealloc ();
48 #if !defined (__STDC__) && !defined (strcpy)
49 extern char *strcpy ();
50 #endif /* !__STDC__ && !strcpy */
52 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
53 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
55 /* Flag values that builtins can have. */
56 #define BUILTIN_FLAG_SPECIAL 0x01
57 #define BUILTIN_FLAG_ASSIGNMENT 0x02
59 /* If this stream descriptor is non-zero, then write
60 texinfo documentation to it. */
61 FILE *documentation_file = (FILE *)NULL;
63 /* Non-zero means to only produce documentation. */
64 int only_documentation = 0;
66 /* Non-zero means to not do any productions. */
67 int inhibit_production = 0;
69 #if !defined (OLDCODE)
70 int no_long_document = 0;
73 /* The name of a directory to precede the filename when reporting
75 char *error_directory = (char *)NULL;
77 /* The name of the structure file. */
78 char *struct_filename = (char *)NULL;
80 /* The name of the external declaration file. */
81 char *extern_filename = (char *)NULL;
83 /* Here is a structure for manipulating arrays of data. */
85 int size; /* Number of slots allocated to array. */
86 int sindex; /* Current location in array. */
87 int width; /* Size of each element. */
88 int growth_rate; /* How fast to grow. */
89 char **array; /* The array itself. */
92 /* Here is a structure defining a single BUILTIN. */
94 char *name; /* The name of this builtin. */
95 char *function; /* The name of the function to call. */
96 char *shortdoc; /* The short documentation for this builtin. */
97 char *docname; /* Possible name for documentation string. */
98 ARRAY *longdoc; /* The long documentation for this builtin. */
99 ARRAY *dependencies; /* Null terminated array of #define names. */
100 int flags; /* Flags for this builtin. */
103 /* Here is a structure which defines a DEF file. */
105 char *filename; /* The name of the input def file. */
106 ARRAY *lines; /* The contents of the file. */
107 int line_number; /* The current line number. */
108 char *production; /* The name of the production file. */
109 FILE *output; /* Open file stream for PRODUCTION. */
110 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
113 /* The array of all builtins encountered during execution of this code. */
114 ARRAY *saved_builtins = (ARRAY *)NULL;
116 /* The Posix.2 so-called `special' builtins. */
117 char *special_builtins[] =
119 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
120 "export", "readonly", "return", "set", "shift", "trap", "unset",
124 /* The builtin commands that take assignment statements as arguments. */
125 char *assignment_builtins[] =
127 "alias", "declare", "export", "local", "readonly", "typeset",
131 /* Forward declarations. */
132 static int is_special_builtin ();
133 static int is_assignment_builtin ();
135 #if !defined (HAVE_RENAME)
136 static int rename ();
139 void extract_info ();
144 void write_file_headers ();
145 void write_file_footers ();
146 void write_ifdefs ();
147 void write_endifs ();
148 void write_documentation ();
149 void write_longdocs ();
150 void write_builtins ();
153 void add_documentation ();
155 void must_be_building ();
156 void remove_trailing_whitespace ();
158 /* For each file mentioned on the command line, process it and
159 write the information to STRUCTFILE and EXTERNFILE, while
160 creating the production file if neccessary. */
167 FILE *structfile, *externfile;
168 char *documentation_filename, *temp_struct_filename;
170 structfile = externfile = (FILE *)NULL;
171 documentation_filename = DOCFILE;
172 temp_struct_filename = (char *)NULL;
174 while (arg_index < argc && argv[arg_index][0] == '-')
176 char *arg = argv[arg_index++];
178 if (strcmp (arg, "-externfile") == 0)
179 extern_filename = argv[arg_index++];
180 else if (strcmp (arg, "-structfile") == 0)
181 struct_filename = argv[arg_index++];
182 else if (strcmp (arg, "-noproduction") == 0)
183 inhibit_production = 1;
184 else if (strcmp (arg, "-document") == 0)
185 documentation_file = fopen (documentation_filename, "w");
186 else if (strcmp (arg, "-D") == 0)
191 free (error_directory);
193 error_directory = xmalloc (2 + strlen (argv[arg_index]));
194 strcpy (error_directory, argv[arg_index]);
195 len = strlen (error_directory);
197 if (len && error_directory[len - 1] != '/')
198 strcat (error_directory, "/");
202 else if (strcmp (arg, "-documentonly") == 0)
204 only_documentation = 1;
205 documentation_file = fopen (documentation_filename, "w");
207 #if !defined (OLDCODE)
208 else if (strcmp (arg, "-nodocument") == 0)
209 no_long_document = 1;
210 #endif /* !OLDCODE */
213 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
218 /* If there are no files to process, just quit now. */
219 if (arg_index == argc)
222 if (!only_documentation)
224 /* Open the files. */
227 temp_struct_filename = xmalloc (15);
228 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
229 structfile = fopen (temp_struct_filename, "w");
232 file_error (temp_struct_filename);
237 externfile = fopen (extern_filename, "w");
240 file_error (extern_filename);
243 /* Write out the headers. */
244 write_file_headers (structfile, externfile);
247 if (documentation_file)
249 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
251 fprintf (documentation_file, "@ftable @asis\n");
254 /* Process the .def files. */
255 while (arg_index < argc)
259 arg = argv[arg_index++];
261 extract_info (arg, structfile, externfile);
264 /* Close the files. */
265 if (!only_documentation)
267 /* Write the footers. */
268 write_file_footers (structfile, externfile);
272 write_longdocs (structfile, saved_builtins);
274 rename (temp_struct_filename, struct_filename);
281 if (documentation_file)
283 fprintf (documentation_file, "@end ftable\n");
284 fclose (documentation_file);
290 /* **************************************************************** */
292 /* Array Functions and Manipulators */
294 /* **************************************************************** */
296 /* Make a new array, and return a pointer to it. The array will
297 contain elements of size WIDTH, and is initialized to no elements. */
304 array = (ARRAY *)xmalloc (sizeof (ARRAY));
307 array->width = width;
309 /* Default to increasing size in units of 20. */
310 array->growth_rate = 20;
312 array->array = (char **)NULL;
317 /* Copy the array of strings in ARRAY. */
319 copy_string_array (array)
326 return (ARRAY *)NULL;
328 copy = array_create (sizeof (char *));
330 copy->size = array->size;
331 copy->sindex = array->sindex;
332 copy->width = array->width;
334 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
336 for (i = 0; i < array->sindex; i++)
337 copy->array[i] = savestring (array->array[i]);
339 copy->array[i] = (char *)NULL;
344 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
346 array_add (element, array)
350 if (array->sindex + 2 > array->size)
351 array->array = (char **)xrealloc
352 (array->array, (array->size += array->growth_rate) * array->width);
354 #if defined (HAVE_BCOPY)
355 bcopy (&element, (char *) &(array->array[array->sindex]), array->width);
357 bzero ((char *) &(array->array[array->sindex]), array->width);
359 array->array[array->sindex++] = element;
360 array->array[array->sindex] = (char *)NULL;
361 #endif /* !HAVE_BCOPY */
364 /* Free an allocated array and data pointer. */
375 /* **************************************************************** */
377 /* Processing a DEF File */
379 /* **************************************************************** */
381 /* The definition of a function. */
382 typedef int Function ();
383 typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
385 /* Structure handles processor directives. */
388 mk_handler_func_t *function;
391 extern int builtin_handler __P((char *, DEF_FILE *, char *));
392 extern int function_handler __P((char *, DEF_FILE *, char *));
393 extern int short_doc_handler __P((char *, DEF_FILE *, char *));
394 extern int comment_handler __P((char *, DEF_FILE *, char *));
395 extern int depends_on_handler __P((char *, DEF_FILE *, char *));
396 extern int produces_handler __P((char *, DEF_FILE *, char *));
397 extern int end_handler __P((char *, DEF_FILE *, char *));
398 extern int docname_handler __P((char *, DEF_FILE *, char *));
400 HANDLER_ENTRY handlers[] = {
401 { "BUILTIN", builtin_handler },
402 { "DOCNAME", docname_handler },
403 { "FUNCTION", function_handler },
404 { "SHORT_DOC", short_doc_handler },
405 { "$", comment_handler },
406 { "COMMENT", comment_handler },
407 { "DEPENDS_ON", depends_on_handler },
408 { "PRODUCES", produces_handler },
409 { "END", end_handler },
410 { (char *)NULL, (mk_handler_func_t *)NULL }
413 /* Return the entry in the table of handlers for NAME. */
415 find_directive (directive)
420 for (i = 0; handlers[i].directive; i++)
421 if (strcmp (handlers[i].directive, directive) == 0)
422 return (&handlers[i]);
424 return ((HANDLER_ENTRY *)NULL);
427 /* Non-zero indicates that a $BUILTIN has been seen, but not
428 the corresponding $END. */
429 static int building_builtin = 0;
431 /* Non-zero means to output cpp line and file information before
432 printing the current line to the production file. */
433 int output_cpp_line_info = 0;
435 /* The main function of this program. Read FILENAME and act on what is
436 found. Lines not starting with a dollar sign are copied to the
437 $PRODUCES target, if one is present. Lines starting with a dollar sign
438 are directives to this program, specifying the name of the builtin, the
439 function to call, the short documentation and the long documentation
440 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
441 target. After the file has been processed, write out the names of
442 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
443 is ignored, as is "$$ comment text". */
445 extract_info (filename, structfile, externfile)
447 FILE *structfile, *externfile;
456 if (stat (filename, &finfo) == -1)
457 file_error (filename);
459 fd = open (filename, O_RDONLY, 0666);
462 file_error (filename);
464 file_size = (size_t)finfo.st_size;
465 buffer = xmalloc (1 + file_size);
467 if ((nr = read (fd, buffer, file_size)) < 0)
468 file_error (filename);
470 /* This is needed on WIN32, and does not hurt on Unix. */
478 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
482 /* Create and fill in the initial structure describing this file. */
483 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
484 defs->filename = filename;
485 defs->lines = array_create (sizeof (char *));
486 defs->line_number = 0;
487 defs->production = (char *)NULL;
488 defs->output = (FILE *)NULL;
489 defs->builtins = (ARRAY *)NULL;
491 /* Build the array of lines. */
493 while (i < file_size)
495 array_add (&buffer[i], defs->lines);
497 while (buffer[i] != '\n' && i < file_size)
502 /* Begin processing the input file. We don't write any output
503 until we have a file to write output to. */
504 output_cpp_line_info = 1;
506 /* Process each line in the array. */
507 for (i = 0; line = defs->lines->array[i]; i++)
509 defs->line_number = i;
515 HANDLER_ENTRY *handler;
517 /* Isolate the directive. */
518 for (j = 0; line[j] && !whitespace (line[j]); j++);
520 directive = xmalloc (j);
521 strncpy (directive, line + 1, j - 1);
522 directive[j -1] = '\0';
524 /* Get the function handler and call it. */
525 handler = find_directive (directive);
529 line_error (defs, "Unknown directive `%s'", directive);
535 /* Advance to the first non-whitespace character. */
536 while (whitespace (line[j]))
539 /* Call the directive handler with the FILE, and ARGS. */
540 (*(handler->function)) (directive, defs, line + j);
546 if (building_builtin)
547 add_documentation (defs, line);
548 else if (defs->output)
550 if (output_cpp_line_info)
552 /* If we're handed an absolute pathname, don't prepend
553 the directory name. */
554 if (defs->filename[0] == '/')
555 fprintf (defs->output, "#line %d \"%s\"\n",
556 defs->line_number + 1, defs->filename);
558 fprintf (defs->output, "#line %d \"%s%s\"\n",
559 defs->line_number + 1,
560 error_directory ? error_directory : "./",
562 output_cpp_line_info = 0;
565 fprintf (defs->output, "%s\n", line);
570 /* Close the production file. */
572 fclose (defs->output);
574 /* The file has been processed. Write the accumulated builtins to
575 the builtins.c file, and write the extern definitions to the
577 write_builtins (defs, structfile, externfile);
583 #define free_safely(x) if (x) free (x)
586 free_builtin (builtin)
587 BUILTIN_DESC *builtin;
591 free_safely (builtin->name);
592 free_safely (builtin->function);
593 free_safely (builtin->shortdoc);
594 free_safely (builtin->docname);
596 if (builtin->longdoc)
597 array_free (builtin->longdoc);
599 if (builtin->dependencies)
601 for (i = 0; builtin->dependencies->array[i]; i++)
602 free (builtin->dependencies->array[i]);
603 array_free (builtin->dependencies);
607 /* Free all of the memory allocated to a DEF_FILE. */
613 register BUILTIN_DESC *builtin;
615 if (defs->production)
616 free (defs->production);
619 array_free (defs->lines);
623 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
625 free_builtin (builtin);
628 array_free (defs->builtins);
633 /* **************************************************************** */
635 /* The Handler Functions Themselves */
637 /* **************************************************************** */
639 /* Strip surrounding whitespace from STRING, and
640 return a pointer to the start of it. */
642 strip_whitespace (string)
645 while (whitespace (*string))
648 remove_trailing_whitespace (string);
652 /* Remove only the trailing whitespace from STRING. */
654 remove_trailing_whitespace (string)
659 i = strlen (string) - 1;
661 while (i > 0 && whitespace (string[i]))
667 /* Ensure that there is a argument in STRING and return it.
668 FOR_WHOM is the name of the directive which needs the argument.
669 DEFS is the DEF_FILE in which the directive is found.
670 If there is no argument, produce an error. */
672 get_arg (for_whom, defs, string)
673 char *for_whom, *string;
678 new = strip_whitespace (string);
681 line_error (defs, "%s requires an argument", for_whom);
683 return (savestring (new));
686 /* Error if not building a builtin. */
688 must_be_building (directive, defs)
692 if (!building_builtin)
693 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
696 /* Return the current builtin. */
698 current_builtin (directive, defs)
702 must_be_building (directive, defs);
704 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
706 return ((BUILTIN_DESC *)NULL);
709 /* Add LINE to the long documentation for the current builtin.
710 Ignore blank lines until the first non-blank line has been seen. */
712 add_documentation (defs, line)
716 register BUILTIN_DESC *builtin;
718 builtin = current_builtin ("(implied LONGDOC)", defs);
720 remove_trailing_whitespace (line);
722 if (!*line && !builtin->longdoc)
725 if (!builtin->longdoc)
726 builtin->longdoc = array_create (sizeof (char *));
728 array_add (line, builtin->longdoc);
731 /* How to handle the $BUILTIN directive. */
733 builtin_handler (self, defs, arg)
741 /* If we are already building a builtin, we cannot start a new one. */
742 if (building_builtin)
744 line_error (defs, "%s found before $END", self);
748 output_cpp_line_info++;
750 /* Get the name of this builtin, and stick it in the array. */
751 name = get_arg (self, defs, arg);
753 /* If this is the first builtin, create the array to hold them. */
755 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
757 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
759 new->function = (char *)NULL;
760 new->shortdoc = (char *)NULL;
761 new->docname = (char *)NULL;
762 new->longdoc = (ARRAY *)NULL;
763 new->dependencies = (ARRAY *)NULL;
766 if (is_special_builtin (name))
767 new->flags |= BUILTIN_FLAG_SPECIAL;
768 if (is_assignment_builtin (name))
769 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
771 array_add ((char *)new, defs->builtins);
772 building_builtin = 1;
777 /* How to handle the $FUNCTION directive. */
779 function_handler (self, defs, arg)
784 register BUILTIN_DESC *builtin;
786 builtin = current_builtin (self, defs);
790 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
793 if (builtin->function)
794 line_error (defs, "%s already has a function (%s)",
795 builtin->name, builtin->function);
797 builtin->function = get_arg (self, defs, arg);
802 /* How to handle the $DOCNAME directive. */
804 docname_handler (self, defs, arg)
809 register BUILTIN_DESC *builtin;
811 builtin = current_builtin (self, defs);
813 if (builtin->docname)
814 line_error (defs, "%s already had a docname (%s)",
815 builtin->name, builtin->docname);
817 builtin->docname = get_arg (self, defs, arg);
822 /* How to handle the $SHORT_DOC directive. */
824 short_doc_handler (self, defs, arg)
829 register BUILTIN_DESC *builtin;
831 builtin = current_builtin (self, defs);
833 if (builtin->shortdoc)
834 line_error (defs, "%s already has short documentation (%s)",
835 builtin->name, builtin->shortdoc);
837 builtin->shortdoc = get_arg (self, defs, arg);
842 /* How to handle the $COMMENT directive. */
844 comment_handler (self, defs, arg)
852 /* How to handle the $DEPENDS_ON directive. */
854 depends_on_handler (self, defs, arg)
859 register BUILTIN_DESC *builtin;
862 builtin = current_builtin (self, defs);
863 dependent = get_arg (self, defs, arg);
865 if (!builtin->dependencies)
866 builtin->dependencies = array_create (sizeof (char *));
868 array_add (dependent, builtin->dependencies);
873 /* How to handle the $PRODUCES directive. */
875 produces_handler (self, defs, arg)
880 /* If just hacking documentation, don't change any of the production
882 if (only_documentation)
885 output_cpp_line_info++;
887 if (defs->production)
888 line_error (defs, "%s already has a %s definition", defs->filename, self);
891 defs->production = get_arg (self, defs, arg);
893 if (inhibit_production)
896 defs->output = fopen (defs->production, "w");
899 file_error (defs->production);
901 fprintf (defs->output, "/* %s, created from %s. */\n",
902 defs->production, defs->filename);
907 /* How to handle the $END directive. */
909 end_handler (self, defs, arg)
914 must_be_building (self, defs);
915 building_builtin = 0;
919 /* **************************************************************** */
921 /* Error Handling Functions */
923 /* **************************************************************** */
925 /* Produce an error for DEFS with FORMAT and ARGS. */
927 line_error (defs, format, arg1, arg2)
929 char *format, *arg1, *arg2;
931 if (defs->filename[0] != '/')
932 fprintf (stderr, "%s", error_directory ? error_directory : "./");
933 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
934 fprintf (stderr, format, arg1, arg2);
935 fprintf (stderr, "\n");
939 /* Print error message for FILENAME. */
941 file_error (filename)
948 /* **************************************************************** */
950 /* xmalloc and xrealloc () */
952 /* **************************************************************** */
954 static void memory_error_and_abort ();
960 char *temp = (char *)malloc (bytes);
963 memory_error_and_abort ();
968 xrealloc (pointer, bytes)
975 temp = (char *)malloc (bytes);
977 temp = (char *)realloc (pointer, bytes);
980 memory_error_and_abort ();
986 memory_error_and_abort ()
988 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
992 /* **************************************************************** */
994 /* Creating the Struct and Extern Files */
996 /* **************************************************************** */
998 /* Return a pointer to a newly allocated builtin which is
999 an exact copy of BUILTIN. */
1001 copy_builtin (builtin)
1002 BUILTIN_DESC *builtin;
1006 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1008 new->name = savestring (builtin->name);
1009 new->shortdoc = savestring (builtin->shortdoc);
1010 new->longdoc = copy_string_array (builtin->longdoc);
1011 new->dependencies = copy_string_array (builtin->dependencies);
1014 builtin->function ? savestring (builtin->function) : (char *)NULL;
1016 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
1021 /* How to save away a builtin. */
1023 save_builtin (builtin)
1024 BUILTIN_DESC *builtin;
1026 BUILTIN_DESC *newbuiltin;
1028 newbuiltin = copy_builtin (builtin);
1030 /* If this is the first builtin to be saved, create the array
1032 if (!saved_builtins)
1033 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1035 array_add ((char *)newbuiltin, saved_builtins);
1038 /* Flags that mean something to write_documentation (). */
1039 #define STRING_ARRAY 1
1042 char *structfile_header[] = {
1043 "/* builtins.c -- the built in shell commands. */",
1045 "/* This file is manufactured by ./mkbuiltins, and should not be",
1046 " edited by hand. See the source to mkbuiltins for details. */",
1048 "/* Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.",
1050 " This file is part of GNU Bash, the Bourne Again SHell.",
1052 " Bash is free software; you can redistribute it and/or modify it",
1053 " under the terms of the GNU General Public License as published by",
1054 " the Free Software Foundation; either version 2, or (at your option)",
1055 " any later version.",
1057 " Bash is distributed in the hope that it will be useful, but WITHOUT",
1058 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1059 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public",
1060 " License for more details.",
1062 " You should have received a copy of the GNU General Public License",
1063 " along with Bash; see the file COPYING. If not, write to the Free",
1064 " Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */",
1066 "/* The list of shell builtins. Each element is name, function, flags,",
1067 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1068 " of help lines. The function takes a WORD_LIST *; the first word in the",
1069 " list is the first arg to the command. The list has already had word",
1070 " expansion performed.",
1072 " Functions which need to look at only the simple commands (e.g.",
1073 " the enable_builtin ()), should ignore entries where",
1074 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
1075 " the list of shell reserved control structures, like `if' and `while'.",
1076 " The end of the list is denoted with a NULL name field. */",
1078 "#include \"../builtins.h\"",
1082 char *structfile_footer[] = {
1083 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0 }",
1086 "struct builtin *shell_builtins = static_shell_builtins;",
1087 "struct builtin *current_builtin;",
1089 "int num_shell_builtins =",
1090 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1094 /* Write out any neccessary opening information for
1095 STRUCTFILE and EXTERNFILE. */
1097 write_file_headers (structfile, externfile)
1098 FILE *structfile, *externfile;
1104 for (i = 0; structfile_header[i]; i++)
1105 fprintf (structfile, "%s\n", structfile_header[i]);
1107 fprintf (structfile, "#include \"%s\"\n",
1108 extern_filename ? extern_filename : "builtext.h");
1109 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1113 fprintf (externfile,
1114 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1115 extern_filename ? extern_filename : "builtext.h");
1118 /* Write out any necessary closing information for
1119 STRUCTFILE and EXTERNFILE. */
1121 write_file_footers (structfile, externfile)
1122 FILE *structfile, *externfile;
1126 /* Write out the footers. */
1129 for (i = 0; structfile_footer[i]; i++)
1130 fprintf (structfile, "%s\n", structfile_footer[i]);
1134 /* Write out the information accumulated in DEFS to
1135 STRUCTFILE and EXTERNFILE. */
1137 write_builtins (defs, structfile, externfile)
1139 FILE *structfile, *externfile;
1143 /* Write out the information. */
1146 register BUILTIN_DESC *builtin;
1148 for (i = 0; i < defs->builtins->sindex; i++)
1150 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1152 /* Write out any #ifdefs that may be there. */
1153 if (!only_documentation)
1155 if (builtin->dependencies)
1157 write_ifdefs (externfile, builtin->dependencies->array);
1158 write_ifdefs (structfile, builtin->dependencies->array);
1161 /* Write the extern definition. */
1164 if (builtin->function)
1165 fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
1168 fprintf (externfile, "extern char *%s_doc[];\n",
1169 builtin->docname ? builtin->docname : builtin->name);
1172 /* Write the structure definition. */
1175 fprintf (structfile, " { \"%s\", ", builtin->name);
1177 if (builtin->function)
1178 fprintf (structfile, "%s, ", builtin->function);
1180 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
1182 fprintf (structfile, "%s%s%s, %s_doc,\n",
1183 "BUILTIN_ENABLED | STATIC_BUILTIN",
1184 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1185 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1186 builtin->docname ? builtin->docname : builtin->name);
1189 (structfile, " \"%s\", (char *)NULL },\n",
1190 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1192 /* Save away this builtin for later writing of the
1193 long documentation strings. */
1194 save_builtin (builtin);
1197 /* Write out the matching #endif, if neccessary. */
1198 if (builtin->dependencies)
1201 write_endifs (externfile, builtin->dependencies->array);
1204 write_endifs (structfile, builtin->dependencies->array);
1208 if (documentation_file)
1210 fprintf (documentation_file, "@item %s\n", builtin->name);
1212 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1218 /* Write out the long documentation strings in BUILTINS to STREAM. */
1220 write_longdocs (stream, builtins)
1225 register BUILTIN_DESC *builtin;
1227 for (i = 0; i < builtins->sindex; i++)
1229 builtin = (BUILTIN_DESC *)builtins->array[i];
1231 if (builtin->dependencies)
1232 write_ifdefs (stream, builtin->dependencies->array);
1234 /* Write the long documentation strings. */
1235 fprintf (stream, "char *%s_doc[] =",
1236 builtin->docname ? builtin->docname : builtin->name);
1237 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1239 if (builtin->dependencies)
1240 write_endifs (stream, builtin->dependencies->array);
1245 /* Write an #ifdef string saying what needs to be defined (or not defined)
1246 in order to allow compilation of the code that will follow.
1247 STREAM is the stream to write the information to,
1248 DEFINES is a null terminated array of define names.
1249 If a define is preceded by an `!', then the sense of the test is
1252 write_ifdefs (stream, defines)
1261 fprintf (stream, "#if ");
1263 for (i = 0; defines[i]; i++)
1265 char *def = defines[i];
1268 fprintf (stream, "!defined (%s)", def + 1);
1270 fprintf (stream, "defined (%s)", def);
1273 fprintf (stream, " && ");
1275 fprintf (stream, "\n");
1278 /* Write an #endif string saying what defines controlled the compilation
1279 of the immediately preceding code.
1280 STREAM is the stream to write the information to.
1281 DEFINES is a null terminated array of define names. */
1283 write_endifs (stream, defines)
1292 fprintf (stream, "#endif /* ");
1294 for (i = 0; defines[i]; i++)
1296 fprintf (stream, "%s", defines[i]);
1299 fprintf (stream, " && ");
1302 fprintf (stream, " */\n");
1305 /* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
1306 and quoting special characters in the string. */
1308 write_documentation (stream, documentation, indentation, flags)
1310 char **documentation;
1311 int indentation, flags;
1314 register char *line;
1315 int string_array, texinfo;
1320 string_array = flags & STRING_ARRAY;
1322 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
1324 #if !defined (OLDCODE)
1325 /* XXX -- clean me up; for experiment only */
1326 if (no_long_document)
1327 goto end_of_document;
1328 #endif /* !OLDCODE */
1330 for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1332 /* Allow #ifdef's to be written out verbatim. */
1336 fprintf (stream, "%s\n", line);
1341 fprintf (stream, " \"");
1344 for (j = 0; j < indentation; j++)
1345 fprintf (stream, " ");
1349 for (j = 0; line[j]; j++)
1355 fprintf (stream, "\\%c", line[j]);
1359 fprintf (stream, "%c", line[j]);
1363 fprintf (stream, "\",\n");
1367 for (j = 0; line[j]; j++)
1374 fprintf (stream, "@%c", line[j]);
1378 fprintf (stream, "%c", line[j]);
1381 fprintf (stream, "\n");
1384 fprintf (stream, "%s\n", line);
1387 #if !defined (OLDCODE)
1389 #endif /* !OLDCODE */
1392 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1396 _find_in_table (name, name_table)
1397 char *name, *name_table[];
1401 for (i = 0; name_table[i]; i++)
1402 if (strcmp (name, name_table[i]) == 0)
1408 is_special_builtin (name)
1411 return (_find_in_table (name, special_builtins));
1415 is_assignment_builtin (name)
1418 return (_find_in_table (name, assignment_builtins));
1421 #if !defined (HAVE_RENAME)
1427 if (link (from, to) < 0)
1432 #endif /* !HAVE_RENAME */