root/htags/anchor.c(240.html)

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cmp
  2. anchor_prepare
  3. anchor_load
  4. anchor_unload
  5. anchor_first
  6. anchor_next
  7. anchor_get
  8. define_line
  9. anchor_getlinks
  10. anchor_dump

/*
 * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
 *      2008    Tama Communications Corporation
 *
 * This file is part of GNU GLOBAL.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #ifdef STDC_HEADERS #include <stdlib.h> #endif #ifdef HAVE_STRING_H #include <string.h> #else #include <strings.h> #endif #ifdef HAVE_CTYPE_H #include <ctype.h> #endif #include "global.h" #include "anchor.h" #include "htags.h" static XARGS *anchor_input[GTAGLIM]; static struct anchor *table; static VARRAY *vb; static struct anchor *start; static struct anchor *curp; static struct anchor *end; static struct anchor *CURRENT; /* compare routine for qsort(3) */
static int cmp(const void *s1, const void *s2) { return ((struct anchor *)s1)->lineno - ((struct anchor *)s2)->lineno; } /* * Pointers (as lineno). */
static int FIRST; static int LAST; static struct anchor *CURRENTDEF; /* * anchor_prepare: setup input stream. * * i) anchor_stream file pointer of path list */
void anchor_prepare(FILE *anchor_stream) { /* * Option table: * We use blank string as null option instead of null string("") * not to change the command length. This length influences * the number of arguments in the xargs processing. */
char *options[] = {NULL, " ", "r", "s"}; char comline[MAXFILLEN]; int db; for (db = GTAGS; db < GTAGLIM; db++) { anchor_input[db] = NULL; /* * Htags(1) should not use gtags-parser(1) directly; * it should use global(1) with the -f option instead. * Because gtags-parser is part of the implementation of * gtags(1) and global(1), and htags is only an application * program which uses global(1). If htags depends on * gtags-parser, it will become difficult to change the * implementation of gtags and global. * * Though the output of global -f is not necessarily sorted * by the path, it is guaranteed that the records concerning * the same file are consecutive. */
if (gtags_exist[db] == 1) { snprintf(comline, sizeof(comline), "%s -f%s --nofilter=path", global_path, options[db]); anchor_input[db] = xargs_open_with_file(comline, 0, anchor_stream); } } } /* * anchor_load: load anchor table * * i) path path name */
void anchor_load(const char *path) { int db; FIRST = LAST = 0; end = CURRENT = NULL; if (vb == NULL) vb = varray_open(sizeof(struct anchor), 1000); else varray_reset(vb); for (db = GTAGS; db < GTAGLIM; db++) { XARGS *xp; char *ctags_x; if ((xp = anchor_input[db]) == NULL) continue; /* * Read from input stream until it reaches end of file * or the line of another file appears. */
while ((ctags_x = xargs_read(xp)) != NULL) { SPLIT ptable; struct anchor *a; int type; if (split(ctags_x, 4, &ptable) < 4) { recover(&ptable); die("too small number of parts in anchor_load().\n'%s'", ctags_x); } if (!locatestring(ptable.part[PART_PATH].start, "./", MATCH_AT_FIRST)) { recover(&ptable); die("The output of parser is illegal.\n%s", ctags_x); } if (strcmp(ptable.part[PART_PATH].start, path) != 0) { recover(&ptable); xargs_unread(xp); break; } if (db == GTAGS) { char *p = ptable.part[PART_LINE].start; for (; *p && isspace((unsigned char)*p); p++) ; if (!*p) { recover(&ptable); die("The output of parser is illegal.\n%s", ctags_x); } /* * Function header is applied only to the anchor whoes type is 'D'. * (D: function, M: macro, T: type) */
type = 'T'; if (*p == '#') type = 'M'; else if (locatestring(p, "typedef", MATCH_AT_FIRST)) type = 'T'; else if ((p = locatestring(p, ptable.part[PART_TAG].start, MATCH_FIRST)) != NULL) { /* skip a tag and the following blanks */
p += strlen(ptable.part[PART_TAG].start); for (; *p && isspace((unsigned char)*p); p++) ; if (*p == '(') type = 'D'; } } else if (db == GRTAGS) type = 'R'; else type = 'Y'; /* allocate an entry */
a = varray_append(vb); a->lineno = atoi(ptable.part[PART_LNO].start); a->type = type; a->done = 0; settag(a, ptable.part[PART_TAG].start); recover(&ptable); } if (ctags_x == NULL) { xargs_close(anchor_input[db]); anchor_input[db] = NULL; } } if (vb->length == 0) { table = NULL; } else { int i, used = vb->length; /* * Sort by lineno. */
table = varray_assign(vb, 0, 0); qsort(table, used, sizeof(struct anchor), cmp); /* * Setup some lineno. */
for (i = 0; i < used; i++) if (table[i].type == 'D') break; if (i < used) FIRST = table[i].lineno; for (i = used - 1; i >= 0; i--) if (table[i].type == 'D') break; if (i >= 0) LAST = table[i].lineno; } /* * Setup loop range. */
start = table; curp = NULL; end = &table[vb->length]; /* anchor_dump(stderr, 0);*/
} /* * anchor_unload: unload anchor table */
void anchor_unload(void) { struct anchor *a; for (a = start; a && a < end; a++) { if (a->reserve) { free(a->reserve); a->reserve = NULL; } } /* We don't free varray */
/* varray_close(vb); */
FIRST = LAST = 0; start = curp = end = NULL; } /* * anchor_first: return the first anchor */
struct anchor * anchor_first(void) { if (!start || start == end) return NULL; CURRENT = start; if (CURRENT->type == 'D') CURRENTDEF = CURRENT; return CURRENT; } /* * anchor_next: return the next anchor */
struct anchor * anchor_next(void) { if (!start) return NULL; if (++CURRENT >= end) return NULL; if (CURRENT->type == 'D') CURRENTDEF = CURRENT; return CURRENT; } /* * anchor_get: return the specified anchor * * i) name name of anchor * i) length lenght of the name * i) type ==0: not specified * !=0: D, M, T, R, Y */
struct anchor * anchor_get(const char *name, int length, int type, int lineno) { struct anchor *p = curp ? curp : start; if (table == NULL) return NULL; if (p->lineno > lineno) return NULL; /* * set pointer to the top of the cluster. */
for (; p < end && p->lineno < lineno; p++) ; if (p >= end || p->lineno != lineno) return NULL; curp = p; for (; p < end && p->lineno == lineno; p++) if (!p->done && p->length == length && !strcmp(gettag(p), name)) if (!type || p->type == type) return p; return NULL; } /* * define_line: check whether or not this is a define line. * * i) lineno line number * go) curp pointer to the current cluster * r) 1: definition, 0: not definition */
int define_line(int lineno) { struct anchor *p = curp ? curp : start; if (table == NULL) return 0; if (p->lineno > lineno) return 0; /* * set pointer to the top of the cluster. */
for (; p < end && p->lineno < lineno; p++) ; if (p >= end || p->lineno != lineno) return 0; curp = p; for (; p < end && p->lineno == lineno; p++) if (p->type == 'D') return 1; return 0; } /* * anchor_getlinks: return anchor link array * (previous, next, first, last, top, bottom) */
int * anchor_getlinks(int lineno) { static int ref[A_SIZE]; int i; for (i = 0; i < A_SIZE; i++) ref[i] = 0; if (lineno >= 1 && start) { struct anchor *c, *p; if (CURRENTDEF == NULL) { for (c = start; c < end; c++) if (c->lineno == lineno && c->type == 'D') break; CURRENTDEF = c; } else { for (c = CURRENTDEF; c >= start; c--) if (c->lineno == lineno && c->type == 'D') break; } for (p = c - 1; p >= start; p--) if (p->type == 'D') { ref[A_PREV] = p->lineno; break; } for (p = c + 1; p < end; p++) if (p->type == 'D') { ref[A_NEXT] = p->lineno; break; } } if (FIRST > 0 && lineno != FIRST) ref[A_FIRST] = FIRST; if (LAST > 0 && lineno != LAST) ref[A_LAST] = LAST; if (lineno != 0) ref[A_TOP] = -1; if (lineno != -1) ref[A_BOTTOM] = -2; if (FIRST > 0 && FIRST == LAST) { if (lineno == 0) ref[A_LAST] = 0; if (lineno == -1) ref[A_FIRST] = 0; } return ref; } void anchor_dump(FILE *op, int lineno) { struct anchor *a; if (op == NULL) op = stderr; for (a = start; a < end ; a++) if (lineno == 0 || a->lineno == lineno) fprintf(op, "%d %s(%c)\n", a->lineno, gettag(a), a->type); }

/* [<][>][^][v][top][bottom][index][help] */