Bump to 608
[platform/upstream/less.git] / tags.c
diff --git a/tags.c b/tags.c
index 0566be7..03e2973 100644 (file)
--- a/tags.c
+++ b/tags.c
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -10,7 +10,7 @@
 
 #include "less.h"
 
-#define        WHITESP(c)      ((c)==' ' || (c)=='\t')
+#define WHITESP(c)      ((c)==' ' || (c)=='\t')
 
 #if TAGS
 
@@ -22,6 +22,7 @@ static int curseq;
 
 extern int linenums;
 extern int sigs;
+extern int ctldisp;
 
 enum tag_result {
        TAG_FOUND,
@@ -35,21 +36,21 @@ enum tag_result {
  * 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.
@@ -63,15 +64,15 @@ struct taglist {
        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) \
@@ -88,9 +89,9 @@ static struct tag *curtag;
  * Delete tag structures.
  */
        public void
-cleantags()
+cleantags(VOID_PARAM)
 {
-       register struct tag *tp;
+       struct tag *tp;
 
        /*
         * Delete any existing tag list.
@@ -100,6 +101,8 @@ cleantags()
        while ((tp = taglist.tl_first) != TAG_END)
        {
                TAG_RM(tp);
+               free(tp->tag_file);
+               free(tp->tag_pattern);
                free(tp);
        }
        curtag = NULL;
@@ -117,7 +120,7 @@ maketagent(name, file, linenum, pattern, endline)
        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));
@@ -138,7 +141,7 @@ maketagent(name, file, linenum, pattern, endline)
  * Get tag mode.
  */
        public int
-gettagtype()
+gettagtype(VOID_PARAM)
 {
        int f;
 
@@ -170,7 +173,7 @@ gettagtype()
  */
        public void
 findtag(tag)
-       register char *tag;
+       char *tag;
 {
        int type = gettagtype();
        enum tag_result result;
@@ -200,7 +203,7 @@ findtag(tag)
  * Search for a tag.
  */
        public POSITION
-tagsearch()
+tagsearch(VOID_PARAM)
 {
        if (curtag == NULL)
                return (NULL_POSITION);  /* No gtags loaded! */
@@ -242,7 +245,7 @@ prevtag(n)
  * Return the total number of tags.
  */
        public int
-ntags()
+ntags(VOID_PARAM)
 {
        return total;
 }
@@ -251,7 +254,7 @@ ntags()
  * Return the sequence number of current tag.
  */
        public int
-curr_tag()
+curr_tag(VOID_PARAM)
 {
        return curseq;
 }
@@ -266,11 +269,12 @@ curr_tag()
  */
        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;
@@ -349,17 +353,24 @@ findctag(tag)
                        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);
@@ -377,34 +388,57 @@ findctag(tag)
  * 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 
@@ -418,7 +452,7 @@ ctagsearch()
                 * 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++;
 
@@ -439,19 +473,21 @@ ctagsearch()
                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);
                }
        }
 
@@ -471,10 +507,10 @@ ctagsearch()
  */
        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;
 
@@ -503,7 +539,7 @@ findgtag(tag, type)
                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)
@@ -563,7 +599,7 @@ findgtag(tag, 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.
@@ -597,7 +633,7 @@ findgtag(tag, type)
        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
@@ -605,7 +641,7 @@ static int circular = 0;    /* 1: circular tag structure */
  * appropriate tag.
  */
        static char *
-nextgtag()
+nextgtag(VOID_PARAM)
 {
        struct tag *tp;
 
@@ -635,7 +671,7 @@ nextgtag()
  * at the appropriate tag.
  */
        static char *
-prevgtag()
+prevgtag(VOID_PARAM)
 {
        struct tag *tp;
 
@@ -665,7 +701,7 @@ prevgtag()
  * 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! */
@@ -682,9 +718,9 @@ gtagsearch()
  * |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>
@@ -693,8 +729,8 @@ gtagsearch()
  * |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
@@ -702,19 +738,19 @@ gtagsearch()
  */
        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);
@@ -724,24 +760,24 @@ getentry(buf, tag, file, line)
         */
        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)
@@ -753,5 +789,5 @@ getentry(buf, tag, file, line)
                return (0);
        return (-1);
 }
-  
+
 #endif