improve of cmpl.
[bush.git] / builtins / mkbuiltins.c
blob9f5de88c51caf3af95e33f184e24507aa0d92411
1 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
4 /* Copyright (C) 1987-2020 Free Software Foundation, Inc.
6 This file is part of GNU Bush, the Bourne Again SHell.
8 Bush 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 Bush 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 Bush. If not, see <http://www.gnu.org/licenses/>.
22 #if !defined (CROSS_COMPILING)
23 # include <config.h>
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
30 # define HAVE_RENAME
31 #endif /* CROSS_COMPILING */
33 #if defined (HAVE_UNISTD_H)
34 # ifdef _MINIX
35 # include <sys/types.h>
36 # endif
37 # include <unistd.h>
38 #endif
40 #ifndef _MINIX
41 # include "../src/bushtypes.h"
42 # if defined (HAVE_SYS_FILE_H)
43 # include <sys/file.h>
44 # endif
45 #endif
47 #include "posixstat.h"
48 #include "filecntl.h"
50 #include "../src/bushansi.h"
51 #include <stdio.h>
52 #include <errno.h>
54 #include "stdc.h"
56 #define DOCFILE "builtins.texi"
58 #ifndef errno
59 extern int errno;
60 #endif
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_LOCALVAR 0x04
75 #define BUILTIN_FLAG_POSIX_BUILTIN 0x08
77 #define BASE_INDENT 4
79 /* If this stream descriptor is non-zero, then write
80 texinfo documentation to it. */
81 FILE *documentation_file = (FILE *)NULL;
83 /* Non-zero means to only produce documentation. */
84 int only_documentation = 0;
86 /* Non-zero means to not do any productions. */
87 int inhibit_production = 0;
89 /* Non-zero means to not add functions (xxx_builtin) to the members of the
90 produced `struct builtin []' */
91 int inhibit_functions = 0;
93 /* Non-zero means to produce separate help files for each builtin, named by
94 the builtin name, in `./helpfiles'. */
95 int separate_helpfiles = 0;
97 /* Non-zero means to create single C strings for each `longdoc', with
98 embedded newlines, for ease of translation. */
99 int single_longdoc_strings = 1;
101 /* The name of a directory into which the separate external help files will
102 eventually be installed. */
103 char *helpfile_directory;
105 /* The name of a directory to precede the filename when reporting
106 errors. */
107 char *error_directory = (char *)NULL;
109 /* The name of the structure file. */
110 char *struct_filename = (char *)NULL;
112 /* The name of the external declaration file. */
113 char *extern_filename = (char *)NULL;
115 /* Here is a structure for manipulating arrays of data. */
116 typedef struct {
117 int size; /* Number of slots allocated to array. */
118 int sindex; /* Current location in array. */
119 int width; /* Size of each element. */
120 int growth_rate; /* How fast to grow. */
121 char **array; /* The array itself. */
122 } ARRAY;
124 /* Here is a structure defining a single BUILTIN. */
125 typedef struct {
126 char *name; /* The name of this builtin. */
127 char *function; /* The name of the function to call. */
128 char *shortdoc; /* The short documentation for this builtin. */
129 char *docname; /* Possible name for documentation string. */
130 ARRAY *longdoc; /* The long documentation for this builtin. */
131 ARRAY *dependencies; /* Null terminated array of #define names. */
132 int flags; /* Flags for this builtin. */
133 } BUILTIN_DESC;
135 /* Here is a structure which defines a DEF file. */
136 typedef struct {
137 char *filename; /* The name of the input def file. */
138 ARRAY *lines; /* The contents of the file. */
139 int line_number; /* The current line number. */
140 char *production; /* The name of the production file. */
141 FILE *output; /* Open file stream for PRODUCTION. */
142 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
143 } DEF_FILE;
145 /* The array of all builtins encountered during execution of this code. */
146 ARRAY *saved_builtins = (ARRAY *)NULL;
148 /* The Posix.2 so-called `special' builtins. */
149 char *special_builtins[] =
151 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
152 "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
153 (char *)NULL
156 /* The builtin commands that take assignment statements as arguments. */
157 char *assignment_builtins[] =
159 "alias", "declare", "export", "local", "readonly", "typeset",
160 (char *)NULL
163 char *localvar_builtins[] =
165 "declare", "local", "typeset", (char *)NULL
168 /* The builtin commands that are special to the POSIX search order. */
169 char *posix_builtins[] =
171 "alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "jobs",
172 "kill", "newgrp", "pwd", "read", "true", "umask", "unalias", "wait",
173 (char *)NULL
176 /* Forward declarations. */
177 static int is_special_builtin ();
178 static int is_assignment_builtin ();
179 static int is_localvar_builtin ();
180 static int is_posix_builtin ();
182 #if !defined (HAVE_RENAME)
183 static int rename ();
184 #endif
186 void extract_info ();
188 void file_error ();
189 void line_error ();
191 void write_file_headers ();
192 void write_file_footers ();
193 void write_ifdefs ();
194 void write_endifs ();
195 void write_documentation ();
196 void write_longdocs ();
197 void write_builtins ();
199 int write_helpfiles ();
201 void free_defs ();
202 void add_documentation ();
204 void must_be_building ();
205 void remove_trailing_whitespace ();
207 #define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
210 /* For each file mentioned on the command line, process it and
211 write the information to STRUCTFILE and EXTERNFILE, while
212 creating the production file if necessary. */
214 main (argc, argv)
215 int argc;
216 char **argv;
218 int arg_index = 1;
219 FILE *structfile, *externfile;
220 char *documentation_filename, *temp_struct_filename;
222 structfile = externfile = (FILE *)NULL;
223 documentation_filename = DOCFILE;
224 temp_struct_filename = (char *)NULL;
226 while (arg_index < argc && argv[arg_index][0] == '-')
228 char *arg = argv[arg_index++];
230 if (strcmp (arg, "-externfile") == 0)
231 extern_filename = argv[arg_index++];
232 else if (strcmp (arg, "-structfile") == 0)
233 struct_filename = argv[arg_index++];
234 else if (strcmp (arg, "-noproduction") == 0)
235 inhibit_production = 1;
236 else if (strcmp (arg, "-nofunctions") == 0)
237 inhibit_functions = 1;
238 else if (strcmp (arg, "-document") == 0)
239 documentation_file = fopen (documentation_filename, "w");
240 else if (strcmp (arg, "-D") == 0)
242 int len;
244 if (error_directory)
245 free (error_directory);
247 error_directory = xmalloc (2 + strlen (argv[arg_index]));
248 strcpy (error_directory, argv[arg_index]);
249 len = strlen (error_directory);
251 if (len && error_directory[len - 1] != '/')
252 strcat (error_directory, "/");
254 arg_index++;
256 else if (strcmp (arg, "-documentonly") == 0)
258 only_documentation = 1;
259 documentation_file = fopen (documentation_filename, "w");
261 else if (strcmp (arg, "-H") == 0)
263 separate_helpfiles = 1;
264 helpfile_directory = argv[arg_index++];
266 else if (strcmp (arg, "-S") == 0)
267 single_longdoc_strings = 0;
268 else
270 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
271 exit (2);
275 /* If there are no files to process, just quit now. */
276 if (arg_index == argc)
277 exit (0);
279 if (!only_documentation)
281 /* Open the files. */
282 if (struct_filename)
284 temp_struct_filename = xmalloc (15);
285 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
286 structfile = fopen (temp_struct_filename, "w");
288 if (!structfile)
289 file_error (temp_struct_filename);
292 if (extern_filename)
294 externfile = fopen (extern_filename, "w");
296 if (!externfile)
297 file_error (extern_filename);
300 /* Write out the headers. */
301 write_file_headers (structfile, externfile);
304 if (documentation_file)
306 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
307 argv[0]);
308 fprintf (documentation_file, "@ftable @asis\n");
311 /* Process the .def files. */
312 while (arg_index < argc)
314 register char *arg;
316 arg = argv[arg_index++];
318 extract_info (arg, structfile, externfile);
321 /* Close the files. */
322 if (!only_documentation)
324 /* Write the footers. */
325 write_file_footers (structfile, externfile);
327 if (structfile)
329 write_longdocs (structfile, saved_builtins);
330 fclose (structfile);
331 rename (temp_struct_filename, struct_filename);
334 if (externfile)
335 fclose (externfile);
338 #if 0
339 /* This is now done by a different program */
340 if (separate_helpfiles)
342 write_helpfiles (saved_builtins);
344 #endif
346 if (documentation_file)
348 fprintf (documentation_file, "@end ftable\n");
349 fclose (documentation_file);
352 exit (0);
355 /* **************************************************************** */
356 /* */
357 /* Array Functions and Manipulators */
358 /* */
359 /* **************************************************************** */
361 /* Make a new array, and return a pointer to it. The array will
362 contain elements of size WIDTH, and is initialized to no elements. */
363 ARRAY *
364 array_create (width)
365 int width;
367 ARRAY *array;
369 array = (ARRAY *)xmalloc (sizeof (ARRAY));
370 array->size = 0;
371 array->sindex = 0;
372 array->width = width;
374 /* Default to increasing size in units of 20. */
375 array->growth_rate = 20;
377 array->array = (char **)NULL;
379 return (array);
382 /* Copy the array of strings in ARRAY. */
383 ARRAY *
384 copy_string_array (array)
385 ARRAY *array;
387 register int i;
388 ARRAY *copy;
390 if (!array)
391 return (ARRAY *)NULL;
393 copy = array_create (sizeof (char *));
395 copy->size = array->size;
396 copy->sindex = array->sindex;
397 copy->width = array->width;
399 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
401 for (i = 0; i < array->sindex; i++)
402 copy->array[i] = savestring (array->array[i]);
404 copy->array[i] = (char *)NULL;
406 return (copy);
409 /* Add ELEMENT to ARRAY, growing the array if necessary. */
410 void
411 array_add (element, array)
412 char *element;
413 ARRAY *array;
415 if (array->sindex + 2 > array->size)
416 array->array = (char **)xrealloc
417 (array->array, (array->size += array->growth_rate) * array->width);
419 array->array[array->sindex++] = element;
420 array->array[array->sindex] = (char *)NULL;
423 /* Free an allocated array and data pointer. */
424 void
425 array_free (array)
426 ARRAY *array;
428 if (array->array)
429 free (array->array);
431 free (array);
434 /* **************************************************************** */
435 /* */
436 /* Processing a DEF File */
437 /* */
438 /* **************************************************************** */
440 /* The definition of a function. */
441 typedef int Function ();
442 typedef int mk_handler_func_t PARAMS((char *, DEF_FILE *, char *));
444 /* Structure handles processor directives. */
445 typedef struct {
446 char *directive;
447 mk_handler_func_t *function;
448 } HANDLER_ENTRY;
450 extern int builtin_handler PARAMS((char *, DEF_FILE *, char *));
451 extern int function_handler PARAMS((char *, DEF_FILE *, char *));
452 extern int short_doc_handler PARAMS((char *, DEF_FILE *, char *));
453 extern int comment_handler PARAMS((char *, DEF_FILE *, char *));
454 extern int depends_on_handler PARAMS((char *, DEF_FILE *, char *));
455 extern int produces_handler PARAMS((char *, DEF_FILE *, char *));
456 extern int end_handler PARAMS((char *, DEF_FILE *, char *));
457 extern int docname_handler PARAMS((char *, DEF_FILE *, char *));
459 HANDLER_ENTRY handlers[] = {
460 { "BUILTIN", builtin_handler },
461 { "DOCNAME", docname_handler },
462 { "FUNCTION", function_handler },
463 { "SHORT_DOC", short_doc_handler },
464 { "$", comment_handler },
465 { "COMMENT", comment_handler },
466 { "DEPENDS_ON", depends_on_handler },
467 { "PRODUCES", produces_handler },
468 { "END", end_handler },
469 { (char *)NULL, (mk_handler_func_t *)NULL }
472 /* Return the entry in the table of handlers for NAME. */
473 HANDLER_ENTRY *
474 find_directive (directive)
475 char *directive;
477 register int i;
479 for (i = 0; handlers[i].directive; i++)
480 if (strcmp (handlers[i].directive, directive) == 0)
481 return (&handlers[i]);
483 return ((HANDLER_ENTRY *)NULL);
486 /* Non-zero indicates that a $BUILTIN has been seen, but not
487 the corresponding $END. */
488 static int building_builtin = 0;
490 /* Non-zero means to output cpp line and file information before
491 printing the current line to the production file. */
492 int output_cpp_line_info = 0;
494 /* The main function of this program. Read FILENAME and act on what is
495 found. Lines not starting with a dollar sign are copied to the
496 $PRODUCES target, if one is present. Lines starting with a dollar sign
497 are directives to this program, specifying the name of the builtin, the
498 function to call, the short documentation and the long documentation
499 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
500 target. After the file has been processed, write out the names of
501 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
502 is ignored, as is "$$ comment text". */
503 void
504 extract_info (filename, structfile, externfile)
505 char *filename;
506 FILE *structfile, *externfile;
508 register int i;
509 DEF_FILE *defs;
510 struct stat finfo;
511 size_t file_size;
512 char *buffer, *line;
513 int fd, nr;
515 if (stat (filename, &finfo) == -1)
516 file_error (filename);
518 fd = open (filename, O_RDONLY, 0666);
520 if (fd == -1)
521 file_error (filename);
523 file_size = (size_t)finfo.st_size;
524 buffer = xmalloc (1 + file_size);
526 if ((nr = read (fd, buffer, file_size)) < 0)
527 file_error (filename);
529 /* This is needed on WIN32, and does not hurt on Unix. */
530 if (nr < file_size)
531 file_size = nr;
533 close (fd);
535 if (nr == 0)
537 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
538 free (buffer);
539 return;
542 /* Create and fill in the initial structure describing this file. */
543 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
544 defs->filename = filename;
545 defs->lines = array_create (sizeof (char *));
546 defs->line_number = 0;
547 defs->production = (char *)NULL;
548 defs->output = (FILE *)NULL;
549 defs->builtins = (ARRAY *)NULL;
551 /* Build the array of lines. */
552 i = 0;
553 while (i < file_size)
555 array_add (&buffer[i], defs->lines);
557 while (i < file_size && buffer[i] != '\n')
558 i++;
559 buffer[i++] = '\0';
562 /* Begin processing the input file. We don't write any output
563 until we have a file to write output to. */
564 output_cpp_line_info = 1;
566 /* Process each line in the array. */
567 for (i = 0; line = defs->lines->array[i]; i++)
569 defs->line_number = i;
571 if (*line == '$')
573 register int j;
574 char *directive;
575 HANDLER_ENTRY *handler;
577 /* Isolate the directive. */
578 for (j = 0; line[j] && !whitespace (line[j]); j++);
580 directive = xmalloc (j);
581 strncpy (directive, line + 1, j - 1);
582 directive[j -1] = '\0';
584 /* Get the function handler and call it. */
585 handler = find_directive (directive);
587 if (!handler)
589 line_error (defs, "Unknown directive `%s'", directive);
590 free (directive);
591 continue;
593 else
595 /* Advance to the first non-whitespace character. */
596 while (whitespace (line[j]))
597 j++;
599 /* Call the directive handler with the FILE, and ARGS. */
600 (*(handler->function)) (directive, defs, line + j);
602 free (directive);
604 else
606 if (building_builtin)
607 add_documentation (defs, line);
608 else if (defs->output)
610 if (output_cpp_line_info)
612 /* If we're handed an absolute pathname, don't prepend
613 the directory name. */
614 if (defs->filename[0] == '/')
615 fprintf (defs->output, "#line %d \"%s\"\n",
616 defs->line_number + 1, defs->filename);
617 else
618 fprintf (defs->output, "#line %d \"%s%s\"\n",
619 defs->line_number + 1,
620 error_directory ? error_directory : "./",
621 defs->filename);
622 output_cpp_line_info = 0;
625 fprintf (defs->output, "%s\n", line);
630 /* Close the production file. */
631 if (defs->output)
632 fclose (defs->output);
634 /* The file has been processed. Write the accumulated builtins to
635 the builtins.c file, and write the extern definitions to the
636 builtext.h file. */
637 write_builtins (defs, structfile, externfile);
639 free (buffer);
640 free_defs (defs);
643 #define free_safely(x) if (x) free (x)
645 static void
646 free_builtin (builtin)
647 BUILTIN_DESC *builtin;
649 register int i;
651 free_safely (builtin->name);
652 free_safely (builtin->function);
653 free_safely (builtin->shortdoc);
654 free_safely (builtin->docname);
656 if (builtin->longdoc)
657 array_free (builtin->longdoc);
659 if (builtin->dependencies)
661 for (i = 0; builtin->dependencies->array[i]; i++)
662 free (builtin->dependencies->array[i]);
663 array_free (builtin->dependencies);
667 /* Free all of the memory allocated to a DEF_FILE. */
668 void
669 free_defs (defs)
670 DEF_FILE *defs;
672 register int i;
673 register BUILTIN_DESC *builtin;
675 if (defs->production)
676 free (defs->production);
678 if (defs->lines)
679 array_free (defs->lines);
681 if (defs->builtins)
683 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
685 free_builtin (builtin);
686 free (builtin);
688 array_free (defs->builtins);
690 free (defs);
693 /* **************************************************************** */
694 /* */
695 /* The Handler Functions Themselves */
696 /* */
697 /* **************************************************************** */
699 /* Strip surrounding whitespace from STRING, and
700 return a pointer to the start of it. */
701 char *
702 strip_whitespace (string)
703 char *string;
705 while (whitespace (*string))
706 string++;
708 remove_trailing_whitespace (string);
709 return (string);
712 /* Remove only the trailing whitespace from STRING. */
713 void
714 remove_trailing_whitespace (string)
715 char *string;
717 register int i;
719 i = strlen (string) - 1;
721 while (i > 0 && whitespace (string[i]))
722 i--;
724 string[++i] = '\0';
727 /* Ensure that there is a argument in STRING and return it.
728 FOR_WHOM is the name of the directive which needs the argument.
729 DEFS is the DEF_FILE in which the directive is found.
730 If there is no argument, produce an error. */
731 char *
732 get_arg (for_whom, defs, string)
733 char *for_whom, *string;
734 DEF_FILE *defs;
736 char *new;
738 new = strip_whitespace (string);
740 if (!*new)
741 line_error (defs, "%s requires an argument", for_whom);
743 return (savestring (new));
746 /* Error if not building a builtin. */
747 void
748 must_be_building (directive, defs)
749 char *directive;
750 DEF_FILE *defs;
752 if (!building_builtin)
753 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
756 /* Return the current builtin. */
757 BUILTIN_DESC *
758 current_builtin (directive, defs)
759 char *directive;
760 DEF_FILE *defs;
762 must_be_building (directive, defs);
763 if (defs->builtins)
764 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
765 else
766 return ((BUILTIN_DESC *)NULL);
769 /* Add LINE to the long documentation for the current builtin.
770 Ignore blank lines until the first non-blank line has been seen. */
771 void
772 add_documentation (defs, line)
773 DEF_FILE *defs;
774 char *line;
776 register BUILTIN_DESC *builtin;
778 builtin = current_builtin ("(implied LONGDOC)", defs);
780 remove_trailing_whitespace (line);
782 if (!*line && !builtin->longdoc)
783 return;
785 if (!builtin->longdoc)
786 builtin->longdoc = array_create (sizeof (char *));
788 array_add (line, builtin->longdoc);
791 /* How to handle the $BUILTIN directive. */
793 builtin_handler (self, defs, arg)
794 char *self;
795 DEF_FILE *defs;
796 char *arg;
798 BUILTIN_DESC *new;
799 char *name;
801 /* If we are already building a builtin, we cannot start a new one. */
802 if (building_builtin)
804 line_error (defs, "%s found before $END", self);
805 return (-1);
808 output_cpp_line_info++;
810 /* Get the name of this builtin, and stick it in the array. */
811 name = get_arg (self, defs, arg);
813 /* If this is the first builtin, create the array to hold them. */
814 if (!defs->builtins)
815 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
817 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
818 new->name = name;
819 new->function = (char *)NULL;
820 new->shortdoc = (char *)NULL;
821 new->docname = (char *)NULL;
822 new->longdoc = (ARRAY *)NULL;
823 new->dependencies = (ARRAY *)NULL;
824 new->flags = 0;
826 if (is_special_builtin (name))
827 new->flags |= BUILTIN_FLAG_SPECIAL;
828 if (is_assignment_builtin (name))
829 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
830 if (is_localvar_builtin (name))
831 new->flags |= BUILTIN_FLAG_LOCALVAR;
832 if (is_posix_builtin (name))
833 new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
835 array_add ((char *)new, defs->builtins);
836 building_builtin = 1;
838 return (0);
841 /* How to handle the $FUNCTION directive. */
843 function_handler (self, defs, arg)
844 char *self;
845 DEF_FILE *defs;
846 char *arg;
848 register BUILTIN_DESC *builtin;
850 builtin = current_builtin (self, defs);
852 if (builtin == 0)
854 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
855 exit (1);
857 if (builtin->function)
858 line_error (defs, "%s already has a function (%s)",
859 builtin->name, builtin->function);
860 else
861 builtin->function = get_arg (self, defs, arg);
863 return (0);
866 /* How to handle the $DOCNAME directive. */
868 docname_handler (self, defs, arg)
869 char *self;
870 DEF_FILE *defs;
871 char *arg;
873 register BUILTIN_DESC *builtin;
875 builtin = current_builtin (self, defs);
877 if (builtin->docname)
878 line_error (defs, "%s already had a docname (%s)",
879 builtin->name, builtin->docname);
880 else
881 builtin->docname = get_arg (self, defs, arg);
883 return (0);
886 /* How to handle the $SHORT_DOC directive. */
888 short_doc_handler (self, defs, arg)
889 char *self;
890 DEF_FILE *defs;
891 char *arg;
893 register BUILTIN_DESC *builtin;
895 builtin = current_builtin (self, defs);
897 if (builtin->shortdoc)
898 line_error (defs, "%s already has short documentation (%s)",
899 builtin->name, builtin->shortdoc);
900 else
901 builtin->shortdoc = get_arg (self, defs, arg);
903 return (0);
906 /* How to handle the $COMMENT directive. */
908 comment_handler (self, defs, arg)
909 char *self;
910 DEF_FILE *defs;
911 char *arg;
913 return (0);
916 /* How to handle the $DEPENDS_ON directive. */
918 depends_on_handler (self, defs, arg)
919 char *self;
920 DEF_FILE *defs;
921 char *arg;
923 register BUILTIN_DESC *builtin;
924 char *dependent;
926 builtin = current_builtin (self, defs);
927 dependent = get_arg (self, defs, arg);
929 if (!builtin->dependencies)
930 builtin->dependencies = array_create (sizeof (char *));
932 array_add (dependent, builtin->dependencies);
934 return (0);
937 /* How to handle the $PRODUCES directive. */
939 produces_handler (self, defs, arg)
940 char *self;
941 DEF_FILE *defs;
942 char *arg;
944 /* If just hacking documentation, don't change any of the production
945 files. */
946 if (only_documentation)
947 return (0);
949 output_cpp_line_info++;
951 if (defs->production)
952 line_error (defs, "%s already has a %s definition", defs->filename, self);
953 else
955 defs->production = get_arg (self, defs, arg);
957 if (inhibit_production)
958 return (0);
960 defs->output = fopen (defs->production, "w");
962 if (!defs->output)
963 file_error (defs->production);
965 fprintf (defs->output, "/* %s, created from %s. */\n",
966 defs->production, defs->filename);
968 return (0);
971 /* How to handle the $END directive. */
973 end_handler (self, defs, arg)
974 char *self;
975 DEF_FILE *defs;
976 char *arg;
978 must_be_building (self, defs);
979 building_builtin = 0;
980 return (0);
983 /* **************************************************************** */
984 /* */
985 /* Error Handling Functions */
986 /* */
987 /* **************************************************************** */
989 /* Produce an error for DEFS with FORMAT and ARGS. */
990 void
991 line_error (defs, format, arg1, arg2)
992 DEF_FILE *defs;
993 char *format, *arg1, *arg2;
995 if (defs->filename[0] != '/')
996 fprintf (stderr, "%s", error_directory ? error_directory : "./");
997 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
998 fprintf (stderr, format, arg1, arg2);
999 fprintf (stderr, "\n");
1000 fflush (stderr);
1003 /* Print error message for FILENAME. */
1004 void
1005 file_error (filename)
1006 char *filename;
1008 perror (filename);
1009 exit (2);
1012 /* **************************************************************** */
1013 /* */
1014 /* xmalloc and xrealloc () */
1015 /* */
1016 /* **************************************************************** */
1018 static void memory_error_and_abort ();
1020 static char *
1021 xmalloc (bytes)
1022 int bytes;
1024 char *temp = (char *)malloc (bytes);
1026 if (!temp)
1027 memory_error_and_abort ();
1028 return (temp);
1031 static char *
1032 xrealloc (pointer, bytes)
1033 char *pointer;
1034 int bytes;
1036 char *temp;
1038 if (!pointer)
1039 temp = (char *)malloc (bytes);
1040 else
1041 temp = (char *)realloc (pointer, bytes);
1043 if (!temp)
1044 memory_error_and_abort ();
1046 return (temp);
1049 static void
1050 memory_error_and_abort ()
1052 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
1053 abort ();
1056 /* **************************************************************** */
1057 /* */
1058 /* Creating the Struct and Extern Files */
1059 /* */
1060 /* **************************************************************** */
1062 /* Return a pointer to a newly allocated builtin which is
1063 an exact copy of BUILTIN. */
1064 BUILTIN_DESC *
1065 copy_builtin (builtin)
1066 BUILTIN_DESC *builtin;
1068 BUILTIN_DESC *new;
1070 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1072 new->name = savestring (builtin->name);
1073 new->shortdoc = savestring (builtin->shortdoc);
1074 new->longdoc = copy_string_array (builtin->longdoc);
1075 new->dependencies = copy_string_array (builtin->dependencies);
1077 new->function =
1078 builtin->function ? savestring (builtin->function) : (char *)NULL;
1079 new->docname =
1080 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
1082 return (new);
1085 /* How to save away a builtin. */
1086 void
1087 save_builtin (builtin)
1088 BUILTIN_DESC *builtin;
1090 BUILTIN_DESC *newbuiltin;
1092 newbuiltin = copy_builtin (builtin);
1094 /* If this is the first builtin to be saved, create the array
1095 to hold it. */
1096 if (!saved_builtins)
1097 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1099 array_add ((char *)newbuiltin, saved_builtins);
1102 /* Flags that mean something to write_documentation (). */
1103 #define STRING_ARRAY 0x01
1104 #define TEXINFO 0x02
1105 #define PLAINTEXT 0x04
1106 #define HELPFILE 0x08
1108 char *structfile_header[] = {
1109 "/* builtins.c -- the built in shell commands. */",
1111 "/* This file is manufactured by ./mkbuiltins, and should not be",
1112 " edited by hand. See the source to mkbuiltins for details. */",
1114 "/* Copyright (C) 1987-2015 Free Software Foundation, Inc.",
1116 " This file is part of GNU Bush, the Bourne Again SHell.",
1118 " Bush is free software: you can redistribute it and/or modify",
1119 " it under the terms of the GNU General Public License as published by",
1120 " the Free Software Foundation, either version 3 of the License, or",
1121 " (at your option) any later version.",
1123 " Bush is distributed in the hope that it will be useful,",
1124 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
1125 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
1126 " GNU General Public License for more details.",
1128 " You should have received a copy of the GNU General Public License",
1129 " along with Bush. If not, see <http://www.gnu.org/licenses/>.",
1130 "*/",
1132 "/* The list of shell builtins. Each element is name, function, flags,",
1133 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1134 " of help lines. The function takes a WORD_LIST *; the first word in the",
1135 " list is the first arg to the command. The list has already had word",
1136 " expansion performed.",
1138 " Functions which need to look at only the simple commands (e.g.",
1139 " the enable_builtin ()), should ignore entries where",
1140 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
1141 " the list of shell reserved control structures, like `if' and `while'.",
1142 " The end of the list is denoted with a NULL name field. */",
1144 "/* TRANSLATORS: Please do not translate command names in descriptions */",
1146 "#include \"../src/builtins.h\"",
1147 (char *)NULL
1150 char *structfile_footer[] = {
1151 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0, (char *)0x0 }",
1152 "};",
1154 "struct builtin *shell_builtins = static_shell_builtins;",
1155 "struct builtin *current_builtin;",
1157 "int num_shell_builtins =",
1158 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1159 (char *)NULL
1162 /* Write out any necessary opening information for
1163 STRUCTFILE and EXTERNFILE. */
1164 void
1165 write_file_headers (structfile, externfile)
1166 FILE *structfile, *externfile;
1168 register int i;
1170 if (structfile)
1172 for (i = 0; structfile_header[i]; i++)
1173 fprintf (structfile, "%s\n", structfile_header[i]);
1175 fprintf (structfile, "#include \"%s\"\n",
1176 extern_filename ? extern_filename : "builtext.h");
1178 fprintf (structfile, "#include \"src/bushintl.h\"\n");
1180 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1183 if (externfile)
1184 fprintf (externfile,
1185 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1186 extern_filename ? extern_filename : "builtext.h");
1189 /* Write out any necessary closing information for
1190 STRUCTFILE and EXTERNFILE. */
1191 void
1192 write_file_footers (structfile, externfile)
1193 FILE *structfile, *externfile;
1195 register int i;
1197 /* Write out the footers. */
1198 if (structfile)
1200 for (i = 0; structfile_footer[i]; i++)
1201 fprintf (structfile, "%s\n", structfile_footer[i]);
1205 /* Write out the information accumulated in DEFS to
1206 STRUCTFILE and EXTERNFILE. */
1207 void
1208 write_builtins (defs, structfile, externfile)
1209 DEF_FILE *defs;
1210 FILE *structfile, *externfile;
1212 register int i;
1214 /* Write out the information. */
1215 if (defs->builtins)
1217 register BUILTIN_DESC *builtin;
1219 for (i = 0; i < defs->builtins->sindex; i++)
1221 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1223 /* Write out any #ifdefs that may be there. */
1224 if (!only_documentation)
1226 if (builtin->dependencies)
1228 write_ifdefs (externfile, builtin->dependencies->array);
1229 write_ifdefs (structfile, builtin->dependencies->array);
1232 /* Write the extern definition. */
1233 if (externfile)
1235 if (builtin->function)
1236 fprintf (externfile, "extern int %s PARAMS((WORD_LIST *));\n",
1237 builtin->function);
1239 fprintf (externfile, "extern char * const %s_doc[];\n",
1240 document_name (builtin));
1243 /* Write the structure definition. */
1244 if (structfile)
1246 fprintf (structfile, " { \"%s\", ", builtin->name);
1248 if (builtin->function && inhibit_functions == 0)
1249 fprintf (structfile, "%s, ", builtin->function);
1250 else
1251 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
1253 fprintf (structfile, "%s%s%s%s%s, %s_doc,\n",
1254 "BUILTIN_ENABLED | STATIC_BUILTIN",
1255 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1256 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1257 (builtin->flags & BUILTIN_FLAG_LOCALVAR) ? " | LOCALVAR_BUILTIN" : "",
1258 (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
1259 document_name (builtin));
1261 /* Don't translate short document summaries that are identical
1262 to command names */
1263 if (builtin->shortdoc && strcmp (builtin->name, builtin->shortdoc) == 0)
1265 if (inhibit_functions)
1266 fprintf (structfile, " \"%s\", \"%s\" },\n",
1267 builtin->shortdoc ? builtin->shortdoc : builtin->name,
1268 document_name (builtin));
1269 else
1270 fprintf (structfile, " \"%s\", (char *)NULL },\n",
1271 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1273 else
1275 if (inhibit_functions)
1276 fprintf (structfile, " N_(\"%s\"), \"%s\" },\n",
1277 builtin->shortdoc ? builtin->shortdoc : builtin->name,
1278 document_name (builtin));
1279 else
1280 fprintf (structfile, " N_(\"%s\"), (char *)NULL },\n",
1281 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1285 if (structfile || separate_helpfiles)
1286 /* Save away this builtin for later writing of the
1287 long documentation strings. */
1288 save_builtin (builtin);
1290 /* Write out the matching #endif, if necessary. */
1291 if (builtin->dependencies)
1293 if (externfile)
1294 write_endifs (externfile, builtin->dependencies->array);
1296 if (structfile)
1297 write_endifs (structfile, builtin->dependencies->array);
1301 if (documentation_file)
1303 fprintf (documentation_file, "@item %s\n", builtin->name);
1304 write_documentation
1305 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1311 /* Write out the long documentation strings in BUILTINS to STREAM. */
1312 void
1313 write_longdocs (stream, builtins)
1314 FILE *stream;
1315 ARRAY *builtins;
1317 register int i;
1318 register BUILTIN_DESC *builtin;
1319 char *dname;
1320 char *sarray[2];
1322 for (i = 0; i < builtins->sindex; i++)
1324 builtin = (BUILTIN_DESC *)builtins->array[i];
1326 if (builtin->dependencies)
1327 write_ifdefs (stream, builtin->dependencies->array);
1329 /* Write the long documentation strings. */
1330 dname = document_name (builtin);
1331 fprintf (stream, "char * const %s_doc[] =", dname);
1333 if (separate_helpfiles)
1335 int l = strlen (helpfile_directory) + strlen (dname) + 1;
1336 sarray[0] = (char *)xmalloc (l + 1);
1337 sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
1338 sarray[1] = (char *)NULL;
1339 write_documentation (stream, sarray, 0, STRING_ARRAY|HELPFILE);
1340 free (sarray[0]);
1342 else
1343 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1345 if (builtin->dependencies)
1346 write_endifs (stream, builtin->dependencies->array);
1351 void
1352 write_dummy_declarations (stream, builtins)
1353 FILE *stream;
1354 ARRAY *builtins;
1356 register int i;
1357 BUILTIN_DESC *builtin;
1359 for (i = 0; structfile_header[i]; i++)
1360 fprintf (stream, "%s\n", structfile_header[i]);
1362 for (i = 0; i < builtins->sindex; i++)
1364 builtin = (BUILTIN_DESC *)builtins->array[i];
1366 /* How to guarantee that no builtin is written more than once? */
1367 fprintf (stream, "int %s () { return (0); }\n", builtin->function);
1371 /* Write an #ifdef string saying what needs to be defined (or not defined)
1372 in order to allow compilation of the code that will follow.
1373 STREAM is the stream to write the information to,
1374 DEFINES is a null terminated array of define names.
1375 If a define is preceded by an `!', then the sense of the test is
1376 reversed. */
1377 void
1378 write_ifdefs (stream, defines)
1379 FILE *stream;
1380 char **defines;
1382 register int i;
1384 if (!stream)
1385 return;
1387 fprintf (stream, "#if ");
1389 for (i = 0; defines[i]; i++)
1391 char *def = defines[i];
1393 if (*def == '!')
1394 fprintf (stream, "!defined (%s)", def + 1);
1395 else
1396 fprintf (stream, "defined (%s)", def);
1398 if (defines[i + 1])
1399 fprintf (stream, " && ");
1401 fprintf (stream, "\n");
1404 /* Write an #endif string saying what defines controlled the compilation
1405 of the immediately preceding code.
1406 STREAM is the stream to write the information to.
1407 DEFINES is a null terminated array of define names. */
1408 void
1409 write_endifs (stream, defines)
1410 FILE *stream;
1411 char **defines;
1413 register int i;
1415 if (!stream)
1416 return;
1418 fprintf (stream, "#endif /* ");
1420 for (i = 0; defines[i]; i++)
1422 fprintf (stream, "%s", defines[i]);
1424 if (defines[i + 1])
1425 fprintf (stream, " && ");
1428 fprintf (stream, " */\n");
1431 /* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
1432 and quoting special characters in the string. Handle special things for
1433 internationalization (gettext) and the single-string vs. multiple-strings
1434 issues. */
1435 void
1436 write_documentation (stream, documentation, indentation, flags)
1437 FILE *stream;
1438 char **documentation;
1439 int indentation, flags;
1441 register int i, j;
1442 register char *line;
1443 int string_array, texinfo, base_indent, filename_p;
1445 if (stream == 0)
1446 return;
1448 string_array = flags & STRING_ARRAY;
1449 filename_p = flags & HELPFILE;
1451 if (string_array)
1453 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n"); /* } */
1454 if (single_longdoc_strings)
1456 if (filename_p == 0)
1458 if (documentation && documentation[0] && documentation[0][0])
1459 fprintf (stream, "N_(\"");
1460 else
1461 fprintf (stream, "N_(\" "); /* the empty string translates specially. */
1463 else
1464 fprintf (stream, "\"");
1468 base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
1470 for (i = 0, texinfo = (flags & TEXINFO); documentation && (line = documentation[i]); i++)
1472 /* Allow #ifdef's to be written out verbatim, but don't put them into
1473 separate help files. */
1474 if (*line == '#')
1476 if (string_array && filename_p == 0 && single_longdoc_strings == 0)
1477 fprintf (stream, "%s\n", line);
1478 continue;
1481 /* prefix with N_( for gettext */
1482 if (string_array && single_longdoc_strings == 0)
1484 if (filename_p == 0)
1486 if (line[0])
1487 fprintf (stream, " N_(\"");
1488 else
1489 fprintf (stream, " N_(\" "); /* the empty string translates specially. */
1491 else
1492 fprintf (stream, " \"");
1495 if (indentation)
1496 for (j = 0; j < indentation; j++)
1497 fprintf (stream, " ");
1499 /* Don't indent the first line, because of how the help builtin works. */
1500 if (i == 0)
1501 indentation += base_indent;
1503 if (string_array)
1505 for (j = 0; line[j]; j++)
1507 switch (line[j])
1509 case '\\':
1510 case '"':
1511 fprintf (stream, "\\%c", line[j]);
1512 break;
1514 default:
1515 fprintf (stream, "%c", line[j]);
1519 /* closing right paren for gettext */
1520 if (single_longdoc_strings == 0)
1522 if (filename_p == 0)
1523 fprintf (stream, "\"),\n");
1524 else
1525 fprintf (stream, "\",\n");
1527 else if (documentation[i+1])
1528 /* don't add extra newline after last line */
1529 fprintf (stream, "\\n\\\n");
1531 else if (texinfo)
1533 for (j = 0; line[j]; j++)
1535 switch (line[j])
1537 case '@':
1538 case '{':
1539 case '}':
1540 fprintf (stream, "@%c", line[j]);
1541 break;
1543 default:
1544 fprintf (stream, "%c", line[j]);
1547 fprintf (stream, "\n");
1549 else
1550 fprintf (stream, "%s\n", line);
1553 /* closing right paren for gettext */
1554 if (string_array && single_longdoc_strings)
1556 if (filename_p == 0)
1557 fprintf (stream, "\"),\n");
1558 else
1559 fprintf (stream, "\",\n");
1562 if (string_array)
1563 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1567 write_helpfiles (builtins)
1568 ARRAY *builtins;
1570 char *helpfile, *bname;
1571 FILE *helpfp;
1572 int i, hdlen;
1573 BUILTIN_DESC *builtin;
1575 i = mkdir ("helpfiles", 0777);
1576 if (i < 0 && errno != EEXIST)
1578 fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
1579 return -1;
1582 hdlen = strlen ("helpfiles/");
1583 for (i = 0; i < builtins->sindex; i++)
1585 builtin = (BUILTIN_DESC *)builtins->array[i];
1587 bname = document_name (builtin);
1588 helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
1589 sprintf (helpfile, "helpfiles/%s", bname);
1591 helpfp = fopen (helpfile, "w");
1592 if (helpfp == 0)
1594 fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
1595 free (helpfile);
1596 continue;
1599 write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
1601 fflush (helpfp);
1602 fclose (helpfp);
1603 free (helpfile);
1605 return 0;
1608 static int
1609 _find_in_table (name, name_table)
1610 char *name, *name_table[];
1612 register int i;
1614 for (i = 0; name_table[i]; i++)
1615 if (strcmp (name, name_table[i]) == 0)
1616 return 1;
1617 return 0;
1620 static int
1621 is_special_builtin (name)
1622 char *name;
1624 return (_find_in_table (name, special_builtins));
1627 static int
1628 is_assignment_builtin (name)
1629 char *name;
1631 return (_find_in_table (name, assignment_builtins));
1634 static int
1635 is_localvar_builtin (name)
1636 char *name;
1638 return (_find_in_table (name, localvar_builtins));
1641 static int
1642 is_posix_builtin (name)
1643 char *name;
1645 return (_find_in_table (name, posix_builtins));
1648 #if !defined (HAVE_RENAME)
1649 static int
1650 rename (from, to)
1651 char *from, *to;
1653 unlink (to);
1654 if (link (from, to) < 0)
1655 return (-1);
1656 unlink (from);
1657 return (0);
1659 #endif /* !HAVE_RENAME */