# define xrnew(op,n,Type) ((Type *) xrealloc ((op), (n) * sizeof (Type)))
#endif
+#define xstrncpy(d_,s_,l_) \
+ do { \
+ char* dst_=d_; \
+ dst_[0]='\0'; \
+ strncat((dst_),(s_),(l_)-1); \
+ } while(0)
+
+
typedef int bool;
typedef void Lang_function(FILE *);
char *skip_non_spaces PP((char *cp));
char *savenstr PP((char *cp, int len));
char *savestr PP((char *cp));
-char *etags_strchr PP((char *sp, int c));
-char *etags_strrchr PP((char *sp, int c));
char *etags_getcwd PP((void));
char *relative_filename PP((char *file, char *dir));
char *absolute_filename PP((char *file, char *dir));
long *xmalloc PP((unsigned int size));
long *xrealloc PP((char *ptr, unsigned int size));
\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
+\f
char searchar = '/'; /* use /.../ searches */
char *tagfile; /* output file */
puts("\n");
puts("-a, --append\n\
- Append tag entries to existing tags file.");
+ Append tag entries to existing tags file.");
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.");
puts("-C, --c++\n\
- Treat files whose name suffix defaults to C language as C++ files.");
+ Treat files whose name suffix defaults to C language as C++ files.");
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.");
}
#ifdef ETAGS_REGEXPS
puts("-r /REGEXP/, --regex=/REGEXP/ or --regex=@regexfile\n\
- Make a tag for each line matching pattern REGEXP in the\n\
- following files. regexfile is a file containing one REGEXP\n\
+ Make a tag for each line matching pattern REGEXP in the\n\
+ following files. regexfile is a file containing one REGEXP\n\
per line. REGEXP is anchored (as if preceded by ^).\n\
The form /REGEXP/NAME/ creates a named tag. For example Tcl\n\
named tags can be created with:\n\
--regex=/proc[ \\t]+\\([^ \\t]+\\)/\\1/.");
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.");
#endif /* ETAGS_REGEXPS */
puts("-o FILE, --output=FILE\n\
- Write the tags to FILE.");
+ Write the tags to FILE.");
#ifdef OO_BROWSER
puts("-O, --oo-browser\n\
Generate a specialized tags format used only by the Altrasoft OO-Browser.");
#endif
puts("-I, --ignore-indentation\n\
- Don't rely on indentation quite as much as normal. Currently,\n\
- this means not to assume that a closing brace in the first\n\
- column is the final brace of a function or structure\n\
- definition in C and C++.");
+ Don't rely on indentation quite as much as normal. Currently,\n\
+ this means not to assume that a closing brace in the first\n\
+ column is the final brace of a function or structure\n\
+ definition in C and C++.");
if (CTAGS) {
puts("-t, --typedefs\n\
- Generate tag entries for C typedefs.");
+ Generate tag entries for C 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.");
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.");
puts("-v, --vgrind\n\
- Generates an index of items intended for human consumption,\n\
- similar to the output of vgrind. The index is sorted, and\n\
- gives the page number of each item.");
+ Generates an index of items intended for human consumption,\n\
+ similar to the output of vgrind. The index is sorted, and\n\
+ gives the page number of each item.");
puts("-w, --no-warn\n\
- Suppress warning messages about entries defined in multiple\n\
- files.");
+ Suppress warning messages about entries defined in multiple\n\
+ files.");
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.");
+ Print this help message.");
print_language_names();
/*
* If etags, always find typedefs and structure tags. Why not?
* Also default is to find macro constants, enum constants and
- * global variables.
+ * global variables.
*/
if (!CTAGS) {
typedefs = typedefs_and_cplusplus = constantypedefs = TRUE;
case 'o':
if (tagfile) {
/* convert char to string, to call error with */
- char buf[2];
- sprintf(buf, "%c", opt);
+ char buf[]=" ";
+ buf[0]=opt;
error("-%s option may only be given once.",
buf);
suggest_asking_for_help();
if (update) {
char cmd[BUFSIZ];
+ int sz;
for (i = 0; i < current_arg; ++i) {
if (argbuffer[i].arg_type != at_filename)
continue;
- sprintf(cmd,
- "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
- tagfile, argbuffer[i].what, tagfile);
+ sz = snprintf(cmd, sizeof(cmd),
+ "mv %s OTAGS;fgrep -v '\t%s\t' OTAGS >%s;rm OTAGS",
+ tagfile, argbuffer[i].what, tagfile);
+ if(sz >= 0 && (size_t)sz < sizeof(cmd))
+ fatal("failed to build shell command line", (char *)NULL);
if (system(cmd) != GOOD)
fatal("failed to execute shell command", (char *)NULL);
}
if (update) {
char cmd[BUFSIZ];
- sprintf(cmd, "sort %s -o %s", tagfile, tagfile);
+ int sz = snprintf(cmd, sizeof(cmd), "sort %s -o %s", tagfile, tagfile);
+ if(sz >= 0 && (size_t)sz < sizeof(cmd))
+ fatal("failed to build sort command line", (char *)NULL);
exit(system(cmd));
}
return GOOD;
FILE *inf;
canonicalize_filename(file);
- if (stat(file, &stat_buf) == 0 && !S_ISREG(stat_buf.st_mode)) {
- error("skipping %s: it is not a regular file.", file);
- return;
- }
if (streq(file, tagfile) && !streq(tagfile, "-")) {
error("skipping inclusion of %s in self.", file);
return;
}
inf = fopen(file, "r");
+ if (stat(file, &stat_buf) == 0 && !S_ISREG(stat_buf.st_mode)) {
+ error("skipping %s: it is not a regular file.", file);
+ if( inf != NULL)
+ fclose(inf);
+ return;
+ }
if (inf == NULL) {
perror(file);
return;
import, C_JAVA, st_C_ignore
package, C_JAVA, st_C_ignore
friend, C_PLPL, st_C_ignore
-extends, C_JAVA, st_C_javastruct
-implements, C_JAVA, st_C_javastruct
+extends, C_JAVA, st_C_javastruct
+implements, C_JAVA, st_C_javastruct
interface, C_JAVA, st_C_struct
-class, C_PLPL, st_C_class
+class, C_PLPL, st_C_class
namespace, C_PLPL, st_C_struct
-domain, C_STAR, st_C_struct
-union, 0, st_C_union
-struct, 0, st_C_struct
-enum, 0, st_C_enum
-typedef, 0, st_C_typedef
-define, 0, st_C_define
+domain, C_STAR, st_C_struct
+union, 0, st_C_union
+struct, 0, st_C_struct
+enum, 0, st_C_enum
+typedef, 0, st_C_typedef
+define, 0, st_C_define
inline, 0, st_C_inline
bool, C_PLPL, st_C_typespec
-long, 0, st_C_typespec
-short, 0, st_C_typespec
-int, 0, st_C_typespec
-char, 0, st_C_typespec
-float, 0, st_C_typespec
-double, 0, st_C_typespec
-signed, 0, st_C_typespec
+long, 0, st_C_typespec
+short, 0, st_C_typespec
+int, 0, st_C_typespec
+char, 0, st_C_typespec
+float, 0, st_C_typespec
+double, 0, st_C_typespec
+signed, 0, st_C_typespec
unsigned, 0, st_C_typespec
-auto, 0, st_C_typespec
-void, 0, st_C_typespec
-extern, 0, st_C_extern
-static, 0, st_C_typespec
-const, 0, st_C_const
+auto, 0, st_C_typespec
+void, 0, st_C_typespec
+extern, 0, st_C_extern
+static, 0, st_C_typespec
+const, 0, st_C_const
volatile, 0, st_C_typespec
explicit, C_PLPL, st_C_typespec
mutable, C_PLPL, st_C_typespec
* 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 iff the token is a function or #define macro
* with args. C_EXT is which language we are looking at.
objdef = omethodtag;
methodlen = len;
grow_linebuffer(&token_name, methodlen + 1);
- strncpy(token_name.buffer, str, len);
+ xstrncpy(token_name.buffer, str, methodlen+1);
token_name.buffer[methodlen] = '\0';
token_name.len = methodlen;
return TRUE;
/*
* 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.
*/
#define current_lb_is_new (newndx == curndx)
#define switch_line_buffers() (curndx = 1 - curndx)
(&token_name,
toklen +
1);
- strncpy
+ xstrncpy
(token_name.
buffer,
newlb.
buffer +
tokoff,
- toklen);
- token_name.
- buffer
- [toklen] =
- '\0';
+ toklen + 1);
token_name.len =
toklen;
/* Name macros. */
== tend
#ifdef OO_BROWSER
/* Also name #define constants,
- enumerations and enum_labels.
- Conditionalize `funorvar' reference
- here or #defines will appear without
- their #names.
- -- Bob Weiner, Altrasoft, 4/25/1998 */
+ enumerations and enum_labels.
+ Conditionalize `funorvar' reference
+ here or #defines will appear without
+ their #names.
+ -- Bob Weiner, Altrasoft, 4/25/1998 */
||
((oo_browser_format || funorvar)
&&
LOOP_ON_INPUT_LINES(inf, lb, dummy)
continue;
+ (void)dummy; // Silence set-not-read warning.
}
\f
/* Fortran parsing */
/* save all values for later tagging */
grow_linebuffer(&tline, lb.len + 1);
- strcpy(tline.buffer, lb.buffer);
+ xstrncpy(tline.buffer, lb.buffer, lb.len + 1);
save_lineno = lineno;
save_lcno = linecharno;
* Prolog support (rewritten) by Anders Lindgren, Mar. 96
*
* Assumes that the predicate starts at column 0.
- * Only the first clause of a predicate is added.
+ * Only the first clause of a predicate is added.
*/
int prolog_pred PP((char *s, char *last));
void prolog_skip_comment PP((linebuffer * plb, FILE * inf));
else if (len + 1 > allocated)
last = xrnew(last, len + 1, char);
allocated = len + 1;
- strncpy(last, cp, len);
- last[len] = '\0';
+ xstrncpy(last, cp, allocated);
}
}
+ free(last);
}
void prolog_skip_comment(plb, inf)
return -1;
}
\f
-/*
+/*
* Support for Erlang -- Anders Lindgren, Feb 1996.
*
* Generates tags for functions, defines, and records.
continue;
else if (cp[0] == '-') { /* attribute, e.g. "-define" */
erlang_attribute(cp);
+ free(last);
last = NULL;
} else if ((len = erlang_func(cp, last)) > 0) {
- /*
+ /*
* Function. Store the function name so that we only
* generates a tag for the first clause.
*/
else if (len + 1 > allocated)
last = xrnew(last, len + 1, char);
allocated = len + 1;
- strncpy(last, cp, len);
- last[len] = '\0';
+ xstrncpy(last, cp, allocated);
}
}
+ free(last);
}
/*
}
/*
- * Handle attributes. Currently, tags are generated for defines
+ * Handle attributes. Currently, tags are generated for defines
* and records.
*
* They are on the form:
void analyse_regex(regex_arg)
char *regex_arg;
{
- if (regex_arg == NULL)
+ if (regex_arg == NULL) {
free_patterns(); /* --no-regex: remove existing regexps */
-
+ return;
+ }
/* A real --regexp option or a line in a regexp file. */
switch (regex_arg[0]) {
/* Comments in regexp file or null arg to --regex. */
size -= 1;
/* Allocate space and do the substitutions. */
- result = xnew(size + 1, char);
+ size_t avail = size + 1;
+ result = xnew(avail, char);
for (t = result; *out != '\0'; out++)
if (*out == '\\' && isdigit(*++out)) {
/* Using "dig2" satisfies my debugger. Bleah. */
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;
- } else
+ avail -= diglen;
+ } else {
*t++ = *out;
+ avail --;
+ }
*t = '\0';
if (DEBUG && (t > result + size || t - result != strlen(result)))
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 System V strrchr, included for portability.
- */
-char *etags_strrchr(sp, c)
-register char *sp;
-register int c;
-{
- register char *r;
-
- r = NULL;
- do {
- if (*sp == c)
- r = sp;
- } while (*sp++);
- return r;
-}
-
-/*
- * Return the ptr in sp at which the character c first
- * appears; NULL if not found
- *
- * Identical to System V strchr, included for portability.
- */
-char *etags_strchr(sp, c)
-register char *sp;
-register int c;
-{
- do {
- if (*sp == c)
- return sp;
- } while (*sp++);
- return NULL;
-}
-
/* Skip spaces, return new pointer. */
char *skip_spaces(cp)
char *cp;
{
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 -= 4 )
+ strncat(res, "../", res_left );
/* Add the file name relative to the common root of file and dir. */
- strcat(res, fp);
+ strncat(res, fp, res_left);
free(afn);
return res;