aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorPaul Eggert2019-11-26 13:53:41 -0800
committerPaul Eggert2019-11-26 13:57:00 -0800
commitcffa5703b95fba3624dc54db5e693bae559eac5f (patch)
tree7ac0719a3db6a29399ed4389ff27f1d0aeb211e5 /lib-src
parent75b41a38dd0735fe63457e12741656c63972d3ce (diff)
downloademacs-cffa5703b95fba3624dc54db5e693bae559eac5f.tar.gz
emacs-cffa5703b95fba3624dc54db5e693bae559eac5f.zip
etags: remove some arbitrary limits
etags had undefined behavior if input files, lines, tags, etc., had more than INT_MAX bytes. Clean up the usage of integer types to fix the overflow errors I found. * admin/merge-gnulib (GNULIB_MODULES): Add mempcpy. * lib-src/etags.c: Include inttypes.h, intprops.h. (memcpyz): New function. Use it to simplify several occurrences of memcpy followed by storing a trailing '\0'. (xnew): Use xnmalloc, to catch overflow on integer multiplication. (xrnew): Change last arg to multiplier. The type is not needed. All callers changed. (node, lineno, charno, linecharno, invalidcharno, make_tag): (pfnote, add_node, number_len, C_symtype, lbz, Makefile_targets) (readline): Use intmax_t for line numbers and character positions, instead of int or long. (linebuffer, make_tag, pfnote, total_size_of_entries, put_entry) (in_word_set, C_symtype, token, cstack, pushclass_above): (popclass_above, write_classname, consider_token, C_entries) (Ruby_functions, Makefile_targets, Lua_functions, TeX_commands) (TeX_decode_env, erlang_func, erlang_attribute, erlang_atom) (substitute, regex_tag_multiline, nocase_tail, readline_interval) (readline, savenstr, concat, etags_getcwd, relative_filename) (linebuffer_setlen): Use ptrdiff_t for object sizes, instead of int or long or unsigned or size_t. (write_classname, C_entries): Avoid sprintf, as the result could exceed INT_MAX bytes and then behavior goes haywire. (main): Use int, instead of unsigned, for argv counts. (get_language_from_filename): Use bool for boolean. (Ruby_functions): Prefer strcpy to memcpy when copying "=". (linebuffer_setlen): Use ‘if’ instead of ‘while’. (memory_full, xnmalloc, xnrealloc): New functions. (xmalloc): Use memory_full, and take a ptrdiff_t instead of a size_t. (xrealloc): Remove; no longer needed. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/mempcpy.c, m4/mempcpy.m4: New files, copied from Gnulib.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/etags.c404
1 files changed, 211 insertions, 193 deletions
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 6409407e466..0665cb00b9b 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -114,6 +114,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
114# define O_CLOEXEC O_NOINHERIT 114# define O_CLOEXEC O_NOINHERIT
115#endif /* WINDOWSNT */ 115#endif /* WINDOWSNT */
116 116
117#include <inttypes.h>
117#include <limits.h> 118#include <limits.h>
118#include <unistd.h> 119#include <unistd.h>
119#include <stdarg.h> 120#include <stdarg.h>
@@ -123,6 +124,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
123#include <errno.h> 124#include <errno.h>
124#include <fcntl.h> 125#include <fcntl.h>
125#include <binary-io.h> 126#include <binary-io.h>
127#include <intprops.h>
126#include <unlocked-io.h> 128#include <unlocked-io.h>
127#include <c-ctype.h> 129#include <c-ctype.h>
128#include <c-strcase.h> 130#include <c-strcase.h>
@@ -141,6 +143,14 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4";
141# define CTAGS false 143# define CTAGS false
142#endif 144#endif
143 145
146/* Copy to DEST from SRC (containing LEN bytes), and append a NUL byte. */
147static void
148memcpyz (void *dest, void const *src, ptrdiff_t len)
149{
150 char *e = mempcpy (dest, src, len);
151 *e = '\0';
152}
153
144static bool 154static bool
145streq (char const *s, char const *t) 155streq (char const *s, char const *t)
146{ 156{
@@ -235,11 +245,11 @@ endtoken (unsigned char c)
235/* 245/*
236 * xnew, xrnew -- allocate, reallocate storage 246 * xnew, xrnew -- allocate, reallocate storage
237 * 247 *
238 * SYNOPSIS: Type *xnew (int n, Type); 248 * SYNOPSIS: Type *xnew (ptrdiff_t n, Type);
239 * void xrnew (OldPointer, int n, Type); 249 * void xrnew (OldPointer, ptrdiff_t n, int multiplier);
240 */ 250 */
241#define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type))) 251#define xnew(n, Type) ((Type *) xnmalloc (n, sizeof (Type)))
242#define xrnew(op, n, Type) ((op) = (Type *) xrealloc (op, (n) * sizeof (Type))) 252#define xrnew(op, n, m) ((op) = xnrealloc (op, n, (m) * sizeof *(op)))
243 253
244typedef void Lang_function (FILE *); 254typedef void Lang_function (FILE *);
245 255
@@ -282,8 +292,8 @@ typedef struct node_st
282 bool valid; /* write this tag on the tag file */ 292 bool valid; /* write this tag on the tag file */
283 bool is_func; /* function tag: use regexp in CTAGS mode */ 293 bool is_func; /* function tag: use regexp in CTAGS mode */
284 bool been_warned; /* warning already given for duplicated tag */ 294 bool been_warned; /* warning already given for duplicated tag */
285 int lno; /* line number tag is on */ 295 intmax_t lno; /* line number tag is on */
286 long cno; /* character number line starts on */ 296 intmax_t cno; /* character number line starts on */
287} node; 297} node;
288 298
289/* 299/*
@@ -295,8 +305,8 @@ typedef struct node_st
295 */ 305 */
296typedef struct 306typedef struct
297{ 307{
298 long size; 308 ptrdiff_t size;
299 int len; 309 ptrdiff_t len;
300 char *buffer; 310 char *buffer;
301} linebuffer; 311} linebuffer;
302 312
@@ -365,7 +375,7 @@ static void just_read_file (FILE *);
365 375
366static language *get_language_from_langname (const char *); 376static language *get_language_from_langname (const char *);
367static void readline (linebuffer *, FILE *); 377static void readline (linebuffer *, FILE *);
368static long readline_internal (linebuffer *, FILE *, char const *); 378static ptrdiff_t readline_internal (linebuffer *, FILE *, char const *);
369static bool nocase_tail (const char *); 379static bool nocase_tail (const char *);
370static void get_tag (char *, char **); 380static void get_tag (char *, char **);
371static void get_lispy_tag (char *); 381static void get_lispy_tag (char *);
@@ -385,7 +395,7 @@ static void process_file (FILE *, char *, language *);
385static void find_entries (FILE *); 395static void find_entries (FILE *);
386static void free_tree (node *); 396static void free_tree (node *);
387static void free_fdesc (fdesc *); 397static void free_fdesc (fdesc *);
388static void pfnote (char *, bool, char *, int, int, long); 398static void pfnote (char *, bool, char *, ptrdiff_t, intmax_t, intmax_t);
389static void invalidate_nodes (fdesc *, node **); 399static void invalidate_nodes (fdesc *, node **);
390static void put_entries (node *); 400static void put_entries (node *);
391 401
@@ -393,7 +403,7 @@ static char *concat (const char *, const char *, const char *);
393static char *skip_spaces (char *); 403static char *skip_spaces (char *);
394static char *skip_non_spaces (char *); 404static char *skip_non_spaces (char *);
395static char *skip_name (char *); 405static char *skip_name (char *);
396static char *savenstr (const char *, int); 406static char *savenstr (const char *, ptrdiff_t);
397static char *savestr (const char *); 407static char *savestr (const char *);
398static char *etags_getcwd (void); 408static char *etags_getcwd (void);
399static char *relative_filename (char *, char *); 409static char *relative_filename (char *, char *);
@@ -403,9 +413,11 @@ static bool filename_is_absolute (char *f);
403static void canonicalize_filename (char *); 413static void canonicalize_filename (char *);
404static char *etags_mktmp (void); 414static char *etags_mktmp (void);
405static void linebuffer_init (linebuffer *); 415static void linebuffer_init (linebuffer *);
406static void linebuffer_setlen (linebuffer *, int); 416static void linebuffer_setlen (linebuffer *, ptrdiff_t);
407static void *xmalloc (size_t); 417static void *xmalloc (ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1));
408static void *xrealloc (void *, size_t); 418static void *xnmalloc (ptrdiff_t, ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1,2));
419static void *xnrealloc (void *, ptrdiff_t, ptrdiff_t)
420 ATTRIBUTE_ALLOC_SIZE ((2,3));
409 421
410 422
411static char searchar = '/'; /* use /.../ searches */ 423static char searchar = '/'; /* use /.../ searches */
@@ -420,12 +432,12 @@ static ptrdiff_t whatlen_max; /* maximum length of any 'what' member */
420static fdesc *fdhead; /* head of file description list */ 432static fdesc *fdhead; /* head of file description list */
421static fdesc *curfdp; /* current file description */ 433static fdesc *curfdp; /* current file description */
422static char *infilename; /* current input file name */ 434static char *infilename; /* current input file name */
423static int lineno; /* line number of current line */ 435static intmax_t lineno; /* line number of current line */
424static long charno; /* current character number */ 436static intmax_t charno; /* current character number */
425static long linecharno; /* charno of start of current line */ 437static intmax_t linecharno; /* charno of start of current line */
426static char *dbp; /* pointer to start of current tag */ 438static char *dbp; /* pointer to start of current tag */
427 439
428static const int invalidcharno = -1; 440static intmax_t const invalidcharno = -1;
429 441
430static node *nodehead; /* the head of the binary tree of tags */ 442static node *nodehead; /* the head of the binary tree of tags */
431static node *last_node; /* the last node created */ 443static node *last_node; /* the last node created */
@@ -1070,7 +1082,7 @@ int
1070main (int argc, char **argv) 1082main (int argc, char **argv)
1071{ 1083{
1072 int i; 1084 int i;
1073 unsigned int nincluded_files; 1085 int nincluded_files;
1074 char **included_files; 1086 char **included_files;
1075 argument *argbuffer; 1087 argument *argbuffer;
1076 int current_arg, file_count; 1088 int current_arg, file_count;
@@ -1484,7 +1496,7 @@ get_language_from_interpreter (char *interpreter)
1484 * Return a language given the file name. 1496 * Return a language given the file name.
1485 */ 1497 */
1486static language * 1498static language *
1487get_language_from_filename (char *file, int case_sensitive) 1499get_language_from_filename (char *file, bool case_sensitive)
1488{ 1500{
1489 language *lang; 1501 language *lang;
1490 const char **name, **ext, *suffix; 1502 const char **name, **ext, *suffix;
@@ -1918,26 +1930,26 @@ find_entries (FILE *inf)
1918 */ 1930 */
1919static void 1931static void
1920make_tag (const char *name, /* tag name, or NULL if unnamed */ 1932make_tag (const char *name, /* tag name, or NULL if unnamed */
1921 int namelen, /* tag length */ 1933 ptrdiff_t namelen, /* tag length */
1922 bool is_func, /* tag is a function */ 1934 bool is_func, /* tag is a function */
1923 char *linestart, /* start of the line where tag is */ 1935 char *linestart, /* start of the line where tag is */
1924 int linelen, /* length of the line where tag is */ 1936 ptrdiff_t linelen, /* length of the line where tag is */
1925 int lno, /* line number */ 1937 intmax_t lno, /* line number */
1926 long int cno) /* character number */ 1938 intmax_t cno) /* character number */
1927{ 1939{
1928 bool named = (name != NULL && namelen > 0); 1940 bool named = (name != NULL && namelen > 0);
1929 char *nname = NULL; 1941 char *nname = NULL;
1930 1942
1931 if (debug) 1943 if (debug)
1932 fprintf (stderr, "%s on %s:%d: %s\n", 1944 fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n",
1933 named ? name : "(unnamed)", curfdp->taggedfname, lno, linestart); 1945 named ? name : "(unnamed)", curfdp->taggedfname, lno, linestart);
1934 1946
1935 if (!CTAGS && named) /* maybe set named to false */ 1947 if (!CTAGS && named) /* maybe set named to false */
1936 /* Let's try to make an implicit tag name, that is, create an unnamed tag 1948 /* Let's try to make an implicit tag name, that is, create an unnamed tag
1937 such that etags.el can guess a name from it. */ 1949 such that etags.el can guess a name from it. */
1938 { 1950 {
1939 int i; 1951 ptrdiff_t i;
1940 register const char *cp = name; 1952 const char *cp = name;
1941 1953
1942 for (i = 0; i < namelen; i++) 1954 for (i = 0; i < namelen; i++)
1943 if (notinname (*cp++)) 1955 if (notinname (*cp++))
@@ -1963,8 +1975,8 @@ make_tag (const char *name, /* tag name, or NULL if unnamed */
1963 1975
1964/* Record a tag. */ 1976/* Record a tag. */
1965static void 1977static void
1966pfnote (char *name, bool is_func, char *linestart, int linelen, int lno, 1978pfnote (char *name, bool is_func, char *linestart, ptrdiff_t linelen,
1967 long int cno) 1979 intmax_t lno, intmax_t cno)
1968 /* tag name, or NULL if unnamed */ 1980 /* tag name, or NULL if unnamed */
1969 /* tag is a function */ 1981 /* tag is a function */
1970 /* start of the line where tag is */ 1982 /* start of the line where tag is */
@@ -2197,7 +2209,8 @@ add_node (node *np, node **cur_node_p)
2197 if (!no_warnings) 2209 if (!no_warnings)
2198 { 2210 {
2199 fprintf (stderr, 2211 fprintf (stderr,
2200 "Duplicate entry in file %s, line %d: %s\n", 2212 ("Duplicate entry in file %s, "
2213 "line %"PRIdMAX": %s\n"),
2201 np->fdp->infname, lineno, np->name); 2214 np->fdp->infname, lineno, np->name);
2202 fprintf (stderr, "Second entry ignored\n"); 2215 fprintf (stderr, "Second entry ignored\n");
2203 } 2216 }
@@ -2293,12 +2306,12 @@ invalidate_nodes (fdesc *badfdp, node **npp)
2293} 2306}
2294 2307
2295 2308
2296static int total_size_of_entries (node *); 2309static ptrdiff_t total_size_of_entries (node *);
2297static int number_len (long) ATTRIBUTE_CONST; 2310static int number_len (intmax_t) ATTRIBUTE_CONST;
2298 2311
2299/* Length of a non-negative number's decimal representation. */ 2312/* Length of a non-negative number's decimal representation. */
2300static int 2313static int
2301number_len (long int num) 2314number_len (intmax_t num)
2302{ 2315{
2303 int len = 1; 2316 int len = 1;
2304 while ((num /= 10) > 0) 2317 while ((num /= 10) > 0)
@@ -2312,10 +2325,10 @@ number_len (long int num)
2312 * This count is irrelevant with etags.el since emacs 19.34 at least, 2325 * This count is irrelevant with etags.el since emacs 19.34 at least,
2313 * but is still supplied for backward compatibility. 2326 * but is still supplied for backward compatibility.
2314 */ 2327 */
2315static int 2328static ptrdiff_t
2316total_size_of_entries (register node *np) 2329total_size_of_entries (node *np)
2317{ 2330{
2318 register int total = 0; 2331 ptrdiff_t total = 0;
2319 2332
2320 for (; np != NULL; np = np->right) 2333 for (; np != NULL; np = np->right)
2321 if (np->valid) 2334 if (np->valid)
@@ -2323,7 +2336,7 @@ total_size_of_entries (register node *np)
2323 total += strlen (np->regex) + 1; /* pat\177 */ 2336 total += strlen (np->regex) + 1; /* pat\177 */
2324 if (np->name != NULL) 2337 if (np->name != NULL)
2325 total += strlen (np->name) + 1; /* name\001 */ 2338 total += strlen (np->name) + 1; /* name\001 */
2326 total += number_len ((long) np->lno) + 1; /* lno, */ 2339 total += number_len (np->lno) + 1; /* lno, */
2327 if (np->cno != invalidcharno) /* cno */ 2340 if (np->cno != invalidcharno) /* cno */
2328 total += number_len (np->cno); 2341 total += number_len (np->cno);
2329 total += 1; /* newline */ 2342 total += 1; /* newline */
@@ -2347,7 +2360,7 @@ put_entry (node *np)
2347 if (fdp != np->fdp) 2360 if (fdp != np->fdp)
2348 { 2361 {
2349 fdp = np->fdp; 2362 fdp = np->fdp;
2350 fprintf (tagf, "\f\n%s,%d\n", 2363 fprintf (tagf, "\f\n%s,%"PRIdPTR"\n",
2351 fdp->taggedfname, total_size_of_entries (np)); 2364 fdp->taggedfname, total_size_of_entries (np));
2352 fdp->written = true; 2365 fdp->written = true;
2353 } 2366 }
@@ -2358,9 +2371,9 @@ put_entry (node *np)
2358 fputs (np->name, tagf); 2371 fputs (np->name, tagf);
2359 fputc ('\001', tagf); 2372 fputc ('\001', tagf);
2360 } 2373 }
2361 fprintf (tagf, "%d,", np->lno); 2374 fprintf (tagf, "%"PRIdMAX",", np->lno);
2362 if (np->cno != invalidcharno) 2375 if (np->cno != invalidcharno)
2363 fprintf (tagf, "%ld", np->cno); 2376 fprintf (tagf, "%"PRIdMAX, np->cno);
2364 fputs ("\n", tagf); 2377 fputs ("\n", tagf);
2365 } 2378 }
2366 else 2379 else
@@ -2372,10 +2385,10 @@ put_entry (node *np)
2372 if (cxref_style) 2385 if (cxref_style)
2373 { 2386 {
2374 if (vgrind_style) 2387 if (vgrind_style)
2375 fprintf (stdout, "%s %s %d\n", 2388 fprintf (stdout, "%s %s %"PRIdMAX"\n",
2376 np->name, np->fdp->taggedfname, (np->lno + 63) / 64); 2389 np->name, np->fdp->taggedfname, (np->lno + 63) / 64);
2377 else 2390 else
2378 fprintf (stdout, "%-16s %3d %-16s %s\n", 2391 fprintf (stdout, "%-16s %3"PRIdMAX" %-16s %s\n",
2379 np->name, np->lno, np->fdp->taggedfname, np->regex); 2392 np->name, np->lno, np->fdp->taggedfname, np->regex);
2380 } 2393 }
2381 else 2394 else
@@ -2397,7 +2410,7 @@ put_entry (node *np)
2397 } 2410 }
2398 else 2411 else
2399 { /* anything else; text pattern inadequate */ 2412 { /* anything else; text pattern inadequate */
2400 fprintf (tagf, "%d", np->lno); 2413 fprintf (tagf, "%"PRIdMAX, np->lno);
2401 } 2414 }
2402 putc ('\n', tagf); 2415 putc ('\n', tagf);
2403 } 2416 }
@@ -2591,7 +2604,7 @@ hash (const char *str, int len)
2591} 2604}
2592 2605
2593static struct C_stab_entry * 2606static struct C_stab_entry *
2594in_word_set (register const char *str, register unsigned int len) 2607in_word_set (const char *str, ptrdiff_t len)
2595{ 2608{
2596 enum 2609 enum
2597 { 2610 {
@@ -2658,9 +2671,9 @@ in_word_set (register const char *str, register unsigned int len)
2658/*%>*/ 2671/*%>*/
2659 2672
2660static enum sym_type 2673static enum sym_type
2661C_symtype (char *str, int len, int c_ext) 2674C_symtype (char *str, ptrdiff_t len, int c_ext)
2662{ 2675{
2663 register struct C_stab_entry *se = in_word_set (str, len); 2676 struct C_stab_entry *se = in_word_set (str, len);
2664 2677
2665 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext))) 2678 if (se == NULL || (se->c_ext && !(c_ext & se->c_ext)))
2666 return st_none; 2679 return st_none;
@@ -2770,8 +2783,8 @@ static enum
2770static struct tok 2783static struct tok
2771{ 2784{
2772 char *line; /* string containing the token */ 2785 char *line; /* string containing the token */
2773 int offset; /* where the token starts in LINE */ 2786 ptrdiff_t offset; /* where the token starts in LINE */
2774 int length; /* token length */ 2787 ptrdiff_t length; /* token length */
2775 /* 2788 /*
2776 The previous members can be used to pass strings around for generic 2789 The previous members can be used to pass strings around for generic
2777 purposes. The following ones specifically refer to creating tags. In this 2790 purposes. The following ones specifically refer to creating tags. In this
@@ -2782,23 +2795,23 @@ static struct tok
2782 invalidated whenever a state machine is 2795 invalidated whenever a state machine is
2783 reset prematurely */ 2796 reset prematurely */
2784 bool named; /* create a named tag */ 2797 bool named; /* create a named tag */
2785 int lineno; /* source line number of tag */ 2798 intmax_t lineno; /* source line number of tag */
2786 long linepos; /* source char number of tag */ 2799 intmax_t linepos; /* source char number of tag */
2787} token; /* latest token read */ 2800} token; /* latest token read */
2788 2801
2789/* 2802/*
2790 * Variables and functions for dealing with nested structures. 2803 * Variables and functions for dealing with nested structures.
2791 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001) 2804 * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001)
2792 */ 2805 */
2793static void pushclass_above (int, char *, int); 2806static void pushclass_above (ptrdiff_t, char *, ptrdiff_t);
2794static void popclass_above (int); 2807static void popclass_above (ptrdiff_t);
2795static void write_classname (linebuffer *, const char *qualifier); 2808static void write_classname (linebuffer *, const char *qualifier);
2796 2809
2797static struct { 2810static struct {
2798 char **cname; /* nested class names */ 2811 char **cname; /* nested class names */
2799 int *bracelev; /* nested class brace level */ 2812 ptrdiff_t *bracelev; /* nested class brace level */
2800 int nl; /* class nesting level (elements used) */ 2813 ptrdiff_t nl; /* class nesting level (elements used) */
2801 int size; /* length of the array */ 2814 ptrdiff_t size; /* length of the array */
2802} cstack; /* stack for nested declaration tags */ 2815} cstack; /* stack for nested declaration tags */
2803/* Current struct nesting depth (namespace, class, struct, union, enum). */ 2816/* Current struct nesting depth (namespace, class, struct, union, enum). */
2804#define nestlev (cstack.nl) 2817#define nestlev (cstack.nl)
@@ -2807,17 +2820,17 @@ static struct {
2807 && bracelev == cstack.bracelev[nestlev-1] + 1) 2820 && bracelev == cstack.bracelev[nestlev-1] + 1)
2808 2821
2809static void 2822static void
2810pushclass_above (int bracelev, char *str, int len) 2823pushclass_above (ptrdiff_t bracelev, char *str, ptrdiff_t len)
2811{ 2824{
2812 int nl; 2825 ptrdiff_t nl;
2813 2826
2814 popclass_above (bracelev); 2827 popclass_above (bracelev);
2815 nl = cstack.nl; 2828 nl = cstack.nl;
2816 if (nl >= cstack.size) 2829 if (nl >= cstack.size)
2817 { 2830 {
2818 int size = cstack.size *= 2; 2831 xrnew (cstack.cname, cstack.size, 2);
2819 xrnew (cstack.cname, size, char *); 2832 xrnew (cstack.bracelev, cstack.size, 2);
2820 xrnew (cstack.bracelev, size, int); 2833 cstack.size *= 2;
2821 } 2834 }
2822 assert (nl == 0 || cstack.bracelev[nl-1] < bracelev); 2835 assert (nl == 0 || cstack.bracelev[nl-1] < bracelev);
2823 cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len); 2836 cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len);
@@ -2826,11 +2839,9 @@ pushclass_above (int bracelev, char *str, int len)
2826} 2839}
2827 2840
2828static void 2841static void
2829popclass_above (int bracelev) 2842popclass_above (ptrdiff_t bracelev)
2830{ 2843{
2831 int nl; 2844 for (ptrdiff_t nl = cstack.nl - 1;
2832
2833 for (nl = cstack.nl - 1;
2834 nl >= 0 && cstack.bracelev[nl] >= bracelev; 2845 nl >= 0 && cstack.bracelev[nl] >= bracelev;
2835 nl--) 2846 nl--)
2836 { 2847 {
@@ -2842,8 +2853,7 @@ popclass_above (int bracelev)
2842static void 2853static void
2843write_classname (linebuffer *cn, const char *qualifier) 2854write_classname (linebuffer *cn, const char *qualifier)
2844{ 2855{
2845 int i, len; 2856 ptrdiff_t len;
2846 int qlen = strlen (qualifier);
2847 2857
2848 if (cstack.nl == 0 || cstack.cname[0] == NULL) 2858 if (cstack.nl == 0 || cstack.cname[0] == NULL)
2849 { 2859 {
@@ -2857,18 +2867,22 @@ write_classname (linebuffer *cn, const char *qualifier)
2857 linebuffer_setlen (cn, len); 2867 linebuffer_setlen (cn, len);
2858 strcpy (cn->buffer, cstack.cname[0]); 2868 strcpy (cn->buffer, cstack.cname[0]);
2859 } 2869 }
2860 for (i = 1; i < cstack.nl; i++) 2870 for (ptrdiff_t i = 1; i < cstack.nl; i++)
2861 { 2871 {
2862 char *s = cstack.cname[i]; 2872 char *s = cstack.cname[i];
2863 if (s == NULL) 2873 if (s == NULL)
2864 continue; 2874 continue;
2865 linebuffer_setlen (cn, len + qlen + strlen (s)); 2875 int qlen = strlen (qualifier);
2866 len += sprintf (cn->buffer + len, "%s%s", qualifier, s); 2876 ptrdiff_t slen = strlen (s);
2877 linebuffer_setlen (cn, len + qlen + slen);
2878 memcpyz (stpcpy (cn->buffer + len, qualifier), s, slen);
2879 len += qlen + slen;
2867 } 2880 }
2868} 2881}
2869 2882
2870 2883
2871static bool consider_token (char *, int, int, int *, int, int, bool *); 2884static bool consider_token (char *, ptrdiff_t, int, int *,
2885 ptrdiff_t, ptrdiff_t, bool *);
2872static void make_C_tag (bool); 2886static void make_C_tag (bool);
2873 2887
2874/* 2888/*
@@ -2889,8 +2903,8 @@ static void make_C_tag (bool);
2889 */ 2903 */
2890 2904
2891static bool 2905static bool
2892consider_token (char *str, int len, int c, int *c_extp, 2906consider_token (char *str, ptrdiff_t len, int c, int *c_extp,
2893 int bracelev, int parlev, bool *is_func_or_var) 2907 ptrdiff_t bracelev, ptrdiff_t parlev, bool *is_func_or_var)
2894 /* IN: token pointer */ 2908 /* IN: token pointer */
2895 /* IN: token length */ 2909 /* IN: token length */
2896 /* IN: first char after the token */ 2910 /* IN: first char after the token */
@@ -2903,7 +2917,7 @@ consider_token (char *str, int len, int c, int *c_extp,
2903 structtype is the type of the preceding struct-like keyword, and 2917 structtype is the type of the preceding struct-like keyword, and
2904 structbracelev is the brace level where it has been seen. */ 2918 structbracelev is the brace level where it has been seen. */
2905 static enum sym_type structtype; 2919 static enum sym_type structtype;
2906 static int structbracelev; 2920 static ptrdiff_t structbracelev;
2907 static enum sym_type toktype; 2921 static enum sym_type toktype;
2908 2922
2909 2923
@@ -3098,8 +3112,7 @@ consider_token (char *str, int len, int c, int *c_extp,
3098 fvdef = fvnone; 3112 fvdef = fvnone;
3099 objdef = omethodtag; 3113 objdef = omethodtag;
3100 linebuffer_setlen (&token_name, len); 3114 linebuffer_setlen (&token_name, len);
3101 memcpy (token_name.buffer, str, len); 3115 memcpyz (token_name.buffer, str, len);
3102 token_name.buffer[len] = '\0';
3103 return true; 3116 return true;
3104 } 3117 }
3105 return false; 3118 return false;
@@ -3113,11 +3126,10 @@ consider_token (char *str, int len, int c, int *c_extp,
3113 objdef = omethodtag; 3126 objdef = omethodtag;
3114 if (class_qualify) 3127 if (class_qualify)
3115 { 3128 {
3116 int oldlen = token_name.len; 3129 ptrdiff_t oldlen = token_name.len;
3117 fvdef = fvnone; 3130 fvdef = fvnone;
3118 linebuffer_setlen (&token_name, oldlen + len); 3131 linebuffer_setlen (&token_name, oldlen + len);
3119 memcpy (token_name.buffer + oldlen, str, len); 3132 memcpyz (token_name.buffer + oldlen, str, len);
3120 token_name.buffer[oldlen + len] = '\0';
3121 } 3133 }
3122 return true; 3134 return true;
3123 } 3135 }
@@ -3228,7 +3240,7 @@ consider_token (char *str, int len, int c, int *c_extp,
3228 */ 3240 */
3229static struct 3241static struct
3230{ 3242{
3231 long linepos; 3243 intmax_t linepos;
3232 linebuffer lb; 3244 linebuffer lb;
3233} lbs[2]; 3245} lbs[2];
3234 3246
@@ -3302,19 +3314,19 @@ C_entries (int c_ext, FILE *inf)
3302 /* extension of C */ 3314 /* extension of C */
3303 /* input file */ 3315 /* input file */
3304{ 3316{
3305 register char c; /* latest char read; '\0' for end of line */ 3317 char c; /* latest char read; '\0' for end of line */
3306 register char *lp; /* pointer one beyond the character `c' */ 3318 char *lp; /* pointer one beyond the character `c' */
3307 int curndx, newndx; /* indices for current and new lb */ 3319 bool curndx, newndx; /* indices for current and new lb */
3308 register int tokoff; /* offset in line of start of current token */ 3320 ptrdiff_t tokoff; /* offset in line of start of current token */
3309 register int toklen; /* length of current token */ 3321 ptrdiff_t toklen; /* length of current token */
3310 const char *qualifier; /* string used to qualify names */ 3322 const char *qualifier; /* string used to qualify names */
3311 int qlen; /* length of qualifier */ 3323 int qlen; /* length of qualifier */
3312 int bracelev; /* current brace level */ 3324 ptrdiff_t bracelev; /* current brace level */
3313 int bracketlev; /* current bracket level */ 3325 ptrdiff_t bracketlev; /* current bracket level */
3314 int parlev; /* current parenthesis level */ 3326 ptrdiff_t parlev; /* current parenthesis level */
3315 int attrparlev; /* __attribute__ parenthesis level */ 3327 ptrdiff_t attrparlev; /* __attribute__ parenthesis level */
3316 int templatelev; /* current template level */ 3328 ptrdiff_t templatelev; /* current template level */
3317 int typdefbracelev; /* bracelev where a typedef struct body begun */ 3329 ptrdiff_t typdefbracelev; /* bracelev where a typedef struct body begun */
3318 bool incomm, inquote, inchar, quotednl, midtoken; 3330 bool incomm, inquote, inchar, quotednl, midtoken;
3319 bool yacc_rules; /* in the rules part of a yacc file */ 3331 bool yacc_rules; /* in the rules part of a yacc file */
3320 struct tok savetoken = {0}; /* token saved during preprocessor handling */ 3332 struct tok savetoken = {0}; /* token saved during preprocessor handling */
@@ -3327,7 +3339,7 @@ C_entries (int c_ext, FILE *inf)
3327 cstack.size = (DEBUG) ? 1 : 4; 3339 cstack.size = (DEBUG) ? 1 : 4;
3328 cstack.nl = 0; 3340 cstack.nl = 0;
3329 cstack.cname = xnew (cstack.size, char *); 3341 cstack.cname = xnew (cstack.size, char *);
3330 cstack.bracelev = xnew (cstack.size, int); 3342 cstack.bracelev = xnew (cstack.size, ptrdiff_t);
3331 } 3343 }
3332 3344
3333 tokoff = toklen = typdefbracelev = 0; /* keep compiler quiet */ 3345 tokoff = toklen = typdefbracelev = 0; /* keep compiler quiet */
@@ -3579,20 +3591,19 @@ C_entries (int c_ext, FILE *inf)
3579 { 3591 {
3580 if (class_qualify) 3592 if (class_qualify)
3581 { 3593 {
3582 int len;
3583 write_classname (&token_name, qualifier); 3594 write_classname (&token_name, qualifier);
3584 len = token_name.len; 3595 ptrdiff_t len = token_name.len;
3585 linebuffer_setlen (&token_name, 3596 linebuffer_setlen (&token_name,
3586 len + qlen + toklen); 3597 len + qlen + toklen);
3587 sprintf (token_name.buffer + len, "%s%.*s", 3598 memcpyz (stpcpy (token_name.buffer + len,
3588 qualifier, toklen, 3599 qualifier),
3589 newlb.buffer + tokoff); 3600 newlb.buffer + tokoff, toklen);
3590 } 3601 }
3591 else 3602 else
3592 { 3603 {
3593 linebuffer_setlen (&token_name, toklen); 3604 linebuffer_setlen (&token_name, toklen);
3594 sprintf (token_name.buffer, "%.*s", 3605 memcpyz (token_name.buffer,
3595 toklen, newlb.buffer + tokoff); 3606 newlb.buffer + tokoff, toklen);
3596 } 3607 }
3597 token.named = true; 3608 token.named = true;
3598 } 3609 }
@@ -3601,17 +3612,19 @@ C_entries (int c_ext, FILE *inf)
3601 { 3612 {
3602 if (class_qualify) 3613 if (class_qualify)
3603 { 3614 {
3604 int len = strlen (objtag) + 2 + toklen; 3615 ptrdiff_t len = strlen (objtag) + 2 + toklen;
3605 linebuffer_setlen (&token_name, len); 3616 linebuffer_setlen (&token_name, len);
3606 sprintf (token_name.buffer, "%s(%.*s)", 3617 char *p1 = stpcpy (token_name.buffer, objtag);
3607 objtag, toklen, 3618 char *p2 = stpcpy (p1, "(");
3608 newlb.buffer + tokoff); 3619 char *p3 = mempcpy (p2, newlb.buffer + tokoff,
3620 toklen);
3621 strcpy (p3, ")");
3609 } 3622 }
3610 else 3623 else
3611 { 3624 {
3612 linebuffer_setlen (&token_name, toklen); 3625 linebuffer_setlen (&token_name, toklen);
3613 sprintf (token_name.buffer, "%.*s", 3626 memcpyz (token_name.buffer,
3614 toklen, newlb.buffer + tokoff); 3627 newlb.buffer + tokoff, toklen);
3615 } 3628 }
3616 token.named = true; 3629 token.named = true;
3617 } 3630 }
@@ -3625,8 +3638,8 @@ C_entries (int c_ext, FILE *inf)
3625 /* GNU DEFUN and similar macros */ 3638 /* GNU DEFUN and similar macros */
3626 { 3639 {
3627 bool defun = (newlb.buffer[tokoff] == 'F'); 3640 bool defun = (newlb.buffer[tokoff] == 'F');
3628 int off = tokoff; 3641 ptrdiff_t off = tokoff;
3629 int len = toklen; 3642 ptrdiff_t len = toklen;
3630 3643
3631 if (defun) 3644 if (defun)
3632 { 3645 {
@@ -3635,9 +3648,8 @@ C_entries (int c_ext, FILE *inf)
3635 3648
3636 /* First, tag it as its C name */ 3649 /* First, tag it as its C name */
3637 linebuffer_setlen (&token_name, toklen); 3650 linebuffer_setlen (&token_name, toklen);
3638 memcpy (token_name.buffer, 3651 memcpyz (token_name.buffer,
3639 newlb.buffer + tokoff, toklen); 3652 newlb.buffer + tokoff, toklen);
3640 token_name.buffer[toklen] = '\0';
3641 token.named = true; 3653 token.named = true;
3642 token.lineno = lineno; 3654 token.lineno = lineno;
3643 token.offset = tokoff; 3655 token.offset = tokoff;
@@ -3650,9 +3662,8 @@ C_entries (int c_ext, FILE *inf)
3650 /* Rewrite the tag so that emacs lisp DEFUNs 3662 /* Rewrite the tag so that emacs lisp DEFUNs
3651 can be found also by their elisp name */ 3663 can be found also by their elisp name */
3652 linebuffer_setlen (&token_name, len); 3664 linebuffer_setlen (&token_name, len);
3653 memcpy (token_name.buffer, 3665 memcpyz (token_name.buffer,
3654 newlb.buffer + off, len); 3666 newlb.buffer + off, len);
3655 token_name.buffer[len] = '\0';
3656 if (defun) 3667 if (defun)
3657 while (--len >= 0) 3668 while (--len >= 0)
3658 if (token_name.buffer[len] == '_') 3669 if (token_name.buffer[len] == '_')
@@ -3662,9 +3673,8 @@ C_entries (int c_ext, FILE *inf)
3662 else 3673 else
3663 { 3674 {
3664 linebuffer_setlen (&token_name, toklen); 3675 linebuffer_setlen (&token_name, toklen);
3665 memcpy (token_name.buffer, 3676 memcpyz (token_name.buffer,
3666 newlb.buffer + tokoff, toklen); 3677 newlb.buffer + tokoff, toklen);
3667 token_name.buffer[toklen] = '\0';
3668 /* Name macros and members. */ 3678 /* Name macros and members. */
3669 token.named = (structdef == stagseen 3679 token.named = (structdef == stagseen
3670 || typdef == ttypeseen 3680 || typdef == ttypeseen
@@ -3790,7 +3800,7 @@ C_entries (int c_ext, FILE *inf)
3790 objdef = omethodcolon; 3800 objdef = omethodcolon;
3791 if (class_qualify) 3801 if (class_qualify)
3792 { 3802 {
3793 int toklen = token_name.len; 3803 ptrdiff_t toklen = token_name.len;
3794 linebuffer_setlen (&token_name, toklen + 1); 3804 linebuffer_setlen (&token_name, toklen + 1);
3795 strcpy (token_name.buffer + toklen, ":"); 3805 strcpy (token_name.buffer + toklen, ":");
3796 } 3806 }
@@ -4061,7 +4071,7 @@ C_entries (int c_ext, FILE *inf)
4061 } 4071 }
4062 if (uqname > token_name.buffer) 4072 if (uqname > token_name.buffer)
4063 { 4073 {
4064 int uqlen = strlen (uqname); 4074 ptrdiff_t uqlen = strlen (uqname);
4065 linebuffer_setlen (&token_name, uqlen); 4075 linebuffer_setlen (&token_name, uqlen);
4066 memmove (token_name.buffer, uqname, uqlen + 1); 4076 memmove (token_name.buffer, uqname, uqlen + 1);
4067 } 4077 }
@@ -4979,12 +4989,11 @@ Ruby_functions (FILE *inf)
4979 size_t name_len = cp - np + 1; 4989 size_t name_len = cp - np + 1;
4980 char *wr_name = xnew (name_len + 1, char); 4990 char *wr_name = xnew (name_len + 1, char);
4981 4991
4982 memcpy (wr_name, np, name_len - 1); 4992 strcpy (mempcpy (wr_name, np, name_len - 1), "=");
4983 memcpy (wr_name + name_len - 1, "=", 2);
4984 pfnote (wr_name, true, lb.buffer, cp - lb.buffer + 1, 4993 pfnote (wr_name, true, lb.buffer, cp - lb.buffer + 1,
4985 lineno, linecharno); 4994 lineno, linecharno);
4986 if (debug) 4995 if (debug)
4987 fprintf (stderr, "%s on %s:%d: %s\n", wr_name, 4996 fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n", wr_name,
4988 curfdp->taggedfname, lineno, lb.buffer); 4997 curfdp->taggedfname, lineno, lb.buffer);
4989 continuation = false; 4998 continuation = false;
4990 } 4999 }
@@ -5178,8 +5187,8 @@ static void
5178Pascal_functions (FILE *inf) 5187Pascal_functions (FILE *inf)
5179{ 5188{
5180 linebuffer tline; /* mostly copied from C_entries */ 5189 linebuffer tline; /* mostly copied from C_entries */
5181 long save_lcno; 5190 intmax_t save_lcno, save_lineno;
5182 int save_lineno, namelen, taglen; 5191 ptrdiff_t namelen, taglen;
5183 char c, *name; 5192 char c, *name;
5184 5193
5185 bool /* each of these flags is true if: */ 5194 bool /* each of these flags is true if: */
@@ -5455,7 +5464,7 @@ Lua_functions (FILE *inf)
5455 if (tp_dot || tp_colon) 5464 if (tp_dot || tp_colon)
5456 { 5465 {
5457 char *p = tp_dot > tp_colon ? tp_dot : tp_colon; 5466 char *p = tp_dot > tp_colon ? tp_dot : tp_colon;
5458 int len_add = p - tag_name + 1; 5467 ptrdiff_t len_add = p - tag_name + 1;
5459 5468
5460 get_tag (bp + len_add, NULL); 5469 get_tag (bp + len_add, NULL);
5461 } 5470 }
@@ -5656,7 +5665,7 @@ TeX_commands (FILE *inf)
5656 if (strneq (cp, key->buffer, key->len)) 5665 if (strneq (cp, key->buffer, key->len))
5657 { 5666 {
5658 char *p; 5667 char *p;
5659 int namelen, linelen; 5668 ptrdiff_t namelen, linelen;
5660 bool opgrp = false; 5669 bool opgrp = false;
5661 5670
5662 cp = skip_spaces (cp + key->len); 5671 cp = skip_spaces (cp + key->len);
@@ -5693,8 +5702,8 @@ TeX_commands (FILE *inf)
5693static void 5702static void
5694TEX_decode_env (const char *evarname, const char *defenv) 5703TEX_decode_env (const char *evarname, const char *defenv)
5695{ 5704{
5696 register const char *env, *p; 5705 const char *env, *p;
5697 int i, len; 5706 ptrdiff_t len;
5698 5707
5699 /* Append default string to environment. */ 5708 /* Append default string to environment. */
5700 env = getenv (evarname); 5709 env = getenv (evarname);
@@ -5711,7 +5720,7 @@ TEX_decode_env (const char *evarname, const char *defenv)
5711 5720
5712 /* Unpack environment string into token table. Be careful about */ 5721 /* Unpack environment string into token table. Be careful about */
5713 /* zero-length strings (leading ':', "::" and trailing ':') */ 5722 /* zero-length strings (leading ':', "::" and trailing ':') */
5714 for (i = 0; *env != '\0';) 5723 for (ptrdiff_t i = 0; *env != '\0'; )
5715 { 5724 {
5716 p = strchr (env, ':'); 5725 p = strchr (env, ':');
5717 if (!p) /* End of environment string. */ 5726 if (!p) /* End of environment string. */
@@ -5811,8 +5820,7 @@ HTML_labels (FILE *inf)
5811 for (end = dbp; *end != '\0' && intoken (*end); end++) 5820 for (end = dbp; *end != '\0' && intoken (*end); end++)
5812 continue; 5821 continue;
5813 linebuffer_setlen (&token_name, end - dbp); 5822 linebuffer_setlen (&token_name, end - dbp);
5814 memcpy (token_name.buffer, dbp, end - dbp); 5823 memcpyz (token_name.buffer, dbp, end - dbp);
5815 token_name.buffer[end - dbp] = '\0';
5816 5824
5817 dbp = end; 5825 dbp = end;
5818 intag = false; /* we found what we looked for */ 5826 intag = false; /* we found what we looked for */
@@ -5906,11 +5914,10 @@ Prolog_functions (FILE *inf)
5906 tags later. */ 5914 tags later. */
5907 if (allocated <= len) 5915 if (allocated <= len)
5908 { 5916 {
5909 xrnew (last, len + 1, char); 5917 xrnew (last, len + 1, 1);
5910 allocated = len + 1; 5918 allocated = len + 1;
5911 } 5919 }
5912 memcpy (last, cp, len); 5920 memcpyz (last, cp, len);
5913 last[len] = '\0';
5914 lastlen = len; 5921 lastlen = len;
5915 } 5922 }
5916 } 5923 }
@@ -6031,9 +6038,9 @@ prolog_atom (char *s, size_t pos)
6031 * Assumes that Erlang functions start at column 0. 6038 * Assumes that Erlang functions start at column 0.
6032 * Original code by Anders Lindgren (1996) 6039 * Original code by Anders Lindgren (1996)
6033 */ 6040 */
6034static int erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *); 6041static ptrdiff_t erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *);
6035static void erlang_attribute (char *); 6042static void erlang_attribute (char *);
6036static int erlang_atom (char *); 6043static ptrdiff_t erlang_atom (char *);
6037 6044
6038static void 6045static void
6039Erlang_functions (FILE *inf) 6046Erlang_functions (FILE *inf)
@@ -6070,11 +6077,10 @@ Erlang_functions (FILE *inf)
6070 tags later. */ 6077 tags later. */
6071 if (allocated <= len) 6078 if (allocated <= len)
6072 { 6079 {
6073 xrnew (last, len + 1, char); 6080 xrnew (last, len + 1, 1);
6074 allocated = len + 1; 6081 allocated = len + 1;
6075 } 6082 }
6076 memcpy (last, cp + name_offset, len); 6083 memcpyz (last, cp + name_offset, len);
6077 last[len] = '\0';
6078 lastlen = len; 6084 lastlen = len;
6079 } 6085 }
6080 } 6086 }
@@ -6093,7 +6099,7 @@ Erlang_functions (FILE *inf)
6093 * Return the size of the name of the function, or 0 if no function 6099 * Return the size of the name of the function, or 0 if no function
6094 * was found. 6100 * was found.
6095 */ 6101 */
6096static int 6102static ptrdiff_t
6097erlang_func (char *s, char *last, ptrdiff_t lastlen, ptrdiff_t *name_offset) 6103erlang_func (char *s, char *last, ptrdiff_t lastlen, ptrdiff_t *name_offset)
6098{ 6104{
6099 char *name = s; 6105 char *name = s;
@@ -6133,15 +6139,13 @@ static void
6133erlang_attribute (char *s) 6139erlang_attribute (char *s)
6134{ 6140{
6135 char *cp = s; 6141 char *cp = s;
6136 int pos;
6137 int len;
6138 6142
6139 if ((LOOKING_AT (cp, "-define") || LOOKING_AT (cp, "-record")) 6143 if ((LOOKING_AT (cp, "-define") || LOOKING_AT (cp, "-record"))
6140 && *cp++ == '(') 6144 && *cp++ == '(')
6141 { 6145 {
6142 cp = skip_spaces (cp); 6146 cp = skip_spaces (cp);
6143 len = erlang_atom (cp); 6147 ptrdiff_t len = erlang_atom (cp);
6144 pos = cp + len - s; 6148 ptrdiff_t pos = cp + len - s;
6145 if (len > 0) 6149 if (len > 0)
6146 { 6150 {
6147 /* If the name is quoted, the quotes are not part of the name. */ 6151 /* If the name is quoted, the quotes are not part of the name. */
@@ -6161,10 +6165,10 @@ erlang_attribute (char *s)
6161 * Consume an Erlang atom (or variable). 6165 * Consume an Erlang atom (or variable).
6162 * Return the number of bytes consumed, or -1 if there was an error. 6166 * Return the number of bytes consumed, or -1 if there was an error.
6163 */ 6167 */
6164static int 6168static ptrdiff_t
6165erlang_atom (char *s) 6169erlang_atom (char *s)
6166{ 6170{
6167 int pos = 0; 6171 ptrdiff_t pos = 0;
6168 6172
6169 if (c_isalpha (s[pos]) || s[pos] == '_') 6173 if (c_isalpha (s[pos]) || s[pos] == '_')
6170 { 6174 {
@@ -6437,10 +6441,9 @@ static char *
6437substitute (char *in, char *out, struct re_registers *regs) 6441substitute (char *in, char *out, struct re_registers *regs)
6438{ 6442{
6439 char *result, *t; 6443 char *result, *t;
6440 int size, dig, diglen;
6441 6444
6442 result = NULL; 6445 result = NULL;
6443 size = strlen (out); 6446 ptrdiff_t size = strlen (out);
6444 6447
6445 /* Pass 1: figure out how much to allocate by finding all \N strings. */ 6448 /* Pass 1: figure out how much to allocate by finding all \N strings. */
6446 if (out[size - 1] == '\\') 6449 if (out[size - 1] == '\\')
@@ -6450,8 +6453,8 @@ substitute (char *in, char *out, struct re_registers *regs)
6450 t = strchr (t + 2, '\\')) 6453 t = strchr (t + 2, '\\'))
6451 if (c_isdigit (t[1])) 6454 if (c_isdigit (t[1]))
6452 { 6455 {
6453 dig = t[1] - '0'; 6456 int dig = t[1] - '0';
6454 diglen = regs->end[dig] - regs->start[dig]; 6457 ptrdiff_t diglen = regs->end[dig] - regs->start[dig];
6455 size += diglen - 2; 6458 size += diglen - 2;
6456 } 6459 }
6457 else 6460 else
@@ -6464,8 +6467,8 @@ substitute (char *in, char *out, struct re_registers *regs)
6464 for (t = result; *out != '\0'; out++) 6467 for (t = result; *out != '\0'; out++)
6465 if (*out == '\\' && c_isdigit (*++out)) 6468 if (*out == '\\' && c_isdigit (*++out))
6466 { 6469 {
6467 dig = *out - '0'; 6470 int dig = *out - '0';
6468 diglen = regs->end[dig] - regs->start[dig]; 6471 ptrdiff_t diglen = regs->end[dig] - regs->start[dig];
6469 memcpy (t, in + regs->start[dig], diglen); 6472 memcpy (t, in + regs->start[dig], diglen);
6470 t += diglen; 6473 t += diglen;
6471 } 6474 }
@@ -6474,7 +6477,7 @@ substitute (char *in, char *out, struct re_registers *regs)
6474 *t = '\0'; 6477 *t = '\0';
6475 6478
6476 assert (t <= result + size); 6479 assert (t <= result + size);
6477 assert (t - result == (int)strlen (result)); 6480 assert (t == result + strlen (result));
6478 6481
6479 return result; 6482 return result;
6480} 6483}
@@ -6511,7 +6514,7 @@ regex_tag_multiline (void)
6511 6514
6512 for (rp = p_head; rp != NULL; rp = rp->p_next) 6515 for (rp = p_head; rp != NULL; rp = rp->p_next)
6513 { 6516 {
6514 int match = 0; 6517 ptrdiff_t match = 0;
6515 6518
6516 if (!rp->multi_line) 6519 if (!rp->multi_line)
6517 continue; /* skip normal regexps */ 6520 continue; /* skip normal regexps */
@@ -6572,7 +6575,7 @@ regex_tag_multiline (void)
6572 charno - linecharno + 1, lineno, linecharno); 6575 charno - linecharno + 1, lineno, linecharno);
6573 6576
6574 if (debug) 6577 if (debug)
6575 fprintf (stderr, "%s on %s:%d: %s\n", 6578 fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n",
6576 name ? name : "(unnamed)", curfdp->taggedfname, 6579 name ? name : "(unnamed)", curfdp->taggedfname,
6577 lineno, buffer + linecharno); 6580 lineno, buffer + linecharno);
6578 } 6581 }
@@ -6589,7 +6592,7 @@ regex_tag_multiline (void)
6589static bool 6592static bool
6590nocase_tail (const char *cp) 6593nocase_tail (const char *cp)
6591{ 6594{
6592 int len = 0; 6595 ptrdiff_t len = 0;
6593 6596
6594 while (*cp != '\0' && c_tolower (*cp) == c_tolower (dbp[len])) 6597 while (*cp != '\0' && c_tolower (*cp) == c_tolower (dbp[len]))
6595 cp++, len++; 6598 cp++, len++;
@@ -6648,7 +6651,7 @@ get_lispy_tag (register char *bp)
6648 * If multi-line regular expressions are requested, each line read is 6651 * If multi-line regular expressions are requested, each line read is
6649 * appended to `filebuf'. 6652 * appended to `filebuf'.
6650 */ 6653 */
6651static long 6654static ptrdiff_t
6652readline_internal (linebuffer *lbp, FILE *stream, char const *filename) 6655readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
6653{ 6656{
6654 char *buffer = lbp->buffer; 6657 char *buffer = lbp->buffer;
@@ -6664,8 +6667,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
6664 if (p == pend) 6667 if (p == pend)
6665 { 6668 {
6666 /* We're at the end of linebuffer: expand it. */ 6669 /* We're at the end of linebuffer: expand it. */
6670 xrnew (buffer, lbp->size, 2);
6667 lbp->size *= 2; 6671 lbp->size *= 2;
6668 xrnew (buffer, lbp->size, char);
6669 p += buffer - lbp->buffer; 6672 p += buffer - lbp->buffer;
6670 pend = buffer + lbp->size; 6673 pend = buffer + lbp->size;
6671 lbp->buffer = buffer; 6674 lbp->buffer = buffer;
@@ -6702,13 +6705,12 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
6702 while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */ 6705 while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */
6703 { 6706 {
6704 /* Expand filebuf. */ 6707 /* Expand filebuf. */
6708 xrnew (filebuf.buffer, filebuf.size, 2);
6705 filebuf.size *= 2; 6709 filebuf.size *= 2;
6706 xrnew (filebuf.buffer, filebuf.size, char);
6707 } 6710 }
6708 memcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len); 6711 strcpy (mempcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len),
6709 filebuf.len += lbp->len; 6712 "\n");
6710 filebuf.buffer[filebuf.len++] = '\n'; 6713 filebuf.len += lbp->len + 1;
6711 filebuf.buffer[filebuf.len] = '\0';
6712 } 6714 }
6713 6715
6714 return lbp->len + chars_deleted; 6716 return lbp->len + chars_deleted;
@@ -6722,10 +6724,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename)
6722static void 6724static void
6723readline (linebuffer *lbp, FILE *stream) 6725readline (linebuffer *lbp, FILE *stream)
6724{ 6726{
6725 long result;
6726
6727 linecharno = charno; /* update global char number of line start */ 6727 linecharno = charno; /* update global char number of line start */
6728 result = readline_internal (lbp, stream, infilename); /* read line */ 6728 ptrdiff_t result = readline_internal (lbp, stream, infilename);
6729 lineno += 1; /* increment global line number */ 6729 lineno += 1; /* increment global line number */
6730 charno += result; /* increment global char number */ 6730 charno += result; /* increment global char number */
6731 6731
@@ -6737,10 +6737,10 @@ readline (linebuffer *lbp, FILE *stream)
6737 /* Check whether this is a #line directive. */ 6737 /* Check whether this is a #line directive. */
6738 if (result > 12 && strneq (lbp->buffer, "#line ", 6)) 6738 if (result > 12 && strneq (lbp->buffer, "#line ", 6))
6739 { 6739 {
6740 unsigned int lno; 6740 intmax_t lno;
6741 int start = 0; 6741 int start = 0;
6742 6742
6743 if (sscanf (lbp->buffer, "#line %u \"%n", &lno, &start) >= 1 6743 if (sscanf (lbp->buffer, "#line %"SCNdMAX" \"%n", &lno, &start) >= 1
6744 && start > 0) /* double quote character found */ 6744 && start > 0) /* double quote character found */
6745 { 6745 {
6746 char *endp = lbp->buffer + start; 6746 char *endp = lbp->buffer + start;
@@ -6850,7 +6850,7 @@ readline (linebuffer *lbp, FILE *stream)
6850 } /* if #line directives should be considered */ 6850 } /* if #line directives should be considered */
6851 6851
6852 { 6852 {
6853 int match; 6853 ptrdiff_t match;
6854 regexp *rp; 6854 regexp *rp;
6855 char *name; 6855 char *name;
6856 6856
@@ -6900,7 +6900,7 @@ readline (linebuffer *lbp, FILE *stream)
6900 /* Force explicit tag name, if a name is there. */ 6900 /* Force explicit tag name, if a name is there. */
6901 pfnote (name, true, lbp->buffer, match, lineno, linecharno); 6901 pfnote (name, true, lbp->buffer, match, lineno, linecharno);
6902 if (debug) 6902 if (debug)
6903 fprintf (stderr, "%s on %s:%d: %s\n", 6903 fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n",
6904 name ? name : "(unnamed)", curfdp->taggedfname, 6904 name ? name : "(unnamed)", curfdp->taggedfname,
6905 lineno, lbp->buffer); 6905 lineno, lbp->buffer);
6906 } 6906 }
@@ -6925,11 +6925,11 @@ savestr (const char *cp)
6925} 6925}
6926 6926
6927/* 6927/*
6928 * Return a pointer to a space of size LEN+1 allocated with xnew where 6928 * Return a pointer to a space of size LEN+1 allocated with xnew
6929 * the string CP has been copied for at most the first LEN characters. 6929 * with a copy of CP (containing LEN bytes) followed by a NUL byte.
6930 */ 6930 */
6931static char * 6931static char *
6932savenstr (const char *cp, int len) 6932savenstr (const char *cp, ptrdiff_t len)
6933{ 6933{
6934 char *dp = xnew (len + 1, char); 6934 char *dp = xnew (len + 1, char);
6935 dp[len] = '\0'; 6935 dp[len] = '\0';
@@ -7013,13 +7013,9 @@ verror (char const *format, va_list ap)
7013static char * 7013static char *
7014concat (const char *s1, const char *s2, const char *s3) 7014concat (const char *s1, const char *s2, const char *s3)
7015{ 7015{
7016 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); 7016 ptrdiff_t len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
7017 char *result = xnew (len1 + len2 + len3 + 1, char); 7017 char *result = xnew (len1 + len2 + len3 + 1, char);
7018 7018 strcpy (stpcpy (stpcpy (result, s1), s2), s3);
7019 strcpy (result, s1);
7020 strcpy (result + len1, s2);
7021 strcpy (result + len1 + len2, s3);
7022
7023 return result; 7019 return result;
7024} 7020}
7025 7021
@@ -7029,16 +7025,16 @@ concat (const char *s1, const char *s2, const char *s3)
7029static char * 7025static char *
7030etags_getcwd (void) 7026etags_getcwd (void)
7031{ 7027{
7032 int bufsize = 200; 7028 ptrdiff_t bufsize = 200;
7033 char *path = xnew (bufsize, char); 7029 char *path = xnew (bufsize, char);
7034 7030
7035 while (getcwd (path, bufsize) == NULL) 7031 while (getcwd (path, bufsize) == NULL)
7036 { 7032 {
7037 if (errno != ERANGE) 7033 if (errno != ERANGE)
7038 pfatal ("getcwd"); 7034 pfatal ("getcwd");
7039 bufsize *= 2;
7040 free (path); 7035 free (path);
7041 path = xnew (bufsize, char); 7036 path = xnmalloc (bufsize, 2 * sizeof *path);
7037 bufsize *= 2;
7042 } 7038 }
7043 7039
7044 canonicalize_filename (path); 7040 canonicalize_filename (path);
@@ -7099,7 +7095,7 @@ static char *
7099relative_filename (char *file, char *dir) 7095relative_filename (char *file, char *dir)
7100{ 7096{
7101 char *fp, *dp, *afn, *res; 7097 char *fp, *dp, *afn, *res;
7102 int i; 7098 ptrdiff_t i;
7103 7099
7104 /* Find the common root of file and dir (with a trailing slash). */ 7100 /* Find the common root of file and dir (with a trailing slash). */
7105 afn = absolute_filename (file, cwd); 7101 afn = absolute_filename (file, cwd);
@@ -7282,32 +7278,54 @@ linebuffer_init (linebuffer *lbp)
7282 7278
7283/* Set the minimum size of a string contained in a linebuffer. */ 7279/* Set the minimum size of a string contained in a linebuffer. */
7284static void 7280static void
7285linebuffer_setlen (linebuffer *lbp, int toksize) 7281linebuffer_setlen (linebuffer *lbp, ptrdiff_t toksize)
7286{ 7282{
7287 while (lbp->size <= toksize) 7283 if (lbp->size <= toksize)
7288 { 7284 {
7289 lbp->size *= 2; 7285 ptrdiff_t multiplier = toksize / lbp->size + 1;
7290 xrnew (lbp->buffer, lbp->size, char); 7286 xrnew (lbp->buffer, lbp->size, multiplier);
7287 lbp->size *= multiplier;
7291 } 7288 }
7292 lbp->len = toksize; 7289 lbp->len = toksize;
7293} 7290}
7294 7291
7295/* Like malloc but get fatal error if memory is exhausted. */ 7292/* Memory allocators with a fatal error if memory is exhausted. */
7296static void * ATTRIBUTE_MALLOC 7293
7297xmalloc (size_t size) 7294static void
7295memory_full (void)
7296{
7297 fatal ("virtual memory exhausted");
7298}
7299
7300static void *
7301xmalloc (ptrdiff_t size)
7298{ 7302{
7303 if (SIZE_MAX < size)
7304 memory_full ();
7299 void *result = malloc (size); 7305 void *result = malloc (size);
7300 if (result == NULL) 7306 if (result == NULL)
7301 fatal ("virtual memory exhausted"); 7307 memory_full ();
7302 return result; 7308 return result;
7303} 7309}
7304 7310
7305static void * 7311static void *
7306xrealloc (void *ptr, size_t size) 7312xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size)
7307{ 7313{
7308 void *result = realloc (ptr, size); 7314 ptrdiff_t nbytes;
7309 if (result == NULL) 7315 if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes))
7310 fatal ("virtual memory exhausted"); 7316 memory_full ();
7317 return xmalloc (nbytes);
7318}
7319
7320static void *
7321xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size)
7322{
7323 ptrdiff_t nbytes;
7324 if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes)
7325 memory_full ();
7326 void *result = realloc (pa, nbytes);
7327 if (!result)
7328 memory_full ();
7311 return result; 7329 return result;
7312} 7330}
7313 7331