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