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