diff options
author | Tom Tromey <tromey@redhat.com> | 2011-02-08 14:42:56 -0700 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2011-02-08 14:42:56 -0700 |
commit | 00b3c7ac85c3811774305d8ccca6a17ec207b3f1 (patch) | |
tree | 808628395db74d42f5755e5898d04b3d9b69e1b7 /lib-src/make-docfile.c | |
parent | 6ca94a0b49f08f2e59aabc51545eb8a1f726ba8b (diff) | |
download | emacs-00b3c7ac85c3811774305d8ccca6a17ec207b3f1.tar.gz |
Make globals.h a generated header
* configure: Rebuild.
* configure.in (NS_OBJC_OBJ): New subst.
lib-src
* make-docfile.c: Unconditionally include stdlib.h.
(generate_globals): New global.
(xrealloc): New function.
(main): Handle '-g'. Call start_globals, write_globals.
(scan_file): Conditionally call put_filename.
(start_globals): New function.
(struct global): New.
(num_globals, globals): New globals.
(add_global, compare_globals, write_globals): New functions.
(scan_c_file): Update for "-g".
(scan_lisp_file): Fail if "-g".
(enum global_type): New.
src
* Makefile.in (NS_OBJC_OBJ): New variable.
(base_obj): Rename from 'obj'.
(obj): New variable.
(globals.h, gl-stamp, $(obj)): New targets.
(GLOBAL_SOURCES): New variable.
* globals.h: Remove.
* nsselect.m (Vselection_alist): Define. Reverts part of
2011-01-19T22:11:33Z!jan.h.d@swipnet.se.
* buffer.c: Don't use "no_cell" for name of kill-buffer-hook's
variable.
* xselect.c (Vselection_alist): Define. Reverts part of 2011-01-19T23:32:42Z!eggert@cs.ucla.edu.
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..6ce0b886ab4 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_INT, + 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_INT: + 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_INT; + 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) { |