Annotation of src/usr.bin/less/tags.c, Revision 1.1.1.1
1.1 etheisen 1: /*
2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice in the documentation and/or other materials provided with
12: * the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27:
28: #include "less.h"
29:
30: #define WHITESP(c) ((c)==' ' || (c)=='\t')
31:
32: #if TAGS
33:
34: public char *tagfile;
35: public char *tags = "tags";
36:
37: static char *tagpattern;
38: static int taglinenum;
39:
40: extern int linenums;
41: extern int sigs;
42: extern int jump_sline;
43:
44: /*
45: * Find a tag in the "tags" file.
46: * Sets "tagfile" to the name of the file containing the tag,
47: * and "tagpattern" to the search pattern which should be used
48: * to find the tag.
49: */
50: public void
51: findtag(tag)
52: register char *tag;
53: {
54: char *p;
55: char *q;
56: register FILE *f;
57: register int taglen;
58: int search_char;
59: int err;
60: static char tline[200];
61:
62: if ((f = fopen(tags, "r")) == NULL)
63: {
64: error("No tags file", NULL_PARG);
65: tagfile = NULL;
66: return;
67: }
68:
69: taglen = strlen(tag);
70:
71: /*
72: * Search the tags file for the desired tag.
73: */
74: while (fgets(tline, sizeof(tline), f) != NULL)
75: {
76: if (strncmp(tag, tline, taglen) != 0 || !WHITESP(tline[taglen]))
77: continue;
78:
79: /*
80: * Found it.
81: * The line contains the tag, the filename and the
82: * location in the file, separated by white space.
83: * The location is either a decimal line number,
84: * or a search pattern surrounded by a pair of delimiters.
85: * Parse the line and extract these parts.
86: */
87: tagfile = tagpattern = NULL;
88: taglinenum = 0;
89:
90: /*
91: * Skip over the whitespace after the tag name.
92: */
93: p = skipsp(tline+taglen);
94: if (*p == '\0')
95: /* File name is missing! */
96: continue;
97:
98: /*
99: * Save the file name.
100: * Skip over the whitespace after the file name.
101: */
102: tagfile = p;
103: while (!WHITESP(*p) && *p != '\0')
104: p++;
105: *p++ = '\0';
106: p = skipsp(p);
107: if (*p == '\0')
108: /* Pattern is missing! */
109: continue;
110:
111: /*
112: * First see if it is a line number.
113: */
114: taglinenum = getnum(&p, 0, &err);
115: if (err)
116: {
117: /*
118: * No, it must be a pattern.
119: * Delete the initial "^" (if present) and
120: * the final "$" from the pattern.
121: * Delete any backslash in the pattern.
122: */
123: taglinenum = 0;
124: search_char = *p++;
125: if (*p == '^')
126: p++;
127: tagpattern = q = p;
128: while (*p != search_char && *p != '\0')
129: {
130: if (*p == '\\')
131: p++;
132: *q++ = *p++;
133: }
134: if (q[-1] == '$')
135: q--;
136: *q = '\0';
137: }
138:
139: fclose(f);
140: return;
141: }
142: fclose(f);
143: error("No such tag in tags file", NULL_PARG);
144: tagfile = NULL;
145: }
146:
147: /*
148: * Search for a tag.
149: * This is a stripped-down version of search().
150: * We don't use search() for several reasons:
151: * - We don't want to blow away any search string we may have saved.
152: * - The various regular-expression functions (from different systems:
153: * regcmp vs. re_comp) behave differently in the presence of
154: * parentheses (which are almost always found in a tag).
155: */
156: public POSITION
157: tagsearch()
158: {
159: POSITION pos, linepos;
160: int linenum;
161: char *line;
162:
163: /*
164: * If we have the line number of the tag instead of the pattern,
165: * just use find_pos.
166: */
167: if (taglinenum)
168: return (find_pos(taglinenum));
169:
170: pos = ch_zero();
171: linenum = find_linenum(pos);
172:
173: for (;;)
174: {
175: /*
176: * Get lines until we find a matching one or
177: * until we hit end-of-file.
178: */
179: if (ABORT_SIGS())
180: return (NULL_POSITION);
181:
182: /*
183: * Read the next line, and save the
184: * starting position of that line in linepos.
185: */
186: linepos = pos;
187: pos = forw_raw_line(pos, &line);
188: if (linenum != 0)
189: linenum++;
190:
191: if (pos == NULL_POSITION)
192: {
193: /*
194: * We hit EOF without a match.
195: */
196: error("Tag not found", NULL_PARG);
197: return (NULL_POSITION);
198: }
199:
200: /*
201: * If we're using line numbers, we might as well
202: * remember the information we have now (the position
203: * and line number of the current line).
204: */
205: if (linenums)
206: add_lnum(linenum, pos);
207:
208: /*
209: * Test the line to see if we have a match.
210: * Use strncmp because the pattern may be
211: * truncated (in the tags file) if it is too long.
212: */
213: if (strncmp(tagpattern, line, strlen(tagpattern)) == 0)
214: break;
215: }
216:
217: return (linepos);
218: }
219:
220: #endif