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