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