source: vendor/bash/3.1/builtins/mkbuiltins.c

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

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