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