Mercurial > emacs
annotate lib-src/make-docfile.c @ 4987:f052db139432
(read_c_string): For "", concatenate the two strings.
| author | Richard M. Stallman <rms@gnu.org> |
|---|---|
| date | Fri, 12 Nov 1993 21:12:35 +0000 |
| parents | 507f64624555 |
| children | dfe798027eac |
| rev | line source |
|---|---|
| 24 | 1 /* Generate doc-string file for GNU Emacs from source files. |
| 638 | 2 Copyright (C) 1985, 1986, 1992 Free Software Foundation, Inc. |
| 24 | 3 |
| 4 This file is part of GNU Emacs. | |
| 5 | |
| 38 | 6 GNU Emacs is free software; you can redistribute it and/or modify |
| 7 it under the terms of the GNU General Public License as published by | |
| 638 | 8 the Free Software Foundation; either version 2, or (at your option) |
| 38 | 9 any later version. |
| 24 | 10 |
| 38 | 11 GNU Emacs is distributed in the hope that it will be useful, |
| 12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 GNU General Public License for more details. | |
| 15 | |
| 16 You should have received a copy of the GNU General Public License | |
| 17 along with GNU Emacs; see the file COPYING. If not, write to | |
| 18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
| 24 | 19 |
| 20 /* The arguments given to this program are all the C and Lisp source files | |
| 21 of GNU Emacs. .elc and .el and .c files are allowed. | |
| 22 A .o file can also be specified; the .c file it was made from is used. | |
| 23 This helps the makefile pass the correct list of files. | |
| 24 | |
| 25 The results, which go to standard output or to a file | |
| 26 specified with -a or -o (-a to append, -o to start from nothing), | |
| 27 are entries containing function or variable names and their documentation. | |
| 28 Each entry starts with a ^_ character. | |
| 29 Then comes F for a function or V for a variable. | |
| 30 Then comes the function or variable name, terminated with a newline. | |
| 31 Then comes the documentation for that function or variable. | |
| 32 */ | |
| 33 | |
| 34 #include <stdio.h> | |
| 35 | |
| 36 FILE *outfile; | |
| 37 | |
| 38 main (argc, argv) | |
| 39 int argc; | |
| 40 char **argv; | |
| 41 { | |
| 42 int i; | |
| 43 int err_count = 0; | |
| 44 | |
| 45 outfile = stdout; | |
| 46 | |
| 47 /* If first two args are -o FILE, output to FILE. */ | |
| 48 i = 1; | |
| 49 if (argc > i + 1 && !strcmp (argv[i], "-o")) | |
| 50 { | |
| 51 outfile = fopen (argv[i + 1], "w"); | |
| 52 i += 2; | |
| 53 } | |
| 54 if (argc > i + 1 && !strcmp (argv[i], "-a")) | |
| 55 { | |
| 56 outfile = fopen (argv[i + 1], "a"); | |
| 57 i += 2; | |
| 58 } | |
|
2814
0da5b58e98ed
Install patches from David J. Mackenzie to make the srcdir option
Jim Blandy <jimb@redhat.com>
parents:
2483
diff
changeset
|
59 if (argc > i + 1 && !strcmp (argv[i], "-d")) |
|
0da5b58e98ed
Install patches from David J. Mackenzie to make the srcdir option
Jim Blandy <jimb@redhat.com>
parents:
2483
diff
changeset
|
60 { |
|
0da5b58e98ed
Install patches from David J. Mackenzie to make the srcdir option
Jim Blandy <jimb@redhat.com>
parents:
2483
diff
changeset
|
61 chdir (argv[i + 1]); |
|
0da5b58e98ed
Install patches from David J. Mackenzie to make the srcdir option
Jim Blandy <jimb@redhat.com>
parents:
2483
diff
changeset
|
62 i += 2; |
|
0da5b58e98ed
Install patches from David J. Mackenzie to make the srcdir option
Jim Blandy <jimb@redhat.com>
parents:
2483
diff
changeset
|
63 } |
| 24 | 64 |
| 65 for (; i < argc; i++) | |
| 66 err_count += scan_file (argv[i]); /* err_count seems to be {mis,un}used */ | |
| 67 #ifndef VMS | |
| 68 exit (err_count); /* see below - shane */ | |
| 3028 | 69 #endif /* VMS */ |
| 24 | 70 } |
| 71 | |
| 164 | 72 /* Read file FILENAME and output its doc strings to outfile. */ |
| 24 | 73 /* Return 1 if file is not found, 0 if it is found. */ |
| 74 | |
| 75 scan_file (filename) | |
| 76 char *filename; | |
| 77 { | |
| 78 int len = strlen (filename); | |
| 79 if (!strcmp (filename + len - 4, ".elc")) | |
| 80 return scan_lisp_file (filename); | |
| 81 else if (!strcmp (filename + len - 3, ".el")) | |
| 82 return scan_lisp_file (filename); | |
| 83 else | |
| 84 return scan_c_file (filename); | |
| 85 } | |
| 86 | |
| 87 char buf[128]; | |
| 88 | |
| 89 /* Skip a C string from INFILE, | |
| 90 and return the character that follows the closing ". | |
| 164 | 91 If printflag is positive, output string contents to outfile. |
| 24 | 92 If it is negative, store contents in buf. |
| 93 Convert escape sequences \n and \t to newline and tab; | |
| 94 discard \ followed by newline. */ | |
| 95 | |
| 96 read_c_string (infile, printflag) | |
| 97 FILE *infile; | |
| 98 int printflag; | |
| 99 { | |
| 100 register int c; | |
| 101 char *p = buf; | |
| 102 | |
| 103 c = getc (infile); | |
| 104 while (c != EOF) | |
| 105 { | |
| 106 while (c != '"' && c != EOF) | |
| 107 { | |
| 108 if (c == '\\') | |
| 109 { | |
| 110 c = getc (infile); | |
| 111 if (c == '\n') | |
| 112 { | |
| 113 c = getc (infile); | |
| 114 continue; | |
| 115 } | |
| 116 if (c == 'n') | |
| 117 c = '\n'; | |
| 118 if (c == 't') | |
| 119 c = '\t'; | |
| 120 } | |
| 121 if (printflag > 0) | |
| 122 putc (c, outfile); | |
| 123 else if (printflag < 0) | |
| 124 *p++ = c; | |
| 125 c = getc (infile); | |
| 126 } | |
| 127 c = getc (infile); | |
| 128 if (c != '"') | |
| 129 break; | |
|
4987
f052db139432
(read_c_string): For "", concatenate the two strings.
Richard M. Stallman <rms@gnu.org>
parents:
3591
diff
changeset
|
130 /* If we had a "", concatenate the two strings. */ |
| 24 | 131 c = getc (infile); |
| 132 } | |
| 133 | |
| 134 if (printflag < 0) | |
| 135 *p = 0; | |
| 136 | |
| 137 return c; | |
| 138 } | |
| 139 | |
| 140 /* Write to file OUT the argument names of the function whose text is in BUF. | |
| 141 MINARGS and MAXARGS are the minimum and maximum number of arguments. */ | |
| 142 | |
| 143 write_c_args (out, buf, minargs, maxargs) | |
| 144 FILE *out; | |
| 145 char *buf; | |
| 146 int minargs, maxargs; | |
| 147 { | |
| 1206 | 148 register char *p; |
| 1250 | 149 int in_ident = 0; |
| 150 int just_spaced = 0; | |
| 24 | 151 |
| 168 | 152 fprintf (out, "arguments: "); |
| 24 | 153 |
| 1206 | 154 for (p = buf; *p; p++) |
| 24 | 155 { |
| 1250 | 156 char c = *p; |
|
2483
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
157 int ident_start = 0; |
| 1250 | 158 |
| 159 /* Notice when we start printing a new identifier. */ | |
| 160 if ((('A' <= c && c <= 'Z') | |
| 161 || ('a' <= c && c <= 'z') | |
| 162 || ('0' <= c && c <= '9') | |
| 163 || c == '_') | |
| 164 != in_ident) | |
| 24 | 165 { |
| 1250 | 166 if (!in_ident) |
| 167 { | |
| 168 in_ident = 1; | |
|
2483
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
169 ident_start = 1; |
| 1206 | 170 |
| 1250 | 171 if (minargs == 0 && maxargs > 0) |
| 172 fprintf (out, "&optional "); | |
| 173 just_spaced = 1; | |
| 1206 | 174 |
| 1250 | 175 minargs--; |
| 176 maxargs--; | |
| 177 } | |
| 178 else | |
| 179 in_ident = 0; | |
| 24 | 180 } |
| 638 | 181 |
| 1250 | 182 /* Print the C argument list as it would appear in lisp: |
| 183 print underscores as hyphens, and print commas as spaces. | |
| 184 Collapse adjacent spaces into one. */ | |
| 185 if (c == '_') c = '-'; | |
| 186 if (c == ',') c = ' '; | |
| 187 | |
|
2483
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
188 /* In C code, `default' is a reserved word, so we spell it |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
189 `defalt'; unmangle that here. */ |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
190 if (ident_start |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
191 && strncmp (p, "defalt", 6) == 0 |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
192 && ! (('A' <= p[6] && p[6] <= 'Z') |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
193 || ('a' <= p[6] && p[6] <= 'z') |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
194 || ('0' <= p[6] && p[6] <= '9') |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
195 || p[6] == '_')) |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
196 { |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
197 fprintf (out, "default"); |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
198 p += 5; |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
199 in_ident = 0; |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
200 just_spaced = 0; |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
201 } |
|
b4145a12422d
* make-docfile.c (write_c_args): Print an argument named "defalt"
Jim Blandy <jimb@redhat.com>
parents:
1676
diff
changeset
|
202 else if (c != ' ' || ! just_spaced) |
| 1250 | 203 putc (c, out); |
| 204 | |
| 205 just_spaced = (c == ' '); | |
| 24 | 206 } |
| 207 } | |
| 208 | |
| 209 /* Read through a c file. If a .o file is named, | |
| 210 the corresponding .c file is read instead. | |
| 211 Looks for DEFUN constructs such as are defined in ../src/lisp.h. | |
| 212 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */ | |
| 213 | |
| 214 scan_c_file (filename) | |
| 215 char *filename; | |
| 216 { | |
| 217 FILE *infile; | |
| 218 register int c; | |
| 219 register int commas; | |
| 220 register int defunflag; | |
|
1676
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
221 register int defvarperbufferflag; |
| 24 | 222 register int defvarflag; |
| 223 int minargs, maxargs; | |
| 224 | |
| 225 if (filename[strlen (filename) - 1] == 'o') | |
| 226 filename[strlen (filename) - 1] = 'c'; | |
| 227 | |
| 228 infile = fopen (filename, "r"); | |
| 229 | |
| 230 /* No error if non-ex input file */ | |
| 231 if (infile == NULL) | |
| 232 { | |
| 233 perror (filename); | |
| 234 return 0; | |
| 235 } | |
| 236 | |
| 237 c = '\n'; | |
| 238 while (!feof (infile)) | |
| 239 { | |
| 240 if (c != '\n') | |
| 241 { | |
| 242 c = getc (infile); | |
| 243 continue; | |
| 244 } | |
| 245 c = getc (infile); | |
| 246 if (c == ' ') | |
| 247 { | |
| 248 while (c == ' ') | |
| 249 c = getc (infile); | |
| 250 if (c != 'D') | |
| 251 continue; | |
| 252 c = getc (infile); | |
| 253 if (c != 'E') | |
| 254 continue; | |
| 255 c = getc (infile); | |
| 256 if (c != 'F') | |
| 257 continue; | |
| 258 c = getc (infile); | |
| 259 if (c != 'V') | |
| 260 continue; | |
|
1676
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
261 c = getc (infile); |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
262 if (c != 'A') |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
263 continue; |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
264 c = getc (infile); |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
265 if (c != 'R') |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
266 continue; |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
267 c = getc (infile); |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
268 if (c != '_') |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
269 continue; |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
270 |
| 24 | 271 defvarflag = 1; |
| 272 defunflag = 0; | |
|
1676
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
273 |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
274 c = getc (infile); |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
275 defvarperbufferflag = (c == 'P'); |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
276 |
| 24 | 277 c = getc (infile); |
| 278 } | |
| 279 else if (c == 'D') | |
| 280 { | |
| 281 c = getc (infile); | |
| 282 if (c != 'E') | |
| 283 continue; | |
| 284 c = getc (infile); | |
| 285 if (c != 'F') | |
| 286 continue; | |
| 287 c = getc (infile); | |
| 288 defunflag = c == 'U'; | |
| 289 defvarflag = 0; | |
| 290 } | |
| 291 else continue; | |
| 292 | |
| 293 while (c != '(') | |
| 294 { | |
| 295 if (c < 0) | |
| 296 goto eof; | |
| 297 c = getc (infile); | |
| 298 } | |
| 299 | |
| 300 c = getc (infile); | |
| 301 if (c != '"') | |
| 302 continue; | |
| 303 c = read_c_string (infile, -1); | |
| 304 | |
| 305 if (defunflag) | |
| 306 commas = 5; | |
|
1676
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
307 else if (defvarperbufferflag) |
|
e8b3c6b52c1e
* make-docfile.c (scan_c_file): Since DEFVAR_PER_BUFFER now takes
Jim Blandy <jimb@redhat.com>
parents:
1250
diff
changeset
|
308 commas = 2; |
| 24 | 309 else if (defvarflag) |
| 310 commas = 1; | |
| 311 else /* For DEFSIMPLE and DEFPRED */ | |
| 312 commas = 2; | |
| 313 | |
| 314 while (commas) | |
| 315 { | |
| 316 if (c == ',') | |
| 317 { | |
| 318 commas--; | |
| 319 if (defunflag && (commas == 1 || commas == 2)) | |
| 320 { | |
| 321 do | |
| 322 c = getc (infile); | |
| 323 while (c == ' ' || c == '\n' || c == '\t'); | |
| 324 if (c < 0) | |
| 325 goto eof; | |
| 326 ungetc (c, infile); | |
| 327 if (commas == 2) /* pick up minargs */ | |
| 328 fscanf (infile, "%d", &minargs); | |
| 329 else /* pick up maxargs */ | |
| 330 if (c == 'M' || c == 'U') /* MANY || UNEVALLED */ | |
| 331 maxargs = -1; | |
| 332 else | |
| 333 fscanf (infile, "%d", &maxargs); | |
| 334 } | |
| 335 } | |
| 336 if (c < 0) | |
| 337 goto eof; | |
| 338 c = getc (infile); | |
| 339 } | |
| 340 while (c == ' ' || c == '\n' || c == '\t') | |
| 341 c = getc (infile); | |
| 342 if (c == '"') | |
| 343 c = read_c_string (infile, 0); | |
| 344 while (c != ',') | |
| 345 c = getc (infile); | |
| 346 c = getc (infile); | |
| 347 while (c == ' ' || c == '\n' || c == '\t') | |
| 348 c = getc (infile); | |
| 349 | |
| 350 if (c == '"') | |
| 351 { | |
| 352 putc (037, outfile); | |
| 353 putc (defvarflag ? 'V' : 'F', outfile); | |
| 354 fprintf (outfile, "%s\n", buf); | |
| 168 | 355 c = read_c_string (infile, 1); |
| 356 | |
| 357 /* If this is a defun, find the arguments and print them. If | |
| 358 this function takes MANY or UNEVALLED args, then the C source | |
| 359 won't give the names of the arguments, so we shouldn't bother | |
| 360 trying to find them. */ | |
| 361 if (defunflag && maxargs != -1) | |
| 24 | 362 { |
| 363 char argbuf[1024], *p = argbuf; | |
| 364 while (c != ')') | |
| 365 { | |
| 366 if (c < 0) | |
| 367 goto eof; | |
| 368 c = getc (infile); | |
| 369 } | |
| 370 /* Skip into arguments. */ | |
| 371 while (c != '(') | |
| 372 { | |
| 373 if (c < 0) | |
| 374 goto eof; | |
| 375 c = getc (infile); | |
| 376 } | |
| 377 /* Copy arguments into ARGBUF. */ | |
| 378 *p++ = c; | |
| 379 do | |
| 380 *p++ = c = getc (infile); | |
| 381 while (c != ')'); | |
| 382 *p = '\0'; | |
| 383 /* Output them. */ | |
| 384 fprintf (outfile, "\n\n"); | |
| 385 write_c_args (outfile, argbuf, minargs, maxargs); | |
| 386 } | |
| 387 } | |
| 388 } | |
| 389 eof: | |
| 390 fclose (infile); | |
| 391 return 0; | |
| 392 } | |
| 393 | |
| 394 /* Read a file of Lisp code, compiled or interpreted. | |
| 395 Looks for | |
| 396 (defun NAME ARGS DOCSTRING ...) | |
| 753 | 397 (defmacro NAME ARGS DOCSTRING ...) |
| 398 (autoload (quote NAME) FILE DOCSTRING ...) | |
| 24 | 399 (defvar NAME VALUE DOCSTRING) |
| 400 (defconst NAME VALUE DOCSTRING) | |
| 753 | 401 (fset (quote NAME) (make-byte-code ... DOCSTRING ...)) |
| 402 (fset (quote NAME) #[... DOCSTRING ...]) | |
|
2966
e936d56c2354
(scan_lisp_file): Recognize defalias like fset.
Richard M. Stallman <rms@gnu.org>
parents:
2814
diff
changeset
|
403 (defalias (quote NAME) #[... DOCSTRING ...]) |
| 24 | 404 starting in column zero. |
| 753 | 405 (quote NAME) may appear as 'NAME as well. |
| 406 For defun, defmacro, and autoload, we know how to skip over the arglist. | |
|
3591
507f64624555
Apply typo patches from Paul Eggert.
Jim Blandy <jimb@redhat.com>
parents:
3028
diff
changeset
|
407 For defvar, defconst, and fset we skip to the docstring with a kludgy |
| 753 | 408 formatting convention: all docstrings must appear on the same line as the |
| 409 initial open-paren (the one in column zero) and must contain a backslash | |
| 410 and a double-quote immediately after the initial double-quote. No newlines | |
| 411 must appear between the beginning of the form and the first double-quote. | |
| 412 The only source file that must follow this convention is loaddefs.el; aside | |
| 413 from that, it is always the .elc file that we look at, and they are no | |
| 414 problem because byte-compiler output follows this convention. | |
| 24 | 415 The NAME and DOCSTRING are output. |
| 416 NAME is preceded by `F' for a function or `V' for a variable. | |
| 417 An entry is output only if DOCSTRING has \ newline just after the opening " | |
| 418 */ | |
| 419 | |
| 753 | 420 void |
| 421 skip_white (infile) | |
| 422 FILE *infile; | |
| 423 { | |
| 424 char c = ' '; | |
| 425 while (c == ' ' || c == '\t' || c == '\n') | |
| 426 c = getc (infile); | |
| 427 ungetc (c, infile); | |
| 428 } | |
| 429 | |
| 430 void | |
| 431 read_lisp_symbol (infile, buffer) | |
| 432 FILE *infile; | |
| 433 char *buffer; | |
| 434 { | |
| 435 char c; | |
| 436 char *fillp = buffer; | |
| 437 | |
| 438 skip_white (infile); | |
| 439 while (1) | |
| 440 { | |
| 441 c = getc (infile); | |
| 442 if (c == '\\') | |
| 443 *(++fillp) = getc (infile); | |
| 444 else if (c == ' ' || c == '\t' || c == '\n' || c == '(' || c == ')') | |
| 445 { | |
| 446 ungetc (c, infile); | |
| 447 *fillp = 0; | |
| 448 break; | |
| 449 } | |
| 450 else | |
| 451 *fillp++ = c; | |
| 452 } | |
| 453 | |
| 454 if (! buffer[0]) | |
| 455 fprintf (stderr, "## expected a symbol, got '%c'\n", c); | |
| 456 | |
| 457 skip_white (infile); | |
| 458 } | |
| 459 | |
| 460 | |
| 24 | 461 scan_lisp_file (filename) |
| 462 char *filename; | |
| 463 { | |
| 464 FILE *infile; | |
| 465 register int c; | |
| 466 | |
| 467 infile = fopen (filename, "r"); | |
| 468 if (infile == NULL) | |
| 469 { | |
| 470 perror (filename); | |
| 471 return 0; /* No error */ | |
| 472 } | |
| 473 | |
| 474 c = '\n'; | |
| 475 while (!feof (infile)) | |
| 476 { | |
| 753 | 477 char buffer [BUFSIZ]; |
| 478 char *fillp = buffer; | |
| 479 char type; | |
| 480 | |
| 24 | 481 if (c != '\n') |
| 482 { | |
| 483 c = getc (infile); | |
| 484 continue; | |
| 485 } | |
| 486 c = getc (infile); | |
| 487 if (c != '(') | |
| 488 continue; | |
| 164 | 489 |
| 753 | 490 read_lisp_symbol (infile, buffer); |
| 491 | |
| 492 if (! strcmp (buffer, "defun") || | |
| 493 ! strcmp (buffer, "defmacro")) | |
| 24 | 494 { |
| 753 | 495 type = 'F'; |
| 496 read_lisp_symbol (infile, buffer); | |
| 497 | |
| 498 /* Skip the arguments: either "nil" or a list in parens */ | |
| 24 | 499 |
| 500 c = getc (infile); | |
| 753 | 501 if (c == 'n') /* nil */ |
| 502 { | |
| 503 if ((c = getc (infile)) != 'i' || | |
| 504 (c = getc (infile)) != 'l') | |
| 505 { | |
| 506 fprintf (stderr, "## unparsable arglist in %s (%s)\n", | |
| 507 buffer, filename); | |
| 508 continue; | |
| 509 } | |
| 510 } | |
| 511 else if (c != '(') | |
| 512 { | |
| 513 fprintf (stderr, "## unparsable arglist in %s (%s)\n", | |
| 514 buffer, filename); | |
| 515 continue; | |
| 516 } | |
| 517 else | |
| 518 while (c != ')') | |
| 519 c = getc (infile); | |
| 520 skip_white (infile); | |
| 24 | 521 |
| 753 | 522 /* If the next three characters aren't `dquote bslash newline' |
| 523 then we're not reading a docstring. | |
| 524 */ | |
| 525 if ((c = getc (infile)) != '"' || | |
| 526 (c = getc (infile)) != '\\' || | |
| 527 (c = getc (infile)) != '\n') | |
| 24 | 528 { |
| 753 | 529 #ifdef DEBUG |
| 530 fprintf (stderr, "## non-docstring in %s (%s)\n", | |
| 531 buffer, filename); | |
| 532 #endif | |
| 533 continue; | |
| 534 } | |
| 535 } | |
| 536 | |
| 537 else if (! strcmp (buffer, "defvar") || | |
| 538 ! strcmp (buffer, "defconst")) | |
| 539 { | |
| 540 char c1 = 0, c2 = 0; | |
| 541 type = 'V'; | |
| 542 read_lisp_symbol (infile, buffer); | |
| 543 | |
| 544 /* Skip until the first newline; remember the two previous chars. */ | |
| 545 while (c != '\n' && c >= 0) | |
| 546 { | |
| 547 c2 = c1; | |
| 548 c1 = c; | |
| 24 | 549 c = getc (infile); |
| 550 } | |
| 753 | 551 |
| 552 /* If two previous characters were " and \, | |
| 553 this is a doc string. Otherwise, there is none. */ | |
| 554 if (c2 != '"' || c1 != '\\') | |
| 555 { | |
| 556 #ifdef DEBUG | |
| 557 fprintf (stderr, "## non-docstring in %s (%s)\n", | |
| 558 buffer, filename); | |
| 559 #endif | |
| 560 continue; | |
| 561 } | |
| 562 } | |
| 563 | |
|
2966
e936d56c2354
(scan_lisp_file): Recognize defalias like fset.
Richard M. Stallman <rms@gnu.org>
parents:
2814
diff
changeset
|
564 else if (! strcmp (buffer, "fset") || ! strcmp (buffer, "defalias")) |
| 753 | 565 { |
| 566 char c1 = 0, c2 = 0; | |
| 567 type = 'F'; | |
| 568 | |
| 569 c = getc (infile); | |
| 570 if (c == '\'') | |
| 571 read_lisp_symbol (infile, buffer); | |
| 24 | 572 else |
| 573 { | |
| 574 if (c != '(') | |
| 753 | 575 { |
| 576 fprintf (stderr, "## unparsable name in fset in %s\n", | |
| 577 filename); | |
| 578 continue; | |
| 579 } | |
| 580 read_lisp_symbol (infile, buffer); | |
| 581 if (strcmp (buffer, "quote")) | |
| 582 { | |
| 583 fprintf (stderr, "## unparsable name in fset in %s\n", | |
| 584 filename); | |
| 585 continue; | |
| 586 } | |
| 587 read_lisp_symbol (infile, buffer); | |
| 24 | 588 c = getc (infile); |
| 753 | 589 if (c != ')') |
| 590 { | |
| 591 fprintf (stderr, | |
| 592 "## unparsable quoted name in fset in %s\n", | |
| 593 filename); | |
| 594 continue; | |
| 595 } | |
| 24 | 596 } |
| 164 | 597 |
| 753 | 598 /* Skip until the first newline; remember the two previous chars. */ |
| 599 while (c != '\n' && c >= 0) | |
| 24 | 600 { |
| 753 | 601 c2 = c1; |
| 602 c1 = c; | |
| 24 | 603 c = getc (infile); |
| 604 } | |
| 753 | 605 |
| 606 /* If two previous characters were " and \, | |
| 607 this is a doc string. Otherwise, there is none. */ | |
| 608 if (c2 != '"' || c1 != '\\') | |
| 24 | 609 { |
| 753 | 610 #ifdef DEBUG |
| 611 fprintf (stderr, "## non-docstring in %s (%s)\n", | |
| 612 buffer, filename); | |
| 613 #endif | |
| 24 | 614 continue; |
| 615 } | |
| 616 } | |
| 753 | 617 |
| 618 else if (! strcmp (buffer, "autoload")) | |
| 164 | 619 { |
| 753 | 620 type = 'F'; |
| 164 | 621 c = getc (infile); |
| 753 | 622 if (c == '\'') |
| 623 read_lisp_symbol (infile, buffer); | |
| 624 else | |
| 625 { | |
| 626 if (c != '(') | |
| 627 { | |
| 628 fprintf (stderr, "## unparsable name in autoload in %s\n", | |
| 629 filename); | |
| 630 continue; | |
| 631 } | |
| 632 read_lisp_symbol (infile, buffer); | |
| 633 if (strcmp (buffer, "quote")) | |
| 634 { | |
| 635 fprintf (stderr, "## unparsable name in autoload in %s\n", | |
| 636 filename); | |
| 637 continue; | |
| 638 } | |
| 639 read_lisp_symbol (infile, buffer); | |
| 640 c = getc (infile); | |
| 641 if (c != ')') | |
| 642 { | |
| 643 fprintf (stderr, | |
| 644 "## unparsable quoted name in autoload in %s\n", | |
| 645 filename); | |
| 646 continue; | |
| 647 } | |
| 648 } | |
| 649 skip_white (infile); | |
| 650 if ((c = getc (infile)) != '\"') | |
| 651 { | |
| 652 fprintf (stderr, "## autoload of %s unparsable (%s)\n", | |
| 653 buffer, filename); | |
| 654 continue; | |
| 655 } | |
| 656 read_c_string (infile, 0); | |
| 657 skip_white (infile); | |
| 164 | 658 |
| 753 | 659 /* If the next three characters aren't `dquote bslash newline' |
| 660 then we're not reading a docstring. | |
| 661 */ | |
| 662 if ((c = getc (infile)) != '"' || | |
| 663 (c = getc (infile)) != '\\' || | |
| 664 (c = getc (infile)) != '\n') | |
| 665 { | |
| 666 #ifdef DEBUG | |
| 667 fprintf (stderr, "## non-docstring in %s (%s)\n", | |
| 668 buffer, filename); | |
| 669 #endif | |
| 670 continue; | |
| 671 } | |
| 164 | 672 } |
| 24 | 673 |
| 753 | 674 #ifdef DEBUG |
| 675 else if (! strcmp (buffer, "if") || | |
| 676 ! strcmp (buffer, "byte-code")) | |
| 677 ; | |
| 678 #endif | |
| 24 | 679 |
| 753 | 680 else |
| 681 { | |
| 682 #ifdef DEBUG | |
| 683 fprintf (stderr, "## unrecognised top-level form, %s (%s)\n", | |
| 684 buffer, filename); | |
| 685 #endif | |
| 686 continue; | |
| 687 } | |
| 24 | 688 |
| 753 | 689 /* At this point, there is a docstring that we should gobble. |
| 690 The opening quote (and leading backslash-newline) have already | |
| 691 been read. | |
| 692 */ | |
| 693 putc ('\n', outfile); | |
| 24 | 694 putc (037, outfile); |
| 753 | 695 putc (type, outfile); |
| 696 fprintf (outfile, "%s\n", buffer); | |
| 24 | 697 read_c_string (infile, 1); |
| 698 } | |
| 699 fclose (infile); | |
| 700 return 0; | |
| 701 } |
