1 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
4 /* Copyright (C) 1987-2011 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
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
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
74 #define BUILTIN_FLAG_POSIX_BUILTIN 0x04
78 /* If this stream descriptor is non-zero, then write
79 texinfo documentation to it. */
80 FILE *documentation_file = (FILE *)NULL;
82 /* Non-zero means to only produce documentation. */
83 int only_documentation = 0;
85 /* Non-zero means to not do any productions. */
86 int inhibit_production = 0;
88 /* Non-zero means to not add functions (xxx_builtin) to the members of the
89 produced `struct builtin []' */
90 int inhibit_functions = 0;
92 /* Non-zero means to produce separate help files for each builtin, named by
93 the builtin name, in `./helpfiles'. */
94 int separate_helpfiles = 0;
96 /* Non-zero means to create single C strings for each `longdoc', with
97 embedded newlines, for ease of translation. */
98 int single_longdoc_strings = 1;
100 /* The name of a directory into which the separate external help files will
101 eventually be installed. */
102 char *helpfile_directory;
104 /* The name of a directory to precede the filename when reporting
106 char *error_directory = (char *)NULL;
108 /* The name of the structure file. */
109 char *struct_filename = (char *)NULL;
111 /* The name of the external declaration file. */
112 char *extern_filename = (char *)NULL;
114 /* Here is a structure for manipulating arrays of data. */
116 int size; /* Number of slots allocated to array. */
117 int sindex; /* Current location in array. */
118 int width; /* Size of each element. */
119 int growth_rate; /* How fast to grow. */
120 char **array; /* The array itself. */
123 /* Here is a structure defining a single BUILTIN. */
125 char *name; /* The name of this builtin. */
126 char *function; /* The name of the function to call. */
127 char *shortdoc; /* The short documentation for this builtin. */
128 char *docname; /* Possible name for documentation string. */
129 ARRAY *longdoc; /* The long documentation for this builtin. */
130 ARRAY *dependencies; /* Null terminated array of #define names. */
131 int flags; /* Flags for this builtin. */
134 /* Here is a structure which defines a DEF file. */
136 char *filename; /* The name of the input def file. */
137 ARRAY *lines; /* The contents of the file. */
138 int line_number; /* The current line number. */
139 char *production; /* The name of the production file. */
140 FILE *output; /* Open file stream for PRODUCTION. */
141 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
144 /* The array of all builtins encountered during execution of this code. */
145 ARRAY *saved_builtins = (ARRAY *)NULL;
147 /* The Posix.2 so-called `special' builtins. */
148 char *special_builtins[] =
150 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
151 "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
155 /* The builtin commands that take assignment statements as arguments. */
156 char *assignment_builtins[] =
158 "alias", "declare", "export", "local", "readonly", "typeset",
162 /* The builtin commands that are special to the POSIX search order. */
163 char *posix_builtins[] =
165 "alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "jobs",
166 "kill", "newgrp", "pwd", "read", "true", "umask", "unalias", "wait",
170 /* Forward declarations. */
171 static int is_special_builtin ();
172 static int is_assignment_builtin ();
173 static int is_posix_builtin ();
175 #if !defined (HAVE_RENAME)
176 static int rename ();
179 void extract_info ();
184 void write_file_headers ();
185 void write_file_footers ();
186 void write_ifdefs ();
187 void write_endifs ();
188 void write_documentation ();
189 void write_longdocs ();
190 void write_builtins ();
192 int write_helpfiles ();
195 void add_documentation ();
197 void must_be_building ();
198 void remove_trailing_whitespace ();
200 #define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
203 /* For each file mentioned on the command line, process it and
204 write the information to STRUCTFILE and EXTERNFILE, while
205 creating the production file if neccessary. */
212 FILE *structfile, *externfile;
213 char *documentation_filename, *temp_struct_filename;
215 structfile = externfile = (FILE *)NULL;
216 documentation_filename = DOCFILE;
217 temp_struct_filename = (char *)NULL;
219 while (arg_index < argc && argv[arg_index][0] == '-')
221 char *arg = argv[arg_index++];
223 if (strcmp (arg, "-externfile") == 0)
224 extern_filename = argv[arg_index++];
225 else if (strcmp (arg, "-structfile") == 0)
226 struct_filename = argv[arg_index++];
227 else if (strcmp (arg, "-noproduction") == 0)
228 inhibit_production = 1;
229 else if (strcmp (arg, "-nofunctions") == 0)
230 inhibit_functions = 1;
231 else if (strcmp (arg, "-document") == 0)
232 documentation_file = fopen (documentation_filename, "w");
233 else if (strcmp (arg, "-D") == 0)
238 free (error_directory);
240 error_directory = xmalloc (2 + strlen (argv[arg_index]));
241 strcpy (error_directory, argv[arg_index]);
242 len = strlen (error_directory);
244 if (len && error_directory[len - 1] != '/')
245 strcat (error_directory, "/");
249 else if (strcmp (arg, "-documentonly") == 0)
251 only_documentation = 1;
252 documentation_file = fopen (documentation_filename, "w");
254 else if (strcmp (arg, "-H") == 0)
256 separate_helpfiles = 1;
257 helpfile_directory = argv[arg_index++];
259 else if (strcmp (arg, "-S") == 0)
260 single_longdoc_strings = 0;
263 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
268 /* If there are no files to process, just quit now. */
269 if (arg_index == argc)
272 if (!only_documentation)
274 /* Open the files. */
277 temp_struct_filename = xmalloc (15);
278 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
279 structfile = fopen (temp_struct_filename, "w");
282 file_error (temp_struct_filename);
287 externfile = fopen (extern_filename, "w");
290 file_error (extern_filename);
293 /* Write out the headers. */
294 write_file_headers (structfile, externfile);
297 if (documentation_file)
299 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
301 fprintf (documentation_file, "@ftable @asis\n");
304 /* Process the .def files. */
305 while (arg_index < argc)
309 arg = argv[arg_index++];
311 extract_info (arg, structfile, externfile);
314 /* Close the files. */
315 if (!only_documentation)
317 /* Write the footers. */
318 write_file_footers (structfile, externfile);
322 write_longdocs (structfile, saved_builtins);
324 rename (temp_struct_filename, struct_filename);
331 if (separate_helpfiles)
333 write_helpfiles (saved_builtins);
336 if (documentation_file)
338 fprintf (documentation_file, "@end ftable\n");
339 fclose (documentation_file);
345 /* **************************************************************** */
347 /* Array Functions and Manipulators */
349 /* **************************************************************** */
351 /* Make a new array, and return a pointer to it. The array will
352 contain elements of size WIDTH, and is initialized to no elements. */
359 array = (ARRAY *)xmalloc (sizeof (ARRAY));
362 array->width = width;
364 /* Default to increasing size in units of 20. */
365 array->growth_rate = 20;
367 array->array = (char **)NULL;
372 /* Copy the array of strings in ARRAY. */
374 copy_string_array (array)
381 return (ARRAY *)NULL;
383 copy = array_create (sizeof (char *));
385 copy->size = array->size;
386 copy->sindex = array->sindex;
387 copy->width = array->width;
389 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
391 for (i = 0; i < array->sindex; i++)
392 copy->array[i] = savestring (array->array[i]);
394 copy->array[i] = (char *)NULL;
399 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
401 array_add (element, array)
405 if (array->sindex + 2 > array->size)
406 array->array = (char **)xrealloc
407 (array->array, (array->size += array->growth_rate) * array->width);
409 array->array[array->sindex++] = element;
410 array->array[array->sindex] = (char *)NULL;
413 /* Free an allocated array and data pointer. */
424 /* **************************************************************** */
426 /* Processing a DEF File */
428 /* **************************************************************** */
430 /* The definition of a function. */
431 typedef int Function ();
432 typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
434 /* Structure handles processor directives. */
437 mk_handler_func_t *function;
440 extern int builtin_handler __P((char *, DEF_FILE *, char *));
441 extern int function_handler __P((char *, DEF_FILE *, char *));
442 extern int short_doc_handler __P((char *, DEF_FILE *, char *));
443 extern int comment_handler __P((char *, DEF_FILE *, char *));
444 extern int depends_on_handler __P((char *, DEF_FILE *, char *));
445 extern int produces_handler __P((char *, DEF_FILE *, char *));
446 extern int end_handler __P((char *, DEF_FILE *, char *));
447 extern int docname_handler __P((char *, DEF_FILE *, char *));
449 HANDLER_ENTRY handlers[] = {
450 { "BUILTIN", builtin_handler },
451 { "DOCNAME", docname_handler },
452 { "FUNCTION", function_handler },
453 { "SHORT_DOC", short_doc_handler },
454 { "$", comment_handler },
455 { "COMMENT", comment_handler },
456 { "DEPENDS_ON", depends_on_handler },
457 { "PRODUCES", produces_handler },
458 { "END", end_handler },
459 { (char *)NULL, (mk_handler_func_t *)NULL }
462 /* Return the entry in the table of handlers for NAME. */
464 find_directive (directive)
469 for (i = 0; handlers[i].directive; i++)
470 if (strcmp (handlers[i].directive, directive) == 0)
471 return (&handlers[i]);
473 return ((HANDLER_ENTRY *)NULL);
476 /* Non-zero indicates that a $BUILTIN has been seen, but not
477 the corresponding $END. */
478 static int building_builtin = 0;
480 /* Non-zero means to output cpp line and file information before
481 printing the current line to the production file. */
482 int output_cpp_line_info = 0;
484 /* The main function of this program. Read FILENAME and act on what is
485 found. Lines not starting with a dollar sign are copied to the
486 $PRODUCES target, if one is present. Lines starting with a dollar sign
487 are directives to this program, specifying the name of the builtin, the
488 function to call, the short documentation and the long documentation
489 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
490 target. After the file has been processed, write out the names of
491 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
492 is ignored, as is "$$ comment text". */
494 extract_info (filename, structfile, externfile)
496 FILE *structfile, *externfile;
505 if (stat (filename, &finfo) == -1)
506 file_error (filename);
508 fd = open (filename, O_RDONLY, 0666);
511 file_error (filename);
513 file_size = (size_t)finfo.st_size;
514 buffer = xmalloc (1 + file_size);
516 if ((nr = read (fd, buffer, file_size)) < 0)
517 file_error (filename);
519 /* This is needed on WIN32, and does not hurt on Unix. */
527 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
532 /* Create and fill in the initial structure describing this file. */
533 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
534 defs->filename = filename;
535 defs->lines = array_create (sizeof (char *));
536 defs->line_number = 0;
537 defs->production = (char *)NULL;
538 defs->output = (FILE *)NULL;
539 defs->builtins = (ARRAY *)NULL;
541 /* Build the array of lines. */
543 while (i < file_size)
545 array_add (&buffer[i], defs->lines);
547 while (i < file_size && buffer[i] != '\n')
552 /* Begin processing the input file. We don't write any output
553 until we have a file to write output to. */
554 output_cpp_line_info = 1;
556 /* Process each line in the array. */
557 for (i = 0; line = defs->lines->array[i]; i++)
559 defs->line_number = i;
565 HANDLER_ENTRY *handler;
567 /* Isolate the directive. */
568 for (j = 0; line[j] && !whitespace (line[j]); j++);
570 directive = xmalloc (j);
571 strncpy (directive, line + 1, j - 1);
572 directive[j -1] = '\0';
574 /* Get the function handler and call it. */
575 handler = find_directive (directive);
579 line_error (defs, "Unknown directive `%s'", directive);
585 /* Advance to the first non-whitespace character. */
586 while (whitespace (line[j]))
589 /* Call the directive handler with the FILE, and ARGS. */
590 (*(handler->function)) (directive, defs, line + j);
596 if (building_builtin)
597 add_documentation (defs, line);
598 else if (defs->output)
600 if (output_cpp_line_info)
602 /* If we're handed an absolute pathname, don't prepend
603 the directory name. */
604 if (defs->filename[0] == '/')
605 fprintf (defs->output, "#line %d \"%s\"\n",
606 defs->line_number + 1, defs->filename);
608 fprintf (defs->output, "#line %d \"%s%s\"\n",
609 defs->line_number + 1,
610 error_directory ? error_directory : "./",
612 output_cpp_line_info = 0;
615 fprintf (defs->output, "%s\n", line);
620 /* Close the production file. */
622 fclose (defs->output);
624 /* The file has been processed. Write the accumulated builtins to
625 the builtins.c file, and write the extern definitions to the
627 write_builtins (defs, structfile, externfile);
633 #define free_safely(x) if (x) free (x)
636 free_builtin (builtin)
637 BUILTIN_DESC *builtin;
641 free_safely (builtin->name);
642 free_safely (builtin->function);
643 free_safely (builtin->shortdoc);
644 free_safely (builtin->docname);
646 if (builtin->longdoc)
647 array_free (builtin->longdoc);
649 if (builtin->dependencies)
651 for (i = 0; builtin->dependencies->array[i]; i++)
652 free (builtin->dependencies->array[i]);
653 array_free (builtin->dependencies);
657 /* Free all of the memory allocated to a DEF_FILE. */
663 register BUILTIN_DESC *builtin;
665 if (defs->production)
666 free (defs->production);
669 array_free (defs->lines);
673 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
675 free_builtin (builtin);
678 array_free (defs->builtins);
683 /* **************************************************************** */
685 /* The Handler Functions Themselves */
687 /* **************************************************************** */
689 /* Strip surrounding whitespace from STRING, and
690 return a pointer to the start of it. */
692 strip_whitespace (string)
695 while (whitespace (*string))
698 remove_trailing_whitespace (string);
702 /* Remove only the trailing whitespace from STRING. */
704 remove_trailing_whitespace (string)
709 i = strlen (string) - 1;
711 while (i > 0 && whitespace (string[i]))
717 /* Ensure that there is a argument in STRING and return it.
718 FOR_WHOM is the name of the directive which needs the argument.
719 DEFS is the DEF_FILE in which the directive is found.
720 If there is no argument, produce an error. */
722 get_arg (for_whom, defs, string)
723 char *for_whom, *string;
728 new = strip_whitespace (string);
731 line_error (defs, "%s requires an argument", for_whom);
733 return (savestring (new));
736 /* Error if not building a builtin. */
738 must_be_building (directive, defs)
742 if (!building_builtin)
743 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
746 /* Return the current builtin. */
748 current_builtin (directive, defs)
752 must_be_building (directive, defs);
754 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
756 return ((BUILTIN_DESC *)NULL);
759 /* Add LINE to the long documentation for the current builtin.
760 Ignore blank lines until the first non-blank line has been seen. */
762 add_documentation (defs, line)
766 register BUILTIN_DESC *builtin;
768 builtin = current_builtin ("(implied LONGDOC)", defs);
770 remove_trailing_whitespace (line);
772 if (!*line && !builtin->longdoc)
775 if (!builtin->longdoc)
776 builtin->longdoc = array_create (sizeof (char *));
778 array_add (line, builtin->longdoc);
781 /* How to handle the $BUILTIN directive. */
783 builtin_handler (self, defs, arg)
791 /* If we are already building a builtin, we cannot start a new one. */
792 if (building_builtin)
794 line_error (defs, "%s found before $END", self);
798 output_cpp_line_info++;
800 /* Get the name of this builtin, and stick it in the array. */
801 name = get_arg (self, defs, arg);
803 /* If this is the first builtin, create the array to hold them. */
805 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
807 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
809 new->function = (char *)NULL;
810 new->shortdoc = (char *)NULL;
811 new->docname = (char *)NULL;
812 new->longdoc = (ARRAY *)NULL;
813 new->dependencies = (ARRAY *)NULL;
816 if (is_special_builtin (name))
817 new->flags |= BUILTIN_FLAG_SPECIAL;
818 if (is_assignment_builtin (name))
819 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
820 if (is_posix_builtin (name))
821 new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
823 array_add ((char *)new, defs->builtins);
824 building_builtin = 1;
829 /* How to handle the $FUNCTION directive. */
831 function_handler (self, defs, arg)
836 register BUILTIN_DESC *builtin;
838 builtin = current_builtin (self, defs);
842 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
845 if (builtin->function)
846 line_error (defs, "%s already has a function (%s)",
847 builtin->name, builtin->function);
849 builtin->function = get_arg (self, defs, arg);
854 /* How to handle the $DOCNAME directive. */
856 docname_handler (self, defs, arg)
861 register BUILTIN_DESC *builtin;
863 builtin = current_builtin (self, defs);
865 if (builtin->docname)
866 line_error (defs, "%s already had a docname (%s)",
867 builtin->name, builtin->docname);
869 builtin->docname = get_arg (self, defs, arg);
874 /* How to handle the $SHORT_DOC directive. */
876 short_doc_handler (self, defs, arg)
881 register BUILTIN_DESC *builtin;
883 builtin = current_builtin (self, defs);
885 if (builtin->shortdoc)
886 line_error (defs, "%s already has short documentation (%s)",
887 builtin->name, builtin->shortdoc);
889 builtin->shortdoc = get_arg (self, defs, arg);
894 /* How to handle the $COMMENT directive. */
896 comment_handler (self, defs, arg)
904 /* How to handle the $DEPENDS_ON directive. */
906 depends_on_handler (self, defs, arg)
911 register BUILTIN_DESC *builtin;
914 builtin = current_builtin (self, defs);
915 dependent = get_arg (self, defs, arg);
917 if (!builtin->dependencies)
918 builtin->dependencies = array_create (sizeof (char *));
920 array_add (dependent, builtin->dependencies);
925 /* How to handle the $PRODUCES directive. */
927 produces_handler (self, defs, arg)
932 /* If just hacking documentation, don't change any of the production
934 if (only_documentation)
937 output_cpp_line_info++;
939 if (defs->production)
940 line_error (defs, "%s already has a %s definition", defs->filename, self);
943 defs->production = get_arg (self, defs, arg);
945 if (inhibit_production)
948 defs->output = fopen (defs->production, "w");
951 file_error (defs->production);
953 fprintf (defs->output, "/* %s, created from %s. */\n",
954 defs->production, defs->filename);
959 /* How to handle the $END directive. */
961 end_handler (self, defs, arg)
966 must_be_building (self, defs);
967 building_builtin = 0;
971 /* **************************************************************** */
973 /* Error Handling Functions */
975 /* **************************************************************** */
977 /* Produce an error for DEFS with FORMAT and ARGS. */
979 line_error (defs, format, arg1, arg2)
981 char *format, *arg1, *arg2;
983 if (defs->filename[0] != '/')
984 fprintf (stderr, "%s", error_directory ? error_directory : "./");
985 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
986 fprintf (stderr, format, arg1, arg2);
987 fprintf (stderr, "\n");
991 /* Print error message for FILENAME. */
993 file_error (filename)
1000 /* **************************************************************** */
1002 /* xmalloc and xrealloc () */
1004 /* **************************************************************** */
1006 static void memory_error_and_abort ();
1012 char *temp = (char *)malloc (bytes);
1015 memory_error_and_abort ();
1020 xrealloc (pointer, bytes)
1027 temp = (char *)malloc (bytes);
1029 temp = (char *)realloc (pointer, bytes);
1032 memory_error_and_abort ();
1038 memory_error_and_abort ()
1040 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
1044 /* **************************************************************** */
1046 /* Creating the Struct and Extern Files */
1048 /* **************************************************************** */
1050 /* Return a pointer to a newly allocated builtin which is
1051 an exact copy of BUILTIN. */
1053 copy_builtin (builtin)
1054 BUILTIN_DESC *builtin;
1058 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1060 new->name = savestring (builtin->name);
1061 new->shortdoc = savestring (builtin->shortdoc);
1062 new->longdoc = copy_string_array (builtin->longdoc);
1063 new->dependencies = copy_string_array (builtin->dependencies);
1066 builtin->function ? savestring (builtin->function) : (char *)NULL;
1068 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
1073 /* How to save away a builtin. */
1075 save_builtin (builtin)
1076 BUILTIN_DESC *builtin;
1078 BUILTIN_DESC *newbuiltin;
1080 newbuiltin = copy_builtin (builtin);
1082 /* If this is the first builtin to be saved, create the array
1084 if (!saved_builtins)
1085 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1087 array_add ((char *)newbuiltin, saved_builtins);
1090 /* Flags that mean something to write_documentation (). */
1091 #define STRING_ARRAY 0x01
1092 #define TEXINFO 0x02
1093 #define PLAINTEXT 0x04
1094 #define HELPFILE 0x08
1096 char *structfile_header[] = {
1097 "/* builtins.c -- the built in shell commands. */",
1099 "/* This file is manufactured by ./mkbuiltins, and should not be",
1100 " edited by hand. See the source to mkbuiltins for details. */",
1102 "/* Copyright (C) 1987-2012 Free Software Foundation, Inc.",
1104 " This file is part of GNU Bash, the Bourne Again SHell.",
1106 " Bash is free software: you can redistribute it and/or modify",
1107 " it under the terms of the GNU General Public License as published by",
1108 " the Free Software Foundation, either version 3 of the License, or",
1109 " (at your option) any later version.",
1111 " Bash is distributed in the hope that it will be useful,",
1112 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
1113 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
1114 " GNU General Public License for more details.",
1116 " You should have received a copy of the GNU General Public License",
1117 " along with Bash. If not, see <http://www.gnu.org/licenses/>.",
1120 "/* The list of shell builtins. Each element is name, function, flags,",
1121 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1122 " of help lines. The function takes a WORD_LIST *; the first word in the",
1123 " list is the first arg to the command. The list has already had word",
1124 " expansion performed.",
1126 " Functions which need to look at only the simple commands (e.g.",
1127 " the enable_builtin ()), should ignore entries where",
1128 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
1129 " the list of shell reserved control structures, like `if' and `while'.",
1130 " The end of the list is denoted with a NULL name field. */",
1132 "#include \"../builtins.h\"",
1136 char *structfile_footer[] = {
1137 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0, (char *)0x0 }",
1140 "struct builtin *shell_builtins = static_shell_builtins;",
1141 "struct builtin *current_builtin;",
1143 "int num_shell_builtins =",
1144 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1148 /* Write out any neccessary opening information for
1149 STRUCTFILE and EXTERNFILE. */
1151 write_file_headers (structfile, externfile)
1152 FILE *structfile, *externfile;
1158 for (i = 0; structfile_header[i]; i++)
1159 fprintf (structfile, "%s\n", structfile_header[i]);
1161 fprintf (structfile, "#include \"%s\"\n",
1162 extern_filename ? extern_filename : "builtext.h");
1164 fprintf (structfile, "#include \"bashintl.h\"\n");
1166 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1170 fprintf (externfile,
1171 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1172 extern_filename ? extern_filename : "builtext.h");
1175 /* Write out any necessary closing information for
1176 STRUCTFILE and EXTERNFILE. */
1178 write_file_footers (structfile, externfile)
1179 FILE *structfile, *externfile;
1183 /* Write out the footers. */
1186 for (i = 0; structfile_footer[i]; i++)
1187 fprintf (structfile, "%s\n", structfile_footer[i]);
1191 /* Write out the information accumulated in DEFS to
1192 STRUCTFILE and EXTERNFILE. */
1194 write_builtins (defs, structfile, externfile)
1196 FILE *structfile, *externfile;
1200 /* Write out the information. */
1203 register BUILTIN_DESC *builtin;
1205 for (i = 0; i < defs->builtins->sindex; i++)
1207 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1209 /* Write out any #ifdefs that may be there. */
1210 if (!only_documentation)
1212 if (builtin->dependencies)
1214 write_ifdefs (externfile, builtin->dependencies->array);
1215 write_ifdefs (structfile, builtin->dependencies->array);
1218 /* Write the extern definition. */
1221 if (builtin->function)
1222 fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
1225 fprintf (externfile, "extern char * const %s_doc[];\n",
1226 document_name (builtin));
1229 /* Write the structure definition. */
1232 fprintf (structfile, " { \"%s\", ", builtin->name);
1234 if (builtin->function && inhibit_functions == 0)
1235 fprintf (structfile, "%s, ", builtin->function);
1237 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
1239 fprintf (structfile, "%s%s%s%s, %s_doc,\n",
1240 "BUILTIN_ENABLED | STATIC_BUILTIN",
1241 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1242 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1243 (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
1244 document_name (builtin));
1246 if (inhibit_functions)
1248 (structfile, " N_(\"%s\"), \"%s\" },\n",
1249 builtin->shortdoc ? builtin->shortdoc : builtin->name,
1250 document_name (builtin));
1253 (structfile, " N_(\"%s\"), (char *)NULL },\n",
1254 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1258 if (structfile || separate_helpfiles)
1259 /* Save away this builtin for later writing of the
1260 long documentation strings. */
1261 save_builtin (builtin);
1263 /* Write out the matching #endif, if neccessary. */
1264 if (builtin->dependencies)
1267 write_endifs (externfile, builtin->dependencies->array);
1270 write_endifs (structfile, builtin->dependencies->array);
1274 if (documentation_file)
1276 fprintf (documentation_file, "@item %s\n", builtin->name);
1278 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1284 /* Write out the long documentation strings in BUILTINS to STREAM. */
1286 write_longdocs (stream, builtins)
1291 register BUILTIN_DESC *builtin;
1295 for (i = 0; i < builtins->sindex; i++)
1297 builtin = (BUILTIN_DESC *)builtins->array[i];
1299 if (builtin->dependencies)
1300 write_ifdefs (stream, builtin->dependencies->array);
1302 /* Write the long documentation strings. */
1303 dname = document_name (builtin);
1304 fprintf (stream, "char * const %s_doc[] =", dname);
1306 if (separate_helpfiles)
1308 int l = strlen (helpfile_directory) + strlen (dname) + 1;
1309 sarray[0] = (char *)xmalloc (l + 1);
1310 sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
1311 sarray[1] = (char *)NULL;
1312 write_documentation (stream, sarray, 0, STRING_ARRAY|HELPFILE);
1316 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1318 if (builtin->dependencies)
1319 write_endifs (stream, builtin->dependencies->array);
1325 write_dummy_declarations (stream, builtins)
1330 BUILTIN_DESC *builtin;
1332 for (i = 0; structfile_header[i]; i++)
1333 fprintf (stream, "%s\n", structfile_header[i]);
1335 for (i = 0; i < builtins->sindex; i++)
1337 builtin = (BUILTIN_DESC *)builtins->array[i];
1339 /* How to guarantee that no builtin is written more than once? */
1340 fprintf (stream, "int %s () { return (0); }\n", builtin->function);
1344 /* Write an #ifdef string saying what needs to be defined (or not defined)
1345 in order to allow compilation of the code that will follow.
1346 STREAM is the stream to write the information to,
1347 DEFINES is a null terminated array of define names.
1348 If a define is preceded by an `!', then the sense of the test is
1351 write_ifdefs (stream, defines)
1360 fprintf (stream, "#if ");
1362 for (i = 0; defines[i]; i++)
1364 char *def = defines[i];
1367 fprintf (stream, "!defined (%s)", def + 1);
1369 fprintf (stream, "defined (%s)", def);
1372 fprintf (stream, " && ");
1374 fprintf (stream, "\n");
1377 /* Write an #endif string saying what defines controlled the compilation
1378 of the immediately preceding code.
1379 STREAM is the stream to write the information to.
1380 DEFINES is a null terminated array of define names. */
1382 write_endifs (stream, defines)
1391 fprintf (stream, "#endif /* ");
1393 for (i = 0; defines[i]; i++)
1395 fprintf (stream, "%s", defines[i]);
1398 fprintf (stream, " && ");
1401 fprintf (stream, " */\n");
1404 /* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
1405 and quoting special characters in the string. Handle special things for
1406 internationalization (gettext) and the single-string vs. multiple-strings
1409 write_documentation (stream, documentation, indentation, flags)
1411 char **documentation;
1412 int indentation, flags;
1415 register char *line;
1416 int string_array, texinfo, base_indent, filename_p;
1421 string_array = flags & STRING_ARRAY;
1422 filename_p = flags & HELPFILE;
1426 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n"); /* } */
1427 if (single_longdoc_strings)
1429 if (filename_p == 0)
1431 if (documentation && documentation[0] && documentation[0][0])
1432 fprintf (stream, "N_(\"");
1434 fprintf (stream, "N_(\" "); /* the empty string translates specially. */
1437 fprintf (stream, "\"");
1441 base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
1443 for (i = 0, texinfo = (flags & TEXINFO); documentation && (line = documentation[i]); i++)
1445 /* Allow #ifdef's to be written out verbatim, but don't put them into
1446 separate help files. */
1449 if (string_array && filename_p == 0 && single_longdoc_strings == 0)
1450 fprintf (stream, "%s\n", line);
1454 /* prefix with N_( for gettext */
1455 if (string_array && single_longdoc_strings == 0)
1457 if (filename_p == 0)
1460 fprintf (stream, " N_(\"");
1462 fprintf (stream, " N_(\" "); /* the empty string translates specially. */
1465 fprintf (stream, " \"");
1469 for (j = 0; j < indentation; j++)
1470 fprintf (stream, " ");
1472 /* Don't indent the first line, because of how the help builtin works. */
1474 indentation += base_indent;
1478 for (j = 0; line[j]; j++)
1484 fprintf (stream, "\\%c", line[j]);
1488 fprintf (stream, "%c", line[j]);
1492 /* closing right paren for gettext */
1493 if (single_longdoc_strings == 0)
1495 if (filename_p == 0)
1496 fprintf (stream, "\"),\n");
1498 fprintf (stream, "\",\n");
1500 else if (documentation[i+1])
1501 /* don't add extra newline after last line */
1502 fprintf (stream, "\\n\\\n");
1506 for (j = 0; line[j]; j++)
1513 fprintf (stream, "@%c", line[j]);
1517 fprintf (stream, "%c", line[j]);
1520 fprintf (stream, "\n");
1523 fprintf (stream, "%s\n", line);
1526 /* closing right paren for gettext */
1527 if (string_array && single_longdoc_strings)
1529 if (filename_p == 0)
1530 fprintf (stream, "\"),\n");
1532 fprintf (stream, "\",\n");
1536 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1540 write_helpfiles (builtins)
1543 char *helpfile, *bname;
1546 BUILTIN_DESC *builtin;
1548 i = mkdir ("helpfiles", 0777);
1549 if (i < 0 && errno != EEXIST)
1551 fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
1555 hdlen = strlen ("helpfiles/");
1556 for (i = 0; i < builtins->sindex; i++)
1558 builtin = (BUILTIN_DESC *)builtins->array[i];
1560 bname = document_name (builtin);
1561 helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
1562 sprintf (helpfile, "helpfiles/%s", bname);
1564 helpfp = fopen (helpfile, "w");
1567 fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
1572 write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
1582 _find_in_table (name, name_table)
1583 char *name, *name_table[];
1587 for (i = 0; name_table[i]; i++)
1588 if (strcmp (name, name_table[i]) == 0)
1594 is_special_builtin (name)
1597 return (_find_in_table (name, special_builtins));
1601 is_assignment_builtin (name)
1604 return (_find_in_table (name, assignment_builtins));
1608 is_posix_builtin (name)
1611 return (_find_in_table (name, posix_builtins));
1614 #if !defined (HAVE_RENAME)
1620 if (link (from, to) < 0)
1625 #endif /* !HAVE_RENAME */