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