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