ae93bd454ee7503d9cfc608086cabcdc044e1068
[platform/upstream/bash.git] / builtins / mkbuiltins.c
1 /* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2    a single source file called builtins.def. */
3
4 /* Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
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 1, or (at your option) any later
11 version.
12
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
16 for more details.
17
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
21
22 #include <config.h>
23
24 #if defined (HAVE_UNISTD_H)
25 #  include <unistd.h>
26 #endif
27
28 #include "../bashansi.h"
29 #include "../config.h"
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/file.h>
33 #include <sys/stat.h>
34 #include "../filecntl.h"
35
36 #if defined (HAVE_UNISTD_H)
37 #  include <unistd.h>
38 #endif /* HAVE_UNISTD_H */
39
40 #if defined (HAVE_STRING_H)
41 #  include <string.h>
42 #else /* !HAVE_STRING_H */
43 #  include <strings.h>
44 #endif /* !HAVE_STRING_H */
45
46 #define DOCFILE "builtins.texi"
47
48 static char *xmalloc (), *xrealloc ();
49
50 #if !defined (__STDC__) && !defined (strcpy)
51 extern char *strcpy ();
52 #endif /* !__STDC__ && !strcpy */
53
54 #define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
55 #define whitespace(c) (((c) == ' ') || ((c) == '\t'))
56
57 /* Flag values that builtins can have. */
58 #define BUILTIN_FLAG_SPECIAL    0x01
59 #define BUILTIN_FLAG_ASSIGNMENT 0x02
60
61 /* If this stream descriptor is non-zero, then write
62    texinfo documentation to it. */
63 FILE *documentation_file = (FILE *)NULL;
64
65 /* Non-zero means to only produce documentation. */
66 int only_documentation = 0;
67
68 /* Non-zero means to not do any productions. */
69 int inhibit_production = 0;
70
71 #if !defined (OLDCODE)
72 int no_long_document = 0;
73 #endif /* !OLDCODE */
74
75 /* The name of a directory to precede the filename when reporting
76    errors. */
77 char *error_directory = (char *)NULL;
78
79 /* The name of the structure file. */
80 char *struct_filename = (char *)NULL;
81
82 /* The name of the external declaration file. */
83 char *extern_filename = (char *)NULL;
84
85 /* Here is a structure for manipulating arrays of data. */
86 typedef struct {
87   int size;             /* Number of slots allocated to array. */
88   int sindex;           /* Current location in array. */
89   int width;            /* Size of each element. */
90   int growth_rate;      /* How fast to grow. */
91   char **array;         /* The array itself. */
92 } ARRAY;
93
94 /* Here is a structure defining a single BUILTIN. */
95 typedef struct {
96   char *name;           /* The name of this builtin. */
97   char *function;       /* The name of the function to call. */
98   char *shortdoc;       /* The short documentation for this builtin. */
99   char *docname;        /* Possible name for documentation string. */
100   ARRAY *longdoc;       /* The long documentation for this builtin. */
101   ARRAY *dependencies;  /* Null terminated array of #define names. */
102   int flags;            /* Flags for this builtin. */
103 } BUILTIN_DESC;
104
105 /* Here is a structure which defines a DEF file. */
106 typedef struct {
107   char *filename;       /* The name of the input def file. */
108   ARRAY *lines;         /* The contents of the file. */
109   int line_number;      /* The current line number. */
110   char *production;     /* The name of the production file. */
111   FILE *output;         /* Open file stream for PRODUCTION. */
112   ARRAY *builtins;      /* Null terminated array of BUILTIN_DESC *. */
113 } DEF_FILE;
114
115 /* The array of all builtins encountered during execution of this code. */
116 ARRAY *saved_builtins = (ARRAY *)NULL;
117
118 /* The Posix.2 so-called `special' builtins. */
119 char *special_builtins[] =
120 {
121   ":", ".", "source", "break", "continue", "eval", "exec", "exit",
122   "export", "readonly", "return", "set", "shift", "trap", "unset",
123   (char *)NULL
124 };
125
126 /* The builtin commands that take assignment statements as arguments. */
127 char *assignment_builtins[] =
128 {
129   "alias", "declare", "export", "local", "readonly", "typeset",
130   (char *)NULL
131 };
132
133 /* Forward declarations. */
134 static int is_special_builtin ();
135 static int is_assignment_builtin ();
136
137 void extract_info ();
138
139 void file_error ();
140 void line_error ();
141
142 void write_file_headers ();
143 void write_file_footers ();
144 void write_ifdefs ();
145 void write_endifs ();
146 void write_documentation ();
147 void write_longdocs ();
148 void write_builtins ();
149
150 void free_defs ();
151 void add_documentation ();
152
153 void must_be_building ();
154 void remove_trailing_whitespace ();
155 \f
156 /* For each file mentioned on the command line, process it and
157    write the information to STRUCTFILE and EXTERNFILE, while
158    creating the production file if neccessary. */
159 int
160 main (argc, argv)
161      int argc;
162      char **argv;
163 {
164   int arg_index = 1;
165   FILE *structfile, *externfile;
166   char *documentation_filename, *temp_struct_filename;
167
168   structfile = externfile = (FILE *)NULL;
169   documentation_filename = DOCFILE;
170   temp_struct_filename = (char *)NULL;
171
172   while (arg_index < argc && argv[arg_index][0] == '-')
173     {
174       char *arg = argv[arg_index++];
175
176       if (strcmp (arg, "-externfile") == 0)
177         extern_filename = argv[arg_index++];
178       else if (strcmp (arg, "-structfile") == 0)
179         struct_filename = argv[arg_index++];
180       else if (strcmp (arg, "-noproduction") == 0)
181         inhibit_production = 1;
182       else if (strcmp (arg, "-document") == 0)
183         documentation_file = fopen (documentation_filename, "w");
184       else if (strcmp (arg, "-D") == 0)
185         {
186           int len;
187
188           if (error_directory)
189             free (error_directory);
190
191           error_directory = xmalloc (2 + strlen (argv[arg_index]));
192           strcpy (error_directory, argv[arg_index]);
193           len = strlen (error_directory);
194
195           if (len && error_directory[len - 1] != '/')
196             strcat (error_directory, "/");
197
198           arg_index++;
199         }
200       else if (strcmp (arg, "-documentonly") == 0)
201         {
202           only_documentation = 1;
203           documentation_file = fopen (documentation_filename, "w");
204         }
205 #if !defined (OLDCODE)
206       else if (strcmp (arg, "-nodocument") == 0)
207         no_long_document = 1;
208 #endif /* !OLDCODE */        
209       else
210         {
211           fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
212           exit (2);
213         }
214     }
215
216   /* If there are no files to process, just quit now. */
217   if (arg_index == argc)
218     exit (0);
219
220   if (!only_documentation)
221     {
222       /* Open the files. */
223       if (struct_filename)
224         {
225           temp_struct_filename = xmalloc (15);
226           sprintf (temp_struct_filename, "mk-%d", (int) getpid ());
227           structfile = fopen (temp_struct_filename, "w");
228
229           if (!structfile)
230             file_error (temp_struct_filename);
231         }
232
233       if (extern_filename)
234         {
235           externfile = fopen (extern_filename, "w");
236
237           if (!externfile)
238             file_error (extern_filename);
239         }
240
241       /* Write out the headers. */
242       write_file_headers (structfile, externfile);
243     }
244
245   if (documentation_file)
246     {
247       fprintf (documentation_file, "@c Table of builtins created with %s.\n",
248                argv[0]);
249       fprintf (documentation_file, "@ftable @asis\n");
250     }
251
252   /* Process the .def files. */
253   while (arg_index < argc)
254     {
255       register char *arg;
256
257       arg = argv[arg_index++];
258
259       extract_info (arg, structfile, externfile);
260     }
261
262   /* Close the files. */
263   if (!only_documentation)
264     {
265       /* Write the footers. */
266       write_file_footers (structfile, externfile);
267
268       if (structfile)
269         {
270           write_longdocs (structfile, saved_builtins);
271           fclose (structfile);
272           link (temp_struct_filename, struct_filename);
273           unlink (temp_struct_filename);
274         }
275
276       if (externfile)
277         fclose (externfile);
278     }
279
280   if (documentation_file)
281     {
282       fprintf (documentation_file, "@end ftable\n");
283       fclose (documentation_file);
284     }
285
286   exit (0);
287 }
288
289 /* **************************************************************** */
290 /*                                                                  */
291 /*                Array Functions and Manipulators                  */
292 /*                                                                  */
293 /* **************************************************************** */
294
295 /* Make a new array, and return a pointer to it.  The array will
296    contain elements of size WIDTH, and is initialized to no elements. */
297 ARRAY *
298 array_create (width)
299      int width;
300 {
301   ARRAY *array;
302
303   array = (ARRAY *)xmalloc (sizeof (ARRAY));
304   array->size = 0;
305   array->sindex = 0;
306   array->width = width;
307
308   /* Default to increasing size in units of 20. */
309   array->growth_rate = 20;
310
311   array->array = (char **)NULL;
312
313   return (array);
314 }
315
316 /* Copy the array of strings in ARRAY. */
317 ARRAY *
318 copy_string_array (array)
319      ARRAY *array;
320 {
321   register int i;
322   ARRAY *copy;
323
324   if (!array)
325     return (ARRAY *)NULL;
326
327   copy = array_create (sizeof (char *));
328
329   copy->size = array->size;
330   copy->sindex = array->sindex;
331   copy->width = array->width;
332
333   copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
334   
335   for (i = 0; i < array->sindex; i++)
336     copy->array[i] = savestring (array->array[i]);
337
338   copy->array[i] = (char *)NULL;
339
340   return (copy);
341 }
342
343 /* Add ELEMENT to ARRAY, growing the array if neccessary. */
344 void
345 array_add (element, array)
346      char *element;
347      ARRAY *array;
348 {
349   if (array->sindex + 2 > array->size)
350     array->array = (char **)xrealloc
351       (array->array, (array->size += array->growth_rate) * array->width);
352
353 #if defined (HAVE_BCOPY)
354   bcopy (&element, &(array->array[array->sindex]), array->width);
355   array->sindex++;
356   bzero (&(array->array[array->sindex]), array->width);
357 #else
358   array->array[array->sindex++] = element;
359   array->array[array->sindex] = (char *)NULL;
360 #endif /* !HAVE_BCOPY */
361 }
362
363 /* Free an allocated array and data pointer. */
364 void
365 array_free (array)
366      ARRAY *array;
367 {
368   if (array->array)
369     free (array->array);
370
371   free (array);
372 }
373
374 /* **************************************************************** */
375 /*                                                                  */
376 /*                     Processing a DEF File                        */
377 /*                                                                  */
378 /* **************************************************************** */
379
380 /* The definition of a function. */
381 typedef int Function ();
382
383 /* Structure handles processor directives. */
384 typedef struct {
385   char *directive;
386   Function *function;
387 } HANDLER_ENTRY;
388
389 extern int
390   builtin_handler (), function_handler (), short_doc_handler (),
391   comment_handler (), depends_on_handler (), produces_handler (),
392   end_handler (), docname_handler ();
393
394 HANDLER_ENTRY handlers[] = {
395   { "BUILTIN", builtin_handler },
396   { "DOCNAME", docname_handler },
397   { "FUNCTION", function_handler },
398   { "SHORT_DOC", short_doc_handler },
399   { "$", comment_handler },
400   { "COMMENT", comment_handler },
401   { "DEPENDS_ON", depends_on_handler },
402   { "PRODUCES", produces_handler },
403   { "END", end_handler },
404   { (char *)NULL, (Function *)NULL }
405 };
406
407 /* Return the entry in the table of handlers for NAME. */
408 HANDLER_ENTRY *
409 find_directive (directive)
410      char *directive;
411 {
412   register int i;
413
414   for (i = 0; handlers[i].directive; i++)
415     if (strcmp (handlers[i].directive, directive) == 0)
416       return (&handlers[i]);
417
418   return ((HANDLER_ENTRY *)NULL);
419 }
420
421 /* Non-zero indicates that a $BUILTIN has been seen, but not
422    the corresponding $END. */
423 static int building_builtin = 0;
424
425 /* Non-zero means to output cpp line and file information before
426    printing the current line to the production file. */
427 int output_cpp_line_info = 0;
428
429 /* The main function of this program.  Read FILENAME and act on what is
430    found.  Lines not starting with a dollar sign are copied to the
431    $PRODUCES target, if one is present.  Lines starting with a dollar sign
432    are directives to this program, specifying the name of the builtin, the
433    function to call, the short documentation and the long documentation
434    strings.  FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
435    target.  After the file has been processed, write out the names of
436    builtins found in each $BUILTIN.  Plain text found before the $PRODUCES
437    is ignored, as is "$$ comment text". */
438 void
439 extract_info (filename, structfile, externfile)
440      char *filename;
441      FILE *structfile, *externfile;
442 {
443   register int i;
444   DEF_FILE *defs;
445   struct stat finfo;
446   char *buffer, *line;
447   int fd;
448
449   if (stat (filename, &finfo) == -1)
450     file_error (filename);
451
452   fd = open (filename, O_RDONLY, 0666);
453
454   if (fd == -1)
455     file_error (filename);
456
457   buffer = xmalloc (1 + (int)finfo.st_size);
458
459   if (read (fd, buffer, finfo.st_size) != finfo.st_size)
460     file_error (filename);
461
462   close (fd);
463
464   /* Create and fill in the initial structure describing this file. */
465   defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
466   defs->filename = filename;
467   defs->lines = array_create (sizeof (char *));
468   defs->line_number = 0;
469   defs->production = (char *)NULL;
470   defs->output = (FILE *)NULL;
471   defs->builtins = (ARRAY *)NULL;
472
473   /* Build the array of lines. */
474   i = 0;
475   while (i < finfo.st_size)
476     {
477       array_add (&buffer[i], defs->lines);
478
479       while (buffer[i] != '\n' && i < finfo.st_size)
480         i++;
481       buffer[i++] = '\0';
482     }
483
484   /* Begin processing the input file.  We don't write any output
485      until we have a file to write output to. */
486   output_cpp_line_info = 1;
487
488   /* Process each line in the array. */
489   for (i = 0; line = defs->lines->array[i]; i++)
490     {
491       defs->line_number = i;
492
493       if (*line == '$')
494         {
495           register int j;
496           char *directive;
497           HANDLER_ENTRY *handler;
498
499           /* Isolate the directive. */
500           for (j = 0; line[j] && !whitespace (line[j]); j++);
501
502           directive = xmalloc (j);
503           strncpy (directive, line + 1, j - 1);
504           directive[j -1] = '\0';
505
506           /* Get the function handler and call it. */
507           handler = find_directive (directive);
508
509           if (!handler)
510             {
511               line_error (defs, "Unknown directive `%s'", directive);
512               free (directive);
513               continue;
514             }
515           else
516             {
517               /* Advance to the first non-whitespace character. */
518               while (whitespace (line[j]))
519                 j++;
520
521               /* Call the directive handler with the FILE, and ARGS. */
522               (*(handler->function)) (directive, defs, line + j);
523             }
524           free (directive);
525         }
526       else
527         {
528           if (building_builtin)
529             add_documentation (defs, line);
530           else if (defs->output)
531             {
532               if (output_cpp_line_info)
533                 {
534                   /* If we're handed an absolute pathname, don't prepend
535                      the directory name. */
536                   if (defs->filename[0] == '/')
537                     fprintf (defs->output, "#line %d \"%s\"\n",
538                              defs->line_number + 1, defs->filename);
539                   else
540                     fprintf (defs->output, "#line %d \"%s%s\"\n",
541                              defs->line_number + 1,
542                              error_directory ? error_directory : "./",
543                              defs->filename);
544                   output_cpp_line_info = 0;
545                 }
546
547               fprintf (defs->output, "%s\n", line);
548             }
549         }
550     }
551
552   /* Close the production file. */
553   if (defs->output)
554     fclose (defs->output);
555
556   /* The file has been processed.  Write the accumulated builtins to
557      the builtins.c file, and write the extern definitions to the
558      builtext.h file. */
559   write_builtins (defs, structfile, externfile);
560
561   free (buffer);
562   free_defs (defs);
563 }
564
565 #define free_safely(x) if (x) free (x)
566
567 static void
568 free_builtin (builtin)
569      BUILTIN_DESC *builtin;
570 {
571   register int i;
572
573   free_safely (builtin->name);
574   free_safely (builtin->function);
575   free_safely (builtin->shortdoc);
576   free_safely (builtin->docname);
577
578   if (builtin->longdoc)
579     array_free (builtin->longdoc);
580
581   if (builtin->dependencies)
582     {
583       for (i = 0; builtin->dependencies->array[i]; i++)
584         free (builtin->dependencies->array[i]);
585       array_free (builtin->dependencies);
586     }
587 }
588
589 /* Free all of the memory allocated to a DEF_FILE. */
590 void
591 free_defs (defs)
592      DEF_FILE *defs;
593 {
594   register int i;
595   register BUILTIN_DESC *builtin;
596
597   if (defs->production)
598     free (defs->production);
599
600   if (defs->lines)
601     array_free (defs->lines);
602
603   if (defs->builtins)
604     {
605       for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
606         {
607           free_builtin (builtin);
608           free (builtin);
609         }
610       array_free (defs->builtins);
611     }
612   free (defs);
613 }
614
615 /* **************************************************************** */
616 /*                                                                  */
617 /*                   The Handler Functions Themselves               */
618 /*                                                                  */
619 /* **************************************************************** */
620
621 /* Strip surrounding whitespace from STRING, and
622    return a pointer to the start of it. */
623 char *
624 strip_whitespace (string)
625      char *string;
626 {
627   while (whitespace (*string))
628       string++;
629
630   remove_trailing_whitespace (string);
631   return (string);
632 }
633
634 /* Remove only the trailing whitespace from STRING. */
635 void
636 remove_trailing_whitespace (string)
637      char *string;
638 {
639   register int i;
640
641   i = strlen (string) - 1;
642
643   while (i > 0 && whitespace (string[i]))
644     i--;
645
646   string[++i] = '\0';
647 }
648
649 /* Ensure that there is a argument in STRING and return it.
650    FOR_WHOM is the name of the directive which needs the argument.
651    DEFS is the DEF_FILE in which the directive is found.
652    If there is no argument, produce an error. */
653 char *
654 get_arg (for_whom, defs, string)
655      char *for_whom, *string;
656      DEF_FILE *defs;
657 {
658   char *new;
659
660   new = strip_whitespace (string);
661
662   if (!*new)
663     line_error (defs, "%s requires an argument", for_whom);
664
665   return (savestring (new));
666 }
667
668 /* Error if not building a builtin. */
669 void
670 must_be_building (directive, defs)
671      char *directive;
672      DEF_FILE *defs;
673 {
674   if (!building_builtin)
675     line_error (defs, "%s must be inside of a $BUILTIN block", directive);
676 }
677
678 /* Return the current builtin. */
679 BUILTIN_DESC *
680 current_builtin (directive, defs)
681      char *directive;
682      DEF_FILE *defs;
683 {
684   must_be_building (directive, defs);
685   return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
686 }
687
688 /* Add LINE to the long documentation for the current builtin.
689    Ignore blank lines until the first non-blank line has been seen. */
690 void
691 add_documentation (defs, line)
692      DEF_FILE *defs;
693      char *line;
694 {
695   register BUILTIN_DESC *builtin;
696
697   builtin = current_builtin ("(implied LONGDOC)", defs);
698
699   remove_trailing_whitespace (line);
700
701   if (!*line && !builtin->longdoc)
702     return;
703
704   if (!builtin->longdoc)
705     builtin->longdoc = array_create (sizeof (char *));
706
707   array_add (line, builtin->longdoc);
708 }
709
710 /* How to handle the $BUILTIN directive. */
711 int
712 builtin_handler (self, defs, arg)
713      char *self, *arg;
714      DEF_FILE *defs;
715 {
716   BUILTIN_DESC *new;
717   char *name;
718
719   /* If we are already building a builtin, we cannot start a new one. */
720   if (building_builtin)
721     {
722       line_error (defs, "%s found before $END", self);
723       return (-1);
724     }
725
726   output_cpp_line_info++;
727
728   /* Get the name of this builtin, and stick it in the array. */
729   name = get_arg (self, defs, arg);
730
731   /* If this is the first builtin, create the array to hold them. */
732   if (!defs->builtins)
733     defs->builtins = array_create (sizeof (BUILTIN_DESC *));
734
735   new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
736   new->name = name;
737   new->function = (char *)NULL;
738   new->shortdoc = (char *)NULL;
739   new->docname = (char *)NULL;
740   new->longdoc = (ARRAY *)NULL;
741   new->dependencies = (ARRAY *)NULL;
742   new->flags = 0;
743
744   if (is_special_builtin (name))
745     new->flags |= BUILTIN_FLAG_SPECIAL;
746   if (is_assignment_builtin (name))
747     new->flags |= BUILTIN_FLAG_ASSIGNMENT;
748
749   array_add ((char *)new, defs->builtins);
750   building_builtin = 1;
751
752   return (0);
753 }
754
755 /* How to handle the $FUNCTION directive. */
756 int
757 function_handler (self, defs, arg)
758      char *self, *arg;
759      DEF_FILE *defs;
760 {
761   register BUILTIN_DESC *builtin;
762
763   builtin = current_builtin (self, defs);
764
765   if (builtin->function)
766     line_error (defs, "%s already has a function (%s)",
767                 builtin->name, builtin->function);
768   else
769     builtin->function = get_arg (self, defs, arg);
770
771   return (0);
772 }
773
774 /* How to handle the $DOCNAME directive. */
775 int
776 docname_handler (self, defs, arg)
777      char *self, *arg;
778      DEF_FILE *defs;
779 {
780   register BUILTIN_DESC *builtin;
781
782   builtin = current_builtin (self, defs);
783
784   if (builtin->docname)
785     line_error (defs, "%s already had a docname (%s)",
786                 builtin->name, builtin->docname);
787   else
788     builtin->docname = get_arg (self, defs, arg);
789
790   return (0);
791 }
792
793 /* How to handle the $SHORT_DOC directive. */
794 int
795 short_doc_handler (self, defs, arg)
796      char *self, *arg;
797      DEF_FILE *defs;
798 {
799   register BUILTIN_DESC *builtin;
800
801   builtin = current_builtin (self, defs);
802
803   if (builtin->shortdoc)
804     line_error (defs, "%s already has short documentation (%s)",
805                 builtin->name, builtin->shortdoc);
806   else
807     builtin->shortdoc = get_arg (self, defs, arg);
808
809   return (0);
810 }
811
812 /* How to handle the $COMMENT directive. */
813 int
814 comment_handler (self, defs)
815      char *self;
816      DEF_FILE *defs;
817 {
818   return (0);
819 }
820
821 /* How to handle the $DEPENDS_ON directive. */
822 int
823 depends_on_handler (self, defs, arg)
824      char *self, *arg;
825      DEF_FILE *defs;
826 {
827   register BUILTIN_DESC *builtin;
828   char *dependent;
829
830   builtin = current_builtin (self, defs);
831   dependent = get_arg (self, defs, arg);
832
833   if (!builtin->dependencies)
834     builtin->dependencies = array_create (sizeof (char *));
835
836   array_add (dependent, builtin->dependencies);
837
838   return (0);
839 }
840
841 /* How to handle the $PRODUCES directive. */
842 int
843 produces_handler (self, defs, arg)
844      char *self, *arg;
845      DEF_FILE *defs;
846 {
847   /* If just hacking documentation, don't change any of the production
848      files. */
849   if (only_documentation)
850     return (0);
851
852   output_cpp_line_info++;
853
854   if (defs->production)
855     line_error (defs, "%s already has a %s definition", defs->filename, self);
856   else
857     {
858       defs->production = get_arg (self, defs, arg);
859
860       if (inhibit_production)
861         return (0);
862
863       defs->output = fopen (defs->production, "w");
864
865       if (!defs->output)
866         file_error (defs->production);
867
868       fprintf (defs->output, "/* %s, created from %s. */\n",
869                defs->production, defs->filename);
870     }
871   return (0);
872 }
873
874 /* How to handle the $END directive. */
875 int
876 end_handler (self, defs, arg)
877      char *self, *arg;
878      DEF_FILE *defs;
879 {
880   must_be_building (self, defs);
881   building_builtin = 0;
882   return (0);
883 }
884
885 /* **************************************************************** */
886 /*                                                                  */
887 /*                  Error Handling Functions                        */
888 /*                                                                  */
889 /* **************************************************************** */
890
891 /* Produce an error for DEFS with FORMAT and ARGS. */
892 void
893 line_error (defs, format, arg1, arg2)
894      DEF_FILE *defs;
895      char *format, *arg1, *arg2;
896 {
897   if (defs->filename[0] != '/')
898     fprintf (stderr, "%s", error_directory ? error_directory : "./");
899   fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
900   fprintf (stderr, format, arg1, arg2);
901   fprintf (stderr, "\n");
902   fflush (stderr);
903 }
904
905 /* Print error message for FILENAME. */
906 void
907 file_error (filename)
908      char *filename;
909 {
910   perror (filename);
911   exit (2);
912 }
913
914 /* **************************************************************** */
915 /*                                                                  */
916 /*                      xmalloc and xrealloc ()                     */
917 /*                                                                  */
918 /* **************************************************************** */
919
920 static void memory_error_and_abort ();
921
922 static char *
923 xmalloc (bytes)
924      int bytes;
925 {
926   char *temp = (char *)malloc (bytes);
927
928   if (!temp)
929     memory_error_and_abort ();
930   return (temp);
931 }
932
933 static char *
934 xrealloc (pointer, bytes)
935      char *pointer;
936      int bytes;
937 {
938   char *temp;
939
940   if (!pointer)
941     temp = (char *)malloc (bytes);
942   else
943     temp = (char *)realloc (pointer, bytes);
944
945   if (!temp)
946     memory_error_and_abort ();
947
948   return (temp);
949 }
950
951 static void
952 memory_error_and_abort ()
953 {
954   fprintf (stderr, "mkbuiltins: out of virtual memory\n");
955   abort ();
956 }
957
958 /* **************************************************************** */
959 /*                                                                  */
960 /*                Creating the Struct and Extern Files              */
961 /*                                                                  */
962 /* **************************************************************** */
963
964 /* Return a pointer to a newly allocated builtin which is
965    an exact copy of BUILTIN. */
966 BUILTIN_DESC *
967 copy_builtin (builtin)
968      BUILTIN_DESC *builtin;
969 {
970   BUILTIN_DESC *new;
971
972   new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
973
974   new->name         = savestring (builtin->name);
975   new->shortdoc     = savestring (builtin->shortdoc);
976   new->longdoc      = copy_string_array (builtin->longdoc);
977   new->dependencies = copy_string_array (builtin->dependencies);
978
979   new->function =
980     builtin->function ? savestring (builtin->function) : (char *)NULL;
981   new->docname =
982     builtin->docname  ? savestring (builtin->docname)  : (char *)NULL;
983
984   return (new);
985 }
986
987 /* How to save away a builtin. */
988 void
989 save_builtin (builtin)
990      BUILTIN_DESC *builtin;
991 {
992   BUILTIN_DESC *newbuiltin;
993
994   newbuiltin = copy_builtin (builtin);
995
996   /* If this is the first builtin to be saved, create the array
997      to hold it. */
998   if (!saved_builtins)
999       saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1000
1001   array_add ((char *)newbuiltin, saved_builtins);
1002 }
1003
1004 /* Flags that mean something to write_documentation (). */
1005 #define STRING_ARRAY 1
1006 #define TEXINFO 2
1007
1008 char *structfile_header[] = {
1009   "/* builtins.c -- the built in shell commands. */",
1010   "",
1011   "/* This file is manufactured by ./mkbuiltins, and should not be",
1012   "   edited by hand.  See the source to mkbuiltins for details. */",
1013   "",
1014   "/* Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.",
1015   "",
1016   "   This file is part of GNU Bash, the Bourne Again SHell.",
1017   "",
1018   "   Bash is free software; you can redistribute it and/or modify it",
1019   "   under the terms of the GNU General Public License as published by",
1020   "   the Free Software Foundation; either version 1, or (at your option)",
1021   "   any later version.",
1022   "",
1023   "   Bash is distributed in the hope that it will be useful, but WITHOUT",
1024   "   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY",
1025   "   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public",
1026   "   License for more details.",
1027   "",
1028   "   You should have received a copy of the GNU General Public License",
1029   "   along with Bash; see the file COPYING.  If not, write to the Free",
1030   "   Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
1031   "",
1032   "/* The list of shell builtins.  Each element is name, function, flags,",
1033   "   long-doc, short-doc.  The long-doc field contains a pointer to an array",
1034   "   of help lines.  The function takes a WORD_LIST *; the first word in the",
1035   "   list is the first arg to the command.  The list has already had word",
1036   "   expansion performed.",
1037   "",
1038   "   Functions which need to look at only the simple commands (e.g.",
1039   "   the enable_builtin ()), should ignore entries where",
1040   "   (array[i].function == (Function *)NULL).  Such entries are for",
1041   "   the list of shell reserved control structures, like `if' and `while'.",
1042   "   The end of the list is denoted with a NULL name field. */",
1043   "",
1044   "#include \"../builtins.h\"",
1045   (char *)NULL
1046   };
1047
1048 char *structfile_footer[] = {
1049   "  { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
1050   "};",
1051   "",
1052   "struct builtin *shell_builtins = static_shell_builtins;",
1053   "struct builtin *current_builtin;",
1054   "",
1055   "int num_shell_builtins =",
1056   "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
1057   (char *)NULL
1058 };
1059
1060 /* Write out any neccessary opening information for
1061    STRUCTFILE and EXTERNFILE. */
1062 void
1063 write_file_headers (structfile, externfile)
1064      FILE *structfile, *externfile;
1065 {
1066   register int i;
1067
1068   if (structfile)
1069     {
1070       for (i = 0; structfile_header[i]; i++)
1071         fprintf (structfile, "%s\n", structfile_header[i]);
1072
1073       fprintf (structfile, "#include \"%s\"\n",
1074                extern_filename ? extern_filename : "builtext.h");
1075       fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
1076     }
1077
1078   if (externfile)
1079     fprintf (externfile,
1080              "/* %s - The list of builtins found in libbuiltins.a. */\n",
1081              extern_filename ? extern_filename : "builtext.h");
1082 }
1083
1084 /* Write out any necessary closing information for
1085    STRUCTFILE and EXTERNFILE. */
1086 void
1087 write_file_footers (structfile, externfile)
1088      FILE *structfile, *externfile;
1089 {
1090   register int i;
1091
1092   /* Write out the footers. */
1093   if (structfile)
1094     {
1095       for (i = 0; structfile_footer[i]; i++)
1096         fprintf (structfile, "%s\n", structfile_footer[i]);
1097     }
1098 }
1099
1100 /* Write out the information accumulated in DEFS to
1101    STRUCTFILE and EXTERNFILE. */
1102 void
1103 write_builtins (defs, structfile, externfile)
1104      DEF_FILE *defs;
1105      FILE *structfile, *externfile;
1106 {
1107   register int i;
1108
1109   /* Write out the information. */
1110   if (defs->builtins)
1111     {
1112       register BUILTIN_DESC *builtin;
1113
1114       for (i = 0; i < defs->builtins->sindex; i++)
1115         {
1116           builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1117
1118           /* Write out any #ifdefs that may be there. */
1119           if (!only_documentation)
1120             {
1121               if (builtin->dependencies)
1122                 {
1123                   write_ifdefs (externfile, builtin->dependencies->array);
1124                   write_ifdefs (structfile, builtin->dependencies->array);
1125                 }
1126
1127               /* Write the extern definition. */
1128               if (externfile)
1129                 {
1130                   if (builtin->function)
1131                     fprintf (externfile, "extern int %s ();\n",
1132                              builtin->function);
1133
1134                   fprintf (externfile, "extern char *%s_doc[];\n",
1135                            builtin->docname ?builtin->docname : builtin->name);
1136                 }
1137
1138               /* Write the structure definition. */
1139               if (structfile)
1140                 {
1141                   fprintf (structfile, "  { \"%s\", ", builtin->name);
1142
1143                   if (builtin->function)
1144                     fprintf (structfile, "%s, ", builtin->function);
1145                   else
1146                     fprintf (structfile, "(Function *)0x0, ");
1147
1148                   fprintf (structfile, "%s%s%s, %s_doc,\n",
1149                     "BUILTIN_ENABLED | STATIC_BUILTIN",
1150                     (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1151                     (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
1152                     builtin->docname ? builtin->docname : builtin->name);
1153
1154                   fprintf
1155                     (structfile, "     \"%s\", (char *)NULL },\n",
1156                      builtin->shortdoc ? builtin->shortdoc : builtin->name);
1157
1158                   /* Save away this builtin for later writing of the
1159                      long documentation strings. */
1160                   save_builtin (builtin);
1161                 }
1162
1163               /* Write out the matching #endif, if neccessary. */
1164               if (builtin->dependencies)
1165                 {
1166                   if (externfile)
1167                     write_endifs (externfile, builtin->dependencies->array);
1168
1169                   if (structfile)
1170                     write_endifs (structfile, builtin->dependencies->array);
1171                 }
1172             }
1173
1174           if (documentation_file)
1175             {
1176               fprintf (documentation_file, "@item %s\n", builtin->name);
1177               write_documentation
1178                 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1179             }
1180         }
1181     }
1182 }
1183
1184 /* Write out the long documentation strings in BUILTINS to STREAM. */
1185 void
1186 write_longdocs (stream, builtins)
1187      FILE *stream;
1188      ARRAY *builtins;
1189 {
1190   register int i;
1191   register BUILTIN_DESC *builtin;
1192
1193   for (i = 0; i < builtins->sindex; i++)
1194     {
1195       builtin = (BUILTIN_DESC *)builtins->array[i];
1196
1197       if (builtin->dependencies)
1198         write_ifdefs (stream, builtin->dependencies->array);
1199
1200       /* Write the long documentation strings. */
1201       fprintf (stream, "char *%s_doc[] =",
1202                builtin->docname ? builtin->docname : builtin->name);
1203       write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
1204
1205       if (builtin->dependencies)
1206         write_endifs (stream, builtin->dependencies->array);
1207
1208     }
1209 }
1210
1211 /* Write an #ifdef string saying what needs to be defined (or not defined)
1212    in order to allow compilation of the code that will follow.
1213    STREAM is the stream to write the information to,
1214    DEFINES is a null terminated array of define names.
1215    If a define is preceded by an `!', then the sense of the test is
1216    reversed. */
1217 void
1218 write_ifdefs (stream, defines)
1219      FILE *stream;
1220      char **defines;
1221 {
1222   register int i;
1223
1224   if (!stream)
1225     return;
1226
1227   fprintf (stream, "#if ");
1228
1229   for (i = 0; defines[i]; i++)
1230     {
1231       char *def = defines[i];
1232
1233       if (*def == '!')
1234         fprintf (stream, "!defined (%s)", def + 1);
1235       else
1236         fprintf (stream, "defined (%s)", def);
1237
1238       if (defines[i + 1])
1239         fprintf (stream, " && ");
1240     }
1241   fprintf (stream, "\n");
1242 }
1243
1244 /* Write an #endif string saying what defines controlled the compilation
1245    of the immediately preceding code.
1246    STREAM is the stream to write the information to.
1247    DEFINES is a null terminated array of define names. */
1248 void
1249 write_endifs (stream, defines)
1250      FILE *stream;
1251      char **defines;
1252 {
1253   register int i;
1254
1255   if (!stream)
1256     return;
1257
1258   fprintf (stream, "#endif /* ");
1259
1260   for (i = 0; defines[i]; i++)
1261     {
1262       fprintf (stream, "%s", defines[i]);
1263
1264       if (defines[i + 1])
1265         fprintf (stream, " && ");
1266     }
1267
1268   fprintf (stream, " */\n");
1269 }
1270
1271 /* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
1272    and quoting special characters in the string. */
1273 void
1274 write_documentation (stream, documentation, indentation, flags)
1275      FILE *stream;
1276      char **documentation;
1277      int indentation, flags;
1278 {
1279   register int i, j;
1280   register char *line;
1281   int string_array, texinfo;
1282
1283   if (!stream)
1284     return;
1285
1286   string_array = flags & STRING_ARRAY;
1287   if (string_array)
1288     fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
1289
1290 #if !defined (OLDCODE)
1291   /* XXX -- clean me up; for experiment only */
1292   if (no_long_document)
1293     goto end_of_document;
1294 #endif /* !OLDCODE */
1295
1296   for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
1297     {
1298       /* Allow #ifdef's to be written out verbatim. */
1299       if (*line == '#')
1300         {
1301           if (string_array)
1302             fprintf (stream, "%s\n", line);
1303           continue;
1304         }
1305
1306       if (string_array)
1307         fprintf (stream, "  \"");
1308
1309       if (indentation)
1310         for (j = 0; j < indentation; j++)
1311           fprintf (stream, " ");
1312
1313       if (string_array)
1314         {
1315           for (j = 0; line[j]; j++)
1316             {
1317               switch (line[j])
1318                 {
1319                 case '\\':
1320                 case '"':
1321                   fprintf (stream, "\\%c", line[j]);
1322                   break;
1323
1324                 default:
1325                   fprintf (stream, "%c", line[j]);
1326                 }
1327             }
1328
1329           fprintf (stream, "\",\n");
1330         }
1331       else if (texinfo)
1332         {
1333           for (j = 0; line[j]; j++)
1334             {
1335               switch (line[j])
1336                 {
1337                 case '@':
1338                 case '{':
1339                 case '}':
1340                   fprintf (stream, "@%c", line[j]);
1341                   break;
1342
1343                 default:
1344                   fprintf (stream, "%c", line[j]);
1345                 }
1346             }
1347           fprintf (stream, "\n");
1348         }
1349       else
1350         fprintf (stream, "%s\n", line);
1351     }
1352
1353 #if !defined (OLDCODE)
1354 end_of_document:
1355 #endif /* !OLDCODE */
1356
1357   if (string_array)
1358     fprintf (stream, "#endif /* HELP_BUILTIN */\n  (char *)NULL\n};\n");
1359 }
1360
1361 static int
1362 _find_in_table (name, name_table)
1363      char *name, *name_table[];
1364 {
1365   register int i;
1366
1367   for (i = 0; name_table[i]; i++)
1368     if (strcmp (name, name_table[i]) == 0)
1369       return 1;
1370   return 0;
1371 }
1372
1373 static int
1374 is_special_builtin (name)
1375      char *name;
1376 {
1377   return (_find_in_table (name, special_builtins));
1378 }
1379
1380 static int
1381 is_assignment_builtin (name)
1382      char *name;
1383 {
1384   return (_find_in_table (name, assignment_builtins));
1385 }