X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/8678d9e413593b0abab296551a20589745c459da..404dbd373a91c0b994005e88fe703d9144873b27:/lib-src/make-docfile.c diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c index 93994c1ed3..2a5f028976 100644 --- a/lib-src/make-docfile.c +++ b/lib-src/make-docfile.c @@ -1,5 +1,5 @@ /* Generate doc-string file for GNU Emacs from source files. - Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2011 + Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -35,7 +35,7 @@ along with GNU Emacs. If not, see . */ #include -/* defined to be emacs_main, sys_fopen, etc. in config.h */ +/* Defined to be emacs_main, sys_fopen, etc. in config.h. */ #undef main #undef fopen #undef chdir @@ -66,12 +66,18 @@ along with GNU Emacs. If not, see . */ #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP) #endif -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); +/* Use this to suppress gcc's `...may be used before initialized' warnings. */ +#ifdef lint +# define IF_LINT(Code) Code +#else +# define IF_LINT(Code) /* empty */ +#endif + +static int scan_file (char *filename); +static int scan_lisp_file (const char *filename, const char *mode); +static int scan_c_file (char *filename, const char *mode); +static void start_globals (void); +static void write_globals (void); #ifdef MSDOS /* s/msdos.h defines this as sys_chdir, but we're not linking with the @@ -93,7 +99,7 @@ int generate_globals; /* Print error message. `s1' is printf control string, `s2' is arg for it. */ /* VARARGS1 */ -void +static void error (const char *s1, const char *s2) { fprintf (stderr, "%s: ", progname); @@ -104,7 +110,7 @@ error (const char *s1, const char *s2) /* Print error message and exit. */ /* VARARGS1 */ -void +static _Noreturn void fatal (const char *s1, const char *s2) { error (s1, s2); @@ -113,7 +119,7 @@ fatal (const char *s1, const char *s2) /* Like malloc but get fatal error if memory is exhausted. */ -void * +static void * xmalloc (unsigned int size) { void *result = (void *) malloc (size); @@ -124,7 +130,7 @@ xmalloc (unsigned int size) /* Like realloc but get fatal error if memory is exhausted. */ -void * +static void * xrealloc (void *arg, unsigned int size) { void *result = (void *) realloc (arg, size); @@ -212,14 +218,14 @@ main (int argc, char **argv) } /* Add a source file name boundary marker in the output file. */ -void +static void put_filename (char *filename) { char *tmp; for (tmp = filename; *tmp; tmp++) { - if (IS_DIRECTORY_SEP(*tmp)) + if (IS_DIRECTORY_SEP (*tmp)) filename = tmp + 1; } @@ -231,7 +237,7 @@ put_filename (char *filename) /* Read file FILENAME and output its doc strings to outfile. */ /* Return 1 if file is not found, 0 if it is found. */ -int +static int scan_file (char *filename) { @@ -247,7 +253,7 @@ scan_file (char *filename) return scan_c_file (filename, READ_TEXT); } -void +static void start_globals (void) { fprintf (outfile, "/* This file was auto-generated by make-docfile. */\n"); @@ -255,7 +261,7 @@ start_globals (void) fprintf (outfile, "struct emacs_globals {\n"); } -char buf[128]; +static char input_buffer[128]; /* Some state during the execution of `read_c_string_or_comment'. */ struct rcsoc_state @@ -284,7 +290,7 @@ struct rcsoc_state /* Output CH to the file or buffer in STATE. Any pending newlines or spaces are output first. */ -static INLINE void +static inline void put_char (int ch, struct rcsoc_state *state) { int out_ch; @@ -388,14 +394,14 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state) at the beginning of a line will be removed, and *SAW_USAGE set to true if any were encountered. */ -int +static int read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage) { register int c; struct rcsoc_state state; state.in_file = infile; - state.buf_ptr = (printflag < 0 ? buf : 0); + state.buf_ptr = (printflag < 0 ? input_buffer : 0); state.out_file = (printflag > 0 ? outfile : 0); state.pending_spaces = 0; state.pending_newlines = 0; @@ -476,12 +482,12 @@ read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usa /* Write to file OUT the argument names of function FUNC, whose text is in BUF. MINARGS and MAXARGS are the minimum and maximum number of arguments. */ -void +static void write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) { register char *p; int in_ident = 0; - char *ident_start; + char *ident_start IF_LINT (= NULL); size_t ident_length = 0; fprintf (out, "(fn"); @@ -534,7 +540,7 @@ write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) maxargs--; /* In C code, `default' is a reserved word, so we spell it - `defalt'; unmangle that here. */ + `defalt'; demangle that here. */ if (ident_length == 6 && strncmp (ident_start, "defalt", 6) == 0) fprintf (out, "DEFAULT"); else @@ -558,6 +564,7 @@ write_c_args (FILE *out, char *func, char *buf, int minargs, int maxargs) /* The types of globals. */ enum global_type { + FUNCTION, EMACS_INTEGER, BOOLEAN, LISP_OBJECT, @@ -569,6 +576,7 @@ struct global { enum global_type type; char *name; + int value; }; /* All the variable names we saw while scanning C sources in `-g' @@ -578,7 +586,7 @@ int num_globals_allocated; struct global *globals; static void -add_global (enum global_type type, char *name) +add_global (enum global_type type, char *name, int value) { /* Ignore the one non-symbol that can occur. */ if (strcmp (name, "...")) @@ -599,6 +607,7 @@ add_global (enum global_type type, char *name) globals[num_globals - 1].type = type; globals[num_globals - 1].name = name; + globals[num_globals - 1].value = value; } } @@ -607,17 +616,33 @@ compare_globals (const void *a, const void *b) { const struct global *ga = a; const struct global *gb = b; + + if (ga->type == FUNCTION) + { + if (gb->type != FUNCTION) + return 1; + } + else if (gb->type == FUNCTION) + return -1; + return strcmp (ga->name, gb->name); } -void +static void +close_emacs_globals (void) +{ + fprintf (outfile, "};\n"); + fprintf (outfile, "extern struct emacs_globals globals;\n"); +} + +static void write_globals (void) { - int i; + int i, seen_defun = 0; qsort (globals, num_globals, sizeof (struct global), compare_globals); for (i = 0; i < num_globals; ++i) { - char *type; + char const *type; switch (globals[i].type) { @@ -630,20 +655,49 @@ write_globals (void) case LISP_OBJECT: type = "Lisp_Object"; break; + case FUNCTION: + if (!seen_defun) + { + close_emacs_globals (); + fprintf (outfile, "\n"); + seen_defun = 1; + } + 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); + if (globals[i].type != FUNCTION) + { + fprintf (outfile, " %s f_%s;\n", type, globals[i].name); + fprintf (outfile, "#define %s globals.f_%s\n", + globals[i].name, globals[i].name); + } + else + { + /* It would be nice to have a cleaner way to deal with these + special hacks. */ + if (strcmp (globals[i].name, "Fthrow") == 0 + || strcmp (globals[i].name, "Ftop_level") == 0 + || strcmp (globals[i].name, "Fkill_emacs") == 0) + fprintf (outfile, "_Noreturn "); + fprintf (outfile, "EXFUN (%s, ", globals[i].name); + if (globals[i].value == -1) + fprintf (outfile, "MANY"); + else if (globals[i].value == -2) + fprintf (outfile, "UNEVALLED"); + else + fprintf (outfile, "%d", globals[i].value); + fprintf (outfile, ");\n"); + } + 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"); + if (!seen_defun) + close_emacs_globals (); } @@ -652,18 +706,14 @@ write_globals (void) Looks for DEFUN constructs such as are defined in ../src/lisp.h. Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */ -int +static int scan_c_file (char *filename, const char *mode) { FILE *infile; register int c; register int commas; - register int defunflag; - register int defvarperbufferflag; - register int defvarflag; int minargs, maxargs; int extension = filename[strlen (filename) - 1]; - enum global_type type; if (extension == 'o') filename[strlen (filename) - 1] = 'c'; @@ -672,14 +722,14 @@ scan_c_file (char *filename, const char *mode) if (infile == NULL && extension == 'o') { - /* try .m */ + /* Try .m. */ filename[strlen (filename) - 1] = 'm'; infile = fopen (filename, mode); if (infile == NULL) - filename[strlen (filename) - 1] = 'c'; /* don't confuse people */ + filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */ } - /* No error if non-ex input file */ + /* No error if non-ex input file. */ if (infile == NULL) { perror (filename); @@ -693,6 +743,11 @@ scan_c_file (char *filename, const char *mode) while (!feof (infile)) { int doc_keyword = 0; + int defunflag = 0; + int defvarperbufferflag = 0; + int defvarflag = 0; + enum global_type type = INVALID; + char *name; if (c != '\n' && c != '\r') { @@ -726,7 +781,6 @@ scan_c_file (char *filename, const char *mode) continue; defvarflag = 1; - defunflag = 0; c = getc (infile); defvarperbufferflag = (c == 'P'); @@ -738,8 +792,6 @@ scan_c_file (char *filename, const char *mode) type = LISP_OBJECT; else if (c == 'B') type = BOOLEAN; - else - type = INVALID; } c = getc (infile); @@ -758,13 +810,12 @@ scan_c_file (char *filename, const char *mode) continue; c = getc (infile); defunflag = c == 'U'; - defvarflag = 0; - defvarperbufferflag = 0; } else continue; - if (generate_globals && (!defvarflag || defvarperbufferflag - || type == INVALID)) + if (generate_globals + && (!defvarflag || defvarperbufferflag || type == INVALID) + && !defunflag) continue; while (c != '(') @@ -783,7 +834,6 @@ scan_c_file (char *filename, const char *mode) if (generate_globals) { int i = 0; - char *name; /* Skip "," and whitespace. */ do @@ -795,17 +845,21 @@ scan_c_file (char *filename, const char *mode) /* Read in the identifier. */ do { - buf[i++] = c; + input_buffer[i++] = c; c = getc (infile); } - while (! (c == ',' || c == ' ' || c == '\t' || - c == '\n' || c == '\r')); - buf[i] = '\0'; + while (! (c == ',' || c == ' ' || c == '\t' + || c == '\n' || c == '\r')); + input_buffer[i] = '\0'; name = xmalloc (i + 1); - memcpy (name, buf, i + 1); - add_global (type, name); - continue; + memcpy (name, input_buffer, i + 1); + + if (!defunflag) + { + add_global (type, name, 0); + continue; + } } /* DEFVAR_LISP ("name", addr, "doc") @@ -813,12 +867,12 @@ scan_c_file (char *filename, const char *mode) DEFVAR_LISP ("name", addr, doc: /\* doc *\/) */ if (defunflag) - commas = 5; + commas = generate_globals ? 4 : 5; else if (defvarperbufferflag) - commas = 2; + commas = 3; else if (defvarflag) commas = 1; - else /* For DEFSIMPLE and DEFPRED */ + else /* For DEFSIMPLE and DEFPRED. */ commas = 2; while (commas) @@ -836,11 +890,16 @@ scan_c_file (char *filename, const char *mode) if (c < 0) goto eof; ungetc (c, infile); - if (commas == 2) /* pick up minargs */ + if (commas == 2) /* Pick up minargs. */ scanned = fscanf (infile, "%d", &minargs); - else /* pick up maxargs */ + else /* Pick up maxargs. */ if (c == 'M' || c == 'U') /* MANY || UNEVALLED */ - maxargs = -1; + { + if (generate_globals) + maxargs = (c == 'M') ? -1 : -2; + else + maxargs = -1; + } else scanned = fscanf (infile, "%d", &maxargs); if (scanned < 0) @@ -853,6 +912,12 @@ scan_c_file (char *filename, const char *mode) c = getc (infile); } + if (generate_globals) + { + add_global (FUNCTION, name, maxargs); + continue; + } + while (c == ' ' || c == '\n' || c == '\r' || c == '\t') c = getc (infile); @@ -888,10 +953,10 @@ scan_c_file (char *filename, const char *mode) putc (037, outfile); putc (defvarflag ? 'V' : 'F', outfile); - fprintf (outfile, "%s\n", buf); + fprintf (outfile, "%s\n", input_buffer); if (comment) - getc (infile); /* Skip past `*' */ + getc (infile); /* Skip past `*'. */ c = read_c_string_or_comment (infile, 1, comment, &saw_usage); /* If this is a defun, find the arguments and print them. If @@ -931,11 +996,12 @@ scan_c_file (char *filename, const char *mode) *p = '\0'; /* Output them. */ fprintf (outfile, "\n\n"); - write_c_args (outfile, buf, argbuf, minargs, maxargs); + write_c_args (outfile, input_buffer, argbuf, minargs, maxargs); } else if (defunflag && maxargs == -1 && !saw_usage) /* The DOC should provide the usage form. */ - fprintf (stderr, "Missing `usage' for function `%s'.\n", buf); + fprintf (stderr, "Missing `usage' for function `%s'.\n", + input_buffer); } } eof: @@ -976,10 +1042,10 @@ scan_c_file (char *filename, const char *mode) problem because byte-compiler output follows this convention. The NAME and DOCSTRING are output. NAME is preceded by `F' for a function or `V' for a variable. - An entry is output only if DOCSTRING has \ newline just after the opening " + An entry is output only if DOCSTRING has \ newline just after the opening ". */ -void +static void skip_white (FILE *infile) { char c = ' '; @@ -988,7 +1054,7 @@ skip_white (FILE *infile) ungetc (c, infile); } -void +static void read_lisp_symbol (FILE *infile, char *buffer) { char c; @@ -1016,7 +1082,35 @@ read_lisp_symbol (FILE *infile, char *buffer) skip_white (infile); } -int +static int +search_lisp_doc_at_eol (FILE *infile) +{ + char c = 0, c1 = 0, c2 = 0; + + /* Skip until the end of line; remember two previous chars. */ + while (c != '\n' && c != '\r' && c != EOF) + { + c2 = c1; + c1 = c; + c = getc (infile); + } + + /* If two previous characters were " and \, + this is a doc string. Otherwise, there is none. */ + if (c2 != '"' || c1 != '\\') + { +#ifdef DEBUG + fprintf (stderr, "## non-docstring in %s (%s)\n", + buffer, filename); +#endif + if (c != EOF) + ungetc (c, infile); + return 0; + } + return 1; +} + +static int scan_lisp_file (const char *filename, const char *mode) { FILE *infile; @@ -1030,7 +1124,7 @@ scan_lisp_file (const char *filename, const char *mode) if (infile == NULL) { perror (filename); - return 0; /* No error */ + return 0; /* No error. */ } c = '\n'; @@ -1107,7 +1201,7 @@ scan_lisp_file (const char *filename, const char *mode) type = 'F'; read_lisp_symbol (infile, buffer); - /* Skip the arguments: either "nil" or a list in parens */ + /* Skip the arguments: either "nil" or a list in parens. */ c = getc (infile); if (c == 'n') /* nil */ @@ -1146,42 +1240,23 @@ scan_lisp_file (const char *filename, const char *mode) } } + /* defcustom can only occur in uncompiled Lisp files. */ else if (! strcmp (buffer, "defvar") - || ! strcmp (buffer, "defconst")) + || ! strcmp (buffer, "defconst") + || ! strcmp (buffer, "defcustom")) { - char c1 = 0, c2 = 0; type = 'V'; read_lisp_symbol (infile, buffer); if (saved_string == 0) - { - - /* Skip until the end of line; remember two previous chars. */ - while (c != '\n' && c != '\r' && c >= 0) - { - c2 = c1; - c1 = c; - c = getc (infile); - } - - /* If two previous characters were " and \, - this is a doc string. Otherwise, there is none. */ - if (c2 != '"' || c1 != '\\') - { -#ifdef DEBUG - fprintf (stderr, "## non-docstring in %s (%s)\n", - buffer, filename); -#endif - continue; - } - } + if (!search_lisp_doc_at_eol (infile)) + continue; } else if (! strcmp (buffer, "custom-declare-variable") || ! strcmp (buffer, "defvaralias") ) { - char c1 = 0, c2 = 0; type = 'V'; c = getc (infile); @@ -1216,31 +1291,12 @@ scan_lisp_file (const char *filename, const char *mode) } if (saved_string == 0) - { - /* Skip to end of line; remember the two previous chars. */ - while (c != '\n' && c != '\r' && c >= 0) - { - c2 = c1; - c1 = c; - c = getc (infile); - } - - /* If two previous characters were " and \, - this is a doc string. Otherwise, there is none. */ - if (c2 != '"' || c1 != '\\') - { -#ifdef DEBUG - fprintf (stderr, "## non-docstring in %s (%s)\n", - buffer, filename); -#endif - continue; - } - } + if (!search_lisp_doc_at_eol (infile)) + continue; } else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias")) { - char c1 = 0, c2 = 0; type = 'F'; c = getc (infile); @@ -1273,26 +1329,8 @@ scan_lisp_file (const char *filename, const char *mode) } if (saved_string == 0) - { - /* Skip to end of line; remember the two previous chars. */ - while (c != '\n' && c != '\r' && c >= 0) - { - c2 = c1; - c1 = c; - c = getc (infile); - } - - /* If two previous characters were " and \, - this is a doc string. Otherwise, there is none. */ - if (c2 != '"' || c1 != '\\') - { -#ifdef DEBUG - fprintf (stderr, "## non-docstring in %s (%s)\n", - buffer, filename); -#endif - continue; - } - } + if (!search_lisp_doc_at_eol (infile)) + continue; } else if (! strcmp (buffer, "autoload")) @@ -1334,29 +1372,16 @@ scan_lisp_file (const char *filename, const char *mode) continue; } read_c_string_or_comment (infile, 0, 0, 0); - skip_white (infile); if (saved_string == 0) - { - /* If the next three characters aren't `dquote bslash newline' - then we're not reading a docstring. */ - if ((c = getc (infile)) != '"' - || (c = getc (infile)) != '\\' - || ((c = getc (infile)) != '\n' && c != '\r')) - { -#ifdef DEBUG - fprintf (stderr, "## non-docstring in %s (%s)\n", - buffer, filename); -#endif - continue; - } - } + if (!search_lisp_doc_at_eol (infile)) + continue; } #ifdef DEBUG else if (! strcmp (buffer, "if") || ! strcmp (buffer, "byte-code")) - ; + continue; #endif else @@ -1368,12 +1393,10 @@ scan_lisp_file (const char *filename, const char *mode) continue; } - /* At this point, we should either use the previous - dynamic doc string in saved_string - or gobble a doc string from the input file. - - In the latter case, the opening quote (and leading - backslash-newline) have already been read. */ + /* At this point, we should either use the previous dynamic doc string in + saved_string or gobble a doc string from the input file. + In the latter case, the opening quote (and leading backslash-newline) + have already been read. */ putc (037, outfile); putc (type, outfile);