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