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