with Bash; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+#include <config.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
#include "../bashansi.h"
#include "../config.h"
#include <stdio.h>
/* Flag values that builtins can have. */
#define BUILTIN_FLAG_SPECIAL 0x01
+#define BUILTIN_FLAG_ASSIGNMENT 0x02
/* If this stream descriptor is non-zero, then write
texinfo documentation to it. */
"export", "readonly", "return", "set", "shift", "trap", "unset",
(char *)NULL
};
+
+/* The builtin commands that take assignment statements as arguments. */
+char *assignment_builtins[] =
+{
+ "alias", "declare", "export", "local", "readonly", "typeset",
+ (char *)NULL
+};
+
+/* Forward declarations. */
static int is_special_builtin ();
+static int is_assignment_builtin ();
+
+void extract_info ();
+
+void file_error ();
+void line_error ();
+
+void write_file_headers ();
+void write_file_footers ();
+void write_ifdefs ();
+void write_endifs ();
+void write_documentation ();
+void write_longdocs ();
+void write_builtins ();
+void free_defs ();
+void add_documentation ();
+
+void must_be_building ();
+void remove_trailing_whitespace ();
\f
/* For each file mentioned on the command line, process it and
write the information to STRUCTFILE and EXTERNFILE, while
creating the production file if neccessary. */
+int
main (argc, argv)
int argc;
char **argv;
}
/* Add ELEMENT to ARRAY, growing the array if neccessary. */
+void
array_add (element, array)
char *element;
ARRAY *array;
}
/* Free an allocated array and data pointer. */
+void
array_free (array)
ARRAY *array;
{
target. After the file has been processed, write out the names of
builtins found in each $BUILTIN. Plain text found before the $PRODUCES
is ignored, as is "$$ comment text". */
+void
extract_info (filename, structfile, externfile)
char *filename;
FILE *structfile, *externfile;
}
/* Free all of the memory allocated to a DEF_FILE. */
+void
free_defs (defs)
DEF_FILE *defs;
{
}
/* Remove only the trailing whitespace from STRING. */
+void
remove_trailing_whitespace (string)
char *string;
{
}
/* Error if not building a builtin. */
+void
must_be_building (directive, defs)
char *directive;
DEF_FILE *defs;
/* Add LINE to the long documentation for the current builtin.
Ignore blank lines until the first non-blank line has been seen. */
+void
add_documentation (defs, line)
DEF_FILE *defs;
char *line;
char *self, *arg;
DEF_FILE *defs;
{
+ BUILTIN_DESC *new;
+ char *name;
+
/* If we are already building a builtin, we cannot start a new one. */
if (building_builtin)
- return (line_error (defs, "%s found before $END", self));
+ {
+ line_error (defs, "%s found before $END", self);
+ return (-1);
+ }
output_cpp_line_info++;
/* Get the name of this builtin, and stick it in the array. */
- {
- BUILTIN_DESC *new;
- char *name;
-
- name = get_arg (self, defs, arg);
-
- /* If this is the first builtin, create the array to hold them. */
- if (!defs->builtins)
- defs->builtins = array_create (sizeof (BUILTIN_DESC *));
-
- new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
- new->name = name;
- new->function = (char *)NULL;
- new->shortdoc = (char *)NULL;
- new->docname = (char *)NULL;
- new->longdoc = (ARRAY *)NULL;
- new->dependencies = (ARRAY *)NULL;
- new->flags = 0;
-
- if (is_special_builtin (name))
- new->flags |= BUILTIN_FLAG_SPECIAL;
-
- array_add ((char *)new, defs->builtins);
- building_builtin = 1;
- }
+ name = get_arg (self, defs, arg);
+
+ /* If this is the first builtin, create the array to hold them. */
+ if (!defs->builtins)
+ defs->builtins = array_create (sizeof (BUILTIN_DESC *));
+
+ new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
+ new->name = name;
+ new->function = (char *)NULL;
+ new->shortdoc = (char *)NULL;
+ new->docname = (char *)NULL;
+ new->longdoc = (ARRAY *)NULL;
+ new->dependencies = (ARRAY *)NULL;
+ new->flags = 0;
+
+ if (is_special_builtin (name))
+ new->flags |= BUILTIN_FLAG_SPECIAL;
+ if (is_assignment_builtin (name))
+ new->flags |= BUILTIN_FLAG_ASSIGNMENT;
+
+ array_add ((char *)new, defs->builtins);
+ building_builtin = 1;
+
return (0);
}
}
/* How to handle the $SHORT_DOC directive. */
+int
short_doc_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
}
/* How to handle the $COMMENT directive. */
+int
comment_handler (self, defs)
char *self;
DEF_FILE *defs;
{
+ return (0);
}
/* How to handle the $DEPENDS_ON directive. */
+int
depends_on_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
}
/* How to handle the $PRODUCES directive. */
+int
produces_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
}
/* How to handle the $END directive. */
+int
end_handler (self, defs, arg)
char *self, *arg;
DEF_FILE *defs;
{
must_be_building (self, defs);
building_builtin = 0;
+ return (0);
}
/* **************************************************************** */
/* **************************************************************** */
/* Produce an error for DEFS with FORMAT and ARGS. */
+void
line_error (defs, format, arg1, arg2)
DEF_FILE *defs;
char *format, *arg1, *arg2;
}
/* Print error message for FILENAME. */
+void
file_error (filename)
char *filename;
{
static void
memory_error_and_abort ()
{
- fprintf (stderr, "mkbuiltins: Out of virtual memory!\n");
+ fprintf (stderr, "mkbuiltins: out of virtual memory\n");
abort ();
}
}
/* How to save away a builtin. */
+void
save_builtin (builtin)
BUILTIN_DESC *builtin;
{
" along with Bash; see the file COPYING. If not, write to the Free",
" Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */",
"",
- "/* The list of shell builtins. Each element is name, function, enabled-p,",
+ "/* The list of shell builtins. Each element is name, function, flags,",
" long-doc, short-doc. The long-doc field contains a pointer to an array",
" of help lines. The function takes a WORD_LIST *; the first word in the",
" list is the first arg to the command. The list has already had word",
" { (char *)0x0, (Function *)0x0, 0, (char **)0x0, (char *)0x0 }",
"};",
"",
+ "struct builtin *shell_builtins = static_shell_builtins;",
+ "struct builtin *current_builtin;",
+ "",
"int num_shell_builtins =",
- "\tsizeof (shell_builtins) / sizeof (struct builtin) - 1;",
+ "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
(char *)NULL
};
/* Write out any neccessary opening information for
STRUCTFILE and EXTERNFILE. */
+void
write_file_headers (structfile, externfile)
FILE *structfile, *externfile;
{
fprintf (structfile, "#include \"%s\"\n",
extern_filename ? extern_filename : "builtext.h");
- fprintf (structfile, "\nstruct builtin shell_builtins[] = {\n");
+ fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
}
if (externfile)
/* Write out any necessary closing information for
STRUCTFILE and EXTERNFILE. */
+void
write_file_footers (structfile, externfile)
FILE *structfile, *externfile;
{
/* Write out the information accumulated in DEFS to
STRUCTFILE and EXTERNFILE. */
+void
write_builtins (defs, structfile, externfile)
DEF_FILE *defs;
FILE *structfile, *externfile;
{
if (builtin->dependencies)
{
- if (builtin->function)
- write_ifdefs (externfile, builtin->dependencies->array);
+ write_ifdefs (externfile, builtin->dependencies->array);
write_ifdefs (structfile, builtin->dependencies->array);
}
else
fprintf (structfile, "(Function *)0x0, ");
-#define SPECIAL_FLAG_STRING "BUILTIN_ENABLED | STATIC_BUILTIN | SPECIAL_BUILTIN"
-#define NORMAL_FLAG_STRING "BUILTIN_ENABLED | STATIC_BUILTIN"
-
- fprintf (structfile, "%s, %s_doc,\n",
- (builtin->flags & BUILTIN_FLAG_SPECIAL) ?
- SPECIAL_FLAG_STRING :
- NORMAL_FLAG_STRING,
+ fprintf (structfile, "%s%s%s, %s_doc,\n",
+ "BUILTIN_ENABLED | STATIC_BUILTIN",
+ (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
+ (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
builtin->docname ? builtin->docname : builtin->name);
-#undef SPECIAL_FLAG_STRING
-#undef NORMAL_FLAG_STRING
-
fprintf
- (structfile, " \"%s\" },\n",
+ (structfile, " \"%s\", (char *)NULL },\n",
builtin->shortdoc ? builtin->shortdoc : builtin->name);
/* Save away this builtin for later writing of the
}
/* Write out the long documentation strings in BUILTINS to STREAM. */
+void
write_longdocs (stream, builtins)
FILE *stream;
ARRAY *builtins;
DEFINES is a null terminated array of define names.
If a define is preceded by an `!', then the sense of the test is
reversed. */
+void
write_ifdefs (stream, defines)
FILE *stream;
char **defines;
of the immediately preceding code.
STREAM is the stream to write the information to.
DEFINES is a null terminated array of define names. */
+void
write_endifs (stream, defines)
FILE *stream;
char **defines;
/* Write DOCUMENTAION to STREAM, perhaps surrounding it with double-quotes
and quoting special characters in the string. */
+void
write_documentation (stream, documentation, indentation, flags)
FILE *stream;
char **documentation;
{
register int i, j;
register char *line;
- int string_array = (flags & STRING_ARRAY); /* Mutually exclusive. */
- int texinfo = (flags & TEXINFO);
+ int string_array, texinfo;
if (!stream)
return;
+ string_array = flags & STRING_ARRAY;
if (string_array)
- fprintf (stream, " {\n");
+ fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n");
#if !defined (OLDCODE)
/* XXX -- clean me up; for experiment only */
goto end_of_document;
#endif /* !OLDCODE */
- for (i = 0; line = documentation[i]; i++)
+ for (i = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
{
/* Allow #ifdef's to be written out verbatim. */
if (*line == '#')
#endif /* !OLDCODE */
if (string_array)
- fprintf (stream, " (char *)NULL\n};\n");
+ fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
}
static int
-is_special_builtin (name)
- char *name;
+_find_in_table (name, name_table)
+ char *name, *name_table[];
{
register int i;
- for (i = 0; special_builtins[i]; i++)
- if (strcmp (name, special_builtins[i]) == 0)
+ for (i = 0; name_table[i]; i++)
+ if (strcmp (name, name_table[i]) == 0)
return 1;
return 0;
}
+
+static int
+is_special_builtin (name)
+ char *name;
+{
+ return (_find_in_table (name, special_builtins));
+}
+
+static int
+is_assignment_builtin (name)
+ char *name;
+{
+ return (_find_in_table (name, assignment_builtins));
+}