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
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING.  If not, write to the Free Software
20Foundation, 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
59extern int errno;
60#endif
61
62static char *xmalloc (), *xrealloc ();
63
64#if !defined (__STDC__) && !defined (strcpy)
65extern 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. */
79FILE *documentation_file = (FILE *)NULL;
80
81/* Non-zero means to only produce documentation. */
82int only_documentation = 0;
83
84/* Non-zero means to not do any productions. */
85int inhibit_production = 0;
86
87/* Non-zero means to produce separate help files for each builtin, named by
88   the builtin name, in `./helpfiles'. */
89int separate_helpfiles = 0;
90
91/* Non-zero means to create single C strings for each `longdoc', with
92   embedded newlines, for ease of translation. */
93int single_longdoc_strings = 1;
94
95/* The name of a directory into which the separate external help files will
96   eventually be installed. */
97char *helpfile_directory;
98
99/* The name of a directory to precede the filename when reporting
100   errors. */
101char *error_directory = (char *)NULL;
102
103/* The name of the structure file. */
104char *struct_filename = (char *)NULL;
105
106/* The name of the external declaration file. */
107char *extern_filename = (char *)NULL;
108
109/* Here is a structure for manipulating arrays of data. */
110typedef 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. */
119typedef 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. */
130typedef 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. */
140ARRAY *saved_builtins = (ARRAY *)NULL;
141
142/* The Posix.2 so-called `special' builtins. */
143char *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. */
151char *assignment_builtins[] =
152{
153  "alias", "declare", "export", "local", "readonly", "typeset",
154  (char *)NULL
155};
156
157/* Forward declarations. */
158static int is_special_builtin ();
159static int is_assignment_builtin ();
160
161#if !defined (HAVE_RENAME)
162static int rename ();
163#endif
164
165void extract_info ();
166
167void file_error ();
168void line_error ();
169
170void write_file_headers ();
171void write_file_footers ();
172void write_ifdefs ();
173void write_endifs ();
174void write_documentation ();
175void write_longdocs ();
176void write_builtins ();
177
178int write_helpfiles ();
179
180void free_defs ();
181void add_documentation ();
182
183void must_be_building ();
184void remove_trailing_whitespace ();
185
186#define document_name(b)	((b)->docname ? (b)->docname : (b)->name)
187
188
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. */
192int
193main (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. */
337ARRAY *
338array_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. */
357ARRAY *
358copy_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. */
384void
385array_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. */
398void
399array_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. */
415typedef int Function ();
416typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
417
418/* Structure handles processor directives. */
419typedef struct {
420  char *directive;
421  mk_handler_func_t *function;
422} HANDLER_ENTRY;
423
424extern int builtin_handler __P((char *, DEF_FILE *, char *));
425extern int function_handler __P((char *, DEF_FILE *, char *));
426extern int short_doc_handler __P((char *, DEF_FILE *, char *));
427extern int comment_handler __P((char *, DEF_FILE *, char *));
428extern int depends_on_handler __P((char *, DEF_FILE *, char *));
429extern int produces_handler __P((char *, DEF_FILE *, char *));
430extern int end_handler __P((char *, DEF_FILE *, char *));
431extern int docname_handler __P((char *, DEF_FILE *, char *));
432
433HANDLER_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. */
447HANDLER_ENTRY *
448find_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. */
462static 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. */
466int 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". */
477void
478extract_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
618static void
619free_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. */
641void
642free_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. */
674char *
675strip_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. */
686void
687remove_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. */
704char *
705get_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. */
720void
721must_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. */
730BUILTIN_DESC *
731current_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. */
744void
745add_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. */
765int
766builtin_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. */
811int
812function_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. */
836int
837docname_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. */
856int
857short_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. */
876int
877comment_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. */
886int
887depends_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. */
907int
908produces_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. */
941int
942end_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. */
959void
960line_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. */
973void
974file_error (filename)
975     char *filename;
976{
977  perror (filename);
978  exit (2);
979}
980
981/* **************************************************************** */
982/*								    */
983/*			xmalloc and xrealloc ()		     	    */
984/*								    */
985/* **************************************************************** */
986
987static void memory_error_and_abort ();
988
989static char *
990xmalloc (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
1000static char *
1001xrealloc (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
1018static void
1019memory_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. */
1033BUILTIN_DESC *
1034copy_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. */
1055void
1056save_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
1077char *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
1117char *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. */
1131void
1132write_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. */
1158void
1159write_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. */
1174void
1175write_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. */
1259void
1260write_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. */
1304void
1305write_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. */
1335void
1336write_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. */
1362void
1363write_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
1496int
1497write_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
1538static 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
1550static int
1551is_special_builtin (name)
1552     char *name;
1553{
1554  return (_find_in_table (name, special_builtins));
1555}
1556
1557static int
1558is_assignment_builtin (name)
1559     char *name;
1560{
1561  return (_find_in_table (name, assignment_builtins));
1562}
1563
1564#if !defined (HAVE_RENAME)
1565static int
1566rename (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 */
1576