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