#define bool int
+#define xstrncpy(d_,s_,l_) \
+ do { \
+ char* dst_=d_; \
+ dst_[0]='\0'; \
+ strncat((dst_),(s_),(l_)-1); \
+ } while(0)
+
typedef void Lang_function __P((FILE *));
typedef struct
static char *skip_non_spaces __P((char *));
static char *savenstr __P((char *, int));
static char *savestr __P((char *));
-static char *etags_strchr __P((const char *, int));
-static char *etags_strrchr __P((const char *, int));
-static int etags_strcasecmp __P((const char *, const char *));
-static int etags_strncasecmp __P((const char *, const char *, int));
static char *etags_getcwd __P((void));
static char *relative_filename __P((char *, char *));
static char *absolute_filename __P((char *, char *));
static PTR xmalloc __P((unsigned int));
static PTR xrealloc __P((char *, unsigned int));
+
+\f
+#if HAVE_STRRCHR
+#define etags_strrchr strrchr
+#else
+/*
+ * Return the ptr in sp at which the character c last
+ * appears; NULL if not found
+ *
+ * Identical to POSIX strrchr, included for portability.
+ */
+static char *
+etags_strrchr (sp, c)
+register const char *sp;
+register int c;
+{
+ register const char *r;
+
+ r = NULL;
+ do
+ {
+ if (*sp == c)
+ r = sp;
+ } while (*sp++);
+ return (char *)r;
+}
+#endif
+
+#if HAVE_STRCHR
+#define etags_strchr strchr
+#else
+/*
+ * Return the ptr in sp at which the character c first
+ * appears; NULL if not found
+ *
+ * Identical to POSIX strchr, included for portability.
+ */
+static char *
+etags_strchr (sp, c)
+register const char *sp;
+register int c;
+{
+ do
+ {
+ if (*sp == c)
+ return (char *)sp;
+ } while (*sp++);
+ return NULL;
+}
+#endif
+
+#if HAVE_STRCASECMP
+#define etags_strcasecmp strcasecmp
+#else
+/*
+ * Compare two strings, ignoring case for alphabetic characters.
+ *
+ * Same as BSD's strcasecmp, included for portability.
+ */
+static int
+etags_strcasecmp (s1, s2)
+register const char *s1;
+register const char *s2;
+{
+ while (*s1 != '\0'
+ && (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) == lowcase (*s2)
+ : *s1 == *s2))
+ s1++, s2++;
+
+ return (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) - lowcase (*s2)
+ : *s1 - *s2);
+}
+#endif
+
+#if HAVE_STRCASECMP
+#define etags_strncasecmp strncasecmp
+#else
+/*
+ * Compare two strings, ignoring case for alphabetic characters.
+ * Stop after a given number of characters
+ *
+ * Same as BSD's strncasecmp, included for portability.
+ */
+static int
+etags_strncasecmp (s1, s2, n)
+register const char *s1;
+register const char *s2;
+register int n;
+{
+ while (*s1 != '\0' && n-- > 0
+ && (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) == lowcase (*s2)
+ : *s1 == *s2))
+ s1++, s2++;
+
+ if (n < 0)
+ return 0;
+ else
+ return (ISALPHA (*s1) && ISALPHA (*s2)
+ ? lowcase (*s1) - lowcase (*s2)
+ : *s1 - *s2);
+}
+#endif
+
\f
static char searchar = '/'; /* use /.../ searches */
Relative ones are stored relative to the output file's directory.\n");
puts ("-a, --append\n\
- Append tag entries to existing tags file.");
+ Append tag entries to existing tags file.");
puts ("--packages-only\n\
- For Ada files, only generate tags for packages.");
+ For Ada files, only generate tags for packages.");
if (CTAGS)
puts ("-B, --backward-search\n\
- Write the search commands for the tag entries using '?', the\n\
- backward-search command instead of '/', the forward-search command.");
+ Write the search commands for the tag entries using '?', the\n\
+ backward-search command instead of '/', the forward-search command.");
/* This option is mostly obsolete, because etags can now automatically
detect C++. Retained for backward compatibility and for debugging and
if (CTAGS)
puts ("-d, --defines\n\
- Create tag entries for C #define constants and enum constants, too.");
+ Create tag entries for C #define constants and enum constants, too.");
else
puts ("-D, --no-defines\n\
- Don't create tag entries for C #define constants and enum constants.\n\
+ Don't create tag entries for C #define constants and enum constants.\n\
This makes the tags file smaller.");
if (!CTAGS)
puts ("-i FILE, --include=FILE\n\
- Include a note in tag file indicating that, when searching for\n\
- a tag, one should also consult the tags file FILE after\n\
- checking the current file.");
+ Include a note in tag file indicating that, when searching for\n\
+ a tag, one should also consult the tags file FILE after\n\
+ checking the current file.");
puts ("-l LANG, --language=LANG\n\
- Force the following files to be considered as written in the\n\
+ Force the following files to be considered as written in the\n\
named language up to the next --language=LANG option.");
if (CTAGS)
if (PRINT_UNDOCUMENTED_OPTIONS_HELP)
puts ("--no-line-directive\n\
- Ignore #line preprocessor directives in C and derived languages.");
+ Ignore #line preprocessor directives in C and derived languages.");
if (CTAGS)
puts ("--members\n\
in some languages.");
puts ("-r REGEXP, --regex=REGEXP or --regex=@regexfile\n\
- Make a tag for each line matching a regular expression pattern\n\
+ Make a tag for each line matching a regular expression pattern\n\
in the following files. {LANGUAGE}REGEXP uses REGEXP for LANGUAGE\n\
files only. REGEXFILE is a file containing one REGEXP per line.\n\
REGEXP takes the form /TAGREGEXP/TAGNAME/MODS, where TAGNAME/ is\n\
causes dot to match any character, including newline.");
puts ("-R, --no-regex\n\
- Don't create tags from regexps for the following files.");
+ Don't create tags from regexps for the following files.");
puts ("-I, --ignore-indentation\n\
- In C and C++ do not assume that a closing brace in the first\n\
- column is the final brace of a function or structure definition.");
+ In C and C++ do not assume that a closing brace in the first\n\
+ column is the final brace of a function or structure definition.");
puts ("-o FILE, --output=FILE\n\
- Write the tags to FILE.");
+ Write the tags to FILE.");
puts ("--parse-stdin=NAME\n\
- Read from standard input and record tags as belonging to file NAME.");
+ Read from standard input and record tags as belonging to file NAME.");
if (CTAGS)
{
puts ("-t, --typedefs\n\
- Generate tag entries for C and Ada typedefs.");
+ Generate tag entries for C and Ada typedefs.");
puts ("-T, --typedefs-and-c++\n\
- Generate tag entries for C typedefs, C struct/enum/union tags,\n\
- and C++ member functions.");
+ Generate tag entries for C typedefs, C struct/enum/union tags,\n\
+ and C++ member functions.");
}
if (CTAGS)
puts ("-u, --update\n\
- Update the tag entries for the given files, leaving tag\n\
- entries for other files in place. Currently, this is\n\
- implemented by deleting the existing entries for the given\n\
- files and then rewriting the new entries at the end of the\n\
- tags file. It is often faster to simply rebuild the entire\n\
- tag file than to use this.");
+ Update the tag entries for the given files, leaving tag\n\
+ entries for other files in place. Currently, this is\n\
+ implemented by deleting the existing entries for the given\n\
+ files and then rewriting the new entries at the end of the\n\
+ tags file. It is often faster to simply rebuild the entire\n\
+ tag file than to use this.");
if (CTAGS)
{
puts ("-v, --vgrind\n\
- Print on the standard output an index of items intended for\n\
- human consumption, similar to the output of vgrind. The index\n\
- is sorted, and gives the page number of each item.");
+ Print on the standard output an index of items intended for\n\
+ human consumption, similar to the output of vgrind. The index\n\
+ is sorted, and gives the page number of each item.");
if (PRINT_UNDOCUMENTED_OPTIONS_HELP)
puts ("-w, --no-duplicates\n\
- Do not create duplicate tag entries, for compatibility with\n\
+ Do not create duplicate tag entries, for compatibility with\n\
traditional ctags.");
if (PRINT_UNDOCUMENTED_OPTIONS_HELP)
puts ("-w, --no-warn\n\
- Suppress warning messages about duplicate tag entries.");
+ Suppress warning messages about duplicate tag entries.");
puts ("-x, --cxref\n\
- Like --vgrind, but in the style of cxref, rather than vgrind.\n\
- The output uses line numbers instead of page numbers, but\n\
- beyond that the differences are cosmetic; try both to see\n\
- which you like.");
+ Like --vgrind, but in the style of cxref, rather than vgrind.\n\
+ The output uses line numbers instead of page numbers, but\n\
+ beyond that the differences are cosmetic; try both to see\n\
+ which you like.");
}
puts ("-V, --version\n\
- Print the version of the program.\n\
+ Print the version of the program.\n\
-h, --help\n\
- Print this help message.\n\
- Followed by one or more `--language' options prints detailed\n\
- help about tag generation for the specified languages.");
+ Print this help message.\n\
+ Followed by one or more `--language' options prints detailed\n\
+ help about tag generation for the specified languages.");
print_language_names ();
if (update)
{
char cmd[BUFSIZ];
+ int len;
+
for (i = 0; i < current_arg; ++i)
{
switch (argbuffer[i].arg_type)
case at_filename:
case at_stdin:
break;
+ case at_language:
+ case at_regexp:
+ case at_end:
default:
continue; /* the for loop */
}
- sprintf (cmd,
- "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
- tagfile, argbuffer[i].what, tagfile);
+ len = snprintf (cmd, sizeof(cmd),
+ "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
+ tagfile, argbuffer[i].what, tagfile);
+ if (len >= 0 && (size_t)len < sizeof(cmd))
+ fatal ("failed to build shell command line", (char *)NULL);
if (system (cmd) != EXIT_SUCCESS)
fatal ("failed to execute shell command", (char *)NULL);
}
/* Maybe these should be used:
setenv ("LC_COLLATE", "C", 1);
setenv ("LC_ALL", "C", 1); */
- sprintf (cmd, "sort -u -o %.*s %.*s", BUFSIZ, tagfile, BUFSIZ, tagfile);
+ int len = snprintf (cmd, sizeof(cmd),
+ "sort -u -o %.*s %.*s",
+ BUFSIZ, tagfile,
+ BUFSIZ, tagfile);
+ if (len >= 0 && (size_t)len < sizeof(cmd))
+ fatal("failed to build sort shell command line",
+ (char *)NULL);
exit (system (cmd));
}
return EXIT_SUCCESS;
return NULL;
suffix += 1;
for (lang = lang_names; lang->name != NULL; lang++)
- if (lang->suffixes != NULL)
+ if (lang->suffixes != NULL) {
for (ext = lang->suffixes; *ext != NULL; ext++)
- if ((case_sensitive)
- ? streq (*ext, suffix)
- : strcaseeq (*ext, suffix))
+ if (case_sensitive) {
+ if (streq (*ext, suffix))
+ return lang;
+ } else if (strcaseeq (*ext, suffix))
return lang;
+ }
return NULL;
}
language *lang;
{
struct stat stat_buf;
- FILE *inf;
- fdesc *fdp;
- compressor *compr;
- char *compressed_name, *uncompressed_name;
- char *ext, *real_name;
+ FILE *inf = NULL;
+ fdesc *fdp = NULL;
+ compressor *compr = NULL;
+ char *compressed_name = NULL,
+ *uncompressed_name = NULL;
+ char *ext = NULL,
+ *real_name = NULL;
int retval;
canonicalize_filename (file);
error ("skipping inclusion of %s in self.", file);
return;
}
- if ((compr = get_compressor_from_suffix (file, &ext)) == NULL)
+ if ( get_compressor_from_suffix (file, &ext) == NULL)
{
- compressed_name = NULL;
real_name = uncompressed_name = savestr (file);
}
else
goto cleanup;
}
- if (stat (real_name, &stat_buf) != 0)
- {
- /* Reset real_name and try with a different name. */
- real_name = NULL;
- if (compressed_name != NULL) /* try with the given suffix */
+ compr = compressors;
+ do {
+ /* First try to open ... */
+ if (real_name == compressed_name)
{
- if (stat (uncompressed_name, &stat_buf) == 0)
- real_name = uncompressed_name;
+ char *cmd = concat (compr->command, " ", real_name);
+ inf = (FILE *) popen (cmd, "r");
+ free (cmd);
}
- else /* try all possible suffixes */
- {
- for (compr = compressors; compr->suffix != NULL; compr++)
+ else
+ inf = fopen (real_name, "r");
+ if ( inf != NULL ) {
+ /* Open was successfull, check it is a regular file */
+ if (stat (real_name, &stat_buf) == 0 &&
+ !S_ISREG (stat_buf.st_mode))
+ {
+ error ("skipping %s: it is not a regular file.",
+ real_name);
+ fclose(inf);
+ inf = NULL;
+ }
+ }
+ /* Not else from previous if because inner check may reset inf
+ to NULL, at which case we will want to try the next?
+ compressed filename... */
+ if ( inf == NULL ) {
+ /* Reset real_name and try with a different name. */
+ free(compressed_name);
+ real_name = NULL;
+ if (compressed_name != NULL)
+ /* try with the given suffix */
+ {
+ compressed_name = NULL;
+ real_name = uncompressed_name;
+ }
+ else if ( compr && compr->suffix != NULL )
+ /* try all possible suffixes */
{
compressed_name = concat (file, ".", compr->suffix);
- if (stat (compressed_name, &stat_buf) != 0)
- {
- free (compressed_name);
- compressed_name = NULL;
- }
- else
- {
- real_name = compressed_name;
- break;
- }
+ real_name = compressed_name;
+ compr++;
}
}
- if (real_name == NULL)
- {
- perror (file);
- goto cleanup;
- }
- } /* try with a different name */
-
- if (!S_ISREG (stat_buf.st_mode))
- {
- error ("skipping %s: it is not a regular file.", real_name);
- goto cleanup;
- }
- if (real_name == compressed_name)
- {
- char *cmd = concat (compr->command, " ", real_name);
- inf = (FILE *) popen (cmd, "r");
- free (cmd);
- }
- else
- inf = fopen (real_name, "r");
+ } while( inf == NULL && real_name != NULL);
if (inf == NULL)
{
perror (real_name);
/*
* add_node ()
* Adds a node to the tree of nodes. In etags mode, sort by file
- * name. In ctags mode, sort by tag name. Make no attempt at
- * balancing.
+ * name. In ctags mode, sort by tag name. Make no attempt at
+ * balancing.
*
* add_node is the only function allowed to add nodes, so it can
* maintain state.
else
{
len = strlen (cstack.cname[0]);
- linebuffer_setlen (cn, len);
- strcpy (cn->buffer, cstack.cname[0]);
+ linebuffer_setlen (cn, len+1);
+ xstrncpy (cn->buffer, cstack.cname[0],len+1);
}
for (i = 1; i < cstack.nl; i++)
{
* consider_token ()
* checks to see if the current token is at the start of a
* function or variable, or corresponds to a typedef, or
- * is a struct/union/enum tag, or #define, or an enum constant.
+ * is a struct/union/enum tag, or #define, or an enum constant.
*
* *IS_FUNC gets TRUE if the token is a function or #define macro
* with args. C_EXTP points to which language we are looking at.
typdef = ttypeseen;
/* all the rest */
+ case st_C_objprot:
+ case st_C_objimpl:
+ case st_C_objend:
+ case st_C_gnumacro:
+ case st_C_ignore:
+ case st_C_attribute:
+ case st_C_javastruct:
+ case st_C_operator:
+ case st_C_template:
+ case st_C_extern:
+ case st_C_define:
+ case st_C_typedef:
default:
break;
}
return FALSE;
/* all the rest */
+ case st_none:
+ case st_C_objprot:
+ case st_C_objimpl:
+ case st_C_objend:
+ case st_C_gnumacro:
+ case st_C_ignore:
+ case st_C_attribute:
+ case st_C_javastruct:
+ case st_C_operator:
+ case st_C_template:
+ case st_C_extern:
+ case st_C_define:
+ case st_C_typedef:
default:
break;
}
return TRUE;
/* all the rest */
+ case tinbody:
+ case tignore:
default:
break;
}
return FALSE;
/* all the rest */
+ case st_none:
+ case st_C_objprot:
+ case st_C_objimpl:
+ case st_C_objend:
+ case st_C_gnumacro:
+ case st_C_ignore:
+ case st_C_attribute:
+ case st_C_operator:
+ case st_C_extern:
+ case st_C_define:
+ case st_C_typedef:
default:
break;
}
return FALSE;
/* all the rest */
+ case st_none:
+ case st_C_objend:
+ case st_C_gnumacro:
+ case st_C_ignore:
+ case st_C_attribute:
+ case st_C_javastruct:
+ case st_C_operator:
+ case st_C_class:
+ case st_C_template:
+ case st_C_struct:
+ case st_C_extern:
+ case st_C_enum:
+ case st_C_define:
+ case st_C_typedef:
default:
break;
}
{
fvdef = fvnone;
objdef = omethodtag;
- linebuffer_setlen (&token_name, len);
- strncpy (token_name.buffer, str, len);
+ linebuffer_setlen (&token_name, len+1);
+ xstrncpy (token_name.buffer, str, len+1);
token_name.buffer[len] = '\0';
return TRUE;
}
return FALSE;
/* all the rest */
+ case otagseen:
+ case ocatseen:
+ case omethodtag:
default:
break;
}
case fignore:
case vignore:
break;
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case foperator:
+ case fvnameseen:
+ case fstartlist:
default:
fvdef = fvnone;
}
break;
/* all the rest */
+ case tkeyseen:
+ case tinbody:
+ case tend:
+ case tignore:
default:
break;
}
return TRUE;
/* all the rest */
+ case fdefunname:
+ case foperator:
+ case fstartlist:
+ case finlist:
+ case flistseen:
+ case fignore:
+ case vignore:
default:
break;
}
break;
/* all the rest */
+ case st_C_objprot:
+ case st_C_objimpl:
+ case st_C_objend:
+ case st_C_gnumacro:
+ case st_C_attribute:
+ case st_C_javastruct:
+ case st_C_class:
+ case st_C_template:
+ case st_C_struct:
+ case st_C_enum:
+ case st_C_define:
+ case st_C_typedef:
default:
break;
}
/*
* C_entries ()
* This routine finds functions, variables, typedefs,
- * #define's, enum constants and struct/union/enum definitions in
- * C syntax and adds them to the list.
+ * #define's, enum constants and struct/union/enum definitions in
+ * C syntax and adds them to the list.
*/
static void
C_entries (c_ext, inf)
case fignore:
case vignore:
break;
+ case fvnone:
+ case fdefunname:
+ case foperator:
+ case fvnameseen:
+ case flistseen:
default:
fvextern = FALSE;
fvdef = fvnone;
off += 1;
len -= 1;
}
- linebuffer_setlen (&token_name, len);
- strncpy (token_name.buffer,
- newlb.buffer + off, len);
- token_name.buffer[len] = '\0';
+ linebuffer_setlen (&token_name, len+1);
+ xstrncpy (token_name.buffer,
+ newlb.buffer + off, len+1);
if (defun)
while (--len >= 0)
if (token_name.buffer[len] == '_')
}
else
{
- linebuffer_setlen (&token_name, toklen);
- strncpy (token_name.buffer,
- newlb.buffer + tokoff, toklen);
+ linebuffer_setlen (&token_name, toklen+1);
+ xstrncpy (token_name.buffer,
+ newlb.buffer + tokoff, toklen+1);
token_name.buffer[toklen] = '\0';
/* Name macros and members. */
token.named = (structdef == stagseen
break;
/* all the rest */
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case foperator:
+ case fvnameseen:
+ case finlist:
+ case fignore:
+ case vignore:
default:
break;
}
break;
/* all the rest */
+ case ddefineseen:
+ case dignorerest:
default:
break;
}
break;
/* all the rest */
+ case onone:
+ case oprotocol:
+ case oimplementation:
+ case oparenseen:
+ case ocatseen:
+ case oinbody:
+ case omethodsign:
+ case omethodcolon:
+ case oignore:
default:
break;
}
&& plainc && instruct))
make_C_tag (TRUE); /* a function */
/* FALLTHRU */
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case foperator:
+ case fstartlist:
+ case finlist:
+ case vignore:
default:
fvextern = FALSE;
fvdef = fvnone;
token.valid = FALSE;
} /* switch (fvdef) */
/* FALLTHRU */
+ case tkeyseen:
default:
if (!instruct)
typdef = tnone;
break;
/* all the rest */
+ case onone:
+ case oprotocol:
+ case oimplementation:
+ case otagseen:
+ case oparenseen:
+ case ocatseen:
+ case oinbody:
+ case omethodsign:
+ case omethodcolon:
+ case oignore:
default:
break;
}
fvdef = fvnone;
token.valid = FALSE;
break;
+ case fvnone:
default:
fvdef = fvnone;
}
&& (!fvextern || declarations)))
make_C_tag (FALSE); /* a variable */
/* FALLTHRU */
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case fstartlist:
+ case flistseen:
default:
fvdef = fvnone;
}
break;
/* all the rest */
+ case tkeyseen:
+ case tignore:
default:
break;
}
break;
/* all the rest */
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case fstartlist:
+ case finlist:
+ case fignore:
+ case vignore:
default:
break;
}
break;
/* all the rest */
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case foperator:
+ case fvnameseen:
+ case flistseen:
+ case fignore:
+ case vignore:
default:
break;
}
make_C_tag (TRUE); /* an Objective C method */
objdef = oinbody;
break;
+ case onone:
+ case oprotocol:
+ case oimplementation:
+ case oparenseen:
+ case ocatseen:
+ case oinbody:
+ case omethodsign:
+ case omethodcolon:
+ case oignore:
default:
/* Neutralize `extern "C" {' grot. */
if (bracelev == 0 && structdef == snone && nestlev == 0
break;
/* all the rest */
+ case fdefunkey:
+ case fdefunname:
+ case foperator:
+ case fvnameseen:
+ case fstartlist:
+ case finlist:
+ case vignore:
default:
break;
}
break;
/* all the rest */
+ case snone:
default:
break;
}
|| (globals && bracelev == 0 && (!fvextern || declarations)))
make_C_tag (FALSE); /* a variable */
/* FALLTHRU */
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case fstartlist:
+ case flistseen:
default:
fvdef = vignore;
}
case fignore:
case vignore:
break;
+ case fvnone:
+ case fdefunkey:
+ case fdefunname:
+ case fvnameseen:
+ case fstartlist:
+ case flistseen:
default:
fvdef = fvnone;
}
continue;
/* Save all values for later tagging. */
- linebuffer_setlen (&tline, lb.len);
- strcpy (tline.buffer, lb.buffer);
+ linebuffer_setlen (&tline, lb.len+1);
+ xstrncpy(tline.buffer, lb.buffer, lb.len+1);
save_lineno = lineno;
save_lcno = linecharno;
name = tline.buffer + (dbp - lb.buffer);
else
for (end = dbp; *end != '\0' && intoken (*end); end++)
continue;
- linebuffer_setlen (&token_name, end - dbp);
- strncpy (token_name.buffer, dbp, end - dbp);
+ linebuffer_setlen (&token_name, end - dbp+1);
+ xstrncpy (token_name.buffer, dbp, end - dbp+1);
token_name.buffer[end - dbp] = '\0';
dbp = end;
else if (len + 1 > allocated)
xrnew (last, len + 1, char);
allocated = len + 1;
- strncpy (last, cp, len);
- last[len] = '\0';
+ xstrncpy (last, cp, len+1);
}
}
free (last);
continue;
else if (cp[0] == '"') /* Sometimes, strings start in column one */
continue;
- else if (cp[0] == '-') /* attribute, e.g. "-define" */
+ else if (cp[0] == '-') /* attribute, e.g. "-define" */
{
erlang_attribute (cp);
if (last != NULL)
else if (len + 1 > allocated)
xrnew (last, len + 1, char);
allocated = len + 1;
- strncpy (last, cp, len);
- last[len] = '\0';
+ xstrncpy (last, cp, allocated);
}
}
free (last);
/* Allocate space and do the substitutions. */
assert (size >= 0);
- result = xnew (size + 1, char);
+ size_t avail = size + 1;
+ result = xnew (avail, char);
for (t = result; *out != '\0'; out++)
if (*out == '\\' && ISDIGIT (*++out))
{
dig = *out - '0';
diglen = regs->end[dig] - regs->start[dig];
- strncpy (t, in + regs->start[dig], diglen);
+ xstrncpy (t, in + regs->start[dig], avail);
t += diglen;
+ avail -= diglen;
}
- else
+ else {
*t++ = *out;
+ avail --;
+ }
*t = '\0';
assert (t <= result + size);
{
char *buffer = filebuf.buffer;
regexp *rp;
- char *name;
+ char *name = NULL;
for (rp = p_head; rp != NULL; rp = rp->p_next)
{
while (charno < rp->regs.end[0])
if (buffer[charno++] == '\n')
lineno++, linecharno = charno;
- name = rp->name;
- if (name[0] == '\0')
+ if (! rp->name || rp->name[0] == '\0')
name = NULL;
else /* make a named tag */
name = substitute (buffer, rp->name, &rp->regs);
if (rp->force_explicit_name)
- /* Force explicit tag name, if a name is there. */
+ /* Force explicit tag name, if a name
+ is there. */
pfnote (name, TRUE, buffer + linecharno,
- charno - linecharno + 1, lineno, linecharno);
+ charno - linecharno + 1, lineno,
+ linecharno);
+ else if(name == NULL)
+ abort();
else
- make_tag (name, strlen (name), TRUE, buffer + linecharno,
- charno - linecharno + 1, lineno, linecharno);
+ make_tag (name, strlen (name), TRUE,
+ buffer + linecharno,
+ charno - linecharno + 1,
+ lineno, linecharno);
+ free(name);
+ name = NULL;
break;
}
}
if (need_filebuf /* we need filebuf for multi-line regexps */
&& chars_deleted > 0) /* not at EOF */
{
- while (filebuf.size <= filebuf.len + lbp->len + 1) /* +1 for \n */
- {
- /* Expand filebuf. */
+ size_t need = filebuf.len + lbp->len + 1; /* +1 for \n */
+ while (filebuf.size <= need )
filebuf.size *= 2;
- xrnew (filebuf.buffer, filebuf.size, char);
- }
- strncpy (filebuf.buffer + filebuf.len, lbp->buffer, lbp->len);
+ /* Expand filebuf. */
+ xrnew (filebuf.buffer, filebuf.size, char);
+ xstrncpy (filebuf.buffer + filebuf.len, lbp->buffer, filebuf.size - filebuf.len);
filebuf.len += lbp->len;
filebuf.buffer[filebuf.len++] = '\n';
filebuf.buffer[filebuf.len] = '\0';
make_tag (name, strlen (name), TRUE,
lbp->buffer, match, lineno, linecharno);
free(name);
- } else
+ name = NULL;
+ } else
make_tag (rp->name, strlen (rp->name), TRUE,
lbp->buffer, match, lineno, linecharno);
break;
register char *dp;
dp = xnew (len + 1, char);
- strncpy (dp, cp, len);
+ xstrncpy (dp, cp, len+1);
dp[len] = '\0';
return dp;
}
-/*
- * Return the ptr in sp at which the character c last
- * appears; NULL if not found
- *
- * Identical to POSIX strrchr, included for portability.
- */
-static char *
-etags_strrchr (sp, c)
-register const char *sp;
-register int c;
-{
- register const char *r;
-
- r = NULL;
- do
- {
- if (*sp == c)
- r = sp;
- } while (*sp++);
- return (char *)r;
-}
-
-/*
- * Return the ptr in sp at which the character c first
- * appears; NULL if not found
- *
- * Identical to POSIX strchr, included for portability.
- */
-static char *
-etags_strchr (sp, c)
-register const char *sp;
-register int c;
-{
- do
- {
- if (*sp == c)
- return (char *)sp;
- } while (*sp++);
- return NULL;
-}
-
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- *
- * Same as BSD's strcasecmp, included for portability.
- */
-static int
-etags_strcasecmp (s1, s2)
-register const char *s1;
-register const char *s2;
-{
- while (*s1 != '\0'
- && (ISALPHA (*s1) && ISALPHA (*s2)
- ? lowcase (*s1) == lowcase (*s2)
- : *s1 == *s2))
- s1++, s2++;
-
- return (ISALPHA (*s1) && ISALPHA (*s2)
- ? lowcase (*s1) - lowcase (*s2)
- : *s1 - *s2);
-}
-
-/*
- * Compare two strings, ignoring case for alphabetic characters.
- * Stop after a given number of characters
- *
- * Same as BSD's strncasecmp, included for portability.
- */
-static int
-etags_strncasecmp (s1, s2, n)
-register const char *s1;
-register const char *s2;
-register int n;
-{
- while (*s1 != '\0' && n-- > 0
- && (ISALPHA (*s1) && ISALPHA (*s2)
- ? lowcase (*s1) == lowcase (*s2)
- : *s1 == *s2))
- s1++, s2++;
-
- if (n < 0)
- return 0;
- else
- return (ISALPHA (*s1) && ISALPHA (*s2)
- ? lowcase (*s1) - lowcase (*s2)
- : *s1 - *s2);
-}
/* Skip spaces (end of string is not space), return new pointer. */
static char *
int 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);
+ xstrncpy(result, s1, len1+1);
+ xstrncpy(result + len1, s2, len2+1);
+ xstrncpy(result + len1 + len2, s3, len3+1);
result[len1 + len2 + len3] = '\0';
return result;
{
char *fp, *dp, *afn, *res;
int i;
+ ssize_t res_left;
/* Find the common root of file and dir (with a trailing slash). */
afn = absolute_filename (file, cwd);
i = 0;
while ((dp = etags_strchr (dp + 1, '/')) != NULL)
i += 1;
- res = xnew (3*i + strlen (fp) + 1, char);
+ res_left = 3 * i + strlen(fp);
+ res = xnew( res_left + 1, char);
res[0] = '\0';
- while (i-- > 0)
- strcat (res, "../");
+ for ( ; i-- > 0 ; res_left -= 3 )
+ strncat(res, "../", res_left );
/* Add the file name relative to the common root of file and dir. */
- strcat (res, fp);
- free (afn);
+ strncat(res, fp, res_left);
+ free(afn);
return res;
}
while (cp >= res && !filename_is_absolute (cp));
if (cp < res)
cp = slashp; /* the absolute name begins with "/.." */
- strcpy (cp, slashp + 3);
+ slashp += 3;
+ memmove(cp, slashp,strlen(slashp)+1);
slashp = cp;
continue;
}
int toksize;
{
while (lbp->size <= toksize)
- {
lbp->size *= 2;
- xrnew (lbp->buffer, lbp->size, char);
- }
+ xrnew (lbp->buffer, lbp->size, char);
lbp->len = toksize;
}