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
findtag(tag)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
tagsearch()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
221