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