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