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