1 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
4 /* Copyright (C) 1987-2002 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"
33 # if defined (HAVE_SYS_FILE_H)
34 # include <sys/file.h>
38 #include "posixstat.h"
41 #include "../bashansi.h"
47 #define DOCFILE "builtins.texi"
53 static char *xmalloc (), *xrealloc ();
55 #if !defined (__STDC__) && !defined (strcpy)
56 extern char *strcpy ();
57 #endif /* !__STDC__ && !strcpy */
59 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
60 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
62 /* Flag values that builtins can have. */
63 #define BUILTIN_FLAG_SPECIAL 0x01
64 #define BUILTIN_FLAG_ASSIGNMENT 0x02
68 /* If this stream descriptor is non-zero, then write
69 texinfo documentation to it. */
70 FILE *documentation_file = (FILE *)NULL;
72 /* Non-zero means to only produce documentation. */
73 int only_documentation = 0;
75 /* Non-zero means to not do any productions. */
76 int inhibit_production = 0;
78 /* Non-zero means to produce separate help files for each builtin, named by
79 the builtin name, in `./helpfiles'. */
80 int separate_helpfiles = 0;
82 /* Non-zero means to create single C strings for each `longdoc', with
83 embedded newlines, for ease of translation. */
84 int single_longdoc_strings = 1;
86 /* The name of a directory into which the separate external help files will
87 eventually be installed. */
88 char *helpfile_directory;
90 /* The name of a directory to precede the filename when reporting
92 char *error_directory = (char *)NULL;
94 /* The name of the structure file. */
95 char *struct_filename = (char *)NULL;
97 /* The name of the external declaration file. */
98 char *extern_filename = (char *)NULL;
100 /* Here is a structure for manipulating arrays of data. */
102 int size; /* Number of slots allocated to array. */
103 int sindex; /* Current location in array. */
104 int width; /* Size of each element. */
105 int growth_rate; /* How fast to grow. */
106 char **array; /* The array itself. */
109 /* Here is a structure defining a single BUILTIN. */
111 char *name; /* The name of this builtin. */
112 char *function; /* The name of the function to call. */
113 char *shortdoc; /* The short documentation for this builtin. */
114 char *docname; /* Possible name for documentation string. */
115 ARRAY *longdoc; /* The long documentation for this builtin. */
116 ARRAY *dependencies; /* Null terminated array of #define names. */
117 int flags; /* Flags for this builtin. */
120 /* Here is a structure which defines a DEF file. */
122 char *filename; /* The name of the input def file. */
123 ARRAY *lines; /* The contents of the file. */
124 int line_number; /* The current line number. */
125 char *production; /* The name of the production file. */
126 FILE *output; /* Open file stream for PRODUCTION. */
127 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
130 /* The array of all builtins encountered during execution of this code. */
131 ARRAY *saved_builtins = (ARRAY *)NULL;
133 /* The Posix.2 so-called `special' builtins. */
134 char *special_builtins[] =
136 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
137 "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
141 /* The builtin commands that take assignment statements as arguments. */
142 char *assignment_builtins[] =
144 "alias", "declare", "export", "local", "readonly", "typeset",
148 /* Forward declarations. */
149 static int is_special_builtin ();
150 static int is_assignment_builtin ();
152 #if !defined (HAVE_RENAME)
153 static int rename ();
156 void extract_info ();
161 void write_file_headers ();
162 void write_file_footers ();
163 void write_ifdefs ();
164 void write_endifs ();
165 void write_documentation ();
166 void write_longdocs ();
167 void write_builtins ();
169 int write_helpfiles ();
172 void add_documentation ();
174 void must_be_building ();
175 void remove_trailing_whitespace ();
177 #define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
180 /* For each file mentioned on the command line, process it and
181 write the information to STRUCTFILE and EXTERNFILE, while
182 creating the production file if neccessary. */
189 FILE *structfile, *externfile;
190 char *documentation_filename, *temp_struct_filename;
192 structfile = externfile = (FILE *)NULL;
193 documentation_filename = DOCFILE;
194 temp_struct_filename = (char *)NULL;
196 while (arg_index < argc && argv[arg_index][0] == '-')
198 char *arg = argv[arg_index++];
200 if (strcmp (arg, "-externfile") == 0)
201 extern_filename = argv[arg_index++];
202 else if (strcmp (arg, "-structfile") == 0)
203 struct_filename = argv[arg_index++];
204 else if (strcmp (arg, "-noproduction") == 0)
205 inhibit_production = 1;
206 else if (strcmp (arg, "-document") == 0)
207 documentation_file = fopen (documentation_filename, "w");
208 else if (strcmp (arg, "-D") == 0)
213 free (error_directory);
215 error_directory = xmalloc (2 + strlen (argv[arg_index]));
216 strcpy (error_directory, argv[arg_index]);
217 len = strlen (error_directory);
219 if (len && error_directory[len - 1] != '/')
220 strcat (error_directory, "/");
224 else if (strcmp (arg, "-documentonly") == 0)
226 only_documentation = 1;
227 documentation_file = fopen (documentation_filename, "w");
229 else if (strcmp (arg, "-H") == 0)
231 separate_helpfiles = 1;
232 helpfile_directory = argv[arg_index++];
234 else if (strcmp (arg, "-S") == 0)
235 single_longdoc_strings = 0;
238 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
243 /* If there are no files to process, just quit now. */
244 if (arg_index == argc)
247 if (!only_documentation)
249 /* Open the files. */
252 temp_struct_filename = xmalloc (15);
253 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
254 structfile = fopen (temp_struct_filename, "w");
257 file_error (temp_struct_filename);
262 externfile = fopen (extern_filename, "w");
265 file_error (extern_filename);
268 /* Write out the headers. */
269 write_file_headers (structfile, externfile);
272 if (documentation_file)
274 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
276 fprintf (documentation_file, "@ftable @asis\n");
279 /* Process the .def files. */
280 while (arg_index < argc)
284 arg = argv[arg_index++];
286 extract_info (arg, structfile, externfile);
289 /* Close the files. */
290 if (!only_documentation)
292 /* Write the footers. */
293 write_file_footers (structfile, externfile);
297 write_longdocs (structfile, saved_builtins);
299 rename (temp_struct_filename, struct_filename);
306 if (separate_helpfiles)
308 write_helpfiles (saved_builtins);
311 if (documentation_file)
313 fprintf (documentation_file, "@end ftable\n");
314 fclose (documentation_file);
320 /* **************************************************************** */
322 /* Array Functions and Manipulators */
324 /* **************************************************************** */
326 /* Make a new array, and return a pointer to it. The array will
327 contain elements of size WIDTH, and is initialized to no elements. */
334 array = (ARRAY *)xmalloc (sizeof (ARRAY));
337 array->width = width;
339 /* Default to increasing size in units of 20. */
340 array->growth_rate = 20;
342 array->array = (char **)NULL;
347 /* Copy the array of strings in ARRAY. */
349 copy_string_array (array)
356 return (ARRAY *)NULL;
358 copy = array_create (sizeof (char *));
360 copy->size = array->size;
361 copy->sindex = array->sindex;
362 copy->width = array->width;
364 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
366 for (i = 0; i < array->sindex; i++)
367 copy->array[i] = savestring (array->array[i]);
369 copy->array[i] = (char *)NULL;
374 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
376 array_add (element, array)
380 if (array->sindex + 2 > array->size)
381 array->array = (char **)xrealloc
382 (array->array, (array->size += array->growth_rate) * array->width);
384 array->array[array->sindex++] = element;
385 array->array[array->sindex] = (char *)NULL;
388 /* Free an allocated array and data pointer. */
399 /* **************************************************************** */
401 /* Processing a DEF File */
403 /* **************************************************************** */
405 /* The definition of a function. */
406 typedef int Function ();
407 typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
409 /* Structure handles processor directives. */
412 mk_handler_func_t *function;
415 extern int builtin_handler __P((char *, DEF_FILE *, char *));
416 extern int function_handler __P((char *, DEF_FILE *, char *));
417 extern int short_doc_handler __P((char *, DEF_FILE *, char *));
418 extern int comment_handler __P((char *, DEF_FILE *, char *));
419 extern int depends_on_handler __P((char *, DEF_FILE *, char *));
420 extern int produces_handler __P((char *, DEF_FILE *, char *));
421 extern int end_handler __P((char *, DEF_FILE *, char *));
422 extern int docname_handler __P((char *, DEF_FILE *, char *));
424 HANDLER_ENTRY handlers[] = {
425 { "BUILTIN", builtin_handler },
426 { "DOCNAME", docname_handler },
427 { "FUNCTION", function_handler },
428 { "SHORT_DOC", short_doc_handler },
429 { "$", comment_handler },
430 { "COMMENT", comment_handler },
431 { "DEPENDS_ON", depends_on_handler },
432 { "PRODUCES", produces_handler },
433 { "END", end_handler },
434 { (char *)NULL, (mk_handler_func_t *)NULL }
437 /* Return the entry in the table of handlers for NAME. */
439 find_directive (directive)
444 for (i = 0; handlers[i].directive; i++)
445 if (strcmp (handlers[i].directive, directive) == 0)
446 return (&handlers[i]);
448 return ((HANDLER_ENTRY *)NULL);
451 /* Non-zero indicates that a $BUILTIN has been seen, but not
452 the corresponding $END. */
453 static int building_builtin = 0;
455 /* Non-zero means to output cpp line and file information before
456 printing the current line to the production file. */
457 int output_cpp_line_info = 0;
459 /* The main function of this program. Read FILENAME and act on what is
460 found. Lines not starting with a dollar sign are copied to the
461 $PRODUCES target, if one is present. Lines starting with a dollar sign
462 are directives to this program, specifying the name of the builtin, the
463 function to call, the short documentation and the long documentation
464 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
465 target. After the file has been processed, write out the names of
466 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
467 is ignored, as is "$$ comment text". */
469 extract_info (filename, structfile, externfile)
471 FILE *structfile, *externfile;
480 if (stat (filename, &finfo) == -1)
481 file_error (filename);
483 fd = open (filename, O_RDONLY, 0666);
486 file_error (filename);
488 file_size = (size_t)finfo.st_size;
489 buffer = xmalloc (1 + file_size);
491 if ((nr = read (fd, buffer, file_size)) < 0)
492 file_error (filename);
494 /* This is needed on WIN32, and does not hurt on Unix. */
502 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
506 /* Create and fill in the initial structure describing this file. */
507 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
508 defs->filename = filename;
509 defs->lines = array_create (sizeof (char *));
510 defs->line_number = 0;
511 defs->production = (char *)NULL;
512 defs->output = (FILE *)NULL;
513 defs->builtins = (ARRAY *)NULL;
515 /* Build the array of lines. */
517 while (i < file_size)
519 array_add (&buffer[i], defs->lines);
521 while (buffer[i] != '\n' && i < file_size)
526 /* Begin processing the input file. We don't write any output
527 until we have a file to write output to. */
528 output_cpp_line_info = 1;
530 /* Process each line in the array. */
531 for (i = 0; line = defs->lines->array[i]; i++)
533 defs->line_number = i;
539 HANDLER_ENTRY *handler;
541 /* Isolate the directive. */
542 for (j = 0; line[j] && !whitespace (line[j]); j++);
544 directive = xmalloc (j);
545 strncpy (directive, line + 1, j - 1);
546 directive[j -1] = '\0';
548 /* Get the function handler and call it. */
549 handler = find_directive (directive);
553 line_error (defs, "Unknown directive `%s'", directive);
559 /* Advance to the first non-whitespace character. */
560 while (whitespace (line[j]))
563 /* Call the directive handler with the FILE, and ARGS. */
564 (*(handler->function)) (directive, defs, line + j);
570 if (building_builtin)
571 add_documentation (defs, line);
572 else if (defs->output)
574 if (output_cpp_line_info)
576 /* If we're handed an absolute pathname, don't prepend
577 the directory name. */
578 if (defs->filename[0] == '/')
579 fprintf (defs->output, "#line %d \"%s\"\n",
580 defs->line_number + 1, defs->filename);
582 fprintf (defs->output, "#line %d \"%s%s\"\n",
583 defs->line_number + 1,
584 error_directory ? error_directory : "./",
586 output_cpp_line_info = 0;
589 fprintf (defs->output, "%s\n", line);
594 /* Close the production file. */
596 fclose (defs->output);
598 /* The file has been processed. Write the accumulated builtins to
599 the builtins.c file, and write the extern definitions to the
601 write_builtins (defs, structfile, externfile);
607 #define free_safely(x) if (x) free (x)
610 free_builtin (builtin)
611 BUILTIN_DESC *builtin;
615 free_safely (builtin->name);
616 free_safely (builtin->function);
617 free_safely (builtin->shortdoc);
618 free_safely (builtin->docname);
620 if (builtin->longdoc)
621 array_free (builtin->longdoc);
623 if (builtin->dependencies)
625 for (i = 0; builtin->dependencies->array[i]; i++)
626 free (builtin->dependencies->array[i]);
627 array_free (builtin->dependencies);
631 /* Free all of the memory allocated to a DEF_FILE. */
637 register BUILTIN_DESC *builtin;
639 if (defs->production)
640 free (defs->production);
643 array_free (defs->lines);
647 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
649 free_builtin (builtin);
652 array_free (defs->builtins);
657 /* **************************************************************** */
659 /* The Handler Functions Themselves */
661 /* **************************************************************** */
663 /* Strip surrounding whitespace from STRING, and
664 return a pointer to the start of it. */
666 strip_whitespace (string)
669 while (whitespace (*string))
672 remove_trailing_whitespace (string);
676 /* Remove only the trailing whitespace from STRING. */
678 remove_trailing_whitespace (string)
683 i = strlen (string) - 1;
685 while (i > 0 && whitespace (string[i]))
691 /* Ensure that there is a argument in STRING and return it.
692 FOR_WHOM is the name of the directive which needs the argument.
693 DEFS is the DEF_FILE in which the directive is found.
694 If there is no argument, produce an error. */
696 get_arg (for_whom, defs, string)
697 char *for_whom, *string;
702 new = strip_whitespace (string);
705 line_error (defs, "%s requires an argument", for_whom);
707 return (savestring (new));
710 /* Error if not building a builtin. */
712 must_be_building (directive, defs)
716 if (!building_builtin)
717 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
720 /* Return the current builtin. */
722 current_builtin (directive, defs)
726 must_be_building (directive, defs);
728 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
730 return ((BUILTIN_DESC *)NULL);
733 /* Add LINE to the long documentation for the current builtin.
734 Ignore blank lines until the first non-blank line has been seen. */
736 add_documentation (defs, line)
740 register BUILTIN_DESC *builtin;
742 builtin = current_builtin ("(implied LONGDOC)", defs);
744 remove_trailing_whitespace (line);
746 if (!*line && !builtin->longdoc)
749 if (!builtin->longdoc)
750 builtin->longdoc = array_create (sizeof (char *));
752 array_add (line, builtin->longdoc);
755 /* How to handle the $BUILTIN directive. */
757 builtin_handler (self, defs, arg)
765 /* If we are already building a builtin, we cannot start a new one. */
766 if (building_builtin)
768 line_error (defs, "%s found before $END", self);
772 output_cpp_line_info++;
774 /* Get the name of this builtin, and stick it in the array. */
775 name = get_arg (self, defs, arg);
777 /* If this is the first builtin, create the array to hold them. */
779 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
781 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
783 new->function = (char *)NULL;
784 new->shortdoc = (char *)NULL;
785 new->docname = (char *)NULL;
786 new->longdoc = (ARRAY *)NULL;
787 new->dependencies = (ARRAY *)NULL;
790 if (is_special_builtin (name))
791 new->flags |= BUILTIN_FLAG_SPECIAL;
792 if (is_assignment_builtin (name))
793 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
795 array_add ((char *)new, defs->builtins);
796 building_builtin = 1;
801 /* How to handle the $FUNCTION directive. */
803 function_handler (self, defs, arg)
808 register BUILTIN_DESC *builtin;
810 builtin = current_builtin (self, defs);
814 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
817 if (builtin->function)
818 line_error (defs, "%s already has a function (%s)",
819 builtin->name, builtin->function);
821 builtin->function = get_arg (self, defs, arg);
826 /* How to handle the $DOCNAME directive. */
828 docname_handler (self, defs, arg)
833 register BUILTIN_DESC *builtin;
835 builtin = current_builtin (self, defs);
837 if (builtin->docname)
838 line_error (defs, "%s already had a docname (%s)",
839 builtin->name, builtin->docname);
841 builtin->docname = get_arg (self, defs, arg);
846 /* How to handle the $SHORT_DOC directive. */
848 short_doc_handler (self, defs, arg)
853 register BUILTIN_DESC *builtin;
855 builtin = current_builtin (self, defs);
857 if (builtin->shortdoc)
858 line_error (defs, "%s already has short documentation (%s)",
859 builtin->name, builtin->shortdoc);
861 builtin->shortdoc = get_arg (self, defs, arg);
866 /* How to handle the $COMMENT directive. */
868 comment_handler (self, defs, arg)
876 /* How to handle the $DEPENDS_ON directive. */
878 depends_on_handler (self, defs, arg)
883 register BUILTIN_DESC *builtin;
886 builtin = current_builtin (self, defs);
887 dependent = get_arg (self, defs, arg);
889 if (!builtin->dependencies)
890 builtin->dependencies = array_create (sizeof (char *));
892 array_add (dependent, builtin->dependencies);
897 /* How to handle the $PRODUCES directive. */
899 produces_handler (self, defs, arg)
904 /* If just hacking documentation, don't change any of the production
906 if (only_documentation)
909 output_cpp_line_info++;
911 if (defs->production)
912 line_error (defs, "%s already has a %s definition", defs->filename, self);
915 defs->production = get_arg (self, defs, arg);
917 if (inhibit_production)
920 defs->output = fopen (defs->production, "w");
923 file_error (defs->production);
925 fprintf (defs->output, "/* %s, created from %s. */\n",
926 defs->production, defs->filename);
931 /* How to handle the $END directive. */
933 end_handler (self, defs, arg)
938 must_be_building (self, defs);
939 building_builtin = 0;
943 /* **************************************************************** */
945 /* Error Handling Functions */
947 /* **************************************************************** */
949 /* Produce an error for DEFS with FORMAT and ARGS. */
951 line_error (defs, format, arg1, arg2)
953 char *format, *arg1, *arg2;
955 if (defs->filename[0] != '/')
956 fprintf (stderr, "%s", error_directory ? error_directory : "./");
957 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
958 fprintf (stderr, format, arg1, arg2);
959 fprintf (stderr, "\n");
963 /* Print error message for FILENAME. */
965 file_error (filename)
972 /* **************************************************************** */
974 /* xmalloc and xrealloc () */
976 /* **************************************************************** */
978 static void memory_error_and_abort ();
984 char *temp = (char *)malloc (bytes);
987 memory_error_and_abort ();
992 xrealloc (pointer, bytes)
999 temp = (char *)malloc (bytes);
1001 temp = (char *)realloc (pointer, bytes);
1004 memory_error_and_abort ();
1010 memory_error_and_abort ()
1012 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
1016 /* **************************************************************** */
1018 /* Creating the Struct and Extern Files */
1020 /* **************************************************************** */
1022 /* Return a pointer to a newly allocated builtin which is
1023 an exact copy of BUILTIN. */
1025 copy_builtin (builtin)
1026 BUILTIN_DESC *builtin;
1030 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1032 new->name = savestring (builtin->name);
1033 new->shortdoc = savestring (builtin->shortdoc);
1034 new->longdoc = copy_string_array (builtin->longdoc);
1035 new->dependencies = copy_string_array (builtin->dependencies);
1038 builtin->function ? savestring (builtin->function) : (char *)NULL;
1040 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
1045 /* How to save away a builtin. */
1047 save_builtin (builtin)
1048 BUILTIN_DESC *builtin;
1050 BUILTIN_DESC *newbuiltin;
1052 newbuiltin = copy_builtin (builtin);
1054 /* If this is the first builtin to be saved, create the array
1056 if (!saved_builtins)
1057 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1059 array_add ((char *)newbuiltin, saved_builtins);
1062 /* Flags that mean something to write_documentation (). */
1063 #define STRING_ARRAY 0x01
1064 #define TEXINFO 0x02
1065 #define PLAINTEXT 0x04
1066 #define HELPFILE 0x08
1068 char *structfile_header[] = {
1069 "/* builtins.c -- the built in shell commands. */",
1071 "/* This file is manufactured by ./mkbuiltins, and should not be",
1072 " edited by hand. See the source to mkbuiltins for details. */",
1074 "/* Copyright (C) 1987-2002 Free Software Foundation, Inc.",
1076 " This file is part of GNU Bash, the Bourne Again SHell.",
1078 " Bash is free software; you can redistribute it and/or modify it",
1079 " under the terms of the GNU General Public License as published by",
1080 " the Free Software Foundation; either version 2, or (at your option)",
1081 " any later version.",
1083 " Bash is distributed in the hope that it will be useful, but WITHOUT",
1084 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1085 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public",
1086 " License for more details.",
1088 " You should have received a copy of the GNU General Public License",
1089 " along with Bash; see the file COPYING. If not, write to the Free",
1090 " Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */",
1092 "/* The list of shell builtins. Each element is name, function, flags,",
1093 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1094 " of help lines. The function takes a WORD_LIST *; the first word in the",
1095 " list is the first arg to the command. The list has already had word",
1096 " expansion performed.",
1098 " Functions which need to look at only the simple commands (e.g.",
1099 " the enable_builtin ()), should ignore entries where",
1100 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
1101 " the list of shell reserved control structures, like `if' and `while'.",
1102 " The end of the list is denoted with a NULL name field. */",
1104 "#include \"../builtins.h\"",
1108 char *structfile_footer[] = {
1109 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0 }",
1112 "struct builtin *shell_builtins = static_shell_builtins;",
1113 "struct builtin *current_builtin;",
1115 "int num_shell_builtins =",
1116 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1120 /* Write out any neccessary opening information for
1121 STRUCTFILE and EXTERNFILE. */
1123 write_file_headers (structfile, externfile)
1124 FILE *structfile, *externfile;
1130 for (i = 0; structfile_header[i]; i++)
1131 fprintf (structfile, "%s\n", structfile_header[i]);
1133 fprintf (structfile, "#include \"%s\"\n",
1134 extern_filename ? extern_filename : "builtext.h");
1136 fprintf (structfile, "#include \"bashintl.h\"\n");
1138 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1142 fprintf (externfile,
1143 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1144 extern_filename ? extern_filename : "builtext.h");
1147 /* Write out any necessary closing information for
1148 STRUCTFILE and EXTERNFILE. */
1150 write_file_footers (structfile, externfile)
1151 FILE *structfile, *externfile;
1155 /* Write out the footers. */
1158 for (i = 0; structfile_footer[i]; i++)
1159 fprintf (structfile, "%s\n", structfile_footer[i]);
1163 /* Write out the information accumulated in DEFS to
1164 STRUCTFILE and EXTERNFILE. */
1166 write_builtins (defs, structfile, externfile)
1168 FILE *structfile, *externfile;
1172 /* Write out the information. */
1175 register BUILTIN_DESC *builtin;
1177 for (i = 0; i < defs->builtins->sindex; i++)
1179 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1181 /* Write out any #ifdefs that may be there. */
1182 if (!only_documentation)
1184 if (builtin->dependencies)
1186 write_ifdefs (externfile, builtin->dependencies->array);
1187 write_ifdefs (structfile, builtin->dependencies->array);
1190 /* Write the extern definition. */
1193 if (builtin->function)
1194 fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
1197 fprintf (externfile, "extern char * const %s_doc[];\n",
1198 document_name (builtin));
1201 /* Write the structure definition. */
1204 fprintf (structfile, " { \"%s\", ", builtin->name);
1206 if (builtin->function)
1207 fprintf (structfile, "%s, ", builtin->function);
1209 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
1211 fprintf (structfile, "%s%s%s, %s_doc,\n",
1212 "BUILTIN_ENABLED | STATIC_BUILTIN",
1213 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1214 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1215 document_name (builtin));
1218 (structfile, " \"%s\", (char *)NULL },\n",
1219 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1223 if (structfile || separate_helpfiles)
1224 /* Save away this builtin for later writing of the
1225 long documentation strings. */
1226 save_builtin (builtin);
1228 /* Write out the matching #endif, if neccessary. */
1229 if (builtin->dependencies)
1232 write_endifs (externfile, builtin->dependencies->array);
1235 write_endifs (structfile, builtin->dependencies->array);
1239 if (documentation_file)
1241 fprintf (documentation_file, "@item %s\n", builtin->name);
1243 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1249 /* Write out the long documentation strings in BUILTINS to STREAM. */
1251 write_longdocs (stream, builtins)
1256 register BUILTIN_DESC *builtin;
1260 for (i = 0; i < builtins->sindex; i++)
1262 builtin = (BUILTIN_DESC *)builtins->array[i];
1264 if (builtin->dependencies)
1265 write_ifdefs (stream, builtin->dependencies->array);
1267 /* Write the long documentation strings. */
1268 dname = document_name (builtin);
1269 fprintf (stream, "char * const %s_doc[] =", dname);
1271 if (separate_helpfiles)
1273 int l = strlen (helpfile_directory) + strlen (dname) + 1;
1274 sarray[0] = (char *)xmalloc (l + 1);
1275 sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
1276 sarray[1] = (char *)NULL;
1277 write_documentation (stream, sarray, 0, STRING_ARRAY|HELPFILE);
1281 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1283 if (builtin->dependencies)
1284 write_endifs (stream, builtin->dependencies->array);
1289 /* Write an #ifdef string saying what needs to be defined (or not defined)
1290 in order to allow compilation of the code that will follow.
1291 STREAM is the stream to write the information to,
1292 DEFINES is a null terminated array of define names.
1293 If a define is preceded by an `!', then the sense of the test is
1296 write_ifdefs (stream, defines)
1305 fprintf (stream, "#if ");
1307 for (i = 0; defines[i]; i++)
1309 char *def = defines[i];
1312 fprintf (stream, "!defined (%s)", def + 1);
1314 fprintf (stream, "defined (%s)", def);
1317 fprintf (stream, " && ");
1319 fprintf (stream, "\n");
1322 /* Write an #endif string saying what defines controlled the compilation
1323 of the immediately preceding code.
1324 STREAM is the stream to write the information to.
1325 DEFINES is a null terminated array of define names. */
1327 write_endifs (stream, defines)
1336 fprintf (stream, "#endif /* ");
1338 for (i = 0; defines[i]; i++)
1340 fprintf (stream, "%s", defines[i]);
1343 fprintf (stream, " && ");
1346 fprintf (stream, " */\n");
1349 /* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
1350 and quoting special characters in the string. Handle special things for
1351 internationalization (gettext) and the single-string vs. multiple-strings
1354 write_documentation (stream, documentation, indentation, flags)
1356 char **documentation;
1357 int indentation, flags;
1360 register char *line;
1361 int string_array, texinfo, base_indent, last_cpp, filename_p;
1366 string_array = flags & STRING_ARRAY;
1367 filename_p = flags & HELPFILE;
1371 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n"); /* } */
1372 if (single_longdoc_strings)
1374 if (filename_p == 0)
1375 fprintf (stream, "N_(\" "); /* the empty string translates specially. */
1377 fprintf (stream, "\"");
1381 base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
1383 for (i = last_cpp = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1385 /* Allow #ifdef's to be written out verbatim, but don't put them into
1386 separate help files. */
1389 if (string_array && filename_p == 0 && single_longdoc_strings == 0)
1390 fprintf (stream, "%s\n", line);
1397 /* prefix with N_( for gettext */
1398 if (string_array && single_longdoc_strings == 0)
1400 if (filename_p == 0)
1401 fprintf (stream, " N_(\" "); /* the empty string translates specially. */
1403 fprintf (stream, " \"");
1407 for (j = 0; j < indentation; j++)
1408 fprintf (stream, " ");
1410 /* Don't indent the first line, because of how the help builtin works. */
1412 indentation += base_indent;
1416 for (j = 0; line[j]; j++)
1422 fprintf (stream, "\\%c", line[j]);
1426 fprintf (stream, "%c", line[j]);
1430 /* closing right paren for gettext */
1431 if (single_longdoc_strings == 0)
1433 if (filename_p == 0)
1434 fprintf (stream, "\"),\n");
1436 fprintf (stream, "\",\n");
1438 else if (documentation[i+1])
1439 /* don't add extra newline after last line */
1440 fprintf (stream, "\\n\\\n");
1444 for (j = 0; line[j]; j++)
1451 fprintf (stream, "@%c", line[j]);
1455 fprintf (stream, "%c", line[j]);
1458 fprintf (stream, "\n");
1461 fprintf (stream, "%s\n", line);
1464 /* closing right paren for gettext */
1465 if (string_array && single_longdoc_strings)
1467 if (filename_p == 0)
1468 fprintf (stream, "\"),\n");
1470 fprintf (stream, "\",\n");
1474 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1478 write_helpfiles (builtins)
1481 char *helpfile, *bname;
1484 BUILTIN_DESC *builtin;
1486 i = mkdir ("helpfiles", 0777);
1487 if (i < 0 && errno != EEXIST)
1489 fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
1493 hdlen = strlen ("helpfiles/");
1494 for (i = 0; i < builtins->sindex; i++)
1496 builtin = (BUILTIN_DESC *)builtins->array[i];
1498 bname = document_name (builtin);
1499 helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
1500 sprintf (helpfile, "helpfiles/%s", bname);
1502 helpfp = fopen (helpfile, "w");
1505 fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
1510 write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
1520 _find_in_table (name, name_table)
1521 char *name, *name_table[];
1525 for (i = 0; name_table[i]; i++)
1526 if (strcmp (name, name_table[i]) == 0)
1532 is_special_builtin (name)
1535 return (_find_in_table (name, special_builtins));
1539 is_assignment_builtin (name)
1542 return (_find_in_table (name, assignment_builtins));
1545 #if !defined (HAVE_RENAME)
1551 if (link (from, to) < 0)
1556 #endif /* !HAVE_RENAME */