summaryrefslogtreecommitdiffstats
path: root/contrib/less/tags.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2000-05-22 09:53:22 +0000
committerps <ps@FreeBSD.org>2000-05-22 09:53:22 +0000
commit1b28029810e9c377087ea5a45acc8767cf0196b3 (patch)
tree27b16fc210b9a302c9e74f90e36a9b5ed21e6300 /contrib/less/tags.c
downloadFreeBSD-src-1b28029810e9c377087ea5a45acc8767cf0196b3.zip
FreeBSD-src-1b28029810e9c377087ea5a45acc8767cf0196b3.tar.gz
Import the [now] dual licensed version 3.5.4 of less. It is
distributed under your choice of the GPL or a BSD style license. Reviewed by: peter Obtained from: http://home.flash.net/~marknu/less/
Diffstat (limited to 'contrib/less/tags.c')
-rw-r--r--contrib/less/tags.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/contrib/less/tags.c b/contrib/less/tags.c
new file mode 100644
index 0000000..cf531a6
--- /dev/null
+++ b/contrib/less/tags.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 1984-2000 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.
+ *
+ * For more information about less, or for information on how to
+ * contact the author, see the README file.
+ */
+
+
+#include "less.h"
+
+#define WHITESP(c) ((c)==' ' || (c)=='\t')
+
+#if TAGS
+
+public char *tags = "tags";
+
+static char *tagfile;
+static char *tagpattern;
+static int taglinenum;
+static int tagendline;
+
+extern int linenums;
+extern int sigs;
+extern int jump_sline;
+
+/*
+ * Find a tag in the "tags" file.
+ * Sets "tagfile" to the name of the file containing the tag,
+ * and "tagpattern" to the search pattern which should be used
+ * to find the tag.
+ */
+ public void
+findtag(tag)
+ register char *tag;
+{
+ char *p;
+ char *q;
+ register FILE *f;
+ register int taglen;
+ int search_char;
+ int err;
+ char tline[TAGLINE_SIZE];
+
+ p = unquote_file(tags);
+ f = fopen(p, "r");
+ free(p);
+ if (f == NULL)
+ {
+ error("No tags file", NULL_PARG);
+ tagfile = NULL;
+ return;
+ }
+
+ taglen = strlen(tag);
+
+ /*
+ * Search the tags file for the desired tag.
+ */
+ while (fgets(tline, sizeof(tline), f) != NULL)
+ {
+ if (strncmp(tag, tline, taglen) != 0 || !WHITESP(tline[taglen]))
+ continue;
+
+ /*
+ * Found it.
+ * The line contains the tag, the filename and the
+ * location in the file, separated by white space.
+ * The location is either a decimal line number,
+ * or a search pattern surrounded by a pair of delimiters.
+ * Parse the line and extract these parts.
+ */
+ tagfile = tagpattern = NULL;
+ taglinenum = 0;
+
+ /*
+ * Skip over the whitespace after the tag name.
+ */
+ p = skipsp(tline+taglen);
+ if (*p == '\0')
+ /* File name is missing! */
+ continue;
+
+ /*
+ * Save the file name.
+ * Skip over the whitespace after the file name.
+ */
+ tagfile = p;
+ while (!WHITESP(*p) && *p != '\0')
+ p++;
+ *p++ = '\0';
+ p = skipsp(p);
+ if (*p == '\0')
+ /* Pattern is missing! */
+ continue;
+ tagfile = save(tagfile);
+
+ /*
+ * First see if it is a line number.
+ */
+ taglinenum = getnum(&p, 0, &err);
+ if (err)
+ {
+ /*
+ * No, it must be a pattern.
+ * Delete the initial "^" (if present) and
+ * the final "$" from the pattern.
+ * Delete any backslash in the pattern.
+ */
+ taglinenum = 0;
+ search_char = *p++;
+ if (*p == '^')
+ p++;
+ tagpattern = (char *) ecalloc(strlen(p)+1, sizeof(char));
+ q = tagpattern;
+ while (*p != search_char && *p != '\0')
+ {
+ if (*p == '\\')
+ p++;
+ *q++ = *p++;
+ }
+ tagendline = (q[-1] == '$');
+ if (tagendline)
+ q--;
+ *q = '\0';
+ }
+
+ fclose(f);
+ return;
+ }
+ fclose(f);
+ error("No such tag in tags file", NULL_PARG);
+ tagfile = NULL;
+}
+
+ public int
+edit_tagfile()
+{
+ int r;
+
+ if (tagfile == NULL)
+ return (1);
+ r = edit(tagfile);
+ free(tagfile);
+ tagfile = NULL;
+ return (r);
+}
+
+/*
+ * 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).
+ */
+ public POSITION
+tagsearch()
+{
+ POSITION pos, linepos;
+ int linenum;
+ int len;
+ char *line;
+
+ /*
+ * If we have the line number of the tag instead of the pattern,
+ * just use find_pos.
+ */
+ if (taglinenum)
+ return (find_pos(taglinenum));
+
+ pos = ch_zero();
+ linenum = find_linenum(pos);
+
+ for (;;)
+ {
+ /*
+ * Get lines until we find a matching one or
+ * until we hit end-of-file.
+ */
+ if (ABORT_SIGS())
+ return (NULL_POSITION);
+
+ /*
+ * Read the next line, and save the
+ * starting position of that line in linepos.
+ */
+ linepos = pos;
+ pos = forw_raw_line(pos, &line);
+ if (linenum != 0)
+ linenum++;
+
+ if (pos == NULL_POSITION)
+ {
+ /*
+ * We hit EOF without a match.
+ */
+ error("Tag not found", NULL_PARG);
+ return (NULL_POSITION);
+ }
+
+ /*
+ * If we're using line numbers, we might as well
+ * remember the information we have now (the position
+ * and line number of the current line).
+ */
+ 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 = strlen(tagpattern);
+ if (strncmp(tagpattern, line, len) == 0 &&
+ (!tagendline || line[len] == '\0' || line[len] == '\r'))
+ break;
+ }
+
+ free(tagpattern);
+ tagpattern = NULL;
+ return (linepos);
+}
+
+#endif
OpenPOWER on IntegriCloud