diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2011-02-09 23:04:56 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2011-02-09 23:04:56 -0800 |
commit | be6d99804b3efdecf3660c4b51da1945e955fb4d (patch) | |
tree | 99b523c445f7b95572ab668f4e878cd703ff3527 /lib-src/make-docfile.c | |
parent | dd4638842ad1921562bc66049ec81a4530651cdf (diff) | |
parent | 67f02b82f496be403353a1dc918cc4f2278841bb (diff) | |
download | emacs-be6d99804b3efdecf3660c4b51da1945e955fb4d.tar.gz emacs-be6d99804b3efdecf3660c4b51da1945e955fb4d.tar.bz2 emacs-be6d99804b3efdecf3660c4b51da1945e955fb4d.zip |
Merge from mainline.
Diffstat (limited to 'lib-src/make-docfile.c')
-rw-r--r-- | lib-src/make-docfile.c | 185 |
1 files changed, 183 insertions, 2 deletions
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 8addbda0489..93994c1ed3e 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -41,11 +41,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ #undef chdir #include <stdio.h> +#include <stdlib.h> #ifdef MSDOS #include <fcntl.h> #endif /* MSDOS */ #ifdef WINDOWSNT -#include <stdlib.h> #include <fcntl.h> #include <direct.h> #endif /* WINDOWSNT */ @@ -70,6 +70,8 @@ int scan_file (char *filename); int scan_lisp_file (const char *filename, const char *mode); int scan_c_file (char *filename, const char *mode); void fatal (const char *s1, const char *s2) NO_RETURN; +void start_globals (void); +void write_globals (void); #ifdef MSDOS /* s/msdos.h defines this as sys_chdir, but we're not linking with the @@ -85,6 +87,9 @@ FILE *outfile; /* Name this program was invoked with. */ char *progname; +/* Nonzero if this invocation is generating globals.h. */ +int generate_globals; + /* Print error message. `s1' is printf control string, `s2' is arg for it. */ /* VARARGS1 */ @@ -116,6 +121,18 @@ xmalloc (unsigned int size) fatal ("virtual memory exhausted", 0); return result; } + +/* Like realloc but get fatal error if memory is exhausted. */ + +void * +xrealloc (void *arg, unsigned int size) +{ + void *result = (void *) realloc (arg, size); + if (result == NULL) + fatal ("virtual memory exhausted", 0); + return result; +} + int main (int argc, char **argv) @@ -164,10 +181,18 @@ main (int argc, char **argv) } i += 2; } + if (argc > i && !strcmp (argv[i], "-g")) + { + generate_globals = 1; + ++i; + } if (outfile == 0) fatal ("No output file specified", ""); + if (generate_globals) + start_globals (); + first_infile = i; for (; i < argc; i++) { @@ -179,6 +204,10 @@ main (int argc, char **argv) if (j == i) err_count += scan_file (argv[i]); } + + if (err_count == 0 && generate_globals) + write_globals (); + return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -208,7 +237,8 @@ scan_file (char *filename) size_t len = strlen (filename); - put_filename (filename); + if (!generate_globals) + put_filename (filename); if (len > 4 && !strcmp (filename + len - 4, ".elc")) return scan_lisp_file (filename, READ_BINARY); else if (len > 3 && !strcmp (filename + len - 3, ".el")) @@ -216,6 +246,14 @@ scan_file (char *filename) else return scan_c_file (filename, READ_TEXT); } + +void +start_globals (void) +{ + fprintf (outfile, "/* This file was auto-generated by make-docfile. */\n"); + fprintf (outfile, "/* DO NOT EDIT. */\n"); + fprintf (outfile, "struct emacs_globals {\n"); +} char buf[128]; @@ -517,6 +555,98 @@ write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) putc (')', out); } +/* The types of globals. */ +enum global_type +{ + EMACS_INTEGER, + BOOLEAN, + LISP_OBJECT, + INVALID +}; + +/* A single global. */ +struct global +{ + enum global_type type; + char *name; +}; + +/* All the variable names we saw while scanning C sources in `-g' + mode. */ +int num_globals; +int num_globals_allocated; +struct global *globals; + +static void +add_global (enum global_type type, char *name) +{ + /* Ignore the one non-symbol that can occur. */ + if (strcmp (name, "...")) + { + ++num_globals; + + if (num_globals_allocated == 0) + { + num_globals_allocated = 100; + globals = xmalloc (num_globals_allocated * sizeof (struct global)); + } + else if (num_globals == num_globals_allocated) + { + num_globals_allocated *= 2; + globals = xrealloc (globals, + num_globals_allocated * sizeof (struct global)); + } + + globals[num_globals - 1].type = type; + globals[num_globals - 1].name = name; + } +} + +static int +compare_globals (const void *a, const void *b) +{ + const struct global *ga = a; + const struct global *gb = b; + return strcmp (ga->name, gb->name); +} + +void +write_globals (void) +{ + int i; + qsort (globals, num_globals, sizeof (struct global), compare_globals); + for (i = 0; i < num_globals; ++i) + { + char *type; + + switch (globals[i].type) + { + case EMACS_INTEGER: + type = "EMACS_INT"; + break; + case BOOLEAN: + type = "int"; + break; + case LISP_OBJECT: + type = "Lisp_Object"; + break; + default: + fatal ("not a recognized DEFVAR_", 0); + } + + fprintf (outfile, " %s f_%s;\n", type, globals[i].name); + fprintf (outfile, "#define %s globals.f_%s\n", + globals[i].name, globals[i].name); + while (i + 1 < num_globals + && !strcmp (globals[i].name, globals[i + 1].name)) + ++i; + } + + fprintf (outfile, "};\n"); + fprintf (outfile, "extern struct emacs_globals globals;\n"); +} + + /* Read through a c file. If a .o file is named, the corresponding .c or .m file is read instead. Looks for DEFUN constructs such as are defined in ../src/lisp.h. @@ -533,6 +663,7 @@ scan_c_file (char *filename, const char *mode) register int defvarflag; int minargs, maxargs; int extension = filename[strlen (filename) - 1]; + enum global_type type; if (extension == 'o') filename[strlen (filename) - 1] = 'c'; @@ -599,8 +730,23 @@ scan_c_file (char *filename, const char *mode) c = getc (infile); defvarperbufferflag = (c == 'P'); + if (generate_globals) + { + if (c == 'I') + type = EMACS_INTEGER; + else if (c == 'L') + type = LISP_OBJECT; + else if (c == 'B') + type = BOOLEAN; + else + type = INVALID; + } c = getc (infile); + /* We need to distinguish between DEFVAR_BOOL and + DEFVAR_BUFFER_DEFAULTS. */ + if (generate_globals && type == BOOLEAN && c != 'O') + type = INVALID; } else if (c == 'D') { @@ -617,6 +763,10 @@ scan_c_file (char *filename, const char *mode) } else continue; + if (generate_globals && (!defvarflag || defvarperbufferflag + || type == INVALID)) + continue; + while (c != '(') { if (c < 0) @@ -630,6 +780,34 @@ scan_c_file (char *filename, const char *mode) continue; c = read_c_string_or_comment (infile, -1, 0, 0); + if (generate_globals) + { + int i = 0; + char *name; + + /* Skip "," and whitespace. */ + do + { + c = getc (infile); + } + while (c == ',' || c == ' ' || c == '\t' || c == '\n' || c == '\r'); + + /* Read in the identifier. */ + do + { + buf[i++] = c; + c = getc (infile); + } + while (! (c == ',' || c == ' ' || c == '\t' || + c == '\n' || c == '\r')); + buf[i] = '\0'; + + name = xmalloc (i + 1); + memcpy (name, buf, i + 1); + add_global (type, name); + continue; + } + /* DEFVAR_LISP ("name", addr, "doc") DEFVAR_LISP ("name", addr /\* doc *\/) DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */ @@ -845,6 +1023,9 @@ scan_lisp_file (const char *filename, const char *mode) register int c; char *saved_string = 0; + if (generate_globals) + fatal ("scanning lisp file when -g specified", 0); + infile = fopen (filename, mode); if (infile == NULL) { |