aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorJohn Wiegley2016-02-15 14:09:12 -0800
committerJohn Wiegley2016-02-15 14:09:12 -0800
commita644fa367504c4587c1b9e5fc20b7af79e6e99a0 (patch)
tree4647c040ba7c430db2d102e39180950ffd90e49f /lib-src
parent8c4e041bdbc07a159305b41e1bcb64f1d301b99f (diff)
parentf5d6b9bb5b307067547f0b26c74e9f538464bfc6 (diff)
downloademacs-a644fa367504c4587c1b9e5fc20b7af79e6e99a0.tar.gz
emacs-a644fa367504c4587c1b9e5fc20b7af79e6e99a0.zip
Merge from origin/emacs-25
f5d6b9b Revert "Support integer image rotation and respect EXIF rotations" afe7d1f Revert "Document EXIF image rotation" c6f377c Document OS X LANG default eb4a18c Set locale when run from OS X GUI 456c0a3 make-docfile cleanup for I/O, etc. 25ec995 Memory-management cleanup in make-docfile 02d925e Kevin Gallagher has new email address 4ef153b Improve doc strings of 'forward/backward-word-strictly' 3ad05a0 Describe Makefile test targets in test/README
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/make-docfile.c326
1 files changed, 182 insertions, 144 deletions
diff --git a/lib-src/make-docfile.c b/lib-src/make-docfile.c
index 02b5e766ee2..12222c3db3c 100644
--- a/lib-src/make-docfile.c
+++ b/lib-src/make-docfile.c
@@ -37,6 +37,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
37#include <config.h> 37#include <config.h>
38 38
39#include <stdbool.h> 39#include <stdbool.h>
40#include <stddef.h>
41#include <stdint.h>
40#include <stdio.h> 42#include <stdio.h>
41#include <stdlib.h> /* config.h unconditionally includes this anyway */ 43#include <stdlib.h> /* config.h unconditionally includes this anyway */
42 44
@@ -48,6 +50,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
48#endif /* WINDOWSNT */ 50#endif /* WINDOWSNT */
49 51
50#include <binary-io.h> 52#include <binary-io.h>
53#include <intprops.h>
54#include <min-max.h>
51 55
52#ifdef DOS_NT 56#ifdef DOS_NT
53/* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this 57/* Defined to be sys_chdir in ms-w32.h, but only #ifdef emacs, so this
@@ -61,72 +65,79 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
61#define IS_SLASH(c) ((c) == '/') 65#define IS_SLASH(c) ((c) == '/')
62#endif /* not DOS_NT */ 66#endif /* not DOS_NT */
63 67
64static int scan_file (char *filename); 68static void scan_file (char *filename);
65static int scan_lisp_file (const char *filename, const char *mode); 69static void scan_lisp_file (const char *filename, const char *mode);
66static int scan_c_file (char *filename, const char *mode); 70static void scan_c_file (char *filename, const char *mode);
67static int scan_c_stream (FILE *infile); 71static void scan_c_stream (FILE *infile);
68static void start_globals (void); 72static void start_globals (void);
69static void write_globals (void); 73static void write_globals (void);
70 74
71#include <unistd.h> 75#include <unistd.h>
72 76
73/* Name this program was invoked with. */ 77/* Name this program was invoked with. */
74char *progname; 78static char *progname;
75 79
76/* Nonzero if this invocation is generating globals.h. */ 80/* True if this invocation is generating globals.h. */
77int generate_globals; 81static bool generate_globals;
78 82
79/* Print error message. `s1' is printf control string, `s2' is arg for it. */ 83/* Print error message. Args are like vprintf. */
80 84
81/* VARARGS1 */ 85static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
82static void 86verror (char const *m, va_list ap)
83error (const char *s1, const char *s2)
84{ 87{
85 fprintf (stderr, "%s: ", progname); 88 fprintf (stderr, "%s: ", progname);
86 fprintf (stderr, s1, s2); 89 vfprintf (stderr, m, ap);
87 fprintf (stderr, "\n"); 90 fprintf (stderr, "\n");
88} 91}
89 92
90/* Print error message and exit. */ 93/* Print error message. Args are like printf. */
91 94
92/* VARARGS1 */ 95static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
93static _Noreturn void 96error (char const *m, ...)
94fatal (const char *s1, const char *s2)
95{ 97{
96 error (s1, s2); 98 va_list ap;
97 exit (EXIT_FAILURE); 99 va_start (ap, m);
100 verror (m, ap);
101 va_end (ap);
98} 102}
99 103
100/* Like malloc but get fatal error if memory is exhausted. */ 104/* Print error message and exit. Args are like printf. */
101 105
102static void * 106static _Noreturn void ATTRIBUTE_FORMAT_PRINTF (1, 2)
103xmalloc (unsigned int size) 107fatal (char const *m, ...)
104{ 108{
105 void *result = (void *) malloc (size); 109 va_list ap;
106 if (result == NULL) 110 va_start (ap, m);
107 fatal ("virtual memory exhausted", 0); 111 verror (m, ap);
108 return result; 112 va_end (ap);
113 exit (EXIT_FAILURE);
114}
115
116static _Noreturn void
117memory_exhausted (void)
118{
119 fatal ("virtual memory exhausted");
109} 120}
110 121
111/* Like strdup, but get fatal error if memory is exhausted. */ 122/* Like malloc but get fatal error if memory is exhausted. */
112 123
113static char * 124static void *
114xstrdup (char *s) 125xmalloc (ptrdiff_t size)
115{ 126{
116 char *result = strdup (s); 127 void *result = malloc (size);
117 if (! result) 128 if (result == NULL)
118 fatal ("virtual memory exhausted", 0); 129 memory_exhausted ();
119 return result; 130 return result;
120} 131}
121 132
122/* Like realloc but get fatal error if memory is exhausted. */ 133/* Like realloc but get fatal error if memory is exhausted. */
123 134
124static void * 135static void *
125xrealloc (void *arg, unsigned int size) 136xrealloc (void *arg, ptrdiff_t size)
126{ 137{
127 void *result = (void *) realloc (arg, size); 138 void *result = realloc (arg, size);
128 if (result == NULL) 139 if (result == NULL)
129 fatal ("virtual memory exhausted", 0); 140 memory_exhausted ();
130 return result; 141 return result;
131} 142}
132 143
@@ -135,7 +146,6 @@ int
135main (int argc, char **argv) 146main (int argc, char **argv)
136{ 147{
137 int i; 148 int i;
138 int err_count = 0;
139 149
140 progname = argv[0]; 150 progname = argv[0];
141 151
@@ -170,7 +180,7 @@ main (int argc, char **argv)
170 } 180 }
171 if (argc > i && !strcmp (argv[i], "-g")) 181 if (argc > i && !strcmp (argv[i], "-g"))
172 { 182 {
173 generate_globals = 1; 183 generate_globals = true;
174 ++i; 184 ++i;
175 } 185 }
176 186
@@ -192,14 +202,17 @@ main (int argc, char **argv)
192 if (strcmp (argv[i], argv[j]) == 0) 202 if (strcmp (argv[i], argv[j]) == 0)
193 break; 203 break;
194 if (j == i) 204 if (j == i)
195 err_count += scan_file (argv[i]); 205 scan_file (argv[i]);
196 } 206 }
197 } 207 }
198 208
199 if (err_count == 0 && generate_globals) 209 if (generate_globals)
200 write_globals (); 210 write_globals ();
201 211
202 return (err_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS); 212 if (ferror (stdout) || fclose (stdout) != 0)
213 fatal ("write error");
214
215 return EXIT_SUCCESS;
203} 216}
204 217
205/* Add a source file name boundary marker in the output file. */ 218/* Add a source file name boundary marker in the output file. */
@@ -218,22 +231,21 @@ put_filename (char *filename)
218} 231}
219 232
220/* Read file FILENAME and output its doc strings to stdout. 233/* Read file FILENAME and output its doc strings to stdout.
221 Return 1 if file is not found, 0 if it is found. */ 234 Return true if file is found, false otherwise. */
222 235
223static int 236static void
224scan_file (char *filename) 237scan_file (char *filename)
225{ 238{
226 239 ptrdiff_t len = strlen (filename);
227 size_t len = strlen (filename);
228 240
229 if (!generate_globals) 241 if (!generate_globals)
230 put_filename (filename); 242 put_filename (filename);
231 if (len > 4 && !strcmp (filename + len - 4, ".elc")) 243 if (len > 4 && !strcmp (filename + len - 4, ".elc"))
232 return scan_lisp_file (filename, "rb"); 244 scan_lisp_file (filename, "rb");
233 else if (len > 3 && !strcmp (filename + len - 3, ".el")) 245 else if (len > 3 && !strcmp (filename + len - 3, ".el"))
234 return scan_lisp_file (filename, "r"); 246 scan_lisp_file (filename, "r");
235 else 247 else
236 return scan_c_file (filename, "r"); 248 scan_c_file (filename, "r");
237} 249}
238 250
239static void 251static void
@@ -250,7 +262,7 @@ static char input_buffer[128];
250struct rcsoc_state 262struct rcsoc_state
251{ 263{
252 /* A count of spaces and newlines that have been read, but not output. */ 264 /* A count of spaces and newlines that have been read, but not output. */
253 unsigned pending_spaces, pending_newlines; 265 intmax_t pending_spaces, pending_newlines;
254 266
255 /* Where we're reading from. */ 267 /* Where we're reading from. */
256 FILE *in_file; 268 FILE *in_file;
@@ -267,16 +279,16 @@ struct rcsoc_state
267 the input stream. */ 279 the input stream. */
268 const char *cur_keyword_ptr; 280 const char *cur_keyword_ptr;
269 /* Set to true if we saw an occurrence of KEYWORD. */ 281 /* Set to true if we saw an occurrence of KEYWORD. */
270 int saw_keyword; 282 bool saw_keyword;
271}; 283};
272 284
273/* Output CH to the file or buffer in STATE. Any pending newlines or 285/* Output CH to the file or buffer in STATE. Any pending newlines or
274 spaces are output first. */ 286 spaces are output first. */
275 287
276static void 288static void
277put_char (int ch, struct rcsoc_state *state) 289put_char (char ch, struct rcsoc_state *state)
278{ 290{
279 int out_ch; 291 char out_ch;
280 do 292 do
281 { 293 {
282 if (state->pending_newlines > 0) 294 if (state->pending_newlines > 0)
@@ -307,7 +319,7 @@ put_char (int ch, struct rcsoc_state *state)
307 keyword, but were in fact not. */ 319 keyword, but were in fact not. */
308 320
309static void 321static void
310scan_keyword_or_put_char (int ch, struct rcsoc_state *state) 322scan_keyword_or_put_char (char ch, struct rcsoc_state *state)
311{ 323{
312 if (state->keyword 324 if (state->keyword
313 && *state->cur_keyword_ptr == ch 325 && *state->cur_keyword_ptr == ch
@@ -319,7 +331,7 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
319 if (*++state->cur_keyword_ptr == '\0') 331 if (*++state->cur_keyword_ptr == '\0')
320 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */ 332 /* Saw the whole keyword. Set SAW_KEYWORD flag to true. */
321 { 333 {
322 state->saw_keyword = 1; 334 state->saw_keyword = true;
323 335
324 /* Reset the scanning pointer. */ 336 /* Reset the scanning pointer. */
325 state->cur_keyword_ptr = state->keyword; 337 state->cur_keyword_ptr = state->keyword;
@@ -330,22 +342,29 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
330 342
331 /* Skip any whitespace between the keyword and the 343 /* Skip any whitespace between the keyword and the
332 usage string. */ 344 usage string. */
345 int c;
333 do 346 do
334 ch = getc (state->in_file); 347 c = getc (state->in_file);
335 while (ch == ' ' || ch == '\n'); 348 while (c == ' ' || c == '\n');
336 349
337 /* Output the open-paren we just read. */ 350 /* Output the open-paren we just read. */
338 put_char (ch, state); 351 if (c != '(')
352 fatal ("Missing '(' after keyword");
353 put_char (c, state);
339 354
340 /* Skip the function name and replace it with `fn'. */ 355 /* Skip the function name and replace it with `fn'. */
341 do 356 do
342 ch = getc (state->in_file); 357 {
343 while (ch != ' ' && ch != ')'); 358 c = getc (state->in_file);
359 if (c == EOF)
360 fatal ("Unexpected EOF after keyword");
361 }
362 while (c != ' ' && c != ')');
344 put_char ('f', state); 363 put_char ('f', state);
345 put_char ('n', state); 364 put_char ('n', state);
346 365
347 /* Put back the last character. */ 366 /* Put back the last character. */
348 ungetc (ch, state->in_file); 367 ungetc (c, state->in_file);
349 } 368 }
350 } 369 }
351 else 370 else
@@ -369,18 +388,19 @@ scan_keyword_or_put_char (int ch, struct rcsoc_state *state)
369 388
370 389
371/* Skip a C string or C-style comment from INFILE, and return the 390/* Skip a C string or C-style comment from INFILE, and return the
372 character that follows. COMMENT non-zero means skip a comment. If 391 byte that follows, or EOF. COMMENT means skip a comment. If
373 PRINTFLAG is positive, output string contents to stdout. If it is 392 PRINTFLAG is positive, output string contents to stdout. If it is
374 negative, store contents in buf. Convert escape sequences \n and 393 negative, store contents in buf. Convert escape sequences \n and
375 \t to newline and tab; discard \ followed by newline. 394 \t to newline and tab; discard \ followed by newline.
376 If SAW_USAGE is non-zero, then any occurrences of the string `usage:' 395 If SAW_USAGE is non-null, then any occurrences of the string "usage:"
377 at the beginning of a line will be removed, and *SAW_USAGE set to 396 at the beginning of a line will be removed, and *SAW_USAGE set to
378 true if any were encountered. */ 397 true if any were encountered. */
379 398
380static int 399static int
381read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usage) 400read_c_string_or_comment (FILE *infile, int printflag, bool comment,
401 bool *saw_usage)
382{ 402{
383 register int c; 403 int c;
384 struct rcsoc_state state; 404 struct rcsoc_state state;
385 405
386 state.in_file = infile; 406 state.in_file = infile;
@@ -390,7 +410,7 @@ read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usa
390 state.pending_newlines = 0; 410 state.pending_newlines = 0;
391 state.keyword = (saw_usage ? "usage:" : 0); 411 state.keyword = (saw_usage ? "usage:" : 0);
392 state.cur_keyword_ptr = state.keyword; 412 state.cur_keyword_ptr = state.keyword;
393 state.saw_keyword = 0; 413 state.saw_keyword = false;
394 414
395 c = getc (infile); 415 c = getc (infile);
396 if (comment) 416 if (comment)
@@ -468,10 +488,10 @@ read_c_string_or_comment (FILE *infile, int printflag, int comment, int *saw_usa
468static void 488static void
469write_c_args (char *func, char *buf, int minargs, int maxargs) 489write_c_args (char *func, char *buf, int minargs, int maxargs)
470{ 490{
471 register char *p; 491 char *p;
472 int in_ident = 0; 492 bool in_ident = false;
473 char *ident_start IF_LINT (= NULL); 493 char *ident_start IF_LINT (= NULL);
474 size_t ident_length = 0; 494 ptrdiff_t ident_length = 0;
475 495
476 fputs ("(fn", stdout); 496 fputs ("(fn", stdout);
477 497
@@ -491,12 +511,12 @@ write_c_args (char *func, char *buf, int minargs, int maxargs)
491 { 511 {
492 if (!in_ident) 512 if (!in_ident)
493 { 513 {
494 in_ident = 1; 514 in_ident = true;
495 ident_start = p; 515 ident_start = p;
496 } 516 }
497 else 517 else
498 { 518 {
499 in_ident = 0; 519 in_ident = false;
500 ident_length = p - ident_start; 520 ident_length = p - ident_start;
501 } 521 }
502 } 522 }
@@ -575,34 +595,38 @@ enum { DEFUN_noreturn = 1, DEFUN_const = 2 };
575 595
576/* All the variable names we saw while scanning C sources in `-g' 596/* All the variable names we saw while scanning C sources in `-g'
577 mode. */ 597 mode. */
578int num_globals; 598static ptrdiff_t num_globals;
579int num_globals_allocated; 599static ptrdiff_t num_globals_allocated;
580struct global *globals; 600static struct global *globals;
581 601
582static struct global * 602static struct global *
583add_global (enum global_type type, char *name, int value, char const *svalue) 603add_global (enum global_type type, char const *name, int value,
604 char const *svalue)
584{ 605{
585 /* Ignore the one non-symbol that can occur. */ 606 /* Ignore the one non-symbol that can occur. */
586 if (strcmp (name, "...")) 607 if (strcmp (name, "..."))
587 { 608 {
588 ++num_globals; 609 if (num_globals == num_globals_allocated)
589
590 if (num_globals_allocated == 0)
591 { 610 {
592 num_globals_allocated = 100; 611 ptrdiff_t num_globals_max = (min (PTRDIFF_MAX, SIZE_MAX)
593 globals = xmalloc (num_globals_allocated * sizeof (struct global)); 612 / sizeof *globals);
594 } 613 if (num_globals_allocated == num_globals_max)
595 else if (num_globals == num_globals_allocated) 614 memory_exhausted ();
596 { 615 if (num_globals_allocated < num_globals_max / 2)
597 num_globals_allocated *= 2; 616 num_globals_allocated = 2 * num_globals_allocated + 1;
598 globals = xrealloc (globals, 617 else
599 num_globals_allocated * sizeof (struct global)); 618 num_globals_allocated = num_globals_max;
619 globals = xrealloc (globals, num_globals_allocated * sizeof *globals);
600 } 620 }
601 621
622 ++num_globals;
623
624 ptrdiff_t namesize = strlen (name) + 1;
625 char *buf = xmalloc (namesize + (svalue ? strlen (svalue) + 1 : 0));
602 globals[num_globals - 1].type = type; 626 globals[num_globals - 1].type = type;
603 globals[num_globals - 1].name = name; 627 globals[num_globals - 1].name = strcpy (buf, name);
604 if (svalue) 628 if (svalue)
605 globals[num_globals - 1].v.svalue = svalue; 629 globals[num_globals - 1].v.svalue = strcpy (buf + namesize, svalue);
606 else 630 else
607 globals[num_globals - 1].v.value = value; 631 globals[num_globals - 1].v.value = value;
608 globals[num_globals - 1].flags = 0; 632 globals[num_globals - 1].flags = 0;
@@ -634,7 +658,7 @@ compare_globals (const void *a, const void *b)
634} 658}
635 659
636static void 660static void
637close_emacs_globals (int num_symbols) 661close_emacs_globals (ptrdiff_t num_symbols)
638{ 662{
639 printf (("};\n" 663 printf (("};\n"
640 "extern struct emacs_globals globals;\n" 664 "extern struct emacs_globals globals;\n"
@@ -642,17 +666,17 @@ close_emacs_globals (int num_symbols)
642 "#ifndef DEFINE_SYMBOLS\n" 666 "#ifndef DEFINE_SYMBOLS\n"
643 "extern\n" 667 "extern\n"
644 "#endif\n" 668 "#endif\n"
645 "struct Lisp_Symbol alignas (GCALIGNMENT) lispsym[%d];\n"), 669 "struct Lisp_Symbol alignas (GCALIGNMENT) lispsym[%td];\n"),
646 num_symbols); 670 num_symbols);
647} 671}
648 672
649static void 673static void
650write_globals (void) 674write_globals (void)
651{ 675{
652 int i, j; 676 ptrdiff_t i, j;
653 bool seen_defun = false; 677 bool seen_defun = false;
654 int symnum = 0; 678 ptrdiff_t symnum = 0;
655 int num_symbols = 0; 679 ptrdiff_t num_symbols = 0;
656 qsort (globals, num_globals, sizeof (struct global), compare_globals); 680 qsort (globals, num_globals, sizeof (struct global), compare_globals);
657 681
658 j = 0; 682 j = 0;
@@ -665,6 +689,7 @@ write_globals (void)
665 && globals[i].v.value != globals[i + 1].v.value) 689 && globals[i].v.value != globals[i + 1].v.value)
666 error ("function '%s' defined twice with differing signatures", 690 error ("function '%s' defined twice with differing signatures",
667 globals[i].name); 691 globals[i].name);
692 free (globals[i].name);
668 i++; 693 i++;
669 } 694 }
670 num_symbols += globals[i].type == SYMBOL; 695 num_symbols += globals[i].type == SYMBOL;
@@ -697,7 +722,7 @@ write_globals (void)
697 } 722 }
698 break; 723 break;
699 default: 724 default:
700 fatal ("not a recognized DEFVAR_", 0); 725 fatal ("not a recognized DEFVAR_");
701 } 726 }
702 727
703 if (type) 728 if (type)
@@ -707,7 +732,7 @@ write_globals (void)
707 globals[i].name, globals[i].name); 732 globals[i].name, globals[i].name);
708 } 733 }
709 else if (globals[i].type == SYMBOL) 734 else if (globals[i].type == SYMBOL)
710 printf (("#define i%s %d\n" 735 printf (("#define i%s %td\n"
711 "DEFINE_LISP_SYMBOL (%s)\n"), 736 "DEFINE_LISP_SYMBOL (%s)\n"),
712 globals[i].name, symnum++, globals[i].name); 737 globals[i].name, symnum++, globals[i].name);
713 else 738 else
@@ -736,7 +761,7 @@ write_globals (void)
736 761
737 puts ("#ifdef DEFINE_SYMBOLS"); 762 puts ("#ifdef DEFINE_SYMBOLS");
738 puts ("static char const *const defsym_name[] = {"); 763 puts ("static char const *const defsym_name[] = {");
739 for (int i = 0; i < num_globals; i++) 764 for (ptrdiff_t i = 0; i < num_globals; i++)
740 if (globals[i].type == SYMBOL) 765 if (globals[i].type == SYMBOL)
741 printf ("\t\"%s\",\n", globals[i].v.svalue); 766 printf ("\t\"%s\",\n", globals[i].v.svalue);
742 puts ("};"); 767 puts ("};");
@@ -745,9 +770,9 @@ write_globals (void)
745 puts ("#define Qnil builtin_lisp_symbol (0)"); 770 puts ("#define Qnil builtin_lisp_symbol (0)");
746 puts ("#if DEFINE_NON_NIL_Q_SYMBOL_MACROS"); 771 puts ("#if DEFINE_NON_NIL_Q_SYMBOL_MACROS");
747 num_symbols = 0; 772 num_symbols = 0;
748 for (int i = 0; i < num_globals; i++) 773 for (ptrdiff_t i = 0; i < num_globals; i++)
749 if (globals[i].type == SYMBOL && num_symbols++ != 0) 774 if (globals[i].type == SYMBOL && num_symbols++ != 0)
750 printf ("# define %s builtin_lisp_symbol (%d)\n", 775 printf ("# define %s builtin_lisp_symbol (%td)\n",
751 globals[i].name, num_symbols - 1); 776 globals[i].name, num_symbols - 1);
752 puts ("#endif"); 777 puts ("#endif");
753} 778}
@@ -758,11 +783,11 @@ write_globals (void)
758 Looks for DEFUN constructs such as are defined in ../src/lisp.h. 783 Looks for DEFUN constructs such as are defined in ../src/lisp.h.
759 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */ 784 Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */
760 785
761static int 786static void
762scan_c_file (char *filename, const char *mode) 787scan_c_file (char *filename, const char *mode)
763{ 788{
764 FILE *infile; 789 FILE *infile;
765 int extension = filename[strlen (filename) - 1]; 790 char extension = filename[strlen (filename) - 1];
766 791
767 if (extension == 'o') 792 if (extension == 'o')
768 filename[strlen (filename) - 1] = 'c'; 793 filename[strlen (filename) - 1] = 'c';
@@ -778,16 +803,15 @@ scan_c_file (char *filename, const char *mode)
778 filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */ 803 filename[strlen (filename) - 1] = 'c'; /* Don't confuse people. */
779 } 804 }
780 805
781 /* No error if non-ex input file. */
782 if (infile == NULL) 806 if (infile == NULL)
783 { 807 {
784 perror (filename); 808 perror (filename);
785 return 0; 809 exit (EXIT_FAILURE);
786 } 810 }
787 811
788 /* Reset extension to be able to detect duplicate files. */ 812 /* Reset extension to be able to detect duplicate files. */
789 filename[strlen (filename) - 1] = extension; 813 filename[strlen (filename) - 1] = extension;
790 return scan_c_stream (infile); 814 scan_c_stream (infile);
791} 815}
792 816
793/* Return 1 if next input from INFILE is equal to P, -1 if EOF, 817/* Return 1 if next input from INFILE is equal to P, -1 if EOF,
@@ -807,7 +831,7 @@ stream_match (FILE *infile, const char *p)
807 return 1; 831 return 1;
808} 832}
809 833
810static int 834static void
811scan_c_stream (FILE *infile) 835scan_c_stream (FILE *infile)
812{ 836{
813 int commas, minargs, maxargs; 837 int commas, minargs, maxargs;
@@ -815,12 +839,13 @@ scan_c_stream (FILE *infile)
815 839
816 while (!feof (infile)) 840 while (!feof (infile))
817 { 841 {
818 int doc_keyword = 0; 842 bool doc_keyword = false;
819 int defunflag = 0; 843 bool defunflag = false;
820 int defvarperbufferflag = 0; 844 bool defvarperbufferflag = false;
821 int defvarflag = 0; 845 bool defvarflag = false;
822 enum global_type type = INVALID; 846 enum global_type type = INVALID;
823 char *name IF_LINT (= 0); 847 static char *name;
848 static ptrdiff_t name_size;
824 849
825 if (c != '\n' && c != '\r') 850 if (c != '\n' && c != '\r')
826 { 851 {
@@ -866,7 +891,7 @@ scan_c_stream (FILE *infile)
866 if (c != '_') 891 if (c != '_')
867 continue; 892 continue;
868 893
869 defvarflag = 1; 894 defvarflag = true;
870 895
871 c = getc (infile); 896 c = getc (infile);
872 defvarperbufferflag = (c == 'P'); 897 defvarperbufferflag = (c == 'P');
@@ -920,12 +945,12 @@ scan_c_stream (FILE *infile)
920 c = getc (infile); 945 c = getc (infile);
921 if (c != '"') 946 if (c != '"')
922 continue; 947 continue;
923 c = read_c_string_or_comment (infile, -1, 0, 0); 948 c = read_c_string_or_comment (infile, -1, false, 0);
924 } 949 }
925 950
926 if (generate_globals) 951 if (generate_globals)
927 { 952 {
928 int i = 0; 953 ptrdiff_t i = 0;
929 char const *svalue = 0; 954 char const *svalue = 0;
930 955
931 /* Skip "," and whitespace. */ 956 /* Skip "," and whitespace. */
@@ -947,7 +972,16 @@ scan_c_stream (FILE *infile)
947 || c == '\n' || c == '\r')); 972 || c == '\n' || c == '\r'));
948 input_buffer[i] = '\0'; 973 input_buffer[i] = '\0';
949 974
950 name = xmalloc (i + 1); 975 if (name_size <= i)
976 {
977 free (name);
978 name_size = i + 1;
979 ptrdiff_t doubled;
980 if (! INT_MULTIPLY_WRAPV (name_size, 2, &doubled)
981 && doubled <= SIZE_MAX)
982 name_size = doubled;
983 name = xmalloc (name_size);
984 }
951 memcpy (name, input_buffer, i + 1); 985 memcpy (name, input_buffer, i + 1);
952 986
953 if (type == SYMBOL) 987 if (type == SYMBOL)
@@ -957,8 +991,8 @@ scan_c_stream (FILE *infile)
957 while (c == ' ' || c == '\t' || c == '\n' || c == '\r'); 991 while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
958 if (c != '"') 992 if (c != '"')
959 continue; 993 continue;
960 c = read_c_string_or_comment (infile, -1, 0, 0); 994 c = read_c_string_or_comment (infile, -1, false, 0);
961 svalue = xstrdup (input_buffer); 995 svalue = input_buffer;
962 } 996 }
963 997
964 if (!defunflag) 998 if (!defunflag)
@@ -1024,6 +1058,8 @@ scan_c_stream (FILE *infile)
1024 if (generate_globals) 1058 if (generate_globals)
1025 { 1059 {
1026 struct global *g = add_global (FUNCTION, name, maxargs, 0); 1060 struct global *g = add_global (FUNCTION, name, maxargs, 0);
1061 if (!g)
1062 continue;
1027 1063
1028 /* The following code tries to recognize function attributes 1064 /* The following code tries to recognize function attributes
1029 specified after the docstring, e.g.: 1065 specified after the docstring, e.g.:
@@ -1087,7 +1123,7 @@ scan_c_stream (FILE *infile)
1087 c = getc (infile); 1123 c = getc (infile);
1088 1124
1089 if (c == '"') 1125 if (c == '"')
1090 c = read_c_string_or_comment (infile, 0, 0, 0); 1126 c = read_c_string_or_comment (infile, 0, false, 0);
1091 1127
1092 while (c != EOF && c != ',' && c != '/') 1128 while (c != EOF && c != ',' && c != '/')
1093 c = getc (infile); 1129 c = getc (infile);
@@ -1100,7 +1136,7 @@ scan_c_stream (FILE *infile)
1100 c = getc (infile); 1136 c = getc (infile);
1101 if (c == ':') 1137 if (c == ':')
1102 { 1138 {
1103 doc_keyword = 1; 1139 doc_keyword = true;
1104 c = getc (infile); 1140 c = getc (infile);
1105 while (c == ' ' || c == '\n' || c == '\r' || c == '\t') 1141 while (c == ' ' || c == '\n' || c == '\r' || c == '\t')
1106 c = getc (infile); 1142 c = getc (infile);
@@ -1113,8 +1149,8 @@ scan_c_stream (FILE *infile)
1113 ungetc (c, infile), 1149 ungetc (c, infile),
1114 c == '*'))) 1150 c == '*')))
1115 { 1151 {
1116 int comment = c != '"'; 1152 bool comment = c != '"';
1117 int saw_usage; 1153 bool saw_usage;
1118 1154
1119 printf ("\037%c%s\n", defvarflag ? 'V' : 'F', input_buffer); 1155 printf ("\037%c%s\n", defvarflag ? 'V' : 'F', input_buffer);
1120 1156
@@ -1168,8 +1204,8 @@ scan_c_stream (FILE *infile)
1168 } 1204 }
1169 } 1205 }
1170 eof: 1206 eof:
1171 fclose (infile); 1207 if (ferror (infile) || fclose (infile) != 0)
1172 return 0; 1208 fatal ("read error");
1173} 1209}
1174 1210
1175/* Read a file of Lisp code, compiled or interpreted. 1211/* Read a file of Lisp code, compiled or interpreted.
@@ -1245,7 +1281,7 @@ read_lisp_symbol (FILE *infile, char *buffer)
1245 skip_white (infile); 1281 skip_white (infile);
1246} 1282}
1247 1283
1248static int 1284static bool
1249search_lisp_doc_at_eol (FILE *infile) 1285search_lisp_doc_at_eol (FILE *infile)
1250{ 1286{
1251 int c = 0, c1 = 0, c2 = 0; 1287 int c = 0, c1 = 0, c2 = 0;
@@ -1265,20 +1301,19 @@ search_lisp_doc_at_eol (FILE *infile)
1265#ifdef DEBUG 1301#ifdef DEBUG
1266 fprintf (stderr, "## non-docstring found\n"); 1302 fprintf (stderr, "## non-docstring found\n");
1267#endif 1303#endif
1268 if (c != EOF) 1304 ungetc (c, infile);
1269 ungetc (c, infile); 1305 return false;
1270 return 0;
1271 } 1306 }
1272 return 1; 1307 return true;
1273} 1308}
1274 1309
1275#define DEF_ELISP_FILE(fn) { #fn, sizeof(#fn) - 1 } 1310#define DEF_ELISP_FILE(fn) { #fn, sizeof(#fn) - 1 }
1276 1311
1277static int 1312static void
1278scan_lisp_file (const char *filename, const char *mode) 1313scan_lisp_file (const char *filename, const char *mode)
1279{ 1314{
1280 FILE *infile; 1315 FILE *infile;
1281 register int c; 1316 int c;
1282 char *saved_string = 0; 1317 char *saved_string = 0;
1283 /* These are the only files that are loaded uncompiled, and must 1318 /* These are the only files that are loaded uncompiled, and must
1284 follow the conventions of the doc strings expected by this 1319 follow the conventions of the doc strings expected by this
@@ -1286,7 +1321,7 @@ scan_lisp_file (const char *filename, const char *mode)
1286 byte compiler when it produces the .elc files. */ 1321 byte compiler when it produces the .elc files. */
1287 static struct { 1322 static struct {
1288 const char *fn; 1323 const char *fn;
1289 size_t fl; 1324 int fl;
1290 } const uncompiled[] = { 1325 } const uncompiled[] = {
1291 DEF_ELISP_FILE (loaddefs.el), 1326 DEF_ELISP_FILE (loaddefs.el),
1292 DEF_ELISP_FILE (loadup.el), 1327 DEF_ELISP_FILE (loadup.el),
@@ -1294,22 +1329,22 @@ scan_lisp_file (const char *filename, const char *mode)
1294 DEF_ELISP_FILE (cp51932.el), 1329 DEF_ELISP_FILE (cp51932.el),
1295 DEF_ELISP_FILE (eucjp-ms.el) 1330 DEF_ELISP_FILE (eucjp-ms.el)
1296 }; 1331 };
1297 int i, match; 1332 int i;
1298 size_t flen = strlen (filename); 1333 int flen = strlen (filename);
1299 1334
1300 if (generate_globals) 1335 if (generate_globals)
1301 fatal ("scanning lisp file when -g specified", 0); 1336 fatal ("scanning lisp file when -g specified");
1302 if (flen > 3 && !strcmp (filename + flen - 3, ".el")) 1337 if (flen > 3 && !strcmp (filename + flen - 3, ".el"))
1303 { 1338 {
1304 for (i = 0, match = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]); 1339 bool match = false;
1305 i++) 1340 for (i = 0; i < sizeof (uncompiled) / sizeof (uncompiled[0]); i++)
1306 { 1341 {
1307 if (uncompiled[i].fl <= flen 1342 if (uncompiled[i].fl <= flen
1308 && !strcmp (filename + flen - uncompiled[i].fl, uncompiled[i].fn) 1343 && !strcmp (filename + flen - uncompiled[i].fl, uncompiled[i].fn)
1309 && (flen == uncompiled[i].fl 1344 && (flen == uncompiled[i].fl
1310 || IS_SLASH (filename[flen - uncompiled[i].fl - 1]))) 1345 || IS_SLASH (filename[flen - uncompiled[i].fl - 1])))
1311 { 1346 {
1312 match = 1; 1347 match = true;
1313 break; 1348 break;
1314 } 1349 }
1315 } 1350 }
@@ -1321,7 +1356,7 @@ scan_lisp_file (const char *filename, const char *mode)
1321 if (infile == NULL) 1356 if (infile == NULL)
1322 { 1357 {
1323 perror (filename); 1358 perror (filename);
1324 return 0; /* No error. */ 1359 exit (EXIT_FAILURE);
1325 } 1360 }
1326 1361
1327 c = '\n'; 1362 c = '\n';
@@ -1345,22 +1380,24 @@ scan_lisp_file (const char *filename, const char *mode)
1345 c = getc (infile); 1380 c = getc (infile);
1346 if (c == '@') 1381 if (c == '@')
1347 { 1382 {
1348 size_t length = 0; 1383 ptrdiff_t length = 0;
1349 size_t i; 1384 ptrdiff_t i;
1350 1385
1351 /* Read the length. */ 1386 /* Read the length. */
1352 while ((c = getc (infile), 1387 while ((c = getc (infile),
1353 c >= '0' && c <= '9')) 1388 c >= '0' && c <= '9'))
1354 { 1389 {
1355 length *= 10; 1390 if (INT_MULTIPLY_WRAPV (length, 10, &length)
1356 length += c - '0'; 1391 || INT_ADD_WRAPV (length, c - '0', &length)
1392 || SIZE_MAX < length)
1393 memory_exhausted ();
1357 } 1394 }
1358 1395
1359 if (length <= 1) 1396 if (length <= 1)
1360 fatal ("invalid dynamic doc string length", ""); 1397 fatal ("invalid dynamic doc string length");
1361 1398
1362 if (c != ' ') 1399 if (c != ' ')
1363 fatal ("space not found after dynamic doc string length", ""); 1400 fatal ("space not found after dynamic doc string length");
1364 1401
1365 /* The next character is a space that is counted in the length 1402 /* The next character is a space that is counted in the length
1366 but not part of the doc string. 1403 but not part of the doc string.
@@ -1369,7 +1406,7 @@ scan_lisp_file (const char *filename, const char *mode)
1369 1406
1370 /* Read in the contents. */ 1407 /* Read in the contents. */
1371 free (saved_string); 1408 free (saved_string);
1372 saved_string = (char *) xmalloc (length); 1409 saved_string = xmalloc (length);
1373 for (i = 0; i < length; i++) 1410 for (i = 0; i < length; i++)
1374 saved_string[i] = getc (infile); 1411 saved_string[i] = getc (infile);
1375 /* The last character is a ^_. 1412 /* The last character is a ^_.
@@ -1568,7 +1605,7 @@ scan_lisp_file (const char *filename, const char *mode)
1568 buffer, filename); 1605 buffer, filename);
1569 continue; 1606 continue;
1570 } 1607 }
1571 read_c_string_or_comment (infile, 0, 0, 0); 1608 read_c_string_or_comment (infile, 0, false, 0);
1572 1609
1573 if (saved_string == 0) 1610 if (saved_string == 0)
1574 if (!search_lisp_doc_at_eol (infile)) 1611 if (!search_lisp_doc_at_eol (infile))
@@ -1604,10 +1641,11 @@ scan_lisp_file (const char *filename, const char *mode)
1604 saved_string = 0; 1641 saved_string = 0;
1605 } 1642 }
1606 else 1643 else
1607 read_c_string_or_comment (infile, 1, 0, 0); 1644 read_c_string_or_comment (infile, 1, false, 0);
1608 } 1645 }
1609 fclose (infile); 1646 free (saved_string);
1610 return 0; 1647 if (ferror (infile) || fclose (infile) != 0)
1648 fatal ("%s: read error", filename);
1611} 1649}
1612 1650
1613 1651