tags.c revision 1.3
1/*	$OpenBSD: tags.c,v 1.3 2001/11/19 19:02:14 mpech Exp $	*/
2
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
36public char *tagfile;
37public char *tags = "tags";
38
39static char *tagpattern;
40static int taglinenum;
41
42extern int linenums;
43extern int sigs;
44extern 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
53findtag(tag)
54	char *tag;
55{
56	char *p;
57	char *q;
58	FILE *f;
59	int taglen;
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
159tagsearch()
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
223