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