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