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