1 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
4 /* Copyright (C) 1987-2006 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. */
22 #if !defined (CROSS_COMPILING)
24 #else /* CROSS_COMPILING */
25 /* A conservative set of defines based on POSIX/SUS3/XPG6 */
26 # define HAVE_UNISTD_H
27 # define HAVE_STRING_H
28 # define HAVE_STDLIB_H
31 #endif /* CROSS_COMPILING */
33 #if defined (HAVE_UNISTD_H)
35 # include <sys/types.h>
41 # include "../bashtypes.h"
42 # if defined (HAVE_SYS_FILE_H)
43 # include <sys/file.h>
47 #include "posixstat.h"
50 #include "../bashansi.h"
56 #define DOCFILE "builtins.texi"
62 static char *xmalloc (), *xrealloc ();
64 #if !defined (__STDC__) && !defined (strcpy)
65 extern char *strcpy ();
66 #endif /* !__STDC__ && !strcpy */
68 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
69 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
71 /* Flag values that builtins can have. */
72 #define BUILTIN_FLAG_SPECIAL 0x01
73 #define BUILTIN_FLAG_ASSIGNMENT 0x02
77 /* If this stream descriptor is non-zero, then write
78 texinfo documentation to it. */
79 FILE *documentation_file = (FILE *)NULL;
81 /* Non-zero means to only produce documentation. */
82 int only_documentation = 0;
84 /* Non-zero means to not do any productions. */
85 int inhibit_production = 0;
87 /* Non-zero means to produce separate help files for each builtin, named by
88 the builtin name, in `./helpfiles'. */
89 int separate_helpfiles = 0;
91 /* Non-zero means to create single C strings for each `longdoc', with
92 embedded newlines, for ease of translation. */
93 int single_longdoc_strings = 1;
95 /* The name of a directory into which the separate external help files will
96 eventually be installed. */
97 char *helpfile_directory;
99 /* The name of a directory to precede the filename when reporting
101 char *error_directory = (char *)NULL;
103 /* The name of the structure file. */
104 char *struct_filename = (char *)NULL;
106 /* The name of the external declaration file. */
107 char *extern_filename = (char *)NULL;
109 /* Here is a structure for manipulating arrays of data. */
111 int size; /* Number of slots allocated to array. */
112 int sindex; /* Current location in array. */
113 int width; /* Size of each element. */
114 int growth_rate; /* How fast to grow. */
115 char **array; /* The array itself. */
118 /* Here is a structure defining a single BUILTIN. */
120 char *name; /* The name of this builtin. */
121 char *function; /* The name of the function to call. */
122 char *shortdoc; /* The short documentation for this builtin. */
123 char *docname; /* Possible name for documentation string. */
124 ARRAY *longdoc; /* The long documentation for this builtin. */
125 ARRAY *dependencies; /* Null terminated array of #define names. */
126 int flags; /* Flags for this builtin. */
129 /* Here is a structure which defines a DEF file. */
131 char *filename; /* The name of the input def file. */
132 ARRAY *lines; /* The contents of the file. */
133 int line_number; /* The current line number. */
134 char *production; /* The name of the production file. */
135 FILE *output; /* Open file stream for PRODUCTION. */
136 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
139 /* The array of all builtins encountered during execution of this code. */
140 ARRAY *saved_builtins = (ARRAY *)NULL;
142 /* The Posix.2 so-called `special' builtins. */
143 char *special_builtins[] =
145 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
146 "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
150 /* The builtin commands that take assignment statements as arguments. */
151 char *assignment_builtins[] =
153 "alias", "declare", "export", "local", "readonly", "typeset",
157 /* Forward declarations. */
158 static int is_special_builtin ();
159 static int is_assignment_builtin ();
161 #if !defined (HAVE_RENAME)
162 static int rename ();
165 void extract_info ();
170 void write_file_headers ();
171 void write_file_footers ();
172 void write_ifdefs ();
173 void write_endifs ();
174 void write_documentation ();
175 void write_longdocs ();
176 void write_builtins ();
178 int write_helpfiles ();
181 void add_documentation ();
183 void must_be_building ();
184 void remove_trailing_whitespace ();
186 #define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
189 /* For each file mentioned on the command line, process it and
190 write the information to STRUCTFILE and EXTERNFILE, while
191 creating the production file if neccessary. */
198 FILE *structfile, *externfile;
199 char *documentation_filename, *temp_struct_filename;
201 structfile = externfile = (FILE *)NULL;
202 documentation_filename = DOCFILE;
203 temp_struct_filename = (char *)NULL;
205 while (arg_index < argc && argv[arg_index][0] == '-')
207 char *arg = argv[arg_index++];
209 if (strcmp (arg, "-externfile") == 0)
210 extern_filename = argv[arg_index++];
211 else if (strcmp (arg, "-structfile") == 0)
212 struct_filename = argv[arg_index++];
213 else if (strcmp (arg, "-noproduction") == 0)
214 inhibit_production = 1;
215 else if (strcmp (arg, "-document") == 0)
216 documentation_file = fopen (documentation_filename, "w");
217 else if (strcmp (arg, "-D") == 0)
222 free (error_directory);
224 error_directory = xmalloc (2 + strlen (argv[arg_index]));
225 strcpy (error_directory, argv[arg_index]);
226 len = strlen (error_directory);
228 if (len && error_directory[len - 1] != '/')
229 strcat (error_directory, "/");
233 else if (strcmp (arg, "-documentonly") == 0)
235 only_documentation = 1;
236 documentation_file = fopen (documentation_filename, "w");
238 else if (strcmp (arg, "-H") == 0)
240 separate_helpfiles = 1;
241 helpfile_directory = argv[arg_index++];
243 else if (strcmp (arg, "-S") == 0)
244 single_longdoc_strings = 0;
247 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
252 /* If there are no files to process, just quit now. */
253 if (arg_index == argc)
256 if (!only_documentation)
258 /* Open the files. */
261 temp_struct_filename = xmalloc (15);
262 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
263 structfile = fopen (temp_struct_filename, "w");
266 file_error (temp_struct_filename);
271 externfile = fopen (extern_filename, "w");
274 file_error (extern_filename);
277 /* Write out the headers. */
278 write_file_headers (structfile, externfile);
281 if (documentation_file)
283 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
285 fprintf (documentation_file, "@ftable @asis\n");
288 /* Process the .def files. */
289 while (arg_index < argc)
293 arg = argv[arg_index++];
295 extract_info (arg, structfile, externfile);
298 /* Close the files. */
299 if (!only_documentation)
301 /* Write the footers. */
302 write_file_footers (structfile, externfile);
306 write_longdocs (structfile, saved_builtins);
308 rename (temp_struct_filename, struct_filename);
315 if (separate_helpfiles)
317 write_helpfiles (saved_builtins);
320 if (documentation_file)
322 fprintf (documentation_file, "@end ftable\n");
323 fclose (documentation_file);
329 /* **************************************************************** */
331 /* Array Functions and Manipulators */
333 /* **************************************************************** */
335 /* Make a new array, and return a pointer to it. The array will
336 contain elements of size WIDTH, and is initialized to no elements. */
343 array = (ARRAY *)xmalloc (sizeof (ARRAY));
346 array->width = width;
348 /* Default to increasing size in units of 20. */
349 array->growth_rate = 20;
351 array->array = (char **)NULL;
356 /* Copy the array of strings in ARRAY. */
358 copy_string_array (array)
365 return (ARRAY *)NULL;
367 copy = array_create (sizeof (char *));
369 copy->size = array->size;
370 copy->sindex = array->sindex;
371 copy->width = array->width;
373 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
375 for (i = 0; i < array->sindex; i++)
376 copy->array[i] = savestring (array->array[i]);
378 copy->array[i] = (char *)NULL;
383 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
385 array_add (element, array)
389 if (array->sindex + 2 > array->size)
390 array->array = (char **)xrealloc
391 (array->array, (array->size += array->growth_rate) * array->width);
393 array->array[array->sindex++] = element;
394 array->array[array->sindex] = (char *)NULL;
397 /* Free an allocated array and data pointer. */
408 /* **************************************************************** */
410 /* Processing a DEF File */
412 /* **************************************************************** */
414 /* The definition of a function. */
415 typedef int Function ();
416 typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
418 /* Structure handles processor directives. */
421 mk_handler_func_t *function;
424 extern int builtin_handler __P((char *, DEF_FILE *, char *));
425 extern int function_handler __P((char *, DEF_FILE *, char *));
426 extern int short_doc_handler __P((char *, DEF_FILE *, char *));
427 extern int comment_handler __P((char *, DEF_FILE *, char *));
428 extern int depends_on_handler __P((char *, DEF_FILE *, char *));
429 extern int produces_handler __P((char *, DEF_FILE *, char *));
430 extern int end_handler __P((char *, DEF_FILE *, char *));
431 extern int docname_handler __P((char *, DEF_FILE *, char *));
433 HANDLER_ENTRY handlers[] = {
434 { "BUILTIN", builtin_handler },
435 { "DOCNAME", docname_handler },
436 { "FUNCTION", function_handler },
437 { "SHORT_DOC", short_doc_handler },
438 { "$", comment_handler },
439 { "COMMENT", comment_handler },
440 { "DEPENDS_ON", depends_on_handler },
441 { "PRODUCES", produces_handler },
442 { "END", end_handler },
443 { (char *)NULL, (mk_handler_func_t *)NULL }
446 /* Return the entry in the table of handlers for NAME. */
448 find_directive (directive)
453 for (i = 0; handlers[i].directive; i++)
454 if (strcmp (handlers[i].directive, directive) == 0)
455 return (&handlers[i]);
457 return ((HANDLER_ENTRY *)NULL);
460 /* Non-zero indicates that a $BUILTIN has been seen, but not
461 the corresponding $END. */
462 static int building_builtin = 0;
464 /* Non-zero means to output cpp line and file information before
465 printing the current line to the production file. */
466 int output_cpp_line_info = 0;
468 /* The main function of this program. Read FILENAME and act on what is
469 found. Lines not starting with a dollar sign are copied to the
470 $PRODUCES target, if one is present. Lines starting with a dollar sign
471 are directives to this program, specifying the name of the builtin, the
472 function to call, the short documentation and the long documentation
473 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
474 target. After the file has been processed, write out the names of
475 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
476 is ignored, as is "$$ comment text". */
478 extract_info (filename, structfile, externfile)
480 FILE *structfile, *externfile;
489 if (stat (filename, &finfo) == -1)
490 file_error (filename);
492 fd = open (filename, O_RDONLY, 0666);
495 file_error (filename);
497 file_size = (size_t)finfo.st_size;
498 buffer = xmalloc (1 + file_size);
500 if ((nr = read (fd, buffer, file_size)) < 0)
501 file_error (filename);
503 /* This is needed on WIN32, and does not hurt on Unix. */
511 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
515 /* Create and fill in the initial structure describing this file. */
516 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
517 defs->filename = filename;
518 defs->lines = array_create (sizeof (char *));
519 defs->line_number = 0;
520 defs->production = (char *)NULL;
521 defs->output = (FILE *)NULL;
522 defs->builtins = (ARRAY *)NULL;
524 /* Build the array of lines. */
526 while (i < file_size)
528 array_add (&buffer[i], defs->lines);
530 while (buffer[i] != '\n' && i < file_size)
535 /* Begin processing the input file. We don't write any output
536 until we have a file to write output to. */
537 output_cpp_line_info = 1;
539 /* Process each line in the array. */
540 for (i = 0; line = defs->lines->array[i]; i++)
542 defs->line_number = i;
548 HANDLER_ENTRY *handler;
550 /* Isolate the directive. */
551 for (j = 0; line[j] && !whitespace (line[j]); j++);
553 directive = xmalloc (j);
554 strncpy (directive, line + 1, j - 1);
555 directive[j -1] = '\0';
557 /* Get the function handler and call it. */
558 handler = find_directive (directive);
562 line_error (defs, "Unknown directive `%s'", directive);
568 /* Advance to the first non-whitespace character. */
569 while (whitespace (line[j]))
572 /* Call the directive handler with the FILE, and ARGS. */
573 (*(handler->function)) (directive, defs, line + j);
579 if (building_builtin)
580 add_documentation (defs, line);
581 else if (defs->output)
583 if (output_cpp_line_info)
585 /* If we're handed an absolute pathname, don't prepend
586 the directory name. */
587 if (defs->filename[0] == '/')
588 fprintf (defs->output, "#line %d \"%s\"\n",
589 defs->line_number + 1, defs->filename);
591 fprintf (defs->output, "#line %d \"%s%s\"\n",
592 defs->line_number + 1,
593 error_directory ? error_directory : "./",
595 output_cpp_line_info = 0;
598 fprintf (defs->output, "%s\n", line);
603 /* Close the production file. */
605 fclose (defs->output);
607 /* The file has been processed. Write the accumulated builtins to
608 the builtins.c file, and write the extern definitions to the
610 write_builtins (defs, structfile, externfile);
616 #define free_safely(x) if (x) free (x)
619 free_builtin (builtin)
620 BUILTIN_DESC *builtin;
624 free_safely (builtin->name);
625 free_safely (builtin->function);
626 free_safely (builtin->shortdoc);
627 free_safely (builtin->docname);
629 if (builtin->longdoc)
630 array_free (builtin->longdoc);
632 if (builtin->dependencies)
634 for (i = 0; builtin->dependencies->array[i]; i++)
635 free (builtin->dependencies->array[i]);
636 array_free (builtin->dependencies);
640 /* Free all of the memory allocated to a DEF_FILE. */
646 register BUILTIN_DESC *builtin;
648 if (defs->production)
649 free (defs->production);
652 array_free (defs->lines);
656 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
658 free_builtin (builtin);
661 array_free (defs->builtins);
666 /* **************************************************************** */
668 /* The Handler Functions Themselves */
670 /* **************************************************************** */
672 /* Strip surrounding whitespace from STRING, and
673 return a pointer to the start of it. */
675 strip_whitespace (string)
678 while (whitespace (*string))
681 remove_trailing_whitespace (string);
685 /* Remove only the trailing whitespace from STRING. */
687 remove_trailing_whitespace (string)
692 i = strlen (string) - 1;
694 while (i > 0 && whitespace (string[i]))
700 /* Ensure that there is a argument in STRING and return it.
701 FOR_WHOM is the name of the directive which needs the argument.
702 DEFS is the DEF_FILE in which the directive is found.
703 If there is no argument, produce an error. */
705 get_arg (for_whom, defs, string)
706 char *for_whom, *string;
711 new = strip_whitespace (string);
714 line_error (defs, "%s requires an argument", for_whom);
716 return (savestring (new));
719 /* Error if not building a builtin. */
721 must_be_building (directive, defs)
725 if (!building_builtin)
726 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
729 /* Return the current builtin. */
731 current_builtin (directive, defs)
735 must_be_building (directive, defs);
737 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
739 return ((BUILTIN_DESC *)NULL);
742 /* Add LINE to the long documentation for the current builtin.
743 Ignore blank lines until the first non-blank line has been seen. */
745 add_documentation (defs, line)
749 register BUILTIN_DESC *builtin;
751 builtin = current_builtin ("(implied LONGDOC)", defs);
753 remove_trailing_whitespace (line);
755 if (!*line && !builtin->longdoc)
758 if (!builtin->longdoc)
759 builtin->longdoc = array_create (sizeof (char *));
761 array_add (line, builtin->longdoc);
764 /* How to handle the $BUILTIN directive. */
766 builtin_handler (self, defs, arg)
774 /* If we are already building a builtin, we cannot start a new one. */
775 if (building_builtin)
777 line_error (defs, "%s found before $END", self);
781 output_cpp_line_info++;
783 /* Get the name of this builtin, and stick it in the array. */
784 name = get_arg (self, defs, arg);
786 /* If this is the first builtin, create the array to hold them. */
788 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
790 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
792 new->function = (char *)NULL;
793 new->shortdoc = (char *)NULL;
794 new->docname = (char *)NULL;
795 new->longdoc = (ARRAY *)NULL;
796 new->dependencies = (ARRAY *)NULL;
799 if (is_special_builtin (name))
800 new->flags |= BUILTIN_FLAG_SPECIAL;
801 if (is_assignment_builtin (name))
802 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
804 array_add ((char *)new, defs->builtins);
805 building_builtin = 1;
810 /* How to handle the $FUNCTION directive. */
812 function_handler (self, defs, arg)
817 register BUILTIN_DESC *builtin;
819 builtin = current_builtin (self, defs);
823 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
826 if (builtin->function)
827 line_error (defs, "%s already has a function (%s)",
828 builtin->name, builtin->function);
830 builtin->function = get_arg (self, defs, arg);
835 /* How to handle the $DOCNAME directive. */
837 docname_handler (self, defs, arg)
842 register BUILTIN_DESC *builtin;
844 builtin = current_builtin (self, defs);
846 if (builtin->docname)
847 line_error (defs, "%s already had a docname (%s)",
848 builtin->name, builtin->docname);
850 builtin->docname = get_arg (self, defs, arg);
855 /* How to handle the $SHORT_DOC directive. */
857 short_doc_handler (self, defs, arg)
862 register BUILTIN_DESC *builtin;
864 builtin = current_builtin (self, defs);
866 if (builtin->shortdoc)
867 line_error (defs, "%s already has short documentation (%s)",
868 builtin->name, builtin->shortdoc);
870 builtin->shortdoc = get_arg (self, defs, arg);
875 /* How to handle the $COMMENT directive. */
877 comment_handler (self, defs, arg)
885 /* How to handle the $DEPENDS_ON directive. */
887 depends_on_handler (self, defs, arg)
892 register BUILTIN_DESC *builtin;
895 builtin = current_builtin (self, defs);
896 dependent = get_arg (self, defs, arg);
898 if (!builtin->dependencies)
899 builtin->dependencies = array_create (sizeof (char *));
901 array_add (dependent, builtin->dependencies);
906 /* How to handle the $PRODUCES directive. */
908 produces_handler (self, defs, arg)
913 /* If just hacking documentation, don't change any of the production
915 if (only_documentation)
918 output_cpp_line_info++;
920 if (defs->production)
921 line_error (defs, "%s already has a %s definition", defs->filename, self);
924 defs->production = get_arg (self, defs, arg);
926 if (inhibit_production)
929 defs->output = fopen (defs->production, "w");
932 file_error (defs->production);
934 fprintf (defs->output, "/* %s, created from %s. */\n",
935 defs->production, defs->filename);
940 /* How to handle the $END directive. */
942 end_handler (self, defs, arg)
947 must_be_building (self, defs);
948 building_builtin = 0;
952 /* **************************************************************** */
954 /* Error Handling Functions */
956 /* **************************************************************** */
958 /* Produce an error for DEFS with FORMAT and ARGS. */
960 line_error (defs, format, arg1, arg2)
962 char *format, *arg1, *arg2;
964 if (defs->filename[0] != '/')
965 fprintf (stderr, "%s", error_directory ? error_directory : "./");
966 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
967 fprintf (stderr, format, arg1, arg2);
968 fprintf (stderr, "\n");
972 /* Print error message for FILENAME. */
974 file_error (filename)
981 /* **************************************************************** */
983 /* xmalloc and xrealloc () */
985 /* **************************************************************** */
987 static void memory_error_and_abort ();
993 char *temp = (char *)malloc (bytes);
996 memory_error_and_abort ();
1001 xrealloc (pointer, bytes)
1008 temp = (char *)malloc (bytes);
1010 temp = (char *)realloc (pointer, bytes);
1013 memory_error_and_abort ();
1019 memory_error_and_abort ()
1021 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
1025 /* **************************************************************** */
1027 /* Creating the Struct and Extern Files */
1029 /* **************************************************************** */
1031 /* Return a pointer to a newly allocated builtin which is
1032 an exact copy of BUILTIN. */
1034 copy_builtin (builtin)
1035 BUILTIN_DESC *builtin;
1039 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1041 new->name = savestring (builtin->name);
1042 new->shortdoc = savestring (builtin->shortdoc);
1043 new->longdoc = copy_string_array (builtin->longdoc);
1044 new->dependencies = copy_string_array (builtin->dependencies);
1047 builtin->function ? savestring (builtin->function) : (char *)NULL;
1049 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
1054 /* How to save away a builtin. */
1056 save_builtin (builtin)
1057 BUILTIN_DESC *builtin;
1059 BUILTIN_DESC *newbuiltin;
1061 newbuiltin = copy_builtin (builtin);
1063 /* If this is the first builtin to be saved, create the array
1065 if (!saved_builtins)
1066 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1068 array_add ((char *)newbuiltin, saved_builtins);
1071 /* Flags that mean something to write_documentation (). */
1072 #define STRING_ARRAY 0x01
1073 #define TEXINFO 0x02
1074 #define PLAINTEXT 0x04
1075 #define HELPFILE 0x08
1077 char *structfile_header[] = {
1078 "/* builtins.c -- the built in shell commands. */",
1080 "/* This file is manufactured by ./mkbuiltins, and should not be",
1081 " edited by hand. See the source to mkbuiltins for details. */",
1083 "/* Copyright (C) 1987-2002 Free Software Foundation, Inc.",
1085 " This file is part of GNU Bash, the Bourne Again SHell.",
1087 " Bash is free software; you can redistribute it and/or modify it",
1088 " under the terms of the GNU General Public License as published by",
1089 " the Free Software Foundation; either version 2, or (at your option)",
1090 " any later version.",
1092 " Bash is distributed in the hope that it will be useful, but WITHOUT",
1093 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1094 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public",
1095 " License for more details.",
1097 " You should have received a copy of the GNU General Public License",
1098 " along with Bash; see the file COPYING. If not, write to the Free",
1099 " Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */",
1101 "/* The list of shell builtins. Each element is name, function, flags,",
1102 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1103 " of help lines. The function takes a WORD_LIST *; the first word in the",
1104 " list is the first arg to the command. The list has already had word",
1105 " expansion performed.",
1107 " Functions which need to look at only the simple commands (e.g.",
1108 " the enable_builtin ()), should ignore entries where",
1109 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
1110 " the list of shell reserved control structures, like `if' and `while'.",
1111 " The end of the list is denoted with a NULL name field. */",
1113 "#include \"../builtins.h\"",
1117 char *structfile_footer[] = {
1118 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0 }",
1121 "struct builtin *shell_builtins = static_shell_builtins;",
1122 "struct builtin *current_builtin;",
1124 "int num_shell_builtins =",
1125 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1129 /* Write out any neccessary opening information for
1130 STRUCTFILE and EXTERNFILE. */
1132 write_file_headers (structfile, externfile)
1133 FILE *structfile, *externfile;
1139 for (i = 0; structfile_header[i]; i++)
1140 fprintf (structfile, "%s\n", structfile_header[i]);
1142 fprintf (structfile, "#include \"%s\"\n",
1143 extern_filename ? extern_filename : "builtext.h");
1145 fprintf (structfile, "#include \"bashintl.h\"\n");
1147 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1151 fprintf (externfile,
1152 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1153 extern_filename ? extern_filename : "builtext.h");
1156 /* Write out any necessary closing information for
1157 STRUCTFILE and EXTERNFILE. */
1159 write_file_footers (structfile, externfile)
1160 FILE *structfile, *externfile;
1164 /* Write out the footers. */
1167 for (i = 0; structfile_footer[i]; i++)
1168 fprintf (structfile, "%s\n", structfile_footer[i]);
1172 /* Write out the information accumulated in DEFS to
1173 STRUCTFILE and EXTERNFILE. */
1175 write_builtins (defs, structfile, externfile)
1177 FILE *structfile, *externfile;
1181 /* Write out the information. */
1184 register BUILTIN_DESC *builtin;
1186 for (i = 0; i < defs->builtins->sindex; i++)
1188 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1190 /* Write out any #ifdefs that may be there. */
1191 if (!only_documentation)
1193 if (builtin->dependencies)
1195 write_ifdefs (externfile, builtin->dependencies->array);
1196 write_ifdefs (structfile, builtin->dependencies->array);
1199 /* Write the extern definition. */
1202 if (builtin->function)
1203 fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
1206 fprintf (externfile, "extern char * const %s_doc[];\n",
1207 document_name (builtin));
1210 /* Write the structure definition. */
1213 fprintf (structfile, " { \"%s\", ", builtin->name);
1215 if (builtin->function)
1216 fprintf (structfile, "%s, ", builtin->function);
1218 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
1220 fprintf (structfile, "%s%s%s, %s_doc,\n",
1221 "BUILTIN_ENABLED | STATIC_BUILTIN",
1222 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1223 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1224 document_name (builtin));
1227 (structfile, " \"%s\", (char *)NULL },\n",
1228 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1232 if (structfile || separate_helpfiles)
1233 /* Save away this builtin for later writing of the
1234 long documentation strings. */
1235 save_builtin (builtin);
1237 /* Write out the matching #endif, if neccessary. */
1238 if (builtin->dependencies)
1241 write_endifs (externfile, builtin->dependencies->array);
1244 write_endifs (structfile, builtin->dependencies->array);
1248 if (documentation_file)
1250 fprintf (documentation_file, "@item %s\n", builtin->name);
1252 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1258 /* Write out the long documentation strings in BUILTINS to STREAM. */
1260 write_longdocs (stream, builtins)
1265 register BUILTIN_DESC *builtin;
1269 for (i = 0; i < builtins->sindex; i++)
1271 builtin = (BUILTIN_DESC *)builtins->array[i];
1273 if (builtin->dependencies)
1274 write_ifdefs (stream, builtin->dependencies->array);
1276 /* Write the long documentation strings. */
1277 dname = document_name (builtin);
1278 fprintf (stream, "char * const %s_doc[] =", dname);
1280 if (separate_helpfiles)
1282 int l = strlen (helpfile_directory) + strlen (dname) + 1;
1283 sarray[0] = (char *)xmalloc (l + 1);
1284 sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
1285 sarray[1] = (char *)NULL;
1286 write_documentation (stream, sarray, 0, STRING_ARRAY|HELPFILE);
1290 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1292 if (builtin->dependencies)
1293 write_endifs (stream, builtin->dependencies->array);
1298 /* Write an #ifdef string saying what needs to be defined (or not defined)
1299 in order to allow compilation of the code that will follow.
1300 STREAM is the stream to write the information to,
1301 DEFINES is a null terminated array of define names.
1302 If a define is preceded by an `!', then the sense of the test is
1305 write_ifdefs (stream, defines)
1314 fprintf (stream, "#if ");
1316 for (i = 0; defines[i]; i++)
1318 char *def = defines[i];
1321 fprintf (stream, "!defined (%s)", def + 1);
1323 fprintf (stream, "defined (%s)", def);
1326 fprintf (stream, " && ");
1328 fprintf (stream, "\n");
1331 /* Write an #endif string saying what defines controlled the compilation
1332 of the immediately preceding code.
1333 STREAM is the stream to write the information to.
1334 DEFINES is a null terminated array of define names. */
1336 write_endifs (stream, defines)
1345 fprintf (stream, "#endif /* ");
1347 for (i = 0; defines[i]; i++)
1349 fprintf (stream, "%s", defines[i]);
1352 fprintf (stream, " && ");
1355 fprintf (stream, " */\n");
1358 /* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
1359 and quoting special characters in the string. Handle special things for
1360 internationalization (gettext) and the single-string vs. multiple-strings
1363 write_documentation (stream, documentation, indentation, flags)
1365 char **documentation;
1366 int indentation, flags;
1369 register char *line;
1370 int string_array, texinfo, base_indent, last_cpp, filename_p;
1375 string_array = flags & STRING_ARRAY;
1376 filename_p = flags & HELPFILE;
1380 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n"); /* } */
1381 if (single_longdoc_strings)
1383 if (filename_p == 0)
1385 if (documentation && documentation[0] && documentation[0][0])
1386 fprintf (stream, "N_(\"");
1388 fprintf (stream, "N_(\" "); /* the empty string translates specially. */
1391 fprintf (stream, "\"");
1395 base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
1397 for (i = last_cpp = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1399 /* Allow #ifdef's to be written out verbatim, but don't put them into
1400 separate help files. */
1403 if (string_array && filename_p == 0 && single_longdoc_strings == 0)
1404 fprintf (stream, "%s\n", line);
1411 /* prefix with N_( for gettext */
1412 if (string_array && single_longdoc_strings == 0)
1414 if (filename_p == 0)
1417 fprintf (stream, " N_(\"");
1419 fprintf (stream, " N_(\" "); /* the empty string translates specially. */
1422 fprintf (stream, " \"");
1426 for (j = 0; j < indentation; j++)
1427 fprintf (stream, " ");
1429 /* Don't indent the first line, because of how the help builtin works. */
1431 indentation += base_indent;
1435 for (j = 0; line[j]; j++)
1441 fprintf (stream, "\\%c", line[j]);
1445 fprintf (stream, "%c", line[j]);
1449 /* closing right paren for gettext */
1450 if (single_longdoc_strings == 0)
1452 if (filename_p == 0)
1453 fprintf (stream, "\"),\n");
1455 fprintf (stream, "\",\n");
1457 else if (documentation[i+1])
1458 /* don't add extra newline after last line */
1459 fprintf (stream, "\\n\\\n");
1463 for (j = 0; line[j]; j++)
1470 fprintf (stream, "@%c", line[j]);
1474 fprintf (stream, "%c", line[j]);
1477 fprintf (stream, "\n");
1480 fprintf (stream, "%s\n", line);
1483 /* closing right paren for gettext */
1484 if (string_array && single_longdoc_strings)
1486 if (filename_p == 0)
1487 fprintf (stream, "\"),\n");
1489 fprintf (stream, "\",\n");
1493 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1497 write_helpfiles (builtins)
1500 char *helpfile, *bname;
1503 BUILTIN_DESC *builtin;
1505 i = mkdir ("helpfiles", 0777);
1506 if (i < 0 && errno != EEXIST)
1508 fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
1512 hdlen = strlen ("helpfiles/");
1513 for (i = 0; i < builtins->sindex; i++)
1515 builtin = (BUILTIN_DESC *)builtins->array[i];
1517 bname = document_name (builtin);
1518 helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
1519 sprintf (helpfile, "helpfiles/%s", bname);
1521 helpfp = fopen (helpfile, "w");
1524 fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
1529 write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
1539 _find_in_table (name, name_table)
1540 char *name, *name_table[];
1544 for (i = 0; name_table[i]; i++)
1545 if (strcmp (name, name_table[i]) == 0)
1551 is_special_builtin (name)
1554 return (_find_in_table (name, special_builtins));
1558 is_assignment_builtin (name)
1561 return (_find_in_table (name, assignment_builtins));
1564 #if !defined (HAVE_RENAME)
1570 if (link (from, to) < 0)
1575 #endif /* !HAVE_RENAME */