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