/*
- * Copyright (C) 1984-2016 Mark Nudelman
+ * Copyright (C) 1984-2022 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
#include "less.h"
-#define WHITESP(c) ((c)==' ' || (c)=='\t')
+#define WHITESP(c) ((c)==' ' || (c)=='\t')
#if TAGS
extern int linenums;
extern int sigs;
+extern int ctldisp;
enum tag_result {
TAG_FOUND,
* Tag type
*/
enum {
- T_CTAGS, /* 'tags': standard and extended format (ctags) */
- T_CTAGS_X, /* stdin: cross reference format (ctags) */
- T_GTAGS, /* 'GTAGS': function defenition (global) */
- T_GRTAGS, /* 'GRTAGS': function reference (global) */
- T_GSYMS, /* 'GSYMS': other symbols (global) */
- T_GPATH /* 'GPATH': path name (global) */
+ T_CTAGS, /* 'tags': standard and extended format (ctags) */
+ T_CTAGS_X, /* stdin: cross reference format (ctags) */
+ T_GTAGS, /* 'GTAGS': function definition (global) */
+ T_GRTAGS, /* 'GRTAGS': function reference (global) */
+ T_GSYMS, /* 'GSYMS': other symbols (global) */
+ T_GPATH /* 'GPATH': path name (global) */
};
-static enum tag_result findctag();
-static enum tag_result findgtag();
-static char *nextgtag();
-static char *prevgtag();
-static POSITION ctagsearch();
-static POSITION gtagsearch();
-static int getentry();
+static enum tag_result findctag LESSPARAMS((char *tag));
+static enum tag_result findgtag LESSPARAMS((char *tag, int type));
+static char *nextgtag(VOID_PARAM);
+static char *prevgtag(VOID_PARAM);
+static POSITION ctagsearch(VOID_PARAM);
+static POSITION gtagsearch(VOID_PARAM);
+static int getentry LESSPARAMS((char *buf, char **tag, char **file, char **line));
/*
* The list of tags generated by the last findgtag() call.
struct tag *tl_first;
struct tag *tl_last;
};
-#define TAG_END ((struct tag *) &taglist)
-static struct taglist taglist = { TAG_END, TAG_END };
struct tag {
struct tag *next, *prev; /* List links */
- char *tag_file; /* Source file containing the tag */
- LINENUM tag_linenum; /* Appropriate line number in source file */
- char *tag_pattern; /* Pattern used to find the tag */
- char tag_endline; /* True if the pattern includes '$' */
+ char *tag_file; /* Source file containing the tag */
+ LINENUM tag_linenum; /* Appropriate line number in source file */
+ char *tag_pattern; /* Pattern used to find the tag */
+ char tag_endline; /* True if the pattern includes '$' */
};
+#define TAG_END ((struct tag *) &taglist)
+static struct taglist taglist = { TAG_END, TAG_END };
static struct tag *curtag;
#define TAG_INS(tp) \
* Delete tag structures.
*/
public void
-cleantags()
+cleantags(VOID_PARAM)
{
- register struct tag *tp;
+ struct tag *tp;
/*
* Delete any existing tag list.
while ((tp = taglist.tl_first) != TAG_END)
{
TAG_RM(tp);
+ free(tp->tag_file);
+ free(tp->tag_pattern);
free(tp);
}
curtag = NULL;
char *pattern;
int endline;
{
- register struct tag *tp;
+ struct tag *tp;
tp = (struct tag *) ecalloc(sizeof(struct tag), 1);
tp->tag_file = (char *) ecalloc(strlen(file) + 1, sizeof(char));
* Get tag mode.
*/
public int
-gettagtype()
+gettagtype(VOID_PARAM)
{
int f;
*/
public void
findtag(tag)
- register char *tag;
+ char *tag;
{
int type = gettagtype();
enum tag_result result;
* Search for a tag.
*/
public POSITION
-tagsearch()
+tagsearch(VOID_PARAM)
{
if (curtag == NULL)
return (NULL_POSITION); /* No gtags loaded! */
* Return the total number of tags.
*/
public int
-ntags()
+ntags(VOID_PARAM)
{
return total;
}
* Return the sequence number of current tag.
*/
public int
-curr_tag()
+curr_tag(VOID_PARAM)
{
return curseq;
}
*/
static enum tag_result
findctag(tag)
- register char *tag;
+ char *tag;
{
char *p;
- register FILE *f;
- register int taglen;
+ char *q;
+ FILE *f;
+ int taglen;
LINENUM taglinenum;
char *tagfile;
char *tagpattern;
search_char = *p++;
if (*p == '^')
p++;
- tagpattern = p;
+ tagpattern = q = p;
while (*p != search_char && *p != '\0')
{
if (*p == '\\')
p++;
- p++;
+ if (q != p)
+ {
+ *q++ = *p++;
+ } else
+ {
+ q++;
+ p++;
+ }
}
- tagendline = (p[-1] == '$');
+ tagendline = (q[-1] == '$');
if (tagendline)
- p--;
- *p = '\0';
+ q--;
+ *q = '\0';
}
tp = maketagent(tag, tagfile, taglinenum, tagpattern, tagendline);
TAG_INS(tp);
* Edit current tagged file.
*/
public int
-edit_tagfile()
+edit_tagfile(VOID_PARAM)
{
if (curtag == NULL)
return (1);
return (edit(curtag->tag_file));
}
+ static int
+curtag_match(line, linepos)
+ char constant *line;
+ POSITION linepos;
+{
+ /*
+ * Test the line to see if we have a match.
+ * Use strncmp because the pattern may be
+ * truncated (in the tags file) if it is too long.
+ * If tagendline is set, make sure we match all
+ * the way to end of line (no extra chars after the match).
+ */
+ int len = (int) strlen(curtag->tag_pattern);
+ if (strncmp(curtag->tag_pattern, line, len) == 0 &&
+ (!curtag->tag_endline || line[len] == '\0' || line[len] == '\r'))
+ {
+ curtag->tag_linenum = find_linenum(linepos);
+ return 1;
+ }
+ return 0;
+}
+
/*
* Search for a tag.
* This is a stripped-down version of search().
* We don't use search() for several reasons:
- * - We don't want to blow away any search string we may have saved.
- * - The various regular-expression functions (from different systems:
- * regcmp vs. re_comp) behave differently in the presence of
- * parentheses (which are almost always found in a tag).
+ * - We don't want to blow away any search string we may have saved.
+ * - The various regular-expression functions (from different systems:
+ * regcmp vs. re_comp) behave differently in the presence of
+ * parentheses (which are almost always found in a tag).
*/
static POSITION
-ctagsearch()
+ctagsearch(VOID_PARAM)
{
POSITION pos, linepos;
LINENUM linenum;
- int len;
+ int line_len;
char *line;
+ int found;
pos = ch_zero();
linenum = find_linenum(pos);
- for (;;)
+ for (found = 0; !found;)
{
/*
* Get lines until we find a matching one or
* starting position of that line in linepos.
*/
linepos = pos;
- pos = forw_raw_line(pos, &line, (int *)NULL);
+ pos = forw_raw_line(pos, &line, &line_len);
if (linenum != 0)
linenum++;
if (linenums)
add_lnum(linenum, pos);
- /*
- * Test the line to see if we have a match.
- * Use strncmp because the pattern may be
- * truncated (in the tags file) if it is too long.
- * If tagendline is set, make sure we match all
- * the way to end of line (no extra chars after the match).
- */
- len = (int) strlen(curtag->tag_pattern);
- if (strncmp(curtag->tag_pattern, line, len) == 0 &&
- (!curtag->tag_endline || line[len] == '\0' || line[len] == '\r'))
+ if (ctldisp != OPT_ONPLUS)
{
- curtag->tag_linenum = find_linenum(linepos);
- break;
+ if (curtag_match(line, linepos))
+ found = 1;
+ } else
+ {
+ int cvt_ops = CVT_ANSI;
+ int cvt_len = cvt_length(line_len, cvt_ops);
+ int *chpos = cvt_alloc_chpos(cvt_len);
+ char *cline = (char *) ecalloc(1, cvt_len);
+ cvt_text(cline, line, chpos, &line_len, cvt_ops);
+ if (curtag_match(cline, linepos))
+ found = 1;
+ free(chpos);
+ free(cline);
}
}
*/
static enum tag_result
findgtag(tag, type)
- char *tag; /* tag to load */
- int type; /* tags type */
+ char *tag; /* tag to load */
+ int type; /* tags type */
{
- char buf[256];
+ char buf[1024];
FILE *fp;
struct tag *tp;
char *qtag;
char *cmd = lgetenv("LESSGLOBALTAGS");
- if (cmd == NULL || *cmd == '\0')
+ if (isnullenv(cmd))
return TAG_NOFILE;
/* Get suitable flag value for global(1). */
switch (type)
} while (c != '\n' && c != EOF);
}
- if (getentry(buf, &name, &file, &line))
+ if (getentry(buf, &name, &file, &line))
{
/*
* Couldn't parse this line for some reason.
return TAG_FOUND;
}
-static int circular = 0; /* 1: circular tag structure */
+static int circular = 0; /* 1: circular tag structure */
/*
* Return the filename required for the next gtag in the queue that was setup
* appropriate tag.
*/
static char *
-nextgtag()
+nextgtag(VOID_PARAM)
{
struct tag *tp;
* at the appropriate tag.
*/
static char *
-prevgtag()
+prevgtag(VOID_PARAM)
{
struct tag *tp;
* if it was unable to position at the tag, 0 if successful.
*/
static POSITION
-gtagsearch()
+gtagsearch(VOID_PARAM)
{
if (curtag == NULL)
return (NULL_POSITION); /* No gtags loaded! */
* |func 21 subr.c func(arg)
*
* The following commands write this format.
- * o Traditinal Ctags with -x option
- * o Global with -x option
- * See <http://www.gnu.org/software/global/global.html>
+ * o Traditinal Ctags with -x option
+ * o Global with -x option
+ * See <http://www.gnu.org/software/global/global.html>
*
* [extended format]
* <tag> <type> <lineno> <file> <image>
* |func function 21 subr.c func(arg)
*
* The following commands write this format.
- * o Exuberant Ctags with -x option
- * See <http://ctags.sourceforge.net>
+ * o Exuberant Ctags with -x option
+ * See <http://ctags.sourceforge.net>
*
* Returns 0 on success, -1 on error.
* The tag, file, and line will each be NUL-terminated pointers
*/
static int
getentry(buf, tag, file, line)
- char *buf; /* standard or extended ctags -x format data */
- char **tag; /* name of the tag we actually found */
- char **file; /* file in which to find this tag */
- char **line; /* line number of file where this tag is found */
+ char *buf; /* standard or extended ctags -x format data */
+ char **tag; /* name of the tag we actually found */
+ char **file; /* file in which to find this tag */
+ char **line; /* line number of file where this tag is found */
{
char *p = buf;
- for (*tag = p; *p && !IS_SPACE(*p); p++) /* tag name */
+ for (*tag = p; *p && !IS_SPACE(*p); p++) /* tag name */
;
if (*p == 0)
return (-1);
*p++ = 0;
- for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */
+ for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */
;
if (*p == 0)
return (-1);
*/
if (!IS_DIGIT(*p))
{
- for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */
+ for ( ; *p && !IS_SPACE(*p); p++) /* (skip tag type) */
;
- for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */
+ for (; *p && IS_SPACE(*p); p++) /* (skip blanks) */
;
}
if (!IS_DIGIT(*p))
return (-1);
- *line = p; /* line number */
+ *line = p; /* line number */
for (*line = p; *p && !IS_SPACE(*p); p++)
;
if (*p == 0)
return (-1);
*p++ = 0;
- for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */
+ for ( ; *p && IS_SPACE(*p); p++) /* (skip blanks) */
;
if (*p == 0)
return (-1);
- *file = p; /* file name */
+ *file = p; /* file name */
for (*file = p; *p && !IS_SPACE(*p); p++)
;
if (*p == 0)
return (0);
return (-1);
}
-
+
#endif