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