blob: e5177b2e1b88b922cc29430e0f0c7478a4aefed8 [file] [log] [blame]
Jari Aalto726f6381996-08-26 18:22:31 +00001/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
2 a single source file called builtins.def. */
3
Chet Rameyac50fba2014-02-26 09:36:43 -05004/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
Jari Aalto726f6381996-08-26 18:22:31 +00005
Jari Aalto31859422009-01-12 13:36:28 +00006 This file is part of GNU Bash, the Bourne Again SHell.
Jari Aalto726f6381996-08-26 18:22:31 +00007
Jari Aalto31859422009-01-12 13:36:28 +00008 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.
Jari Aalto726f6381996-08-26 18:22:31 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013 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.
Jari Aalto726f6381996-08-26 18:22:31 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018 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*/
Jari Aalto726f6381996-08-26 18:22:31 +000021
Jari Aalto06285672006-10-10 14:15:34 +000022#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 */
Jari Aaltoccc6cda1996-12-23 17:02:34 +000032
33#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000034# ifdef _MINIX
35# include <sys/types.h>
36# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000037# include <unistd.h>
38#endif
39
Jari Aaltocce855b1998-04-17 19:52:44 +000040#ifndef _MINIX
Jari Aaltob80f6442004-07-27 13:29:18 +000041# include "../bashtypes.h"
42# if defined (HAVE_SYS_FILE_H)
43# include <sys/file.h>
44# endif
Jari Aaltocce855b1998-04-17 19:52:44 +000045#endif
46
Jari Aaltobb706242000-03-17 21:46:59 +000047#include "posixstat.h"
48#include "filecntl.h"
Jari Aalto726f6381996-08-26 18:22:31 +000049
Jari Aaltod166f041997-06-05 14:59:13 +000050#include "../bashansi.h"
51#include <stdio.h>
Jari Aalto7117c2d2002-07-17 14:10:11 +000052#include <errno.h>
Jari Aalto726f6381996-08-26 18:22:31 +000053
Jari Aaltof73dda02001-11-13 17:56:06 +000054#include "stdc.h"
55
Jari Aalto726f6381996-08-26 18:22:31 +000056#define DOCFILE "builtins.texi"
57
Jari Aalto7117c2d2002-07-17 14:10:11 +000058#ifndef errno
Ricardo Cerqueiraa02fbff2013-07-25 22:35:34 +010059#include <errno.h>
Jari Aalto7117c2d2002-07-17 14:10:11 +000060#endif
61
Jari Aalto726f6381996-08-26 18:22:31 +000062static 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
Jari Aaltoccc6cda1996-12-23 17:02:34 +000073#define BUILTIN_FLAG_ASSIGNMENT 0x02
Jari Aalto31859422009-01-12 13:36:28 +000074#define BUILTIN_FLAG_POSIX_BUILTIN 0x04
Jari Aalto726f6381996-08-26 18:22:31 +000075
Jari Aalto95732b42005-12-07 14:08:12 +000076#define BASE_INDENT 4
77
Jari Aalto726f6381996-08-26 18:22:31 +000078/* If this stream descriptor is non-zero, then write
79 texinfo documentation to it. */
80FILE *documentation_file = (FILE *)NULL;
81
82/* Non-zero means to only produce documentation. */
83int only_documentation = 0;
84
85/* Non-zero means to not do any productions. */
86int inhibit_production = 0;
87
Chet Rameyac50fba2014-02-26 09:36:43 -050088/* Non-zero means to not add functions (xxx_builtin) to the members of the
89 produced `struct builtin []' */
90int inhibit_functions = 0;
91
Jari Aalto7117c2d2002-07-17 14:10:11 +000092/* Non-zero means to produce separate help files for each builtin, named by
93 the builtin name, in `./helpfiles'. */
94int separate_helpfiles = 0;
95
Jari Aalto95732b42005-12-07 14:08:12 +000096/* Non-zero means to create single C strings for each `longdoc', with
97 embedded newlines, for ease of translation. */
98int single_longdoc_strings = 1;
99
Jari Aalto7117c2d2002-07-17 14:10:11 +0000100/* The name of a directory into which the separate external help files will
101 eventually be installed. */
102char *helpfile_directory;
Jari Aalto726f6381996-08-26 18:22:31 +0000103
104/* The name of a directory to precede the filename when reporting
105 errors. */
106char *error_directory = (char *)NULL;
107
108/* The name of the structure file. */
109char *struct_filename = (char *)NULL;
110
111/* The name of the external declaration file. */
112char *extern_filename = (char *)NULL;
113
114/* Here is a structure for manipulating arrays of data. */
115typedef struct {
116 int size; /* Number of slots allocated to array. */
117 int sindex; /* Current location in array. */
118 int width; /* Size of each element. */
119 int growth_rate; /* How fast to grow. */
120 char **array; /* The array itself. */
121} ARRAY;
122
123/* Here is a structure defining a single BUILTIN. */
124typedef struct {
125 char *name; /* The name of this builtin. */
126 char *function; /* The name of the function to call. */
127 char *shortdoc; /* The short documentation for this builtin. */
128 char *docname; /* Possible name for documentation string. */
129 ARRAY *longdoc; /* The long documentation for this builtin. */
130 ARRAY *dependencies; /* Null terminated array of #define names. */
131 int flags; /* Flags for this builtin. */
132} BUILTIN_DESC;
133
134/* Here is a structure which defines a DEF file. */
135typedef struct {
136 char *filename; /* The name of the input def file. */
137 ARRAY *lines; /* The contents of the file. */
138 int line_number; /* The current line number. */
139 char *production; /* The name of the production file. */
140 FILE *output; /* Open file stream for PRODUCTION. */
141 ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
142} DEF_FILE;
143
144/* The array of all builtins encountered during execution of this code. */
145ARRAY *saved_builtins = (ARRAY *)NULL;
146
147/* The Posix.2 so-called `special' builtins. */
148char *special_builtins[] =
149{
150 ":", ".", "source", "break", "continue", "eval", "exec", "exit",
Jari Aalto95732b42005-12-07 14:08:12 +0000151 "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
Jari Aalto726f6381996-08-26 18:22:31 +0000152 (char *)NULL
153};
Jari Aalto726f6381996-08-26 18:22:31 +0000154
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000155/* The builtin commands that take assignment statements as arguments. */
156char *assignment_builtins[] =
157{
158 "alias", "declare", "export", "local", "readonly", "typeset",
159 (char *)NULL
160};
161
Jari Aalto31859422009-01-12 13:36:28 +0000162/* The builtin commands that are special to the POSIX search order. */
163char *posix_builtins[] =
164{
165 "alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "jobs",
166 "kill", "newgrp", "pwd", "read", "true", "umask", "unalias", "wait",
167 (char *)NULL
168};
169
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000170/* Forward declarations. */
171static int is_special_builtin ();
172static int is_assignment_builtin ();
Jari Aalto31859422009-01-12 13:36:28 +0000173static int is_posix_builtin ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000174
Jari Aaltob72432f1999-02-19 17:11:39 +0000175#if !defined (HAVE_RENAME)
176static int rename ();
177#endif
178
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000179void extract_info ();
180
181void file_error ();
182void line_error ();
183
184void write_file_headers ();
185void write_file_footers ();
186void write_ifdefs ();
187void write_endifs ();
188void write_documentation ();
189void write_longdocs ();
190void write_builtins ();
191
Jari Aalto7117c2d2002-07-17 14:10:11 +0000192int write_helpfiles ();
193
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000194void free_defs ();
195void add_documentation ();
196
197void must_be_building ();
198void remove_trailing_whitespace ();
Jari Aalto7117c2d2002-07-17 14:10:11 +0000199
200#define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
201
Jari Aalto726f6381996-08-26 18:22:31 +0000202
203/* For each file mentioned on the command line, process it and
204 write the information to STRUCTFILE and EXTERNFILE, while
Chet Rameyac50fba2014-02-26 09:36:43 -0500205 creating the production file if necessary. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000206int
Jari Aalto726f6381996-08-26 18:22:31 +0000207main (argc, argv)
208 int argc;
209 char **argv;
210{
211 int arg_index = 1;
212 FILE *structfile, *externfile;
213 char *documentation_filename, *temp_struct_filename;
214
215 structfile = externfile = (FILE *)NULL;
216 documentation_filename = DOCFILE;
217 temp_struct_filename = (char *)NULL;
218
219 while (arg_index < argc && argv[arg_index][0] == '-')
220 {
221 char *arg = argv[arg_index++];
222
223 if (strcmp (arg, "-externfile") == 0)
224 extern_filename = argv[arg_index++];
225 else if (strcmp (arg, "-structfile") == 0)
226 struct_filename = argv[arg_index++];
227 else if (strcmp (arg, "-noproduction") == 0)
228 inhibit_production = 1;
Chet Rameyac50fba2014-02-26 09:36:43 -0500229 else if (strcmp (arg, "-nofunctions") == 0)
230 inhibit_functions = 1;
Jari Aalto726f6381996-08-26 18:22:31 +0000231 else if (strcmp (arg, "-document") == 0)
232 documentation_file = fopen (documentation_filename, "w");
233 else if (strcmp (arg, "-D") == 0)
234 {
235 int len;
236
237 if (error_directory)
238 free (error_directory);
239
240 error_directory = xmalloc (2 + strlen (argv[arg_index]));
241 strcpy (error_directory, argv[arg_index]);
242 len = strlen (error_directory);
243
244 if (len && error_directory[len - 1] != '/')
245 strcat (error_directory, "/");
246
247 arg_index++;
248 }
249 else if (strcmp (arg, "-documentonly") == 0)
250 {
251 only_documentation = 1;
252 documentation_file = fopen (documentation_filename, "w");
253 }
Jari Aalto7117c2d2002-07-17 14:10:11 +0000254 else if (strcmp (arg, "-H") == 0)
255 {
256 separate_helpfiles = 1;
257 helpfile_directory = argv[arg_index++];
258 }
Jari Aalto95732b42005-12-07 14:08:12 +0000259 else if (strcmp (arg, "-S") == 0)
260 single_longdoc_strings = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000261 else
262 {
263 fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
264 exit (2);
265 }
266 }
267
268 /* If there are no files to process, just quit now. */
269 if (arg_index == argc)
270 exit (0);
271
272 if (!only_documentation)
273 {
274 /* Open the files. */
275 if (struct_filename)
276 {
277 temp_struct_filename = xmalloc (15);
Jari Aaltof73dda02001-11-13 17:56:06 +0000278 sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
Jari Aalto726f6381996-08-26 18:22:31 +0000279 structfile = fopen (temp_struct_filename, "w");
280
281 if (!structfile)
282 file_error (temp_struct_filename);
283 }
284
285 if (extern_filename)
286 {
287 externfile = fopen (extern_filename, "w");
288
289 if (!externfile)
290 file_error (extern_filename);
291 }
292
293 /* Write out the headers. */
294 write_file_headers (structfile, externfile);
295 }
296
297 if (documentation_file)
298 {
299 fprintf (documentation_file, "@c Table of builtins created with %s.\n",
300 argv[0]);
301 fprintf (documentation_file, "@ftable @asis\n");
302 }
303
304 /* Process the .def files. */
305 while (arg_index < argc)
306 {
307 register char *arg;
308
309 arg = argv[arg_index++];
310
311 extract_info (arg, structfile, externfile);
312 }
313
314 /* Close the files. */
315 if (!only_documentation)
316 {
317 /* Write the footers. */
318 write_file_footers (structfile, externfile);
319
320 if (structfile)
321 {
322 write_longdocs (structfile, saved_builtins);
323 fclose (structfile);
Jari Aaltob72432f1999-02-19 17:11:39 +0000324 rename (temp_struct_filename, struct_filename);
Jari Aalto726f6381996-08-26 18:22:31 +0000325 }
326
327 if (externfile)
328 fclose (externfile);
329 }
330
Chet Rameyac50fba2014-02-26 09:36:43 -0500331#if 0
332 /* This is now done by a different program */
Jari Aalto7117c2d2002-07-17 14:10:11 +0000333 if (separate_helpfiles)
334 {
335 write_helpfiles (saved_builtins);
336 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500337#endif
Jari Aalto7117c2d2002-07-17 14:10:11 +0000338
Jari Aalto726f6381996-08-26 18:22:31 +0000339 if (documentation_file)
340 {
341 fprintf (documentation_file, "@end ftable\n");
342 fclose (documentation_file);
343 }
344
345 exit (0);
346}
347
348/* **************************************************************** */
349/* */
350/* Array Functions and Manipulators */
351/* */
352/* **************************************************************** */
353
354/* Make a new array, and return a pointer to it. The array will
355 contain elements of size WIDTH, and is initialized to no elements. */
356ARRAY *
357array_create (width)
358 int width;
359{
360 ARRAY *array;
361
362 array = (ARRAY *)xmalloc (sizeof (ARRAY));
363 array->size = 0;
364 array->sindex = 0;
365 array->width = width;
366
367 /* Default to increasing size in units of 20. */
368 array->growth_rate = 20;
369
370 array->array = (char **)NULL;
371
372 return (array);
373}
374
375/* Copy the array of strings in ARRAY. */
376ARRAY *
377copy_string_array (array)
378 ARRAY *array;
379{
380 register int i;
381 ARRAY *copy;
382
383 if (!array)
384 return (ARRAY *)NULL;
385
386 copy = array_create (sizeof (char *));
387
388 copy->size = array->size;
389 copy->sindex = array->sindex;
390 copy->width = array->width;
391
392 copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
393
394 for (i = 0; i < array->sindex; i++)
395 copy->array[i] = savestring (array->array[i]);
396
397 copy->array[i] = (char *)NULL;
398
399 return (copy);
400}
401
Chet Rameyac50fba2014-02-26 09:36:43 -0500402/* Add ELEMENT to ARRAY, growing the array if necessary. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000403void
Jari Aalto726f6381996-08-26 18:22:31 +0000404array_add (element, array)
405 char *element;
406 ARRAY *array;
407{
408 if (array->sindex + 2 > array->size)
409 array->array = (char **)xrealloc
410 (array->array, (array->size += array->growth_rate) * array->width);
411
Jari Aalto726f6381996-08-26 18:22:31 +0000412 array->array[array->sindex++] = element;
413 array->array[array->sindex] = (char *)NULL;
Jari Aalto726f6381996-08-26 18:22:31 +0000414}
415
416/* Free an allocated array and data pointer. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000417void
Jari Aalto726f6381996-08-26 18:22:31 +0000418array_free (array)
419 ARRAY *array;
420{
421 if (array->array)
422 free (array->array);
423
424 free (array);
425}
426
427/* **************************************************************** */
428/* */
429/* Processing a DEF File */
430/* */
431/* **************************************************************** */
432
433/* The definition of a function. */
434typedef int Function ();
Jari Aaltof73dda02001-11-13 17:56:06 +0000435typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
Jari Aalto726f6381996-08-26 18:22:31 +0000436
437/* Structure handles processor directives. */
438typedef struct {
439 char *directive;
Jari Aaltof73dda02001-11-13 17:56:06 +0000440 mk_handler_func_t *function;
Jari Aalto726f6381996-08-26 18:22:31 +0000441} HANDLER_ENTRY;
442
Jari Aaltof73dda02001-11-13 17:56:06 +0000443extern int builtin_handler __P((char *, DEF_FILE *, char *));
444extern int function_handler __P((char *, DEF_FILE *, char *));
445extern int short_doc_handler __P((char *, DEF_FILE *, char *));
446extern int comment_handler __P((char *, DEF_FILE *, char *));
447extern int depends_on_handler __P((char *, DEF_FILE *, char *));
448extern int produces_handler __P((char *, DEF_FILE *, char *));
449extern int end_handler __P((char *, DEF_FILE *, char *));
450extern int docname_handler __P((char *, DEF_FILE *, char *));
Jari Aalto726f6381996-08-26 18:22:31 +0000451
452HANDLER_ENTRY handlers[] = {
453 { "BUILTIN", builtin_handler },
454 { "DOCNAME", docname_handler },
455 { "FUNCTION", function_handler },
456 { "SHORT_DOC", short_doc_handler },
457 { "$", comment_handler },
458 { "COMMENT", comment_handler },
459 { "DEPENDS_ON", depends_on_handler },
460 { "PRODUCES", produces_handler },
461 { "END", end_handler },
Jari Aaltof73dda02001-11-13 17:56:06 +0000462 { (char *)NULL, (mk_handler_func_t *)NULL }
Jari Aalto726f6381996-08-26 18:22:31 +0000463};
464
465/* Return the entry in the table of handlers for NAME. */
466HANDLER_ENTRY *
467find_directive (directive)
468 char *directive;
469{
470 register int i;
471
472 for (i = 0; handlers[i].directive; i++)
473 if (strcmp (handlers[i].directive, directive) == 0)
474 return (&handlers[i]);
475
476 return ((HANDLER_ENTRY *)NULL);
477}
478
479/* Non-zero indicates that a $BUILTIN has been seen, but not
480 the corresponding $END. */
481static int building_builtin = 0;
482
483/* Non-zero means to output cpp line and file information before
484 printing the current line to the production file. */
485int output_cpp_line_info = 0;
486
487/* The main function of this program. Read FILENAME and act on what is
488 found. Lines not starting with a dollar sign are copied to the
489 $PRODUCES target, if one is present. Lines starting with a dollar sign
490 are directives to this program, specifying the name of the builtin, the
491 function to call, the short documentation and the long documentation
492 strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
493 target. After the file has been processed, write out the names of
494 builtins found in each $BUILTIN. Plain text found before the $PRODUCES
495 is ignored, as is "$$ comment text". */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000496void
Jari Aalto726f6381996-08-26 18:22:31 +0000497extract_info (filename, structfile, externfile)
498 char *filename;
499 FILE *structfile, *externfile;
500{
501 register int i;
502 DEF_FILE *defs;
503 struct stat finfo;
Jari Aaltocce855b1998-04-17 19:52:44 +0000504 size_t file_size;
Jari Aalto726f6381996-08-26 18:22:31 +0000505 char *buffer, *line;
Jari Aaltocce855b1998-04-17 19:52:44 +0000506 int fd, nr;
Jari Aalto726f6381996-08-26 18:22:31 +0000507
508 if (stat (filename, &finfo) == -1)
509 file_error (filename);
510
511 fd = open (filename, O_RDONLY, 0666);
512
513 if (fd == -1)
514 file_error (filename);
515
Jari Aaltocce855b1998-04-17 19:52:44 +0000516 file_size = (size_t)finfo.st_size;
517 buffer = xmalloc (1 + file_size);
Jari Aalto726f6381996-08-26 18:22:31 +0000518
Jari Aaltocce855b1998-04-17 19:52:44 +0000519 if ((nr = read (fd, buffer, file_size)) < 0)
Jari Aalto726f6381996-08-26 18:22:31 +0000520 file_error (filename);
521
Jari Aaltob72432f1999-02-19 17:11:39 +0000522 /* This is needed on WIN32, and does not hurt on Unix. */
523 if (nr < file_size)
524 file_size = nr;
525
Jari Aalto726f6381996-08-26 18:22:31 +0000526 close (fd);
527
Jari Aaltocce855b1998-04-17 19:52:44 +0000528 if (nr == 0)
529 {
530 fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
Chet Rameyac50fba2014-02-26 09:36:43 -0500531 free (buffer);
Jari Aaltocce855b1998-04-17 19:52:44 +0000532 return;
533 }
534
Jari Aalto726f6381996-08-26 18:22:31 +0000535 /* Create and fill in the initial structure describing this file. */
536 defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
537 defs->filename = filename;
538 defs->lines = array_create (sizeof (char *));
539 defs->line_number = 0;
540 defs->production = (char *)NULL;
541 defs->output = (FILE *)NULL;
542 defs->builtins = (ARRAY *)NULL;
543
544 /* Build the array of lines. */
545 i = 0;
Jari Aaltocce855b1998-04-17 19:52:44 +0000546 while (i < file_size)
Jari Aalto726f6381996-08-26 18:22:31 +0000547 {
548 array_add (&buffer[i], defs->lines);
549
Chet Rameyac50fba2014-02-26 09:36:43 -0500550 while (i < file_size && buffer[i] != '\n')
Jari Aalto726f6381996-08-26 18:22:31 +0000551 i++;
552 buffer[i++] = '\0';
553 }
554
555 /* Begin processing the input file. We don't write any output
556 until we have a file to write output to. */
557 output_cpp_line_info = 1;
558
559 /* Process each line in the array. */
560 for (i = 0; line = defs->lines->array[i]; i++)
561 {
562 defs->line_number = i;
563
564 if (*line == '$')
565 {
566 register int j;
567 char *directive;
568 HANDLER_ENTRY *handler;
569
570 /* Isolate the directive. */
571 for (j = 0; line[j] && !whitespace (line[j]); j++);
572
573 directive = xmalloc (j);
574 strncpy (directive, line + 1, j - 1);
575 directive[j -1] = '\0';
576
577 /* Get the function handler and call it. */
578 handler = find_directive (directive);
579
580 if (!handler)
581 {
582 line_error (defs, "Unknown directive `%s'", directive);
583 free (directive);
584 continue;
585 }
586 else
587 {
588 /* Advance to the first non-whitespace character. */
589 while (whitespace (line[j]))
590 j++;
591
592 /* Call the directive handler with the FILE, and ARGS. */
593 (*(handler->function)) (directive, defs, line + j);
594 }
595 free (directive);
596 }
597 else
598 {
599 if (building_builtin)
600 add_documentation (defs, line);
601 else if (defs->output)
602 {
603 if (output_cpp_line_info)
604 {
605 /* If we're handed an absolute pathname, don't prepend
606 the directory name. */
607 if (defs->filename[0] == '/')
608 fprintf (defs->output, "#line %d \"%s\"\n",
609 defs->line_number + 1, defs->filename);
610 else
611 fprintf (defs->output, "#line %d \"%s%s\"\n",
612 defs->line_number + 1,
613 error_directory ? error_directory : "./",
614 defs->filename);
615 output_cpp_line_info = 0;
616 }
617
618 fprintf (defs->output, "%s\n", line);
619 }
620 }
621 }
622
623 /* Close the production file. */
624 if (defs->output)
625 fclose (defs->output);
626
627 /* The file has been processed. Write the accumulated builtins to
628 the builtins.c file, and write the extern definitions to the
629 builtext.h file. */
630 write_builtins (defs, structfile, externfile);
631
632 free (buffer);
633 free_defs (defs);
634}
635
636#define free_safely(x) if (x) free (x)
637
638static void
639free_builtin (builtin)
640 BUILTIN_DESC *builtin;
641{
642 register int i;
643
644 free_safely (builtin->name);
645 free_safely (builtin->function);
646 free_safely (builtin->shortdoc);
647 free_safely (builtin->docname);
648
649 if (builtin->longdoc)
650 array_free (builtin->longdoc);
651
652 if (builtin->dependencies)
653 {
654 for (i = 0; builtin->dependencies->array[i]; i++)
655 free (builtin->dependencies->array[i]);
656 array_free (builtin->dependencies);
657 }
658}
659
660/* Free all of the memory allocated to a DEF_FILE. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000661void
Jari Aalto726f6381996-08-26 18:22:31 +0000662free_defs (defs)
663 DEF_FILE *defs;
664{
665 register int i;
666 register BUILTIN_DESC *builtin;
667
668 if (defs->production)
669 free (defs->production);
670
671 if (defs->lines)
672 array_free (defs->lines);
673
674 if (defs->builtins)
675 {
676 for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000677 {
Jari Aalto726f6381996-08-26 18:22:31 +0000678 free_builtin (builtin);
679 free (builtin);
Jari Aalto28ef6c32001-04-06 19:14:31 +0000680 }
Jari Aalto726f6381996-08-26 18:22:31 +0000681 array_free (defs->builtins);
682 }
683 free (defs);
684}
685
686/* **************************************************************** */
687/* */
688/* The Handler Functions Themselves */
689/* */
690/* **************************************************************** */
691
692/* Strip surrounding whitespace from STRING, and
693 return a pointer to the start of it. */
694char *
695strip_whitespace (string)
696 char *string;
697{
698 while (whitespace (*string))
699 string++;
700
701 remove_trailing_whitespace (string);
702 return (string);
703}
704
705/* Remove only the trailing whitespace from STRING. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000706void
Jari Aalto726f6381996-08-26 18:22:31 +0000707remove_trailing_whitespace (string)
708 char *string;
709{
710 register int i;
711
712 i = strlen (string) - 1;
713
714 while (i > 0 && whitespace (string[i]))
715 i--;
716
717 string[++i] = '\0';
718}
719
720/* Ensure that there is a argument in STRING and return it.
721 FOR_WHOM is the name of the directive which needs the argument.
722 DEFS is the DEF_FILE in which the directive is found.
723 If there is no argument, produce an error. */
724char *
725get_arg (for_whom, defs, string)
726 char *for_whom, *string;
727 DEF_FILE *defs;
728{
729 char *new;
730
731 new = strip_whitespace (string);
732
733 if (!*new)
734 line_error (defs, "%s requires an argument", for_whom);
735
736 return (savestring (new));
737}
738
739/* Error if not building a builtin. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000740void
Jari Aalto726f6381996-08-26 18:22:31 +0000741must_be_building (directive, defs)
742 char *directive;
743 DEF_FILE *defs;
744{
745 if (!building_builtin)
746 line_error (defs, "%s must be inside of a $BUILTIN block", directive);
747}
748
749/* Return the current builtin. */
750BUILTIN_DESC *
751current_builtin (directive, defs)
752 char *directive;
753 DEF_FILE *defs;
754{
755 must_be_building (directive, defs);
Jari Aaltocce855b1998-04-17 19:52:44 +0000756 if (defs->builtins)
757 return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
758 else
759 return ((BUILTIN_DESC *)NULL);
Jari Aalto726f6381996-08-26 18:22:31 +0000760}
761
762/* Add LINE to the long documentation for the current builtin.
763 Ignore blank lines until the first non-blank line has been seen. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000764void
Jari Aalto726f6381996-08-26 18:22:31 +0000765add_documentation (defs, line)
766 DEF_FILE *defs;
767 char *line;
768{
769 register BUILTIN_DESC *builtin;
770
771 builtin = current_builtin ("(implied LONGDOC)", defs);
772
773 remove_trailing_whitespace (line);
774
775 if (!*line && !builtin->longdoc)
776 return;
777
778 if (!builtin->longdoc)
779 builtin->longdoc = array_create (sizeof (char *));
780
781 array_add (line, builtin->longdoc);
782}
783
784/* How to handle the $BUILTIN directive. */
785int
786builtin_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000787 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000788 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000789 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000790{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000791 BUILTIN_DESC *new;
792 char *name;
793
Jari Aalto726f6381996-08-26 18:22:31 +0000794 /* If we are already building a builtin, we cannot start a new one. */
795 if (building_builtin)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000796 {
797 line_error (defs, "%s found before $END", self);
798 return (-1);
799 }
Jari Aalto726f6381996-08-26 18:22:31 +0000800
801 output_cpp_line_info++;
802
803 /* Get the name of this builtin, and stick it in the array. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000804 name = get_arg (self, defs, arg);
Jari Aalto726f6381996-08-26 18:22:31 +0000805
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000806 /* If this is the first builtin, create the array to hold them. */
807 if (!defs->builtins)
808 defs->builtins = array_create (sizeof (BUILTIN_DESC *));
Jari Aalto726f6381996-08-26 18:22:31 +0000809
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000810 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
811 new->name = name;
812 new->function = (char *)NULL;
813 new->shortdoc = (char *)NULL;
814 new->docname = (char *)NULL;
815 new->longdoc = (ARRAY *)NULL;
816 new->dependencies = (ARRAY *)NULL;
817 new->flags = 0;
Jari Aalto726f6381996-08-26 18:22:31 +0000818
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000819 if (is_special_builtin (name))
820 new->flags |= BUILTIN_FLAG_SPECIAL;
821 if (is_assignment_builtin (name))
822 new->flags |= BUILTIN_FLAG_ASSIGNMENT;
Jari Aalto31859422009-01-12 13:36:28 +0000823 if (is_posix_builtin (name))
824 new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
Jari Aalto726f6381996-08-26 18:22:31 +0000825
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000826 array_add ((char *)new, defs->builtins);
827 building_builtin = 1;
Jari Aalto726f6381996-08-26 18:22:31 +0000828
Jari Aalto726f6381996-08-26 18:22:31 +0000829 return (0);
830}
831
832/* How to handle the $FUNCTION directive. */
833int
834function_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000835 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000836 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000837 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000838{
839 register BUILTIN_DESC *builtin;
840
841 builtin = current_builtin (self, defs);
842
Jari Aaltocce855b1998-04-17 19:52:44 +0000843 if (builtin == 0)
844 {
845 line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
846 exit (1);
847 }
Jari Aalto726f6381996-08-26 18:22:31 +0000848 if (builtin->function)
849 line_error (defs, "%s already has a function (%s)",
850 builtin->name, builtin->function);
851 else
852 builtin->function = get_arg (self, defs, arg);
853
854 return (0);
855}
856
857/* How to handle the $DOCNAME directive. */
858int
859docname_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000860 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000861 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000862 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000863{
864 register BUILTIN_DESC *builtin;
865
866 builtin = current_builtin (self, defs);
867
868 if (builtin->docname)
869 line_error (defs, "%s already had a docname (%s)",
870 builtin->name, builtin->docname);
871 else
872 builtin->docname = get_arg (self, defs, arg);
873
874 return (0);
875}
876
877/* How to handle the $SHORT_DOC directive. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000878int
Jari Aalto726f6381996-08-26 18:22:31 +0000879short_doc_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000880 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000881 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000882 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000883{
884 register BUILTIN_DESC *builtin;
885
886 builtin = current_builtin (self, defs);
887
888 if (builtin->shortdoc)
889 line_error (defs, "%s already has short documentation (%s)",
890 builtin->name, builtin->shortdoc);
891 else
892 builtin->shortdoc = get_arg (self, defs, arg);
893
894 return (0);
895}
896
897/* How to handle the $COMMENT directive. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000898int
Jari Aaltof73dda02001-11-13 17:56:06 +0000899comment_handler (self, defs, arg)
Jari Aalto726f6381996-08-26 18:22:31 +0000900 char *self;
901 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000902 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000903{
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000904 return (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000905}
906
907/* How to handle the $DEPENDS_ON directive. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000908int
Jari Aalto726f6381996-08-26 18:22:31 +0000909depends_on_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000910 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000911 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000912 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000913{
914 register BUILTIN_DESC *builtin;
915 char *dependent;
916
917 builtin = current_builtin (self, defs);
918 dependent = get_arg (self, defs, arg);
919
920 if (!builtin->dependencies)
921 builtin->dependencies = array_create (sizeof (char *));
922
923 array_add (dependent, builtin->dependencies);
924
925 return (0);
926}
927
928/* How to handle the $PRODUCES directive. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000929int
Jari Aalto726f6381996-08-26 18:22:31 +0000930produces_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000931 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000932 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000933 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000934{
935 /* If just hacking documentation, don't change any of the production
936 files. */
937 if (only_documentation)
938 return (0);
939
940 output_cpp_line_info++;
941
942 if (defs->production)
943 line_error (defs, "%s already has a %s definition", defs->filename, self);
944 else
945 {
946 defs->production = get_arg (self, defs, arg);
947
948 if (inhibit_production)
949 return (0);
950
951 defs->output = fopen (defs->production, "w");
952
953 if (!defs->output)
954 file_error (defs->production);
955
956 fprintf (defs->output, "/* %s, created from %s. */\n",
957 defs->production, defs->filename);
958 }
959 return (0);
960}
961
962/* How to handle the $END directive. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000963int
Jari Aalto726f6381996-08-26 18:22:31 +0000964end_handler (self, defs, arg)
Jari Aaltof73dda02001-11-13 17:56:06 +0000965 char *self;
Jari Aalto726f6381996-08-26 18:22:31 +0000966 DEF_FILE *defs;
Jari Aaltof73dda02001-11-13 17:56:06 +0000967 char *arg;
Jari Aalto726f6381996-08-26 18:22:31 +0000968{
969 must_be_building (self, defs);
970 building_builtin = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000971 return (0);
Jari Aalto726f6381996-08-26 18:22:31 +0000972}
973
974/* **************************************************************** */
975/* */
976/* Error Handling Functions */
977/* */
978/* **************************************************************** */
979
980/* Produce an error for DEFS with FORMAT and ARGS. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000981void
Jari Aalto726f6381996-08-26 18:22:31 +0000982line_error (defs, format, arg1, arg2)
983 DEF_FILE *defs;
984 char *format, *arg1, *arg2;
985{
986 if (defs->filename[0] != '/')
987 fprintf (stderr, "%s", error_directory ? error_directory : "./");
988 fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
989 fprintf (stderr, format, arg1, arg2);
990 fprintf (stderr, "\n");
991 fflush (stderr);
992}
993
994/* Print error message for FILENAME. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000995void
Jari Aalto726f6381996-08-26 18:22:31 +0000996file_error (filename)
997 char *filename;
998{
999 perror (filename);
1000 exit (2);
1001}
1002
1003/* **************************************************************** */
1004/* */
1005/* xmalloc and xrealloc () */
1006/* */
1007/* **************************************************************** */
1008
1009static void memory_error_and_abort ();
1010
1011static char *
1012xmalloc (bytes)
1013 int bytes;
1014{
1015 char *temp = (char *)malloc (bytes);
1016
1017 if (!temp)
1018 memory_error_and_abort ();
1019 return (temp);
1020}
1021
1022static char *
1023xrealloc (pointer, bytes)
1024 char *pointer;
1025 int bytes;
1026{
1027 char *temp;
1028
1029 if (!pointer)
1030 temp = (char *)malloc (bytes);
1031 else
1032 temp = (char *)realloc (pointer, bytes);
1033
1034 if (!temp)
1035 memory_error_and_abort ();
1036
1037 return (temp);
1038}
1039
1040static void
1041memory_error_and_abort ()
1042{
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001043 fprintf (stderr, "mkbuiltins: out of virtual memory\n");
Jari Aalto726f6381996-08-26 18:22:31 +00001044 abort ();
1045}
1046
1047/* **************************************************************** */
1048/* */
1049/* Creating the Struct and Extern Files */
1050/* */
1051/* **************************************************************** */
1052
1053/* Return a pointer to a newly allocated builtin which is
1054 an exact copy of BUILTIN. */
1055BUILTIN_DESC *
1056copy_builtin (builtin)
1057 BUILTIN_DESC *builtin;
1058{
1059 BUILTIN_DESC *new;
1060
1061 new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
1062
Jari Aalto28ef6c32001-04-06 19:14:31 +00001063 new->name = savestring (builtin->name);
1064 new->shortdoc = savestring (builtin->shortdoc);
1065 new->longdoc = copy_string_array (builtin->longdoc);
Jari Aalto726f6381996-08-26 18:22:31 +00001066 new->dependencies = copy_string_array (builtin->dependencies);
1067
1068 new->function =
1069 builtin->function ? savestring (builtin->function) : (char *)NULL;
1070 new->docname =
1071 builtin->docname ? savestring (builtin->docname) : (char *)NULL;
1072
1073 return (new);
1074}
1075
1076/* How to save away a builtin. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001077void
Jari Aalto726f6381996-08-26 18:22:31 +00001078save_builtin (builtin)
1079 BUILTIN_DESC *builtin;
1080{
1081 BUILTIN_DESC *newbuiltin;
1082
1083 newbuiltin = copy_builtin (builtin);
1084
1085 /* If this is the first builtin to be saved, create the array
1086 to hold it. */
1087 if (!saved_builtins)
1088 saved_builtins = array_create (sizeof (BUILTIN_DESC *));
1089
1090 array_add ((char *)newbuiltin, saved_builtins);
1091}
1092
1093/* Flags that mean something to write_documentation (). */
Jari Aalto95732b42005-12-07 14:08:12 +00001094#define STRING_ARRAY 0x01
1095#define TEXINFO 0x02
1096#define PLAINTEXT 0x04
1097#define HELPFILE 0x08
Jari Aalto726f6381996-08-26 18:22:31 +00001098
1099char *structfile_header[] = {
1100 "/* builtins.c -- the built in shell commands. */",
1101 "",
1102 "/* This file is manufactured by ./mkbuiltins, and should not be",
1103 " edited by hand. See the source to mkbuiltins for details. */",
1104 "",
Chet Rameyac50fba2014-02-26 09:36:43 -05001105 "/* Copyright (C) 1987-2012 Free Software Foundation, Inc.",
Jari Aalto726f6381996-08-26 18:22:31 +00001106 "",
1107 " This file is part of GNU Bash, the Bourne Again SHell.",
1108 "",
Jari Aalto31859422009-01-12 13:36:28 +00001109 " Bash is free software: you can redistribute it and/or modify",
1110 " it under the terms of the GNU General Public License as published by",
1111 " the Free Software Foundation, either version 3 of the License, or",
1112 " (at your option) any later version.",
Jari Aalto726f6381996-08-26 18:22:31 +00001113 "",
Jari Aalto31859422009-01-12 13:36:28 +00001114 " Bash is distributed in the hope that it will be useful,",
1115 " but WITHOUT ANY WARRANTY; without even the implied warranty of",
1116 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
1117 " GNU General Public License for more details.",
Jari Aalto726f6381996-08-26 18:22:31 +00001118 "",
1119 " You should have received a copy of the GNU General Public License",
Jari Aalto31859422009-01-12 13:36:28 +00001120 " along with Bash. If not, see <http://www.gnu.org/licenses/>.",
1121 "*/",
Jari Aalto726f6381996-08-26 18:22:31 +00001122 "",
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001123 "/* The list of shell builtins. Each element is name, function, flags,",
Jari Aalto726f6381996-08-26 18:22:31 +00001124 " long-doc, short-doc. The long-doc field contains a pointer to an array",
1125 " of help lines. The function takes a WORD_LIST *; the first word in the",
1126 " list is the first arg to the command. The list has already had word",
1127 " expansion performed.",
1128 "",
1129 " Functions which need to look at only the simple commands (e.g.",
1130 " the enable_builtin ()), should ignore entries where",
Jari Aaltof73dda02001-11-13 17:56:06 +00001131 " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
Jari Aalto726f6381996-08-26 18:22:31 +00001132 " the list of shell reserved control structures, like `if' and `while'.",
1133 " The end of the list is denoted with a NULL name field. */",
1134 "",
1135 "#include \"../builtins.h\"",
1136 (char *)NULL
1137 };
1138
1139char *structfile_footer[] = {
Chet Ramey495aee42011-11-22 19:11:26 -05001140 " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0, (char *)0x0 }",
Jari Aalto726f6381996-08-26 18:22:31 +00001141 "};",
1142 "",
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001143 "struct builtin *shell_builtins = static_shell_builtins;",
1144 "struct builtin *current_builtin;",
1145 "",
Jari Aalto726f6381996-08-26 18:22:31 +00001146 "int num_shell_builtins =",
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001147 "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
Jari Aalto726f6381996-08-26 18:22:31 +00001148 (char *)NULL
1149};
1150
Chet Rameyac50fba2014-02-26 09:36:43 -05001151/* Write out any necessary opening information for
Jari Aalto726f6381996-08-26 18:22:31 +00001152 STRUCTFILE and EXTERNFILE. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001153void
Jari Aalto726f6381996-08-26 18:22:31 +00001154write_file_headers (structfile, externfile)
1155 FILE *structfile, *externfile;
1156{
1157 register int i;
1158
1159 if (structfile)
1160 {
1161 for (i = 0; structfile_header[i]; i++)
1162 fprintf (structfile, "%s\n", structfile_header[i]);
1163
1164 fprintf (structfile, "#include \"%s\"\n",
1165 extern_filename ? extern_filename : "builtext.h");
Jari Aaltob80f6442004-07-27 13:29:18 +00001166
1167 fprintf (structfile, "#include \"bashintl.h\"\n");
1168
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001169 fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
Jari Aalto726f6381996-08-26 18:22:31 +00001170 }
1171
1172 if (externfile)
1173 fprintf (externfile,
1174 "/* %s - The list of builtins found in libbuiltins.a. */\n",
1175 extern_filename ? extern_filename : "builtext.h");
1176}
1177
1178/* Write out any necessary closing information for
1179 STRUCTFILE and EXTERNFILE. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001180void
Jari Aalto726f6381996-08-26 18:22:31 +00001181write_file_footers (structfile, externfile)
1182 FILE *structfile, *externfile;
1183{
1184 register int i;
1185
1186 /* Write out the footers. */
1187 if (structfile)
1188 {
1189 for (i = 0; structfile_footer[i]; i++)
1190 fprintf (structfile, "%s\n", structfile_footer[i]);
1191 }
1192}
1193
1194/* Write out the information accumulated in DEFS to
1195 STRUCTFILE and EXTERNFILE. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001196void
Jari Aalto726f6381996-08-26 18:22:31 +00001197write_builtins (defs, structfile, externfile)
1198 DEF_FILE *defs;
1199 FILE *structfile, *externfile;
1200{
1201 register int i;
1202
1203 /* Write out the information. */
1204 if (defs->builtins)
1205 {
1206 register BUILTIN_DESC *builtin;
1207
1208 for (i = 0; i < defs->builtins->sindex; i++)
1209 {
1210 builtin = (BUILTIN_DESC *)defs->builtins->array[i];
1211
1212 /* Write out any #ifdefs that may be there. */
1213 if (!only_documentation)
1214 {
1215 if (builtin->dependencies)
1216 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001217 write_ifdefs (externfile, builtin->dependencies->array);
Jari Aalto726f6381996-08-26 18:22:31 +00001218 write_ifdefs (structfile, builtin->dependencies->array);
1219 }
1220
1221 /* Write the extern definition. */
1222 if (externfile)
1223 {
1224 if (builtin->function)
Jari Aaltof73dda02001-11-13 17:56:06 +00001225 fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
Jari Aalto726f6381996-08-26 18:22:31 +00001226 builtin->function);
1227
Jari Aalto7117c2d2002-07-17 14:10:11 +00001228 fprintf (externfile, "extern char * const %s_doc[];\n",
1229 document_name (builtin));
Jari Aalto726f6381996-08-26 18:22:31 +00001230 }
1231
1232 /* Write the structure definition. */
1233 if (structfile)
1234 {
1235 fprintf (structfile, " { \"%s\", ", builtin->name);
1236
Chet Rameyac50fba2014-02-26 09:36:43 -05001237 if (builtin->function && inhibit_functions == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001238 fprintf (structfile, "%s, ", builtin->function);
1239 else
Jari Aaltof73dda02001-11-13 17:56:06 +00001240 fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
Jari Aalto726f6381996-08-26 18:22:31 +00001241
Jari Aalto31859422009-01-12 13:36:28 +00001242 fprintf (structfile, "%s%s%s%s, %s_doc,\n",
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001243 "BUILTIN_ENABLED | STATIC_BUILTIN",
1244 (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
1245 (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
Jari Aalto31859422009-01-12 13:36:28 +00001246 (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
Jari Aalto7117c2d2002-07-17 14:10:11 +00001247 document_name (builtin));
Jari Aalto726f6381996-08-26 18:22:31 +00001248
Chet Rameyac50fba2014-02-26 09:36:43 -05001249 if (inhibit_functions)
1250 fprintf
1251 (structfile, " N_(\"%s\"), \"%s\" },\n",
1252 builtin->shortdoc ? builtin->shortdoc : builtin->name,
1253 document_name (builtin));
1254 else
1255 fprintf
1256 (structfile, " N_(\"%s\"), (char *)NULL },\n",
1257 builtin->shortdoc ? builtin->shortdoc : builtin->name);
Jari Aalto726f6381996-08-26 18:22:31 +00001258
Jari Aalto726f6381996-08-26 18:22:31 +00001259 }
1260
Jari Aalto7117c2d2002-07-17 14:10:11 +00001261 if (structfile || separate_helpfiles)
1262 /* Save away this builtin for later writing of the
1263 long documentation strings. */
1264 save_builtin (builtin);
1265
Chet Rameyac50fba2014-02-26 09:36:43 -05001266 /* Write out the matching #endif, if necessary. */
Jari Aalto726f6381996-08-26 18:22:31 +00001267 if (builtin->dependencies)
1268 {
1269 if (externfile)
1270 write_endifs (externfile, builtin->dependencies->array);
1271
1272 if (structfile)
1273 write_endifs (structfile, builtin->dependencies->array);
1274 }
1275 }
1276
1277 if (documentation_file)
1278 {
1279 fprintf (documentation_file, "@item %s\n", builtin->name);
1280 write_documentation
1281 (documentation_file, builtin->longdoc->array, 0, TEXINFO);
1282 }
1283 }
1284 }
1285}
1286
1287/* Write out the long documentation strings in BUILTINS to STREAM. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001288void
Jari Aalto726f6381996-08-26 18:22:31 +00001289write_longdocs (stream, builtins)
1290 FILE *stream;
1291 ARRAY *builtins;
1292{
1293 register int i;
1294 register BUILTIN_DESC *builtin;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001295 char *dname;
1296 char *sarray[2];
Jari Aalto726f6381996-08-26 18:22:31 +00001297
1298 for (i = 0; i < builtins->sindex; i++)
1299 {
1300 builtin = (BUILTIN_DESC *)builtins->array[i];
1301
1302 if (builtin->dependencies)
1303 write_ifdefs (stream, builtin->dependencies->array);
1304
1305 /* Write the long documentation strings. */
Jari Aalto7117c2d2002-07-17 14:10:11 +00001306 dname = document_name (builtin);
1307 fprintf (stream, "char * const %s_doc[] =", dname);
1308
1309 if (separate_helpfiles)
1310 {
1311 int l = strlen (helpfile_directory) + strlen (dname) + 1;
1312 sarray[0] = (char *)xmalloc (l + 1);
1313 sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
1314 sarray[1] = (char *)NULL;
Jari Aalto95732b42005-12-07 14:08:12 +00001315 write_documentation (stream, sarray, 0, STRING_ARRAY|HELPFILE);
Jari Aalto7117c2d2002-07-17 14:10:11 +00001316 free (sarray[0]);
1317 }
1318 else
1319 write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
Jari Aalto726f6381996-08-26 18:22:31 +00001320
1321 if (builtin->dependencies)
1322 write_endifs (stream, builtin->dependencies->array);
1323
1324 }
1325}
1326
Chet Rameyac50fba2014-02-26 09:36:43 -05001327void
1328write_dummy_declarations (stream, builtins)
1329 FILE *stream;
1330 ARRAY *builtins;
1331{
1332 register int i;
1333 BUILTIN_DESC *builtin;
1334
1335 for (i = 0; structfile_header[i]; i++)
1336 fprintf (stream, "%s\n", structfile_header[i]);
1337
1338 for (i = 0; i < builtins->sindex; i++)
1339 {
1340 builtin = (BUILTIN_DESC *)builtins->array[i];
1341
1342 /* How to guarantee that no builtin is written more than once? */
1343 fprintf (stream, "int %s () { return (0); }\n", builtin->function);
1344 }
1345}
1346
Jari Aalto726f6381996-08-26 18:22:31 +00001347/* Write an #ifdef string saying what needs to be defined (or not defined)
1348 in order to allow compilation of the code that will follow.
1349 STREAM is the stream to write the information to,
1350 DEFINES is a null terminated array of define names.
1351 If a define is preceded by an `!', then the sense of the test is
1352 reversed. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001353void
Jari Aalto726f6381996-08-26 18:22:31 +00001354write_ifdefs (stream, defines)
1355 FILE *stream;
1356 char **defines;
1357{
1358 register int i;
1359
1360 if (!stream)
1361 return;
1362
1363 fprintf (stream, "#if ");
1364
1365 for (i = 0; defines[i]; i++)
1366 {
1367 char *def = defines[i];
1368
1369 if (*def == '!')
1370 fprintf (stream, "!defined (%s)", def + 1);
1371 else
1372 fprintf (stream, "defined (%s)", def);
1373
1374 if (defines[i + 1])
1375 fprintf (stream, " && ");
1376 }
1377 fprintf (stream, "\n");
1378}
1379
1380/* Write an #endif string saying what defines controlled the compilation
1381 of the immediately preceding code.
1382 STREAM is the stream to write the information to.
1383 DEFINES is a null terminated array of define names. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001384void
Jari Aalto726f6381996-08-26 18:22:31 +00001385write_endifs (stream, defines)
1386 FILE *stream;
1387 char **defines;
1388{
1389 register int i;
1390
1391 if (!stream)
1392 return;
1393
1394 fprintf (stream, "#endif /* ");
1395
1396 for (i = 0; defines[i]; i++)
1397 {
1398 fprintf (stream, "%s", defines[i]);
1399
1400 if (defines[i + 1])
1401 fprintf (stream, " && ");
1402 }
1403
1404 fprintf (stream, " */\n");
1405}
1406
Jari Aalto95732b42005-12-07 14:08:12 +00001407/* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
1408 and quoting special characters in the string. Handle special things for
1409 internationalization (gettext) and the single-string vs. multiple-strings
1410 issues. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001411void
Jari Aalto726f6381996-08-26 18:22:31 +00001412write_documentation (stream, documentation, indentation, flags)
1413 FILE *stream;
1414 char **documentation;
1415 int indentation, flags;
1416{
1417 register int i, j;
1418 register char *line;
Chet Ramey495aee42011-11-22 19:11:26 -05001419 int string_array, texinfo, base_indent, filename_p;
Jari Aalto726f6381996-08-26 18:22:31 +00001420
Jari Aalto06285672006-10-10 14:15:34 +00001421 if (stream == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001422 return;
1423
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001424 string_array = flags & STRING_ARRAY;
Jari Aalto95732b42005-12-07 14:08:12 +00001425 filename_p = flags & HELPFILE;
Jari Aalto726f6381996-08-26 18:22:31 +00001426
Jari Aalto95732b42005-12-07 14:08:12 +00001427 if (string_array)
Jari Aalto726f6381996-08-26 18:22:31 +00001428 {
Jari Aalto95732b42005-12-07 14:08:12 +00001429 fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n"); /* } */
1430 if (single_longdoc_strings)
1431 {
1432 if (filename_p == 0)
Jari Aalto06285672006-10-10 14:15:34 +00001433 {
1434 if (documentation && documentation[0] && documentation[0][0])
1435 fprintf (stream, "N_(\"");
1436 else
1437 fprintf (stream, "N_(\" "); /* the empty string translates specially. */
1438 }
Jari Aalto95732b42005-12-07 14:08:12 +00001439 else
1440 fprintf (stream, "\"");
1441 }
1442 }
1443
1444 base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
1445
Chet Rameyac50fba2014-02-26 09:36:43 -05001446 for (i = 0, texinfo = (flags & TEXINFO); documentation && (line = documentation[i]); i++)
Jari Aalto95732b42005-12-07 14:08:12 +00001447 {
1448 /* Allow #ifdef's to be written out verbatim, but don't put them into
1449 separate help files. */
Jari Aalto726f6381996-08-26 18:22:31 +00001450 if (*line == '#')
1451 {
Jari Aalto95732b42005-12-07 14:08:12 +00001452 if (string_array && filename_p == 0 && single_longdoc_strings == 0)
Jari Aalto726f6381996-08-26 18:22:31 +00001453 fprintf (stream, "%s\n", line);
1454 continue;
1455 }
1456
Jari Aaltob80f6442004-07-27 13:29:18 +00001457 /* prefix with N_( for gettext */
Jari Aalto95732b42005-12-07 14:08:12 +00001458 if (string_array && single_longdoc_strings == 0)
1459 {
1460 if (filename_p == 0)
Jari Aalto06285672006-10-10 14:15:34 +00001461 {
1462 if (line[0])
1463 fprintf (stream, " N_(\"");
1464 else
1465 fprintf (stream, " N_(\" "); /* the empty string translates specially. */
1466 }
Jari Aalto95732b42005-12-07 14:08:12 +00001467 else
1468 fprintf (stream, " \"");
1469 }
Jari Aalto726f6381996-08-26 18:22:31 +00001470
1471 if (indentation)
1472 for (j = 0; j < indentation; j++)
1473 fprintf (stream, " ");
1474
Jari Aalto95732b42005-12-07 14:08:12 +00001475 /* Don't indent the first line, because of how the help builtin works. */
1476 if (i == 0)
1477 indentation += base_indent;
1478
Jari Aalto726f6381996-08-26 18:22:31 +00001479 if (string_array)
1480 {
1481 for (j = 0; line[j]; j++)
1482 {
1483 switch (line[j])
1484 {
1485 case '\\':
1486 case '"':
1487 fprintf (stream, "\\%c", line[j]);
1488 break;
1489
1490 default:
1491 fprintf (stream, "%c", line[j]);
1492 }
1493 }
1494
Jari Aaltob80f6442004-07-27 13:29:18 +00001495 /* closing right paren for gettext */
Jari Aalto95732b42005-12-07 14:08:12 +00001496 if (single_longdoc_strings == 0)
1497 {
1498 if (filename_p == 0)
1499 fprintf (stream, "\"),\n");
1500 else
1501 fprintf (stream, "\",\n");
1502 }
1503 else if (documentation[i+1])
1504 /* don't add extra newline after last line */
1505 fprintf (stream, "\\n\\\n");
Jari Aalto726f6381996-08-26 18:22:31 +00001506 }
1507 else if (texinfo)
1508 {
1509 for (j = 0; line[j]; j++)
1510 {
1511 switch (line[j])
1512 {
1513 case '@':
1514 case '{':
1515 case '}':
1516 fprintf (stream, "@%c", line[j]);
1517 break;
1518
1519 default:
1520 fprintf (stream, "%c", line[j]);
1521 }
1522 }
1523 fprintf (stream, "\n");
1524 }
1525 else
1526 fprintf (stream, "%s\n", line);
1527 }
1528
Jari Aalto95732b42005-12-07 14:08:12 +00001529 /* closing right paren for gettext */
1530 if (string_array && single_longdoc_strings)
1531 {
1532 if (filename_p == 0)
1533 fprintf (stream, "\"),\n");
1534 else
1535 fprintf (stream, "\",\n");
1536 }
1537
Jari Aalto726f6381996-08-26 18:22:31 +00001538 if (string_array)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001539 fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
1540}
1541
Jari Aalto7117c2d2002-07-17 14:10:11 +00001542int
1543write_helpfiles (builtins)
1544 ARRAY *builtins;
1545{
1546 char *helpfile, *bname;
1547 FILE *helpfp;
1548 int i, hdlen;
1549 BUILTIN_DESC *builtin;
1550
1551 i = mkdir ("helpfiles", 0777);
1552 if (i < 0 && errno != EEXIST)
1553 {
1554 fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
1555 return -1;
1556 }
1557
1558 hdlen = strlen ("helpfiles/");
1559 for (i = 0; i < builtins->sindex; i++)
1560 {
1561 builtin = (BUILTIN_DESC *)builtins->array[i];
1562
1563 bname = document_name (builtin);
1564 helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
1565 sprintf (helpfile, "helpfiles/%s", bname);
1566
1567 helpfp = fopen (helpfile, "w");
1568 if (helpfp == 0)
1569 {
1570 fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
1571 free (helpfile);
1572 continue;
1573 }
1574
1575 write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
1576
1577 fflush (helpfp);
1578 fclose (helpfp);
1579 free (helpfile);
1580 }
1581 return 0;
1582}
1583
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001584static int
1585_find_in_table (name, name_table)
1586 char *name, *name_table[];
1587{
1588 register int i;
1589
1590 for (i = 0; name_table[i]; i++)
1591 if (strcmp (name, name_table[i]) == 0)
1592 return 1;
1593 return 0;
Jari Aalto726f6381996-08-26 18:22:31 +00001594}
1595
1596static int
1597is_special_builtin (name)
1598 char *name;
1599{
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001600 return (_find_in_table (name, special_builtins));
1601}
Jari Aalto726f6381996-08-26 18:22:31 +00001602
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001603static int
1604is_assignment_builtin (name)
1605 char *name;
1606{
1607 return (_find_in_table (name, assignment_builtins));
Jari Aalto726f6381996-08-26 18:22:31 +00001608}
Jari Aaltob72432f1999-02-19 17:11:39 +00001609
Jari Aalto31859422009-01-12 13:36:28 +00001610static int
1611is_posix_builtin (name)
1612 char *name;
1613{
1614 return (_find_in_table (name, posix_builtins));
1615}
1616
Jari Aaltob72432f1999-02-19 17:11:39 +00001617#if !defined (HAVE_RENAME)
1618static int
1619rename (from, to)
1620 char *from, *to;
1621{
1622 unlink (to);
1623 if (link (from, to) < 0)
1624 return (-1);
1625 unlink (from);
1626 return (0);
1627}
1628#endif /* !HAVE_RENAME */