📄 mkbuiltins.c
字号:
defs->builtins = (ARRAY *)NULL; /* Build the array of lines. */ i = 0; while (i < file_size) { array_add (&buffer[i], defs->lines); while (buffer[i] != '\n' && i < file_size) i++; buffer[i++] = '\0'; } /* Begin processing the input file. We don't write any output until we have a file to write output to. */ output_cpp_line_info = 1; /* Process each line in the array. */ for (i = 0; line = defs->lines->array[i]; i++) { defs->line_number = i; if (*line == '$') { register int j; char *directive; HANDLER_ENTRY *handler; /* Isolate the directive. */ for (j = 0; line[j] && !whitespace (line[j]); j++); directive = xmalloc (j); strncpy (directive, line + 1, j - 1); directive[j -1] = '\0'; /* Get the function handler and call it. */ handler = find_directive (directive); if (!handler) { line_error (defs, "Unknown directive `%s'", directive); free (directive); continue; } else { /* Advance to the first non-whitespace character. */ while (whitespace (line[j])) j++; /* Call the directive handler with the FILE, and ARGS. */ (*(handler->function)) (directive, defs, line + j); } free (directive); } else { if (building_builtin) add_documentation (defs, line); else if (defs->output) { if (output_cpp_line_info) { /* If we're handed an absolute pathname, don't prepend the directory name. */ if (defs->filename[0] == '/') fprintf (defs->output, "#line %d \"%s\"\n", defs->line_number + 1, defs->filename); else fprintf (defs->output, "#line %d \"%s%s\"\n", defs->line_number + 1, error_directory ? error_directory : "./", defs->filename); output_cpp_line_info = 0; } fprintf (defs->output, "%s\n", line); } } } /* Close the production file. */ if (defs->output) fclose (defs->output); /* The file has been processed. Write the accumulated builtins to the builtins.c file, and write the extern definitions to the builtext.h file. */ write_builtins (defs, structfile, externfile); free (buffer); free_defs (defs);}#define free_safely(x) if (x) free (x)static voidfree_builtin (builtin) BUILTIN_DESC *builtin;{ register int i; free_safely (builtin->name); free_safely (builtin->function); free_safely (builtin->shortdoc); free_safely (builtin->docname); if (builtin->longdoc) array_free (builtin->longdoc); if (builtin->dependencies) { for (i = 0; builtin->dependencies->array[i]; i++) free (builtin->dependencies->array[i]); array_free (builtin->dependencies); }}/* Free all of the memory allocated to a DEF_FILE. */voidfree_defs (defs) DEF_FILE *defs;{ register int i; register BUILTIN_DESC *builtin; if (defs->production) free (defs->production); if (defs->lines) array_free (defs->lines); if (defs->builtins) { for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++) { free_builtin (builtin); free (builtin); } array_free (defs->builtins); } free (defs);}/* **************************************************************** *//* *//* The Handler Functions Themselves *//* *//* **************************************************************** *//* Strip surrounding whitespace from STRING, and return a pointer to the start of it. */char *strip_whitespace (string) char *string;{ while (whitespace (*string)) string++; remove_trailing_whitespace (string); return (string);}/* Remove only the trailing whitespace from STRING. */voidremove_trailing_whitespace (string) char *string;{ register int i; i = strlen (string) - 1; while (i > 0 && whitespace (string[i])) i--; string[++i] = '\0';}/* Ensure that there is a argument in STRING and return it. FOR_WHOM is the name of the directive which needs the argument. DEFS is the DEF_FILE in which the directive is found. If there is no argument, produce an error. */char *get_arg (for_whom, defs, string) char *for_whom, *string; DEF_FILE *defs;{ char *new; new = strip_whitespace (string); if (!*new) line_error (defs, "%s requires an argument", for_whom); return (savestring (new));}/* Error if not building a builtin. */voidmust_be_building (directive, defs) char *directive; DEF_FILE *defs;{ if (!building_builtin) line_error (defs, "%s must be inside of a $BUILTIN block", directive);}/* Return the current builtin. */BUILTIN_DESC *current_builtin (directive, defs) char *directive; DEF_FILE *defs;{ must_be_building (directive, defs); if (defs->builtins) return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]); else return ((BUILTIN_DESC *)NULL);}/* Add LINE to the long documentation for the current builtin. Ignore blank lines until the first non-blank line has been seen. */voidadd_documentation (defs, line) DEF_FILE *defs; char *line;{ register BUILTIN_DESC *builtin; builtin = current_builtin ("(implied LONGDOC)", defs); remove_trailing_whitespace (line); if (!*line && !builtin->longdoc) return; if (!builtin->longdoc) builtin->longdoc = array_create (sizeof (char *)); array_add (line, builtin->longdoc);}/* How to handle the $BUILTIN directive. */intbuiltin_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ BUILTIN_DESC *new; char *name; /* If we are already building a builtin, we cannot start a new one. */ if (building_builtin) { 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. */ 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; if (is_posix_builtin (name)) new->flags |= BUILTIN_FLAG_POSIX_BUILTIN; array_add ((char *)new, defs->builtins); building_builtin = 1; return (0);}/* How to handle the $FUNCTION directive. */intfunction_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ register BUILTIN_DESC *builtin; builtin = current_builtin (self, defs); if (builtin == 0) { line_error (defs, "syntax error: no current builtin for $FUNCTION directive"); exit (1); } if (builtin->function) line_error (defs, "%s already has a function (%s)", builtin->name, builtin->function); else builtin->function = get_arg (self, defs, arg); return (0);}/* How to handle the $DOCNAME directive. */intdocname_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ register BUILTIN_DESC *builtin; builtin = current_builtin (self, defs); if (builtin->docname) line_error (defs, "%s already had a docname (%s)", builtin->name, builtin->docname); else builtin->docname = get_arg (self, defs, arg); return (0);}/* How to handle the $SHORT_DOC directive. */intshort_doc_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ register BUILTIN_DESC *builtin; builtin = current_builtin (self, defs); if (builtin->shortdoc) line_error (defs, "%s already has short documentation (%s)", builtin->name, builtin->shortdoc); else builtin->shortdoc = get_arg (self, defs, arg); return (0);}/* How to handle the $COMMENT directive. */intcomment_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ return (0);}/* How to handle the $DEPENDS_ON directive. */intdepends_on_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ register BUILTIN_DESC *builtin; char *dependent; builtin = current_builtin (self, defs); dependent = get_arg (self, defs, arg); if (!builtin->dependencies) builtin->dependencies = array_create (sizeof (char *)); array_add (dependent, builtin->dependencies); return (0);}/* How to handle the $PRODUCES directive. */intproduces_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ /* If just hacking documentation, don't change any of the production files. */ if (only_documentation) return (0); output_cpp_line_info++; if (defs->production) line_error (defs, "%s already has a %s definition", defs->filename, self); else { defs->production = get_arg (self, defs, arg); if (inhibit_production) return (0); defs->output = fopen (defs->production, "w"); if (!defs->output) file_error (defs->production); fprintf (defs->output, "/* %s, created from %s. */\n", defs->production, defs->filename); } return (0);}/* How to handle the $END directive. */intend_handler (self, defs, arg) char *self; DEF_FILE *defs; char *arg;{ must_be_building (self, defs); building_builtin = 0; return (0);}/* **************************************************************** *//* *//* Error Handling Functions *//* *//* **************************************************************** *//* Produce an error for DEFS with FORMAT and ARGS. */voidline_error (defs, format, arg1, arg2) DEF_FILE *defs; char *format, *arg1, *arg2;{ if (defs->filename[0] != '/') fprintf (stderr, "%s", error_directory ? error_directory : "./"); fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1); fprintf (stderr, format, arg1, arg2); fprintf (stderr, "\n"); fflush (stderr);}/* Print error message for FILENAME. */voidfile_error (filename) char *filename;{ perror (filename); exit (2);}/* **************************************************************** *//* *//* xmalloc and xrealloc () *//* *//* **************************************************************** */static void memory_error_and_abort ();static char *xmalloc (bytes) int bytes;{ char *temp = (char *)malloc (bytes); if (!temp) memory_error_and_abort (); return (temp);}static char *xrealloc (pointer, bytes) char *pointer; int bytes;{ char *temp; if (!pointer) temp = (char *)malloc (bytes); else temp = (char *)realloc (pointer, bytes); if (!temp) memory_error_and_abort (); return (temp);}static voidmemory_error_and_abort (){ fprintf (stderr, "mkbuiltins: out of virtual memory\n"); abort ();}/* **************************************************************** *//* *//* Creating the Struct and Extern Files *//* *//* **************************************************************** *//* Return a pointer to a newly allocated builtin which is an exact copy of BUILTIN. */BUILTIN_DESC *copy_builtin (builtin) BUILTIN_DESC *builtin;{ BUILTIN_DESC *new; new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC)); new->name = savestring (builtin->name); new->shortdoc = savestring (builtin->shortdoc); new->longdoc = copy_string_array (builtin->longdoc); new->dependencies = copy_string_array (builtin->dependencies); new->function = builtin->function ? savestring (builtin->function) : (char *)NULL; new->docname = builtin->docname ? savestring (builtin->docname) : (char *)NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -