]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/mkbuiltins.c
Imported from ../bash-2.05b.tar.gz.
[thirdparty/bash.git] / builtins / mkbuiltins.c
CommitLineData
726f6388
JA
1/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
3
7117c2d2 4/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
726f6388
JA
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
bb70624e 10Software Foundation; either version 2, or (at your option) any later
726f6388
JA
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
bb70624e 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
726f6388 21
ccc6cda3
JA
22#include <config.h>
23
24#if defined (HAVE_UNISTD_H)
cce855bc
JA
25# ifdef _MINIX
26# include <sys/types.h>
27# endif
ccc6cda3
JA
28# include <unistd.h>
29#endif
30
cce855bc 31#ifndef _MINIX
d166f048 32#include "../bashtypes.h"
726f6388 33#include <sys/file.h>
cce855bc
JA
34#endif
35
bb70624e
JA
36#include "posixstat.h"
37#include "filecntl.h"
726f6388 38
d166f048
JA
39#include "../bashansi.h"
40#include <stdio.h>
7117c2d2 41#include <errno.h>
726f6388 42
f73dda09
JA
43#include "stdc.h"
44
726f6388
JA
45#define DOCFILE "builtins.texi"
46
7117c2d2
JA
47#ifndef errno
48extern int errno;
49#endif
50
726f6388
JA
51static char *xmalloc (), *xrealloc ();
52
53#if !defined (__STDC__) && !defined (strcpy)
54extern 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
ccc6cda3 62#define BUILTIN_FLAG_ASSIGNMENT 0x02
726f6388
JA
63
64/* If this stream descriptor is non-zero, then write
65 texinfo documentation to it. */
66FILE *documentation_file = (FILE *)NULL;
67
68/* Non-zero means to only produce documentation. */
69int only_documentation = 0;
70
71/* Non-zero means to not do any productions. */
72int inhibit_production = 0;
73
7117c2d2
JA
74/* Non-zero means to produce separate help files for each builtin, named by
75 the builtin name, in `./helpfiles'. */
76int separate_helpfiles = 0;
77
78/* The name of a directory into which the separate external help files will
79 eventually be installed. */
80char *helpfile_directory;
726f6388
JA
81
82/* The name of a directory to precede the filename when reporting
83 errors. */
84char *error_directory = (char *)NULL;
85
86/* The name of the structure file. */
87char *struct_filename = (char *)NULL;
88
89/* The name of the external declaration file. */
90char *extern_filename = (char *)NULL;
91
92/* Here is a structure for manipulating arrays of data. */
93typedef 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. */
102typedef 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. */
113typedef 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. */
123ARRAY *saved_builtins = (ARRAY *)NULL;
124
125/* The Posix.2 so-called `special' builtins. */
126char *special_builtins[] =
127{
128 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
129 "export", "readonly", "return", "set", "shift", "trap", "unset",
130 (char *)NULL
131};
ccc6cda3
JA
132
133/* The builtin commands that take assignment statements as arguments. */
134char *assignment_builtins[] =
135{
136 "alias", "declare", "export", "local", "readonly", "typeset",
137 (char *)NULL
138};
139
140/* Forward declarations. */
726f6388 141static int is_special_builtin ();
ccc6cda3
JA
142static int is_assignment_builtin ();
143
b72432fd
JA
144#if !defined (HAVE_RENAME)
145static int rename ();
146#endif
147
ccc6cda3
JA
148void extract_info ();
149
150void file_error ();
151void line_error ();
152
153void write_file_headers ();
154void write_file_footers ();
155void write_ifdefs ();
156void write_endifs ();
157void write_documentation ();
158void write_longdocs ();
159void write_builtins ();
726f6388 160
7117c2d2
JA
161int write_helpfiles ();
162
ccc6cda3
JA
163void free_defs ();
164void add_documentation ();
165
166void must_be_building ();
167void remove_trailing_whitespace ();
7117c2d2
JA
168
169#define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
170
726f6388
JA
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. */
ccc6cda3 175int
726f6388
JA
176main (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 }
7117c2d2
JA
221 else if (strcmp (arg, "-H") == 0)
222 {
223 separate_helpfiles = 1;
224 helpfile_directory = argv[arg_index++];
225 }
726f6388
JA
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);
f73dda09 243 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
726f6388
JA
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);
b72432fd 289 rename (temp_struct_filename, struct_filename);
726f6388
JA
290 }
291
292 if (externfile)
293 fclose (externfile);
294 }
295
7117c2d2
JA
296 if (separate_helpfiles)
297 {
298 write_helpfiles (saved_builtins);
299 }
300
726f6388
JA
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. */
318ARRAY *
319array_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. */
338ARRAY *
339copy_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. */
ccc6cda3 365void
726f6388
JA
366array_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)
d166f048 375 bcopy (&element, (char *) &(array->array[array->sindex]), array->width);
726f6388 376 array->sindex++;
d166f048 377 bzero ((char *) &(array->array[array->sindex]), array->width);
726f6388
JA
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. */
ccc6cda3 385void
726f6388
JA
386array_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. */
402typedef int Function ();
f73dda09 403typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
726f6388
JA
404
405/* Structure handles processor directives. */
406typedef struct {
407 char *directive;
f73dda09 408 mk_handler_func_t *function;
726f6388
JA
409} HANDLER_ENTRY;
410
f73dda09
JA
411extern int builtin_handler __P((char *, DEF_FILE *, char *));
412extern int function_handler __P((char *, DEF_FILE *, char *));
413extern int short_doc_handler __P((char *, DEF_FILE *, char *));
414extern int comment_handler __P((char *, DEF_FILE *, char *));
415extern int depends_on_handler __P((char *, DEF_FILE *, char *));
416extern int produces_handler __P((char *, DEF_FILE *, char *));
417extern int end_handler __P((char *, DEF_FILE *, char *));
418extern int docname_handler __P((char *, DEF_FILE *, char *));
726f6388
JA
419
420HANDLER_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 },
f73dda09 430 { (char *)NULL, (mk_handler_func_t *)NULL }
726f6388
JA
431};
432
433/* Return the entry in the table of handlers for NAME. */
434HANDLER_ENTRY *
435find_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. */
449static 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. */
453int 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". */
ccc6cda3 464void
726f6388
JA
465extract_info (filename, structfile, externfile)
466 char *filename;
467 FILE *structfile, *externfile;
468{
469 register int i;
470 DEF_FILE *defs;
471 struct stat finfo;
cce855bc 472 size_t file_size;
726f6388 473 char *buffer, *line;
cce855bc 474 int fd, nr;
726f6388
JA
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
cce855bc
JA
484 file_size = (size_t)finfo.st_size;
485 buffer = xmalloc (1 + file_size);
726f6388 486
cce855bc 487 if ((nr = read (fd, buffer, file_size)) < 0)
726f6388
JA
488 file_error (filename);
489
b72432fd
JA
490 /* This is needed on WIN32, and does not hurt on Unix. */
491 if (nr < file_size)
492 file_size = nr;
493
726f6388
JA
494 close (fd);
495
cce855bc
JA
496 if (nr == 0)
497 {
498 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
499 return;
500 }
501
726f6388
JA
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;
cce855bc 513 while (i < file_size)
726f6388
JA
514 {
515 array_add (&buffer[i], defs->lines);
516
cce855bc 517 while (buffer[i] != '\n' && i < file_size)
726f6388
JA
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
605static void
606free_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. */
ccc6cda3 628void
726f6388
JA
629free_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++)
28ef6c31 644 {
726f6388
JA
645 free_builtin (builtin);
646 free (builtin);
28ef6c31 647 }
726f6388
JA
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. */
661char *
662strip_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. */
ccc6cda3 673void
726f6388
JA
674remove_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. */
691char *
692get_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. */
ccc6cda3 707void
726f6388
JA
708must_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. */
717BUILTIN_DESC *
718current_builtin (directive, defs)
719 char *directive;
720 DEF_FILE *defs;
721{
722 must_be_building (directive, defs);
cce855bc
JA
723 if (defs->builtins)
724 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
725 else
726 return ((BUILTIN_DESC *)NULL);
726f6388
JA
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. */
ccc6cda3 731void
726f6388
JA
732add_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. */
752int
753builtin_handler (self, defs, arg)
f73dda09 754 char *self;
726f6388 755 DEF_FILE *defs;
f73dda09 756 char *arg;
726f6388 757{
ccc6cda3
JA
758 BUILTIN_DESC *new;
759 char *name;
760
726f6388
JA
761 /* If we are already building a builtin, we cannot start a new one. */
762 if (building_builtin)
ccc6cda3
JA
763 {
764 line_error (defs, "%s found before $END", self);
765 return (-1);
766 }
726f6388
JA
767
768 output_cpp_line_info++;
769
770 /* Get the name of this builtin, and stick it in the array. */
ccc6cda3
JA
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
726f6388
JA
794 return (0);
795}
796
797/* How to handle the $FUNCTION directive. */
798int
799function_handler (self, defs, arg)
f73dda09 800 char *self;
726f6388 801 DEF_FILE *defs;
f73dda09 802 char *arg;
726f6388
JA
803{
804 register BUILTIN_DESC *builtin;
805
806 builtin = current_builtin (self, defs);
807
cce855bc
JA
808 if (builtin == 0)
809 {
810 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
811 exit (1);
812 }
726f6388
JA
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. */
823int
824docname_handler (self, defs, arg)
f73dda09 825 char *self;
726f6388 826 DEF_FILE *defs;
f73dda09 827 char *arg;
726f6388
JA
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. */
ccc6cda3 843int
726f6388 844short_doc_handler (self, defs, arg)
f73dda09 845 char *self;
726f6388 846 DEF_FILE *defs;
f73dda09 847 char *arg;
726f6388
JA
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. */
ccc6cda3 863int
f73dda09 864comment_handler (self, defs, arg)
726f6388
JA
865 char *self;
866 DEF_FILE *defs;
f73dda09 867 char *arg;
726f6388 868{
ccc6cda3 869 return (0);
726f6388
JA
870}
871
872/* How to handle the $DEPENDS_ON directive. */
ccc6cda3 873int
726f6388 874depends_on_handler (self, defs, arg)
f73dda09 875 char *self;
726f6388 876 DEF_FILE *defs;
f73dda09 877 char *arg;
726f6388
JA
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. */
ccc6cda3 894int
726f6388 895produces_handler (self, defs, arg)
f73dda09 896 char *self;
726f6388 897 DEF_FILE *defs;
f73dda09 898 char *arg;
726f6388
JA
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. */
ccc6cda3 928int
726f6388 929end_handler (self, defs, arg)
f73dda09 930 char *self;
726f6388 931 DEF_FILE *defs;
f73dda09 932 char *arg;
726f6388
JA
933{
934 must_be_building (self, defs);
935 building_builtin = 0;
ccc6cda3 936 return (0);
726f6388
JA
937}
938
939/* **************************************************************** */
940/* */
941/* Error Handling Functions */
942/* */
943/* **************************************************************** */
944
945/* Produce an error for DEFS with FORMAT and ARGS. */
ccc6cda3 946void
726f6388
JA
947line_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. */
ccc6cda3 960void
726f6388
JA
961file_error (filename)
962 char *filename;
963{
964 perror (filename);
965 exit (2);
966}
967
968/* **************************************************************** */
969/* */
970/* xmalloc and xrealloc () */
971/* */
972/* **************************************************************** */
973
974static void memory_error_and_abort ();
975
976static char *
977xmalloc (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
987static char *
988xrealloc (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
1005static void
1006memory_error_and_abort ()
1007{
ccc6cda3 1008 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
726f6388
JA
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. */
1020BUILTIN_DESC *
1021copy_builtin (builtin)
1022 BUILTIN_DESC *builtin;
1023{
1024 BUILTIN_DESC *new;
1025
1026 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1027
28ef6c31
JA
1028 new->name = savestring (builtin->name);
1029 new->shortdoc = savestring (builtin->shortdoc);
1030 new->longdoc = copy_string_array (builtin->longdoc);
726f6388
JA
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. */
ccc6cda3 1042void
726f6388
JA
1043save_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 (). */
7117c2d2
JA
1059#define STRING_ARRAY 1
1060#define TEXINFO 2
1061#define PLAINTEXT 4
726f6388
JA
1062
1063char *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 "",
7117c2d2 1069 "/* Copyright (C) 1987-2002 Free Software Foundation, Inc.",
726f6388
JA
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",
bb70624e 1075 " the Free Software Foundation; either version 2, or (at your option)",
726f6388
JA
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",
bb70624e 1085 " Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */",
726f6388 1086 "",
ccc6cda3 1087 "/* The list of shell builtins. Each element is name, function, flags,",
726f6388
JA
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",
f73dda09 1095 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
726f6388
JA
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
1103char *structfile_footer[] = {
f73dda09 1104 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0 }",
726f6388
JA
1105 "};",
1106 "",
ccc6cda3
JA
1107 "struct builtin *shell_builtins = static_shell_builtins;",
1108 "struct builtin *current_builtin;",
1109 "",
726f6388 1110 "int num_shell_builtins =",
ccc6cda3 1111 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
726f6388
JA
1112 (char *)NULL
1113};
1114
1115/* Write out any neccessary opening information for
1116 STRUCTFILE and EXTERNFILE. */
ccc6cda3 1117void
726f6388
JA
1118write_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");
ccc6cda3 1130 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
726f6388
JA
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. */
ccc6cda3 1141void
726f6388
JA
1142write_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. */
ccc6cda3 1157void
726f6388
JA
1158write_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 {
ccc6cda3 1178 write_ifdefs (externfile, builtin->dependencies->array);
726f6388
JA
1179 write_ifdefs (structfile, builtin->dependencies->array);
1180 }
1181
1182 /* Write the extern definition. */
1183 if (externfile)
1184 {
1185 if (builtin->function)
f73dda09 1186 fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
726f6388
JA
1187 builtin->function);
1188
7117c2d2
JA
1189 fprintf (externfile, "extern char * const %s_doc[];\n",
1190 document_name (builtin));
726f6388
JA
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
f73dda09 1201 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
726f6388 1202
ccc6cda3
JA
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" : "",
7117c2d2 1207 document_name (builtin));
726f6388 1208
726f6388 1209 fprintf
ccc6cda3 1210 (structfile, " \"%s\", (char *)NULL },\n",
726f6388
JA
1211 builtin->shortdoc ? builtin->shortdoc : builtin->name);
1212
726f6388
JA
1213 }
1214
7117c2d2
JA
1215 if (structfile || separate_helpfiles)
1216 /* Save away this builtin for later writing of the
1217 long documentation strings. */
1218 save_builtin (builtin);
1219
726f6388
JA
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. */
ccc6cda3 1242void
726f6388
JA
1243write_longdocs (stream, builtins)
1244 FILE *stream;
1245 ARRAY *builtins;
1246{
1247 register int i;
1248 register BUILTIN_DESC *builtin;
7117c2d2
JA
1249 char *dname;
1250 char *sarray[2];
726f6388
JA
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. */
7117c2d2
JA
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);
726f6388
JA
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. */
ccc6cda3 1287void
726f6388
JA
1288write_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. */
ccc6cda3 1318void
726f6388
JA
1319write_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. */
ccc6cda3 1343void
726f6388
JA
1344write_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;
ccc6cda3 1351 int string_array, texinfo;
726f6388
JA
1352
1353 if (!stream)
1354 return;
1355
ccc6cda3 1356 string_array = flags & STRING_ARRAY;
726f6388 1357 if (string_array)
ccc6cda3 1358 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
726f6388 1359
ccc6cda3 1360 for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
726f6388
JA
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
726f6388 1417 if (string_array)
ccc6cda3 1418 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
726f6388
JA
1419}
1420
7117c2d2
JA
1421int
1422write_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
726f6388 1463static int
ccc6cda3
JA
1464_find_in_table (name, name_table)
1465 char *name, *name_table[];
726f6388
JA
1466{
1467 register int i;
1468
ccc6cda3
JA
1469 for (i = 0; name_table[i]; i++)
1470 if (strcmp (name, name_table[i]) == 0)
726f6388
JA
1471 return 1;
1472 return 0;
1473}
ccc6cda3
JA
1474
1475static int
1476is_special_builtin (name)
1477 char *name;
1478{
1479 return (_find_in_table (name, special_builtins));
1480}
1481
1482static int
1483is_assignment_builtin (name)
1484 char *name;
1485{
1486 return (_find_in_table (name, assignment_builtins));
1487}
b72432fd
JA
1488
1489#if !defined (HAVE_RENAME)
1490static int
1491rename (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 */