From 1b28029810e9c377087ea5a45acc8767cf0196b3 Mon Sep 17 00:00:00 2001 From: ps Date: Mon, 22 May 2000 09:53:22 +0000 Subject: 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/ --- contrib/less/tags.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 contrib/less/tags.c (limited to 'contrib/less/tags.c') 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 -- cgit v1.1