home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less3292.zip / tags.c < prev    next >
C/C++ Source or Header  |  1996-08-21  |  6KB  |  246 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995,1996  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 *tags = "tags";
  35.  
  36. static char *tagfile;
  37. static char *tagpattern;
  38. static int taglinenum;
  39. static int tagendline;
  40.  
  41. extern int linenums;
  42. extern int sigs;
  43. extern int jump_sline;
  44.  
  45. /*
  46.  * Find a tag in the "tags" file.
  47.  * Sets "tagfile" to the name of the file containing the tag,
  48.  * and "tagpattern" to the search pattern which should be used
  49.  * to find the tag.
  50.  */
  51.     public void
  52. findtag(tag)
  53.     register char *tag;
  54. {
  55.     char *p;
  56.     char *q;
  57.     register FILE *f;
  58.     register int taglen;
  59.     int search_char;
  60.     int err;
  61.     char tline[TAGLINE_SIZE];
  62.  
  63.     p = unquote_file(tags);
  64.     f = fopen(p, "r");
  65.     free(p);
  66.     if (f == NULL)
  67.     {
  68.         error("No tags file", NULL_PARG);
  69.         tagfile = NULL;
  70.         return;
  71.     }
  72.  
  73.     taglen = strlen(tag);
  74.  
  75.     /*
  76.      * Search the tags file for the desired tag.
  77.      */
  78.     while (fgets(tline, sizeof(tline), f) != NULL)
  79.     {
  80.         if (strncmp(tag, tline, taglen) != 0 || !WHITESP(tline[taglen]))
  81.             continue;
  82.  
  83.         /*
  84.          * Found it.
  85.          * The line contains the tag, the filename and the
  86.          * location in the file, separated by white space.
  87.          * The location is either a decimal line number, 
  88.          * or a search pattern surrounded by a pair of delimiters.
  89.          * Parse the line and extract these parts.
  90.          */
  91.         tagfile = tagpattern = NULL;
  92.         taglinenum = 0;
  93.  
  94.         /*
  95.          * Skip over the whitespace after the tag name.
  96.          */
  97.         p = skipsp(tline+taglen);
  98.         if (*p == '\0')
  99.             /* File name is missing! */
  100.             continue;
  101.  
  102.         /*
  103.          * Save the file name.
  104.          * Skip over the whitespace after the file name.
  105.          */
  106.         tagfile = p;
  107.         while (!WHITESP(*p) && *p != '\0')
  108.             p++;
  109.         *p++ = '\0';
  110.         p = skipsp(p);
  111.         if (*p == '\0')
  112.             /* Pattern is missing! */
  113.             continue;
  114.         tagfile = save(tagfile);
  115.  
  116.         /*
  117.          * First see if it is a line number. 
  118.          */
  119.         taglinenum = getnum(&p, 0, &err);
  120.         if (err)
  121.         {
  122.             /*
  123.              * No, it must be a pattern.
  124.              * Delete the initial "^" (if present) and 
  125.              * the final "$" from the pattern.
  126.              * Delete any backslash in the pattern.
  127.              */
  128.             taglinenum = 0;
  129.             search_char = *p++;
  130.             if (*p == '^')
  131.                 p++;
  132.             tagpattern = (char *) ecalloc(strlen(p)+1, sizeof(char));
  133.             q = tagpattern;
  134.             while (*p != search_char && *p != '\0')
  135.             {
  136.                 if (*p == '\\')
  137.                     p++;
  138.                 *q++ = *p++;
  139.             }
  140.             tagendline = (q[-1] == '$');
  141.             if (tagendline)
  142.                 q--;
  143.             *q = '\0';
  144.         }
  145.  
  146.         fclose(f);
  147.         return;
  148.     }
  149.     fclose(f);
  150.     error("No such tag in tags file", NULL_PARG);
  151.     tagfile = NULL;
  152. }
  153.  
  154.     public int
  155. edit_tagfile()
  156. {
  157.     int r;
  158.  
  159.     if (tagfile == NULL)
  160.         return (1);
  161.     r = edit(tagfile);
  162.     free(tagfile);
  163.     tagfile = NULL;
  164.     return (r);
  165. }
  166.  
  167. /*
  168.  * Search for a tag.
  169.  * This is a stripped-down version of search().
  170.  * We don't use search() for several reasons:
  171.  *   -    We don't want to blow away any search string we may have saved.
  172.  *   -    The various regular-expression functions (from different systems:
  173.  *    regcmp vs. re_comp) behave differently in the presence of 
  174.  *    parentheses (which are almost always found in a tag).
  175.  */
  176.     public POSITION
  177. tagsearch()
  178. {
  179.     POSITION pos, linepos;
  180.     int linenum;
  181.     char *line;
  182.  
  183.     /*
  184.      * If we have the line number of the tag instead of the pattern,
  185.      * just use find_pos.
  186.      */
  187.     if (taglinenum)
  188.         return (find_pos(taglinenum));
  189.  
  190.     pos = ch_zero();
  191.     linenum = find_linenum(pos);
  192.  
  193.     for (;;)
  194.     {
  195.         /*
  196.          * Get lines until we find a matching one or 
  197.          * until we hit end-of-file.
  198.          */
  199.         if (ABORT_SIGS())
  200.             return (NULL_POSITION);
  201.  
  202.         /*
  203.          * Read the next line, and save the 
  204.          * starting position of that line in linepos.
  205.          */
  206.         linepos = pos;
  207.         pos = forw_raw_line(pos, &line);
  208.         if (linenum != 0)
  209.             linenum++;
  210.  
  211.         if (pos == NULL_POSITION)
  212.         {
  213.             /*
  214.              * We hit EOF without a match.
  215.              */
  216.             error("Tag not found", NULL_PARG);
  217.             return (NULL_POSITION);
  218.         }
  219.  
  220.         /*
  221.          * If we're using line numbers, we might as well
  222.          * remember the information we have now (the position
  223.          * and line number of the current line).
  224.          */
  225.         if (linenums)
  226.             add_lnum(linenum, pos);
  227.  
  228.         /*
  229.          * Test the line to see if we have a match.
  230.          * Use strncmp because the pattern may be
  231.          * truncated (in the tags file) if it is too long.
  232.          * If tagendline is set, make sure we match all
  233.          * the way to end of line (no extra chars after the match).
  234.          */
  235.         if (strncmp(tagpattern, line, strlen(tagpattern)) == 0 &&
  236.             (!tagendline || line[strlen(tagpattern)] == '\0'))
  237.             break;
  238.     }
  239.  
  240.     free(tagpattern);
  241.     tagpattern = NULL;
  242.     return (linepos);
  243. }
  244.  
  245. #endif
  246.