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