diff options
-rwxr-xr-x | admin/merge-gnulib | 2 | ||||
-rw-r--r-- | lib-src/etags.c | 404 | ||||
-rw-r--r-- | lib/gnulib.mk.in | 12 | ||||
-rw-r--r-- | lib/mempcpy.c | 28 | ||||
-rw-r--r-- | m4/gnulib-comp.m4 | 9 | ||||
-rw-r--r-- | m4/mempcpy.m4 | 26 |
6 files changed, 287 insertions, 194 deletions
diff --git a/admin/merge-gnulib b/admin/merge-gnulib index 50b0c762a8f..5192916abd0 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -37,7 +37,7 @@ GNULIB_MODULES=' filemode filevercmp flexmember fpieee fstatat fsusage fsync getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog ieee754-h ignore-value intprops largefile lstat - manywarnings memmem-simple memrchr minmax mkostemp mktime nstrftime + manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime pathmax pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat regex sig2str socklen stat-time std-gnu11 stdalign stddef stdio 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"; # define O_CLOEXEC O_NOINHERIT #endif /* WINDOWSNT */ +#include <inttypes.h> #include <limits.h> #include <unistd.h> #include <stdarg.h> @@ -123,6 +124,7 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4"; #include <errno.h> #include <fcntl.h> #include <binary-io.h> +#include <intprops.h> #include <unlocked-io.h> #include <c-ctype.h> #include <c-strcase.h> @@ -141,6 +143,14 @@ char pot_etags_version[] = "@(#) pot revision number is 17.38.1.4"; # define CTAGS false #endif +/* Copy to DEST from SRC (containing LEN bytes), and append a NUL byte. */ +static void +memcpyz (void *dest, void const *src, ptrdiff_t len) +{ + char *e = mempcpy (dest, src, len); + *e = '\0'; +} + static bool streq (char const *s, char const *t) { @@ -235,11 +245,11 @@ endtoken (unsigned char c) /* * xnew, xrnew -- allocate, reallocate storage * - * SYNOPSIS: Type *xnew (int n, Type); - * void xrnew (OldPointer, int n, Type); + * SYNOPSIS: Type *xnew (ptrdiff_t n, Type); + * void xrnew (OldPointer, ptrdiff_t n, int multiplier); */ -#define xnew(n, Type) ((Type *) xmalloc ((n) * sizeof (Type))) -#define xrnew(op, n, Type) ((op) = (Type *) xrealloc (op, (n) * sizeof (Type))) +#define xnew(n, Type) ((Type *) xnmalloc (n, sizeof (Type))) +#define xrnew(op, n, m) ((op) = xnrealloc (op, n, (m) * sizeof *(op))) typedef void Lang_function (FILE *); @@ -282,8 +292,8 @@ typedef struct node_st bool valid; /* write this tag on the tag file */ bool is_func; /* function tag: use regexp in CTAGS mode */ bool been_warned; /* warning already given for duplicated tag */ - int lno; /* line number tag is on */ - long cno; /* character number line starts on */ + intmax_t lno; /* line number tag is on */ + intmax_t cno; /* character number line starts on */ } node; /* @@ -295,8 +305,8 @@ typedef struct node_st */ typedef struct { - long size; - int len; + ptrdiff_t size; + ptrdiff_t len; char *buffer; } linebuffer; @@ -365,7 +375,7 @@ static void just_read_file (FILE *); static language *get_language_from_langname (const char *); static void readline (linebuffer *, FILE *); -static long readline_internal (linebuffer *, FILE *, char const *); +static ptrdiff_t readline_internal (linebuffer *, FILE *, char const *); static bool nocase_tail (const char *); static void get_tag (char *, char **); static void get_lispy_tag (char *); @@ -385,7 +395,7 @@ static void process_file (FILE *, char *, language *); static void find_entries (FILE *); static void free_tree (node *); static void free_fdesc (fdesc *); -static void pfnote (char *, bool, char *, int, int, long); +static void pfnote (char *, bool, char *, ptrdiff_t, intmax_t, intmax_t); static void invalidate_nodes (fdesc *, node **); static void put_entries (node *); @@ -393,7 +403,7 @@ static char *concat (const char *, const char *, const char *); static char *skip_spaces (char *); static char *skip_non_spaces (char *); static char *skip_name (char *); -static char *savenstr (const char *, int); +static char *savenstr (const char *, ptrdiff_t); static char *savestr (const char *); static char *etags_getcwd (void); static char *relative_filename (char *, char *); @@ -403,9 +413,11 @@ static bool filename_is_absolute (char *f); static void canonicalize_filename (char *); static char *etags_mktmp (void); static void linebuffer_init (linebuffer *); -static void linebuffer_setlen (linebuffer *, int); -static void *xmalloc (size_t); -static void *xrealloc (void *, size_t); +static void linebuffer_setlen (linebuffer *, ptrdiff_t); +static void *xmalloc (ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1)); +static void *xnmalloc (ptrdiff_t, ptrdiff_t) ATTRIBUTE_MALLOC_SIZE ((1,2)); +static void *xnrealloc (void *, ptrdiff_t, ptrdiff_t) + ATTRIBUTE_ALLOC_SIZE ((2,3)); static char searchar = '/'; /* use /.../ searches */ @@ -420,12 +432,12 @@ static ptrdiff_t whatlen_max; /* maximum length of any 'what' member */ static fdesc *fdhead; /* head of file description list */ static fdesc *curfdp; /* current file description */ static char *infilename; /* current input file name */ -static int lineno; /* line number of current line */ -static long charno; /* current character number */ -static long linecharno; /* charno of start of current line */ +static intmax_t lineno; /* line number of current line */ +static intmax_t charno; /* current character number */ +static intmax_t linecharno; /* charno of start of current line */ static char *dbp; /* pointer to start of current tag */ -static const int invalidcharno = -1; +static intmax_t const invalidcharno = -1; static node *nodehead; /* the head of the binary tree of tags */ static node *last_node; /* the last node created */ @@ -1070,7 +1082,7 @@ int main (int argc, char **argv) { int i; - unsigned int nincluded_files; + int nincluded_files; char **included_files; argument *argbuffer; int current_arg, file_count; @@ -1484,7 +1496,7 @@ get_language_from_interpreter (char *interpreter) * Return a language given the file name. */ static language * -get_language_from_filename (char *file, int case_sensitive) +get_language_from_filename (char *file, bool case_sensitive) { language *lang; const char **name, **ext, *suffix; @@ -1918,26 +1930,26 @@ find_entries (FILE *inf) */ static void make_tag (const char *name, /* tag name, or NULL if unnamed */ - int namelen, /* tag length */ + ptrdiff_t namelen, /* tag length */ bool is_func, /* tag is a function */ char *linestart, /* start of the line where tag is */ - int linelen, /* length of the line where tag is */ - int lno, /* line number */ - long int cno) /* character number */ + ptrdiff_t linelen, /* length of the line where tag is */ + intmax_t lno, /* line number */ + intmax_t cno) /* character number */ { bool named = (name != NULL && namelen > 0); char *nname = NULL; if (debug) - fprintf (stderr, "%s on %s:%d: %s\n", + fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n", named ? name : "(unnamed)", curfdp->taggedfname, lno, linestart); if (!CTAGS && named) /* maybe set named to false */ /* Let's try to make an implicit tag name, that is, create an unnamed tag such that etags.el can guess a name from it. */ { - int i; - register const char *cp = name; + ptrdiff_t i; + const char *cp = name; for (i = 0; i < namelen; i++) if (notinname (*cp++)) @@ -1963,8 +1975,8 @@ make_tag (const char *name, /* tag name, or NULL if unnamed */ /* Record a tag. */ static void -pfnote (char *name, bool is_func, char *linestart, int linelen, int lno, - long int cno) +pfnote (char *name, bool is_func, char *linestart, ptrdiff_t linelen, + intmax_t lno, intmax_t cno) /* tag name, or NULL if unnamed */ /* tag is a function */ /* start of the line where tag is */ @@ -2197,7 +2209,8 @@ add_node (node *np, node **cur_node_p) if (!no_warnings) { fprintf (stderr, - "Duplicate entry in file %s, line %d: %s\n", + ("Duplicate entry in file %s, " + "line %"PRIdMAX": %s\n"), np->fdp->infname, lineno, np->name); fprintf (stderr, "Second entry ignored\n"); } @@ -2293,12 +2306,12 @@ invalidate_nodes (fdesc *badfdp, node **npp) } -static int total_size_of_entries (node *); -static int number_len (long) ATTRIBUTE_CONST; +static ptrdiff_t total_size_of_entries (node *); +static int number_len (intmax_t) ATTRIBUTE_CONST; /* Length of a non-negative number's decimal representation. */ static int -number_len (long int num) +number_len (intmax_t num) { int len = 1; while ((num /= 10) > 0) @@ -2312,10 +2325,10 @@ number_len (long int num) * This count is irrelevant with etags.el since emacs 19.34 at least, * but is still supplied for backward compatibility. */ -static int -total_size_of_entries (register node *np) +static ptrdiff_t +total_size_of_entries (node *np) { - register int total = 0; + ptrdiff_t total = 0; for (; np != NULL; np = np->right) if (np->valid) @@ -2323,7 +2336,7 @@ total_size_of_entries (register node *np) total += strlen (np->regex) + 1; /* pat\177 */ if (np->name != NULL) total += strlen (np->name) + 1; /* name\001 */ - total += number_len ((long) np->lno) + 1; /* lno, */ + total += number_len (np->lno) + 1; /* lno, */ if (np->cno != invalidcharno) /* cno */ total += number_len (np->cno); total += 1; /* newline */ @@ -2347,7 +2360,7 @@ put_entry (node *np) if (fdp != np->fdp) { fdp = np->fdp; - fprintf (tagf, "\f\n%s,%d\n", + fprintf (tagf, "\f\n%s,%"PRIdPTR"\n", fdp->taggedfname, total_size_of_entries (np)); fdp->written = true; } @@ -2358,9 +2371,9 @@ put_entry (node *np) fputs (np->name, tagf); fputc ('\001', tagf); } - fprintf (tagf, "%d,", np->lno); + fprintf (tagf, "%"PRIdMAX",", np->lno); if (np->cno != invalidcharno) - fprintf (tagf, "%ld", np->cno); + fprintf (tagf, "%"PRIdMAX, np->cno); fputs ("\n", tagf); } else @@ -2372,10 +2385,10 @@ put_entry (node *np) if (cxref_style) { if (vgrind_style) - fprintf (stdout, "%s %s %d\n", + fprintf (stdout, "%s %s %"PRIdMAX"\n", np->name, np->fdp->taggedfname, (np->lno + 63) / 64); else - fprintf (stdout, "%-16s %3d %-16s %s\n", + fprintf (stdout, "%-16s %3"PRIdMAX" %-16s %s\n", np->name, np->lno, np->fdp->taggedfname, np->regex); } else @@ -2397,7 +2410,7 @@ put_entry (node *np) } else { /* anything else; text pattern inadequate */ - fprintf (tagf, "%d", np->lno); + fprintf (tagf, "%"PRIdMAX, np->lno); } putc ('\n', tagf); } @@ -2591,7 +2604,7 @@ hash (const char *str, int len) } static struct C_stab_entry * -in_word_set (register const char *str, register unsigned int len) +in_word_set (const char *str, ptrdiff_t len) { enum { @@ -2658,9 +2671,9 @@ in_word_set (register const char *str, register unsigned int len) /*%>*/ static enum sym_type -C_symtype (char *str, int len, int c_ext) +C_symtype (char *str, ptrdiff_t len, int c_ext) { - register struct C_stab_entry *se = in_word_set (str, len); + struct C_stab_entry *se = in_word_set (str, len); if (se == NULL || (se->c_ext && !(c_ext & se->c_ext))) return st_none; @@ -2770,8 +2783,8 @@ static enum static struct tok { char *line; /* string containing the token */ - int offset; /* where the token starts in LINE */ - int length; /* token length */ + ptrdiff_t offset; /* where the token starts in LINE */ + ptrdiff_t length; /* token length */ /* The previous members can be used to pass strings around for generic purposes. The following ones specifically refer to creating tags. In this @@ -2782,23 +2795,23 @@ static struct tok invalidated whenever a state machine is reset prematurely */ bool named; /* create a named tag */ - int lineno; /* source line number of tag */ - long linepos; /* source char number of tag */ + intmax_t lineno; /* source line number of tag */ + intmax_t linepos; /* source char number of tag */ } token; /* latest token read */ /* * Variables and functions for dealing with nested structures. * Idea by Mykola Dzyuba <mdzyuba@yahoo.com> (2001) */ -static void pushclass_above (int, char *, int); -static void popclass_above (int); +static void pushclass_above (ptrdiff_t, char *, ptrdiff_t); +static void popclass_above (ptrdiff_t); static void write_classname (linebuffer *, const char *qualifier); static struct { char **cname; /* nested class names */ - int *bracelev; /* nested class brace level */ - int nl; /* class nesting level (elements used) */ - int size; /* length of the array */ + ptrdiff_t *bracelev; /* nested class brace level */ + ptrdiff_t nl; /* class nesting level (elements used) */ + ptrdiff_t size; /* length of the array */ } cstack; /* stack for nested declaration tags */ /* Current struct nesting depth (namespace, class, struct, union, enum). */ #define nestlev (cstack.nl) @@ -2807,17 +2820,17 @@ static struct { && bracelev == cstack.bracelev[nestlev-1] + 1) static void -pushclass_above (int bracelev, char *str, int len) +pushclass_above (ptrdiff_t bracelev, char *str, ptrdiff_t len) { - int nl; + ptrdiff_t nl; popclass_above (bracelev); nl = cstack.nl; if (nl >= cstack.size) { - int size = cstack.size *= 2; - xrnew (cstack.cname, size, char *); - xrnew (cstack.bracelev, size, int); + xrnew (cstack.cname, cstack.size, 2); + xrnew (cstack.bracelev, cstack.size, 2); + cstack.size *= 2; } assert (nl == 0 || cstack.bracelev[nl-1] < bracelev); cstack.cname[nl] = (str == NULL) ? NULL : savenstr (str, len); @@ -2826,11 +2839,9 @@ pushclass_above (int bracelev, char *str, int len) } static void -popclass_above (int bracelev) +popclass_above (ptrdiff_t bracelev) { - int nl; - - for (nl = cstack.nl - 1; + for (ptrdiff_t nl = cstack.nl - 1; nl >= 0 && cstack.bracelev[nl] >= bracelev; nl--) { @@ -2842,8 +2853,7 @@ popclass_above (int bracelev) static void write_classname (linebuffer *cn, const char *qualifier) { - int i, len; - int qlen = strlen (qualifier); + ptrdiff_t len; if (cstack.nl == 0 || cstack.cname[0] == NULL) { @@ -2857,18 +2867,22 @@ write_classname (linebuffer *cn, const char *qualifier) linebuffer_setlen (cn, len); strcpy (cn->buffer, cstack.cname[0]); } - for (i = 1; i < cstack.nl; i++) + for (ptrdiff_t i = 1; i < cstack.nl; i++) { char *s = cstack.cname[i]; if (s == NULL) continue; - linebuffer_setlen (cn, len + qlen + strlen (s)); - len += sprintf (cn->buffer + len, "%s%s", qualifier, s); + int qlen = strlen (qualifier); + ptrdiff_t slen = strlen (s); + linebuffer_setlen (cn, len + qlen + slen); + memcpyz (stpcpy (cn->buffer + len, qualifier), s, slen); + len += qlen + slen; } } -static bool consider_token (char *, int, int, int *, int, int, bool *); +static bool consider_token (char *, ptrdiff_t, int, int *, + ptrdiff_t, ptrdiff_t, bool *); static void make_C_tag (bool); /* @@ -2889,8 +2903,8 @@ static void make_C_tag (bool); */ static bool -consider_token (char *str, int len, int c, int *c_extp, - int bracelev, int parlev, bool *is_func_or_var) +consider_token (char *str, ptrdiff_t len, int c, int *c_extp, + ptrdiff_t bracelev, ptrdiff_t parlev, bool *is_func_or_var) /* IN: token pointer */ /* IN: token length */ /* IN: first char after the token */ @@ -2903,7 +2917,7 @@ consider_token (char *str, int len, int c, int *c_extp, structtype is the type of the preceding struct-like keyword, and structbracelev is the brace level where it has been seen. */ static enum sym_type structtype; - static int structbracelev; + static ptrdiff_t structbracelev; static enum sym_type toktype; @@ -3098,8 +3112,7 @@ consider_token (char *str, int len, int c, int *c_extp, fvdef = fvnone; objdef = omethodtag; linebuffer_setlen (&token_name, len); - memcpy (token_name.buffer, str, len); - token_name.buffer[len] = '\0'; + memcpyz (token_name.buffer, str, len); return true; } return false; @@ -3113,11 +3126,10 @@ consider_token (char *str, int len, int c, int *c_extp, objdef = omethodtag; if (class_qualify) { - int oldlen = token_name.len; + ptrdiff_t oldlen = token_name.len; fvdef = fvnone; linebuffer_setlen (&token_name, oldlen + len); - memcpy (token_name.buffer + oldlen, str, len); - token_name.buffer[oldlen + len] = '\0'; + memcpyz (token_name.buffer + oldlen, str, len); } return true; } @@ -3228,7 +3240,7 @@ consider_token (char *str, int len, int c, int *c_extp, */ static struct { - long linepos; + intmax_t linepos; linebuffer lb; } lbs[2]; @@ -3302,19 +3314,19 @@ C_entries (int c_ext, FILE *inf) /* extension of C */ /* input file */ { - register char c; /* latest char read; '\0' for end of line */ - register char *lp; /* pointer one beyond the character `c' */ - int curndx, newndx; /* indices for current and new lb */ - register int tokoff; /* offset in line of start of current token */ - register int toklen; /* length of current token */ + char c; /* latest char read; '\0' for end of line */ + char *lp; /* pointer one beyond the character `c' */ + bool curndx, newndx; /* indices for current and new lb */ + ptrdiff_t tokoff; /* offset in line of start of current token */ + ptrdiff_t toklen; /* length of current token */ const char *qualifier; /* string used to qualify names */ int qlen; /* length of qualifier */ - int bracelev; /* current brace level */ - int bracketlev; /* current bracket level */ - int parlev; /* current parenthesis level */ - int attrparlev; /* __attribute__ parenthesis level */ - int templatelev; /* current template level */ - int typdefbracelev; /* bracelev where a typedef struct body begun */ + ptrdiff_t bracelev; /* current brace level */ + ptrdiff_t bracketlev; /* current bracket level */ + ptrdiff_t parlev; /* current parenthesis level */ + ptrdiff_t attrparlev; /* __attribute__ parenthesis level */ + ptrdiff_t templatelev; /* current template level */ + ptrdiff_t typdefbracelev; /* bracelev where a typedef struct body begun */ bool incomm, inquote, inchar, quotednl, midtoken; bool yacc_rules; /* in the rules part of a yacc file */ struct tok savetoken = {0}; /* token saved during preprocessor handling */ @@ -3327,7 +3339,7 @@ C_entries (int c_ext, FILE *inf) cstack.size = (DEBUG) ? 1 : 4; cstack.nl = 0; cstack.cname = xnew (cstack.size, char *); - cstack.bracelev = xnew (cstack.size, int); + cstack.bracelev = xnew (cstack.size, ptrdiff_t); } tokoff = toklen = typdefbracelev = 0; /* keep compiler quiet */ @@ -3579,20 +3591,19 @@ C_entries (int c_ext, FILE *inf) { if (class_qualify) { - int len; write_classname (&token_name, qualifier); - len = token_name.len; + ptrdiff_t len = token_name.len; linebuffer_setlen (&token_name, len + qlen + toklen); - sprintf (token_name.buffer + len, "%s%.*s", - qualifier, toklen, - newlb.buffer + tokoff); + memcpyz (stpcpy (token_name.buffer + len, + qualifier), + newlb.buffer + tokoff, toklen); } else { linebuffer_setlen (&token_name, toklen); - sprintf (token_name.buffer, "%.*s", - toklen, newlb.buffer + tokoff); + memcpyz (token_name.buffer, + newlb.buffer + tokoff, toklen); } token.named = true; } @@ -3601,17 +3612,19 @@ C_entries (int c_ext, FILE *inf) { if (class_qualify) { - int len = strlen (objtag) + 2 + toklen; + ptrdiff_t len = strlen (objtag) + 2 + toklen; linebuffer_setlen (&token_name, len); - sprintf (token_name.buffer, "%s(%.*s)", - objtag, toklen, - newlb.buffer + tokoff); + char *p1 = stpcpy (token_name.buffer, objtag); + char *p2 = stpcpy (p1, "("); + char *p3 = mempcpy (p2, newlb.buffer + tokoff, + toklen); + strcpy (p3, ")"); } else { linebuffer_setlen (&token_name, toklen); - sprintf (token_name.buffer, "%.*s", - toklen, newlb.buffer + tokoff); + memcpyz (token_name.buffer, + newlb.buffer + tokoff, toklen); } token.named = true; } @@ -3625,8 +3638,8 @@ C_entries (int c_ext, FILE *inf) /* GNU DEFUN and similar macros */ { bool defun = (newlb.buffer[tokoff] == 'F'); - int off = tokoff; - int len = toklen; + ptrdiff_t off = tokoff; + ptrdiff_t len = toklen; if (defun) { @@ -3635,9 +3648,8 @@ C_entries (int c_ext, FILE *inf) /* First, tag it as its C name */ linebuffer_setlen (&token_name, toklen); - memcpy (token_name.buffer, - newlb.buffer + tokoff, toklen); - token_name.buffer[toklen] = '\0'; + memcpyz (token_name.buffer, + newlb.buffer + tokoff, toklen); token.named = true; token.lineno = lineno; token.offset = tokoff; @@ -3650,9 +3662,8 @@ C_entries (int c_ext, FILE *inf) /* Rewrite the tag so that emacs lisp DEFUNs can be found also by their elisp name */ linebuffer_setlen (&token_name, len); - memcpy (token_name.buffer, - newlb.buffer + off, len); - token_name.buffer[len] = '\0'; + memcpyz (token_name.buffer, + newlb.buffer + off, len); if (defun) while (--len >= 0) if (token_name.buffer[len] == '_') @@ -3662,9 +3673,8 @@ C_entries (int c_ext, FILE *inf) else { linebuffer_setlen (&token_name, toklen); - memcpy (token_name.buffer, - newlb.buffer + tokoff, toklen); - token_name.buffer[toklen] = '\0'; + memcpyz (token_name.buffer, + newlb.buffer + tokoff, toklen); /* Name macros and members. */ token.named = (structdef == stagseen || typdef == ttypeseen @@ -3790,7 +3800,7 @@ C_entries (int c_ext, FILE *inf) objdef = omethodcolon; if (class_qualify) { - int toklen = token_name.len; + ptrdiff_t toklen = token_name.len; linebuffer_setlen (&token_name, toklen + 1); strcpy (token_name.buffer + toklen, ":"); } @@ -4061,7 +4071,7 @@ C_entries (int c_ext, FILE *inf) } if (uqname > token_name.buffer) { - int uqlen = strlen (uqname); + ptrdiff_t uqlen = strlen (uqname); linebuffer_setlen (&token_name, uqlen); memmove (token_name.buffer, uqname, uqlen + 1); } @@ -4979,12 +4989,11 @@ Ruby_functions (FILE *inf) size_t name_len = cp - np + 1; char *wr_name = xnew (name_len + 1, char); - memcpy (wr_name, np, name_len - 1); - memcpy (wr_name + name_len - 1, "=", 2); + strcpy (mempcpy (wr_name, np, name_len - 1), "="); pfnote (wr_name, true, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); if (debug) - fprintf (stderr, "%s on %s:%d: %s\n", wr_name, + fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n", wr_name, curfdp->taggedfname, lineno, lb.buffer); continuation = false; } @@ -5178,8 +5187,8 @@ static void Pascal_functions (FILE *inf) { linebuffer tline; /* mostly copied from C_entries */ - long save_lcno; - int save_lineno, namelen, taglen; + intmax_t save_lcno, save_lineno; + ptrdiff_t namelen, taglen; char c, *name; bool /* each of these flags is true if: */ @@ -5455,7 +5464,7 @@ Lua_functions (FILE *inf) if (tp_dot || tp_colon) { char *p = tp_dot > tp_colon ? tp_dot : tp_colon; - int len_add = p - tag_name + 1; + ptrdiff_t len_add = p - tag_name + 1; get_tag (bp + len_add, NULL); } @@ -5656,7 +5665,7 @@ TeX_commands (FILE *inf) if (strneq (cp, key->buffer, key->len)) { char *p; - int namelen, linelen; + ptrdiff_t namelen, linelen; bool opgrp = false; cp = skip_spaces (cp + key->len); @@ -5693,8 +5702,8 @@ TeX_commands (FILE *inf) static void TEX_decode_env (const char *evarname, const char *defenv) { - register const char *env, *p; - int i, len; + const char *env, *p; + ptrdiff_t len; /* Append default string to environment. */ env = getenv (evarname); @@ -5711,7 +5720,7 @@ TEX_decode_env (const char *evarname, const char *defenv) /* Unpack environment string into token table. Be careful about */ /* zero-length strings (leading ':', "::" and trailing ':') */ - for (i = 0; *env != '\0';) + for (ptrdiff_t i = 0; *env != '\0'; ) { p = strchr (env, ':'); if (!p) /* End of environment string. */ @@ -5811,8 +5820,7 @@ HTML_labels (FILE *inf) for (end = dbp; *end != '\0' && intoken (*end); end++) continue; linebuffer_setlen (&token_name, end - dbp); - memcpy (token_name.buffer, dbp, end - dbp); - token_name.buffer[end - dbp] = '\0'; + memcpyz (token_name.buffer, dbp, end - dbp); dbp = end; intag = false; /* we found what we looked for */ @@ -5906,11 +5914,10 @@ Prolog_functions (FILE *inf) tags later. */ if (allocated <= len) { - xrnew (last, len + 1, char); + xrnew (last, len + 1, 1); allocated = len + 1; } - memcpy (last, cp, len); - last[len] = '\0'; + memcpyz (last, cp, len); lastlen = len; } } @@ -6031,9 +6038,9 @@ prolog_atom (char *s, size_t pos) * Assumes that Erlang functions start at column 0. * Original code by Anders Lindgren (1996) */ -static int erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *); +static ptrdiff_t erlang_func (char *, char *, ptrdiff_t, ptrdiff_t *); static void erlang_attribute (char *); -static int erlang_atom (char *); +static ptrdiff_t erlang_atom (char *); static void Erlang_functions (FILE *inf) @@ -6070,11 +6077,10 @@ Erlang_functions (FILE *inf) tags later. */ if (allocated <= len) { - xrnew (last, len + 1, char); + xrnew (last, len + 1, 1); allocated = len + 1; } - memcpy (last, cp + name_offset, len); - last[len] = '\0'; + memcpyz (last, cp + name_offset, len); lastlen = len; } } @@ -6093,7 +6099,7 @@ Erlang_functions (FILE *inf) * Return the size of the name of the function, or 0 if no function * was found. */ -static int +static ptrdiff_t erlang_func (char *s, char *last, ptrdiff_t lastlen, ptrdiff_t *name_offset) { char *name = s; @@ -6133,15 +6139,13 @@ static void erlang_attribute (char *s) { char *cp = s; - int pos; - int len; if ((LOOKING_AT (cp, "-define") || LOOKING_AT (cp, "-record")) && *cp++ == '(') { cp = skip_spaces (cp); - len = erlang_atom (cp); - pos = cp + len - s; + ptrdiff_t len = erlang_atom (cp); + ptrdiff_t pos = cp + len - s; if (len > 0) { /* If the name is quoted, the quotes are not part of the name. */ @@ -6161,10 +6165,10 @@ erlang_attribute (char *s) * Consume an Erlang atom (or variable). * Return the number of bytes consumed, or -1 if there was an error. */ -static int +static ptrdiff_t erlang_atom (char *s) { - int pos = 0; + ptrdiff_t pos = 0; if (c_isalpha (s[pos]) || s[pos] == '_') { @@ -6437,10 +6441,9 @@ static char * substitute (char *in, char *out, struct re_registers *regs) { char *result, *t; - int size, dig, diglen; result = NULL; - size = strlen (out); + ptrdiff_t size = strlen (out); /* Pass 1: figure out how much to allocate by finding all \N strings. */ if (out[size - 1] == '\\') @@ -6450,8 +6453,8 @@ substitute (char *in, char *out, struct re_registers *regs) t = strchr (t + 2, '\\')) if (c_isdigit (t[1])) { - dig = t[1] - '0'; - diglen = regs->end[dig] - regs->start[dig]; + int dig = t[1] - '0'; + ptrdiff_t diglen = regs->end[dig] - regs->start[dig]; size += diglen - 2; } else @@ -6464,8 +6467,8 @@ substitute (char *in, char *out, struct re_registers *regs) for (t = result; *out != '\0'; out++) if (*out == '\\' && c_isdigit (*++out)) { - dig = *out - '0'; - diglen = regs->end[dig] - regs->start[dig]; + int dig = *out - '0'; + ptrdiff_t diglen = regs->end[dig] - regs->start[dig]; memcpy (t, in + regs->start[dig], diglen); t += diglen; } @@ -6474,7 +6477,7 @@ substitute (char *in, char *out, struct re_registers *regs) *t = '\0'; assert (t <= result + size); - assert (t - result == (int)strlen (result)); + assert (t == result + strlen (result)); return result; } @@ -6511,7 +6514,7 @@ regex_tag_multiline (void) for (rp = p_head; rp != NULL; rp = rp->p_next) { - int match = 0; + ptrdiff_t match = 0; if (!rp->multi_line) continue; /* skip normal regexps */ @@ -6572,7 +6575,7 @@ regex_tag_multiline (void) charno - linecharno + 1, lineno, linecharno); if (debug) - fprintf (stderr, "%s on %s:%d: %s\n", + fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n", name ? name : "(unnamed)", curfdp->taggedfname, lineno, buffer + linecharno); } @@ -6589,7 +6592,7 @@ regex_tag_multiline (void) static bool nocase_tail (const char *cp) { - int len = 0; + ptrdiff_t len = 0; while (*cp != '\0' && c_tolower (*cp) == c_tolower (dbp[len])) cp++, len++; @@ -6648,7 +6651,7 @@ get_lispy_tag (register char *bp) * If multi-line regular expressions are requested, each line read is * appended to `filebuf'. */ -static long +static ptrdiff_t readline_internal (linebuffer *lbp, FILE *stream, char const *filename) { char *buffer = lbp->buffer; @@ -6664,8 +6667,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename) if (p == pend) { /* We're at the end of linebuffer: expand it. */ + xrnew (buffer, lbp->size, 2); lbp->size *= 2; - xrnew (buffer, lbp->size, char); p += buffer - lbp->buffer; pend = buffer + lbp->size; lbp->buffer = buffer; @@ -6702,13 +6705,12 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename) while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */ { /* Expand filebuf. */ + xrnew (filebuf.buffer, filebuf.size, 2); filebuf.size *= 2; - xrnew (filebuf.buffer, filebuf.size, char); } - memcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len); - filebuf.len += lbp->len; - filebuf.buffer[filebuf.len++] = '\n'; - filebuf.buffer[filebuf.len] = '\0'; + strcpy (mempcpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len), + "\n"); + filebuf.len += lbp->len + 1; } return lbp->len + chars_deleted; @@ -6722,10 +6724,8 @@ readline_internal (linebuffer *lbp, FILE *stream, char const *filename) static void readline (linebuffer *lbp, FILE *stream) { - long result; - linecharno = charno; /* update global char number of line start */ - result = readline_internal (lbp, stream, infilename); /* read line */ + ptrdiff_t result = readline_internal (lbp, stream, infilename); lineno += 1; /* increment global line number */ charno += result; /* increment global char number */ @@ -6737,10 +6737,10 @@ readline (linebuffer *lbp, FILE *stream) /* Check whether this is a #line directive. */ if (result > 12 && strneq (lbp->buffer, "#line ", 6)) { - unsigned int lno; + intmax_t lno; int start = 0; - if (sscanf (lbp->buffer, "#line %u \"%n", &lno, &start) >= 1 + if (sscanf (lbp->buffer, "#line %"SCNdMAX" \"%n", &lno, &start) >= 1 && start > 0) /* double quote character found */ { char *endp = lbp->buffer + start; @@ -6850,7 +6850,7 @@ readline (linebuffer *lbp, FILE *stream) } /* if #line directives should be considered */ { - int match; + ptrdiff_t match; regexp *rp; char *name; @@ -6900,7 +6900,7 @@ readline (linebuffer *lbp, FILE *stream) /* Force explicit tag name, if a name is there. */ pfnote (name, true, lbp->buffer, match, lineno, linecharno); if (debug) - fprintf (stderr, "%s on %s:%d: %s\n", + fprintf (stderr, "%s on %s:%"PRIdMAX": %s\n", name ? name : "(unnamed)", curfdp->taggedfname, lineno, lbp->buffer); } @@ -6925,11 +6925,11 @@ savestr (const char *cp) } /* - * Return a pointer to a space of size LEN+1 allocated with xnew where - * the string CP has been copied for at most the first LEN characters. + * Return a pointer to a space of size LEN+1 allocated with xnew + * with a copy of CP (containing LEN bytes) followed by a NUL byte. */ static char * -savenstr (const char *cp, int len) +savenstr (const char *cp, ptrdiff_t len) { char *dp = xnew (len + 1, char); dp[len] = '\0'; @@ -7013,13 +7013,9 @@ verror (char const *format, va_list ap) static char * concat (const char *s1, const char *s2, const char *s3) { - int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); + ptrdiff_t len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); char *result = xnew (len1 + len2 + len3 + 1, char); - - strcpy (result, s1); - strcpy (result + len1, s2); - strcpy (result + len1 + len2, s3); - + strcpy (stpcpy (stpcpy (result, s1), s2), s3); return result; } @@ -7029,16 +7025,16 @@ concat (const char *s1, const char *s2, const char *s3) static char * etags_getcwd (void) { - int bufsize = 200; + ptrdiff_t bufsize = 200; char *path = xnew (bufsize, char); while (getcwd (path, bufsize) == NULL) { if (errno != ERANGE) pfatal ("getcwd"); - bufsize *= 2; free (path); - path = xnew (bufsize, char); + path = xnmalloc (bufsize, 2 * sizeof *path); + bufsize *= 2; } canonicalize_filename (path); @@ -7099,7 +7095,7 @@ static char * relative_filename (char *file, char *dir) { char *fp, *dp, *afn, *res; - int i; + ptrdiff_t i; /* Find the common root of file and dir (with a trailing slash). */ afn = absolute_filename (file, cwd); @@ -7282,32 +7278,54 @@ linebuffer_init (linebuffer *lbp) /* Set the minimum size of a string contained in a linebuffer. */ static void -linebuffer_setlen (linebuffer *lbp, int toksize) +linebuffer_setlen (linebuffer *lbp, ptrdiff_t toksize) { - while (lbp->size <= toksize) + if (lbp->size <= toksize) { - lbp->size *= 2; - xrnew (lbp->buffer, lbp->size, char); + ptrdiff_t multiplier = toksize / lbp->size + 1; + xrnew (lbp->buffer, lbp->size, multiplier); + lbp->size *= multiplier; } lbp->len = toksize; } -/* Like malloc but get fatal error if memory is exhausted. */ -static void * ATTRIBUTE_MALLOC -xmalloc (size_t size) +/* Memory allocators with a fatal error if memory is exhausted. */ + +static void +memory_full (void) +{ + fatal ("virtual memory exhausted"); +} + +static void * +xmalloc (ptrdiff_t size) { + if (SIZE_MAX < size) + memory_full (); void *result = malloc (size); if (result == NULL) - fatal ("virtual memory exhausted"); + memory_full (); return result; } static void * -xrealloc (void *ptr, size_t size) +xnmalloc (ptrdiff_t nitems, ptrdiff_t item_size) { - void *result = realloc (ptr, size); - if (result == NULL) - fatal ("virtual memory exhausted"); + ptrdiff_t nbytes; + if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes)) + memory_full (); + return xmalloc (nbytes); +} + +static void * +xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) +{ + ptrdiff_t nbytes; + if (INT_MULTIPLY_WRAPV (nitems, item_size, &nbytes) || SIZE_MAX < nbytes) + memory_full (); + void *result = realloc (pa, nbytes); + if (!result) + memory_full (); return result; } diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 9a2709c22a7..8e3b569b94f 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -116,6 +116,7 @@ # lstat \ # manywarnings \ # memmem-simple \ +# mempcpy \ # memrchr \ # minmax \ # mkostemp \ @@ -2027,6 +2028,17 @@ EXTRA_libgnu_a_SOURCES += memmem.c endif ## end gnulib module memmem-simple +## begin gnulib module mempcpy +ifeq (,$(OMIT_GNULIB_MODULE_mempcpy)) + + +EXTRA_DIST += mempcpy.c + +EXTRA_libgnu_a_SOURCES += mempcpy.c + +endif +## end gnulib module mempcpy + ## begin gnulib module memrchr ifeq (,$(OMIT_GNULIB_MODULE_memrchr)) diff --git a/lib/mempcpy.c b/lib/mempcpy.c new file mode 100644 index 00000000000..d0220e10fb0 --- /dev/null +++ b/lib/mempcpy.c @@ -0,0 +1,28 @@ +/* Copy memory area and return pointer after last written byte. + Copyright (C) 2003, 2007, 2009-2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +void * +mempcpy (void *dest, const void *src, size_t n) +{ + return (char *) memcpy (dest, src, n) + n; +} diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 625c2211665..baf9511aca7 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -118,6 +118,7 @@ AC_DEFUN([gl_EARLY], # Code from module malloca: # Code from module manywarnings: # Code from module memmem-simple: + # Code from module mempcpy: # Code from module memrchr: # Code from module minmax: # Code from module mkostemp: @@ -327,6 +328,12 @@ AC_DEFUN([gl_INIT], AC_LIBOBJ([memmem]) fi gl_STRING_MODULE_INDICATOR([memmem]) + gl_FUNC_MEMPCPY + if test $HAVE_MEMPCPY = 0; then + AC_LIBOBJ([mempcpy]) + gl_PREREQ_MEMPCPY + fi + gl_STRING_MODULE_INDICATOR([mempcpy]) gl_FUNC_MEMRCHR if test $ac_cv_func_memrchr = no; then AC_LIBOBJ([memrchr]) @@ -954,6 +961,7 @@ AC_DEFUN([gl_FILE_LIST], [ lib/md5.c lib/md5.h lib/memmem.c + lib/mempcpy.c lib/memrchr.c lib/minmax.h lib/mkostemp.c @@ -1094,6 +1102,7 @@ AC_DEFUN([gl_FILE_LIST], [ m4/mbstate_t.m4 m4/md5.m4 m4/memmem.m4 + m4/mempcpy.m4 m4/memrchr.m4 m4/minmax.m4 m4/mkostemp.m4 diff --git a/m4/mempcpy.m4 b/m4/mempcpy.m4 new file mode 100644 index 00000000000..b6090eed285 --- /dev/null +++ b/m4/mempcpy.m4 @@ -0,0 +1,26 @@ +# mempcpy.m4 serial 11 +dnl Copyright (C) 2003-2004, 2006-2007, 2009-2019 Free Software Foundation, +dnl Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_MEMPCPY], +[ + dnl Persuade glibc <string.h> to declare mempcpy(). + AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) + + dnl The mempcpy() declaration in lib/string.in.h uses 'restrict'. + AC_REQUIRE([AC_C_RESTRICT]) + + AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) + AC_CHECK_FUNCS([mempcpy]) + if test $ac_cv_func_mempcpy = no; then + HAVE_MEMPCPY=0 + fi +]) + +# Prerequisites of lib/mempcpy.c. +AC_DEFUN([gl_PREREQ_MEMPCPY], [ + : +]) |