Exemplo n.º 1
0
static void
load_notfunction(const char *filename)
{
	FILE *ip;
	STRBUF *sb = strbuf_open(0);
	STRBUF *ib = strbuf_open(0);
	char *p;
	int i;

	if ((ip = fopen(filename, "r")) == NULL)
		die("'%s' cannot read.", filename);
	for (tablesize = 0; (p = strbuf_fgets(ib, ip, STRBUF_NOCRLF)) != NULL; tablesize++)
		strbuf_puts0(sb, p);
	fclose(ip);
	words = (struct words *)check_malloc(sizeof(struct words) * tablesize);
	/*
	 * Don't free *p.
	 */
	p = (char *)check_malloc(strbuf_getlen(sb) + 1);
	memcpy(p, strbuf_value(sb), strbuf_getlen(sb) + 1);
	for (i = 0; i < tablesize; i++) {
		words[i].name = p;
		p += strlen(p) + 1;
	}
	qsort(words, tablesize, sizeof(struct words), cmp);
	strbuf_close(sb);
	strbuf_close(ib);
}
Exemplo n.º 2
0
/*
 * gpath_put: put path name
 *
 *	i)	path	path name
 *	i)	type	path type
 *			GPATH_SOURCE: source file
 *			GPATH_OTHER: other file
 */
void
gpath_put(const char *path, int type)
{
	char fid[MAXFIDLEN];
	STATIC_STRBUF(sb);

	assert(opened > 0);
	if (_mode == 1 && created)
		return;
	if (dbop_get(dbop, path) != NULL)
		return;
	/*
	 * generate new file id for the path.
	 */
	snprintf(fid, sizeof(fid), "%d", _nextkey++);
	/*
	 * path => fid mapping.
	 */
	strbuf_clear(sb);
	strbuf_puts0(sb, fid);
	if (type == GPATH_OTHER)
		strbuf_puts0(sb, "o");
	dbop_put_withlen(dbop, path, strbuf_value(sb), strbuf_getlen(sb));
	/*
	 * fid => path mapping.
	 */
	strbuf_clear(sb);
	strbuf_puts0(sb, path);
	if (type == GPATH_OTHER)
		strbuf_puts0(sb, "o");
	dbop_put_withlen(dbop, fid, strbuf_value(sb), strbuf_getlen(sb));
}
Exemplo n.º 3
0
/*
 * convertpath: convert source file into hypertext path.
 *
 *	i)	dbpath	dbpath
 *	i)	htmldir	HTML directory made by htags(1)
 *	i)	path	source file path
 *	o)	sb	string buffer
 *	r)		0: normal, -1: error
 */
int
convertpath(const char *dbpath, const char *htmldir, const char *path, STRBUF *sb)
{
	static const char *suffix[] = {".html", ".htm"};
	static const char *gz = ".gz";
	int i, lim = sizeof(suffix)/sizeof(char *);
	const char *p;

	strbuf_reset(sb);
	strbuf_puts(sb, htmldir);
	strbuf_puts(sb, "/S/");
	/*
	 * new style.
	 */
	if (gpath_open(dbpath, 0) == 0) {
		int tag1 = strbuf_getlen(sb);

		p = gpath_path2fid(path, NULL);
		if (p == NULL) {
			gpath_close();
			return -1;
		}
		gpath_close();
		strbuf_puts(sb, p);
		for (i = 0; i < lim; i++) {
			int tag2 = strbuf_getlen(sb);
			strbuf_puts(sb, suffix[i]);
			if (test("f", strbuf_value(sb)))
				return 0;
			strbuf_puts(sb, gz);
			if (test("f", strbuf_value(sb)))
				return 0;
			strbuf_setlen(sb, tag2);
		}
		strbuf_setlen(sb, tag1);
	}
	/*
	 * old style.
	 */
	for (p = path + 1; *p; p++)
		strbuf_putc(sb, (*p == '/') ? ' ' : *p);
	for (i = 0; i < lim; i++) {
		int tag = strbuf_getlen(sb);
		strbuf_puts(sb, suffix[i]);
		if (test("f", strbuf_value(sb)))
			return 0;
		strbuf_puts(sb, gz);
		if (test("f", strbuf_value(sb)))
			return 0;
		strbuf_setlen(sb, tag);
	}
	return -1;
}
Exemplo n.º 4
0
/*
 * convert_open: open convert filter
 *
 *	i)	type	PATH_ABSOLUTE, PATH_RELATIVE, PATH_THROUGH
 *	i)	format	tag record format
 *	i)	root	root directory of source tree
 *	i)	cwd	current directory
 *	i)	dbpath	dbpath directory
 *	i)	op	output file
 */
CONVERT *
convert_open(int type, int format, const char *root, const char *cwd, const char *dbpath, FILE *op)
{
	CONVERT *cv = (CONVERT *)check_calloc(sizeof(CONVERT), 1);
	/*
	 * set base directory.
	 */
	cv->abspath = strbuf_open(MAXPATHLEN);
	strbuf_puts(cv->abspath, root);
	strbuf_unputc(cv->abspath, '/');
	cv->start_point = strbuf_getlen(cv->abspath);
	/*
	 * copy elements.
	 */
	if (strlen(cwd) > MAXPATHLEN)
		die("current directory name too long.");
	strlimcpy(cv->basedir, cwd, sizeof(cv->basedir));
	cv->type = type;
	cv->format = format;
	cv->op = op;
	/*
	 * open GPATH.
	 */
	if (gpath_open(dbpath, 0) < 0)
		die("GPATH not found.");
	return cv;
}
Exemplo n.º 5
0
/**
 * Load text from file with replacing @CODE{\@PARENT_DIR\@} macro.
 * Macro @CODE{\@PARENT_DIR\@} is replaced with the parent directory
 * of the @FILE{HTML} directory.
 */
static const char *
sed(FILE *ip, int place)
{
    STATIC_STRBUF(sb);
    const char *parent_dir = (place == SUBDIR) ? "../.." : "..";
    int c, start_position = -1;

    strbuf_clear(sb);
    while ((c = fgetc(ip)) != EOF) {
        strbuf_putc(sb, c);
        if (c == '@') {
            int curpos = strbuf_getlen(sb);
            if (start_position == -1) {
                start_position = curpos - 1;
            } else {
                if (!strncmp("@PARENT_DIR@",
                             strbuf_value(sb) + start_position,
                             curpos - start_position))
                {
                    strbuf_setlen(sb, start_position);
                    strbuf_puts(sb, parent_dir);
                    start_position = -1;
                } else {
                    start_position = curpos - 1;
                }
            }
        } else if (!isalpha(c) && c != '_') {
            if (start_position != -1)
                start_position = -1;
        }
    }
    return strbuf_value(sb);
}
Exemplo n.º 6
0
Arquivo: find.c Projeto: kosaki/gtags
/*
 * find_open: start iterator without GPATH.
 *
 *	i)	start	start directory
 *			If NULL, assumed '.' directory.
 */
void
find_open(const char *start)
{
	struct stack_entry *curp;
	assert(find_mode == 0);
	find_mode = FIND_OPEN;

	/*
	 * This is temporary measures. It doesn't decide how to become final.
	 */
	if (getenv("GTAGSALLOWBLANK"))
		allow_blank = 1;
	if (!start)
		start = "./";
	/*
	 * setup stack.
	 */
	stack = varray_open(sizeof(struct stack_entry), 50);
	current_entry = 0;
	curp = varray_assign(stack, current_entry, 1);
	strlimcpy(dir, start, sizeof(dir));
	curp->dirp = dir + strlen(dir);
	curp->sb = strbuf_open(0);
	if (getdirs(dir, curp->sb) < 0)
		die("cannot open '.' directory.");
	curp->start = curp->p = strbuf_value(curp->sb);
	curp->end   = curp->start + strbuf_getlen(curp->sb);

	/*
	 * prepare regular expressions.
	 */
	prepare_source();
	prepare_skip();
}
Exemplo n.º 7
0
/**
 * xargs_open_with_strbuf: open xargs stream using string buffer
 *
 *	@param[in]	command	command skeleton.
 *	@param[in]	max_args 0: no limit, \>0: max argument
 *	@param[in]	sb	string buffer
 *	@return		xargs structure
 *
 * The @CODE{'\%s'} in the command skeleton is replaced with given arguments. <br>
 * If @CODE{'\%s'} doesn't exist, the arguments is appended to the tail of the
 * skeleton.
 */
XARGS *
xargs_open_with_strbuf(const char *command, int max_args, STRBUF *sb)
{
	XARGS *xp = xargs_open_generic(command, max_args);

	xp->type = XARGS_STRBUF;
	xp->curp = strbuf_value(sb);
	xp->endp = xp->curp + strbuf_getlen(sb);
	return xp;
}
Exemplo n.º 8
0
/**
 * strtrim: make string from original string with deleting blanks.
 *
 *	@param[in]	p	original string.
 *	@param[in]	flag	TRIM_HEAD:	from only head,
 *			TRIM_TAIL:	from only tail,
 *			TRIM_BOTH:	from head and tail,
 *			TRIM_ALL:	from all
 *	@param[out]	len	length of result string,
 *			if len == NULL then nothing returned.
 *	@return		result string
 *
 * Usage:
 *	strtrim(" # define ", TRIM_HEAD, NULL)	=> "# define "
 *	strtrim(" # define ", TRIM_TAIL, NULL)	=> " # define"
 *	strtrim(" # define ", TRIM_BOTH, NULL)	=> "# define"
 *	strtrim(" # define ", TRIM_ALL, NULL)	=> "#define"
 *
 * [Note] The result string area is function local. So, following call
 *	 to this function may destroy the area.
 */
const char *
strtrim(const char *p, int flag, int *len)
{
	STATIC_STRBUF(sb);
	int cut_off = -1;

	strbuf_clear(sb);
	/*
	 * Delete blanks of the head.
	 */
	if (flag != TRIM_TAIL)
		SKIP_BLANKS(p);
	/*
	 * Copy string.
	 */
	for (; *p; p++) {
		if (isspace(*p)) {
			if (flag != TRIM_ALL) {
				if (cut_off == -1 && flag != TRIM_HEAD)
					cut_off = strbuf_getlen(sb);
				strbuf_putc(sb,*p);
			}
		} else {
			strbuf_putc(sb,*p);
			cut_off = -1;
		}
	}
	/*
	 * Delete blanks of the tail.
	 */
	if (cut_off != -1)
		strbuf_setlen(sb, cut_off);
	if (len)
		*len = strbuf_getlen(sb);
	return strbuf_value(sb);
}
Exemplo n.º 9
0
static int
single_select_callback(void *v, int argc, char **argv, char **colname) {
	STATIC_STRBUF(sb);
	DBOP *dbop = (DBOP *)v;

	if (argc > 0) {
		strbuf_clear(sb);
		strbuf_puts(sb, argv[0]);
		dbop->lastsize = strbuf_getlen(sb);
		if (argv[1]) {
			strbuf_putc(sb, '\0');
			strbuf_puts(sb, argv[1]);
		}
		dbop->lastdat = strbuf_value(sb);
		dbop->lastflag = argv[1] ? dbop->lastdat + dbop->lastsize + 1 : NULL;
	} else {
		dbop->lastdat = NULL;
		dbop->lastflag = NULL;
		dbop->lastsize = 0;
	}
	return SQLITE_OK;
}
Exemplo n.º 10
0
/**
 * dbop_put_path: put data and flag by a key.
 *
 *	@param[in]	dbop	descripter
 *	@param[in]	name	key
 *	@param[in]	data	data
 *	@param[in]	flag	flag
 *
 * [Note] This function doesn't support sorted writing.
 */
void
dbop_put_path(DBOP *dbop, const char *name, const char *data, const char *flag)
{
	STATIC_STRBUF(sb);
	DB *db = dbop->db;
	DBT key, dat;
	int status;
	int len;

#ifdef USE_SQLITE3
	if (dbop->openflags & DBOP_SQLITE3) {
		dbop3_put(dbop, name, data, flag);
		return;
	}
#endif
	if (!(len = strlen(name)))
		die("primary key size == 0.");
	if (len > MAXKEYLEN)
		die("primary key too long.");
	strbuf_clear(sb);
	strbuf_puts0(sb, data);
	if (flag)
		strbuf_puts0(sb, flag);
	key.data = (char *)name;
	key.size = len+1;
	dat.data = strbuf_value(sb);
	dat.size = strbuf_getlen(sb);

	status = (*db->put)(db, &key, &dat, 0);
	switch (status) {
	case RET_SUCCESS:
		break;
	case RET_ERROR:
	case RET_SPECIAL:
		die("%s", dbop->put_errmsg ? dbop->put_errmsg : "dbop_put_path failed.");
	}
}
Exemplo n.º 11
0
/*
 * incremental: incremental update
 *
 *	i)	dbpath	dbpath directory
 *	i)	root	root directory of source tree
 *	r)		0: not updated, 1: updated
 */
int
incremental(const char *dbpath, const char *root)
{
	STATISTICS_TIME *tim;
	struct stat statp;
	STRBUF *addlist = strbuf_open(0);
	STRBUF *deletelist = strbuf_open(0);
	STRBUF *addlist_other = strbuf_open(0);
	IDSET *deleteset, *findset;
	int updated = 0;
	const char *path;
	unsigned int id, limit;

	tim = statistics_time_start("Time of inspecting %s and %s.", dbname(GTAGS), dbname(GRTAGS));
	if (vflag) {
		fprintf(stderr, " Tag found in '%s'.\n", dbpath);
		fprintf(stderr, " Incremental updating.\n");
	}
	/*
	 * get modified time of GTAGS.
	 */
	path = makepath(dbpath, dbname(GTAGS), NULL);

	if (gpath_open(dbpath, 0) < 0)
		die("GPATH not found.");
	/*
	 * deleteset:
	 *	The list of the path name which should be deleted from GPATH.
	 * findset:
	 *	The list of the path name which exists in the current project.
	 *	A project is limited by the --file option.
	 */
	deleteset = idset_open(gpath_nextkey());
	findset = idset_open(gpath_nextkey());
	total = 0;
	/*
	 * Make add list and delete list for update.
	 */
	if (single_update) {
		int type;
		const char *fid = gpath_path2fid(single_update, &type);
		/*
		 * The --single-update=file supports only updating.
		 * If it is new file, this option is ignored, and the processing is
		 * automatically switched to the normal procedure.
		 */
		if (fid == NULL) {
			if (vflag)
				fprintf(stderr, " --single-update option ignored, because '%s' is new file.\n", single_update);
			goto normal_update;
		}
		/*
		 * If type != GPATH_SOURCE then we have nothing to do, and you will see
		 * a message 'Global databases are up to date.'.
		 */
		if (type == GPATH_SOURCE) {
			strbuf_puts0(addlist, single_update);
			idset_add(deleteset, atoi(fid));
			total++;
		}
	} else {
normal_update:
		if (file_list)
			find_open_filelist(file_list, root);
		else
			find_open(NULL);
		while ((path = find_read()) != NULL) {
			const char *fid;
			int n_fid = 0;
			int other = 0;

			/* a blank at the head of path means 'NOT SOURCE'. */
			if (*path == ' ') {
				if (test("b", ++path))
					continue;
				other = 1;
			}
			if (stat(path, &statp) < 0)
				die("stat failed '%s'.", path);
			fid = gpath_path2fid(path, NULL);
			if (fid) { 
				n_fid = atoi(fid);
				idset_add(findset, n_fid);
			}
			if (other) {
				if (fid == NULL)
					strbuf_puts0(addlist_other, path);
			} else {
				if (fid == NULL) {
					strbuf_puts0(addlist, path);
					total++;
				} else if (gpath_mtime(NULL, fid) < statp.st_mtime) {
					if (uflag) {
						printf("%s\n", path);
					} else {
						strbuf_puts0(addlist, path);
						total++;
						idset_add(deleteset, n_fid);
					}
				}
			}
		}
		find_close();
		/*
		 * make delete list.
		 */
		if (remove_lost) {
			limit = gpath_nextkey();
		} else {
			limit = 0;
		}
		for (id = 1; id < limit; id++) {
			char fid[MAXFIDLEN];
			int type;

			snprintf(fid, sizeof(fid), "%d", id);
			/*
			 * This is a hole of GPATH. The hole increases if the deletion
			 * and the addition are repeated.
			 */
			if ((path = gpath_fid2path(fid, &type)) == NULL)
				continue;
			/*
			 * The file which does not exist in the findset is treated
			 * assuming that it does not exist in the file system.
			 */
			if (type == GPATH_OTHER) {
				if (!idset_contains(findset, id) || !test("f", path) || test("b", path))
					strbuf_puts0(deletelist, path);
			} else {
				if (!idset_contains(findset, id) || !test("f", path)) {
					strbuf_puts0(deletelist, path);
					idset_add(deleteset, id);
				}
			}
		}
	}
	gpath_close();
	statistics_time_end(tim);
	/*
	 * execute updating.
	 */
	if ((!idset_empty(deleteset) || strbuf_getlen(addlist) > 0) ||
	    (strbuf_getlen(deletelist) + strbuf_getlen(addlist_other) > 0))
	{
		int db;

		updated = 1;
		tim = statistics_time_start("Time of updating %s and %s.", dbname(GTAGS), dbname(GRTAGS));
		if (!idset_empty(deleteset) || strbuf_getlen(addlist) > 0)
			updatetags(dbpath, root, deleteset, addlist);
		if (strbuf_getlen(deletelist) + strbuf_getlen(addlist_other) > 0) {
			const char *start, *end, *p;

			if (vflag)
				fprintf(stderr, "[%s] Updating '%s'.\n", now(), dbname(GPATH));
			gpath_open(dbpath, 2);
			if (strbuf_getlen(deletelist) > 0) {
				start = strbuf_value(deletelist);
				end = start + strbuf_getlen(deletelist);

				for (p = start; p < end; p += strlen(p) + 1)
					gpath_delete(p);
			}
			if (strbuf_getlen(addlist_other) > 0) {
				start = strbuf_value(addlist_other);
				end = start + strbuf_getlen(addlist_other);

				for (p = start; p < end; p += strlen(p) + 1)
					gpath_put(p, GPATH_OTHER);
			}
			gpath_close();
		}
		/*
		 * Update modification time of tag files
		 * because they may have no definitions.
		 */
		for (db = GTAGS; db < GTAGLIM; db++)
			utime(makepath(dbpath, dbname(db), NULL), NULL);
		statistics_time_end(tim);
	}
	if (vflag) {
		if (updated)
			fprintf(stderr, " Global databases have been modified.\n");
		else
			fprintf(stderr, " Global databases are up to date.\n");
		fprintf(stderr, "[%s] Done.\n", now());
	}
	strbuf_close(addlist);
	strbuf_close(deletelist);
	strbuf_close(addlist_other);
	idset_close(deleteset);
	idset_close(findset);

	return updated;
}
Exemplo n.º 12
0
Arquivo: find.c Projeto: kosaki/gtags
/*
 * find_read_traverse: read path without GPATH.
 *
 *	r)		path
 */
char *
find_read_traverse(void)
{
	static char val[MAXPATHLEN];
	char path[MAXPATHLEN];
	struct stack_entry *curp = varray_assign(stack, current_entry, 1);

	for (;;) {
		while (curp->p < curp->end) {
			char type = *(curp->p);
			const char *unit = curp->p + 1;

			curp->p += strlen(curp->p) + 1;

			/*
			 * Skip files described in the skip list.
			 */
				/* makepath() returns unsafe module local area. */
			strlimcpy(path, makepath(dir, unit, NULL), sizeof(path));
			if (type == 'd')
				strcat(path, "/");
			if (skipthisfile(path))
				continue;
			if (type == 'f') {
				/*
				 * Skip the following:
				 * o directory
				 * o file which does not exist
				 * o dead symbolic link
				 */
				if (!test("f", path)) {
					if (test("d", path))
						warning("'%s' is a directory. (Ignored)", path);
					else
						warning("'%s' not found. (Ignored)", path);
					continue;
				}
				/*
				 * GLOBAL cannot treat path which includes blanks.
				 * It will be improved in the future.
				 */
				if (!allow_blank && locatestring(path, " ", MATCH_FIRST)) {
					warning("'%s' ignored, because it includes blank.", &path[2]);
					continue;
				}
				/*
				 * A blank at the head of path means
				 * other than source file.
				 */
				if (regexec(suff, path, 0, 0, 0) == 0) {
					/* source file */
					strlimcpy(val, path, sizeof(val));
				} else {
					/* other file like 'Makefile' */
					val[0] = ' ';
					strlimcpy(&val[1], path, sizeof(val) - 1);
				}
				val[sizeof(val) - 1] = '\0';
				return val;
			}
			if (type == 'd') {
				STRBUF *sb = strbuf_open(0);
				char *dirp = curp->dirp;

				strcat(dirp, unit);
				strcat(dirp, "/");
				if (getdirs(dir, sb) < 0) {
					warning("cannot open directory '%s'. (Ignored)", dir);
					strbuf_close(sb);
					*(curp->dirp) = 0;
					continue;
				}
				/*
				 * Push stack.
				 */
				curp = varray_assign(stack, ++current_entry, 1);
				curp->dirp = dirp + strlen(dirp);
				curp->sb = sb;
				curp->start = curp->p = strbuf_value(sb);
				curp->end   = curp->start + strbuf_getlen(sb);
			}
		}
		strbuf_close(curp->sb);
		curp->sb = NULL;
		if (current_entry == 0)
			break;
		/*
		 * Pop stack.
		 */
		curp = varray_assign(stack, --current_entry, 0);
		*(curp->dirp) = 0;
	}
	find_eof = 1;
	return NULL;
}
Exemplo n.º 13
0
/**
 * gtags_first: return first record
 *
 *	@param[in]	gtop	#GTOP structure
 *	@param[in]	pattern	tag name <br>
 *		- may be regular expression
 *		- may be @VAR{NULL}
 *	@param[in]	flags	#GTOP_PREFIX:	prefix read <br>
 *			#GTOP_KEY:	read key only <br>
 *			#GTOP_PATH:	read path only <br>
 *			#GTOP_NOREGEX:	don't use regular expression. <br>
 *			#GTOP_IGNORECASE:	ignore case distinction. <br>
 *			#GTOP_BASICREGEX:	use basic regular expression. <br>
 *			#GTOP_NOSORT:	don't sort
 *	@return		record
 */
GTP *
gtags_first(GTOP *gtop, const char *pattern, int flags)
{
	int regflags = 0;
	static regex_t reg;
	const char *tagline;
	STATIC_STRBUF(regex);

	strbuf_clear(regex);
	gtop->preg = &reg;
	gtop->key = NULL;
	gtop->prefix = NULL;
	gtop->flags = flags;
	gtop->dbflags = 0;
	gtop->readcount = 1;

	/* Settlement for last time if any */
	if (gtop->path_hash) {
		strhash_close(gtop->path_hash);
		gtop->path_hash = NULL;
	}
	if (gtop->path_array) {
		free(gtop->path_array);
		gtop->path_array = NULL;
	}

	if (flags & GTOP_KEY)
		gtop->dbflags |= DBOP_KEY;
	if (!(flags & GTOP_BASICREGEX))
		regflags |= REG_EXTENDED;

	/*
	 * decide a read method
	 */
	if (pattern == NULL)
		gtop->preg = NULL;
	else if (pattern[0] == 0)
		return NULL;
	else if (!strcmp(pattern, ".*") || !strcmp(pattern, "^.*$") ||
		!strcmp(pattern, "^") || !strcmp(pattern, "$") ||
		!strcmp(pattern, "^.*") || !strcmp(pattern, ".*$")) {
		/*
		 * Since these regular expressions match to any record,
		 * we take sequential read method.
		 */
		gtop->preg = NULL;
	} else if (flags & GTOP_IGNORECASE) {
		regflags |= REG_ICASE;
		if (!isregex(pattern) || flags & GTOP_NOREGEX) {
			gtop->prefix = get_prefix(pattern, flags);
			if (gtop->openflags & GTAGS_DEBUG)
				if (gtop->prefix != NULL)
					fprintf(stderr, "Using prefix: %s\n", gtop->prefix);
			if (gtop->prefix == NULL)
				die("gtags_first: impossible (1).");
			strbuf_putc(regex, '^');
			strbuf_puts(regex, pattern);
			if (!(flags & GTOP_PREFIX))
				strbuf_putc(regex, '$');
		} else if (*pattern == '^' && (gtop->prefix = get_prefix(pattern, flags)) != NULL) {
			if (gtop->openflags & GTAGS_DEBUG)
				fprintf(stderr, "Using prefix: %s\n", gtop->prefix);
			strbuf_puts(regex, pattern);
		} else {
			strbuf_puts(regex, pattern);
		}
	} else {
		if (!isregex(pattern) || flags & GTOP_NOREGEX) {
			if (flags & GTOP_PREFIX)
				gtop->dbflags |= DBOP_PREFIX;
			gtop->key = pattern;
			gtop->preg = NULL;
		} else if (*pattern == '^' && (gtop->key = get_prefix(pattern, flags)) != NULL) {
			if (gtop->openflags & GTAGS_DEBUG)
				fprintf(stderr, "Using prefix: %s\n", gtop->key);
			gtop->dbflags |= DBOP_PREFIX;
			gtop->preg = NULL;
		} else {
			strbuf_puts(regex, pattern);
		}
	}
	if (gtop->prefix) {
		if (gtop->key)
			die("gtags_first: impossible (2).");
		gtop->key = gtop->prefix;
		gtop->dbflags |= DBOP_PREFIX;
	}
	if (strbuf_getlen(regex) > 0) {
		if (gtop->preg == NULL)
			die("gtags_first: impossible (3).");
		if (regcomp(gtop->preg, strbuf_value(regex), regflags) != 0)
			die("invalid regular expression.");
	}
	/*
	 * If GTOP_PATH is set, at first, we collect all path names in a pool and
	 * sort them. gtags_first() and gtags_next() returns one of the pool.
	 */
	if (gtop->flags & GTOP_PATH) {
		struct sh_entry *entry;
		char *p;
		const char *cp;
		unsigned long i;

		gtop->path_hash = strhash_open(HASHBUCKETS);
		/*
		 * Pool path names.
		 *
		 * fid		path name
		 * +--------------------------
		 * |100		./aaa/a.c
		 * |105		./aaa/b.c
		 *  ...
		 */
again0:
		for (tagline = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags);
		     tagline != NULL;
		     tagline = dbop_next(gtop->dbop))
		{
			VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop);
			/* extract file id */
			p = locatestring(tagline, " ", MATCH_FIRST);
			if (p == NULL)
				die("Invalid tag record. '%s'\n", tagline);
			*p = '\0';
			entry = strhash_assign(gtop->path_hash, tagline, 1);
			/* new entry: get path name and set. */
			if (entry->value == NULL) {
				cp = gpath_fid2path(tagline, NULL);
				if (cp == NULL)
					die("GPATH is corrupted.(file id '%s' not found)", tagline);
				entry->value = strhash_strdup(gtop->path_hash, cp, 0);
			}
		}
		if (gtop->prefix && gtags_restart(gtop))
			goto again0;
		/*
		 * Sort path names.
		 *
		 * fid		path name	path_array (sort)
		 * +--------------------------	+---+
		 * |100		./aaa/a.c <-------* |
		 * |105		./aaa/b.c <-------* |
		 *  ...				...
		 */
		gtop->path_array = (char **)check_malloc(gtop->path_hash->entries * sizeof(char *));
		i = 0;
		for (entry = strhash_first(gtop->path_hash); entry != NULL; entry = strhash_next(gtop->path_hash))
			gtop->path_array[i++] = entry->value;
		if (i != gtop->path_hash->entries)
			die("Something is wrong. 'i = %lu, entries = %lu'" , i, gtop->path_hash->entries);
		if (!(gtop->flags & GTOP_NOSORT))
			qsort(gtop->path_array, gtop->path_hash->entries, sizeof(char *), compare_path);
		gtop->path_count = gtop->path_hash->entries;
		gtop->path_index = 0;

		if (gtop->path_index >= gtop->path_count)
			return NULL;
		gtop->gtp.path = gtop->path_array[gtop->path_index++];
		return &gtop->gtp;
	} else if (gtop->flags & GTOP_KEY) {
again1:
		for (gtop->gtp.tag = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags);
		     gtop->gtp.tag != NULL;
		     gtop->gtp.tag = dbop_next(gtop->dbop))
		{
			VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop);
			break;
		}
		if (gtop->gtp.tag == NULL) {
			if (gtop->prefix && gtags_restart(gtop))
				goto again1;
		}
		return gtop->gtp.tag ? &gtop->gtp : NULL;
	} else {
		if (gtop->vb == NULL)
			gtop->vb = varray_open(sizeof(GTP), 200);
		else
			varray_reset(gtop->vb);
		if (gtop->segment_pool == NULL)
			gtop->segment_pool = pool_open();
		else
			pool_reset(gtop->segment_pool);
		if (gtop->path_hash == NULL)
			gtop->path_hash = strhash_open(HASHBUCKETS);
		else
			strhash_reset(gtop->path_hash);
again2:
		tagline = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags);
		if (tagline == NULL) {
			if (gtop->prefix && gtags_restart(gtop))
				goto again2;
			return NULL;
		}
		/*
		 * Dbop_next() wil read the same record again.
		 */
		dbop_unread(gtop->dbop);
		/*
		 * Read a tag segment with sorting.
		 */
		segment_read(gtop);
		return  &gtop->gtp_array[gtop->gtp_index++];
	}
}
Exemplo n.º 14
0
/*
 * updatetags: update tag file.
 *
 *	i)	dbpath		directory in which tag file exist
 *	i)	root		root directory of source tree
 *	i)	deleteset	bit array of fid of deleted or modified files 
 *	i)	addlist		\0 separated list of added or modified files
 */
void
updatetags(const char *dbpath, const char *root, IDSET *deleteset, STRBUF *addlist)
{
	struct put_func_data data;
	int seqno, flags;
	const char *path, *start, *end;

	if (vflag)
		fprintf(stderr, "[%s] Updating '%s' and '%s'.\n", now(), dbname(GTAGS), dbname(GRTAGS));
	/*
	 * Open tag files.
	 */
	data.gtop[GTAGS] = gtags_open(dbpath, root, GTAGS, GTAGS_MODIFY, 0);
	if (test("f", makepath(dbpath, dbname(GRTAGS), NULL))) {
		data.gtop[GRTAGS] = gtags_open(dbpath, root, GRTAGS, GTAGS_MODIFY, 0);
	} else {
		/*
		 * If you set NULL to data.gtop[GRTAGS], parse_file() doesn't write to
		 * GRTAGS. See put_syms().
		 */
		data.gtop[GRTAGS] = NULL;
	}
	/*
	 * Delete tags from GTAGS.
	 */
	if (!idset_empty(deleteset)) {
		if (vflag) {
			char fid[MAXFIDLEN];
			int total = idset_count(deleteset);
			unsigned int id;

			seqno = 1;
			for (id = idset_first(deleteset); id != END_OF_ID; id = idset_next(deleteset)) {
				snprintf(fid, sizeof(fid), "%d", id);
				path = gpath_fid2path(fid, NULL);
				if (path == NULL)
					die("GPATH is corrupted.");
				fprintf(stderr, " [%d/%d] deleting tags of %s\n", seqno++, total, path + 2);
			}
		}
		gtags_delete(data.gtop[GTAGS], deleteset);
		if (data.gtop[GRTAGS] != NULL)
			gtags_delete(data.gtop[GRTAGS], deleteset);
	}
	/*
	 * Set flags.
	 */
	data.gtop[GTAGS]->flags = 0;
	if (extractmethod)
		data.gtop[GTAGS]->flags |= GTAGS_EXTRACTMETHOD;
	data.gtop[GRTAGS]->flags = data.gtop[GTAGS]->flags;
	flags = 0;
	if (debug)
		flags |= PARSER_DEBUG;
	if (wflag)
		flags |= PARSER_WARNING;
	/*
	 * Add tags to GTAGS and GRTAGS.
	 */
	start = strbuf_value(addlist);
	end = start + strbuf_getlen(addlist);
	seqno = 0;
	for (path = start; path < end; path += strlen(path) + 1) {
		gpath_put(path, GPATH_SOURCE);
		data.fid = gpath_path2fid(path, NULL);
		if (data.fid == NULL)
			die("GPATH is corrupted.('%s' not found)", path);
		if (vflag)
			fprintf(stderr, " [%d/%d] extracting tags of %s\n", ++seqno, total, path + 2);
		if (debug)
			fprintf(stderr, "[%s]\n", path + 2);
		parse_file(path, flags, put_syms, &data);
		gtags_flush(data.gtop[GTAGS], data.fid);
		if (data.gtop[GRTAGS] != NULL)
			gtags_flush(data.gtop[GRTAGS], data.fid);
	}
	parser_exit();
	gtags_close(data.gtop[GTAGS]);
	if (data.gtop[GRTAGS] != NULL)
		gtags_close(data.gtop[GRTAGS]);
}
Exemplo n.º 15
0
/**
 * execute_command
 *
 *	@param[in]	xp	xargs structure
 *	@return		!=NULL: file pointer <br>
 *			==NULL: end of argument
 *
 * This function constructs command line from the following, <br>
 *	@STRONG{command}: @CODE{xp-\>command} <br>
 *	@STRONG{argument}: each argument provider <br>
 * execute it on a pipe line, and return the file pointer.
 */
static FILE *
execute_command(XARGS *xp)
{
	int limit;
	STRBUF *comline = strbuf_open(0);
	int count = 0;
	int length;
	FILE *pipe = NULL;
	char *p, *meta_p;

#if defined(_WIN32) && !defined(__CYGWIN__)
	/*
	 * If the command starts with a quote, CMD.EXE requires the entire
	 * command line to be quoted.
	 */
	if (*xp->command == '"')
		strbuf_putc(comline, '"');
#endif
	/*
	 * Copy the part before '%s' of the command skeleton.
	 * The '%s' in the skeleton is replaced with given arguments.
	 */
	meta_p = locatestring(xp->command, "%s", MATCH_FIRST);
	if (meta_p) {
		strbuf_nputs(comline, xp->command, meta_p - xp->command);
		limit = exec_line_limit(strlen(meta_p + 2));
	} else {
		strbuf_puts(comline, xp->command);
		limit = exec_line_limit(0);
	}
	/*
	 * Append arguments as many as possible.
	 */
	switch (xp->type) {
	case XARGS_FILE:
		for (
			/* initial */
			fseek(xp->ip, xp->fptr, SEEK_SET)
			;
			/* continuation condition */
			(LT_MAX &&
				((p = (strbuf_getlen(xp->path) > 0 ?
				strbuf_value(xp->path) :
				strbuf_fgets(xp->path, xp->ip, STRBUF_NOCRLF))) != NULL))
			;
			/* preparation */
			strbuf_reset(xp->path)
		)
			APPEND_ARGUMENT(p);
		xp->fptr = ftell(xp->ip);
		break;
	case XARGS_ARGV:
		for (; LT_MAX && xp->argc > 0; xp->argc--, xp->argv++)
			APPEND_ARGUMENT(xp->argv[0])
		break;
	case XARGS_STRBUF:
		for (; LT_MAX && xp->curp < xp->endp; xp->curp += length + 1)
			APPEND_ARGUMENT(xp->curp)
		break;
	case XARGS_FIND:
		for (; LT_MAX && (p = repeat_find_read()) != NULL; repeat_find_next())
			APPEND_ARGUMENT(p)
		break;
	}
	/*
	 * Copy the left part of the command skeleton.
	 */
	if (meta_p) {
		strbuf_putc(comline, ' ');
		strbuf_puts(comline, meta_p + 2);
	}
#if defined(_WIN32) && !defined(__CYGWIN__)
	if (*xp->command == '"')
		strbuf_putc(comline, '"');
#endif
	if (count > 0) {
		pipe = popen(strbuf_value(comline), "r");
		if (pipe == NULL)
			die("cannot execute command '%s'.", strbuf_value(comline));
	}
	strbuf_close(comline);
	return pipe;
}
Exemplo n.º 16
0
/*
 * Make duplicate object index.
 *
 * If referred tag is only one, direct link which points the tag is generated.
 * Else if two or more tag exists, indirect link which points the tag list
 * is generated.
 */
int
makedupindex(void)
{
	STRBUF *sb = strbuf_open(0);
	STRBUF *tmp = strbuf_open(0);
	STRBUF *command = strbuf_open(0);
	int definition_count = 0;
	char srcdir[MAXPATHLEN];
	int db;
	FILEOP *fileop = NULL;
	FILE *op = NULL;
	FILE *ip = NULL;

	snprintf(srcdir, sizeof(srcdir), "../%s", SRCS);
	for (db = GTAGS; db < GTAGLIM; db++) {
		const char *kind = kinds[db];
		const char *option = options[db];
		int writing = 0;
		int count = 0;
		int entry_count = 0;
		const char *ctags_xid, *ctags_x;
		char tag[IDENTLEN], prev[IDENTLEN], first_line[MAXBUFLEN];

		if (gtags_exist[db] == 0)
			continue;
		prev[0] = 0;
		first_line[0] = 0;
		/*
		 * construct command line.
		 */
		strbuf_reset(command);
		strbuf_sprintf(command, "%s -x%s --result=ctags-xid --encode-path=\" \t\" --nofilter=path", quote_shell(global_path), option);
		/*
		 * Optimization when the --dynamic option is specified.
		 */
		if (dynamic) {
			strbuf_puts(command, " --nosource");
			if (db != GSYMS)
				strbuf_puts(command, " --nofilter=sort");
		}
		strbuf_puts(command, " \".*\"");
		if ((ip = popen(strbuf_value(command), "r")) == NULL)
			die("cannot execute command '%s'.", strbuf_value(command));
		while ((ctags_xid = strbuf_fgets(sb, ip, STRBUF_NOCRLF)) != NULL) {
			char fid[MAXFIDLEN];

			ctags_x = parse_xid(ctags_xid, fid, NULL);
			/* tag name */
			(void)strcpy_withterm(tag, ctags_x, sizeof(tag), ' ');
			if (strcmp(prev, tag)) {
				count++;
				if (vflag)
					fprintf(stderr, " [%d] adding %s %s\n", count, kind, tag);
				if (writing) {
					if (!dynamic) {
						fputs_nl(gen_list_end(), op);
						fputs_nl(body_end, op);
						fputs_nl(gen_page_end(), op);
						close_file(fileop);
						html_count++;
					}
					writing = 0;
					/*
					 * cache record: " <fid>\0<entry number>\0"
					 */
					strbuf_reset(tmp);
					strbuf_putc(tmp, ' ');
					strbuf_putn(tmp, count - 1);
					strbuf_putc(tmp, '\0');
					strbuf_putn(tmp, entry_count);
					cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1);
				}				
				/* single entry */
				if (first_line[0]) {
					char fid[MAXFIDLEN];
					const char *ctags_x = parse_xid(first_line, fid, NULL);
					const char *lno = nextelement(ctags_x);

					strbuf_reset(tmp);
					strbuf_puts_withterm(tmp, lno, ' ');
					strbuf_putc(tmp, '\0');
					strbuf_puts(tmp, fid);
					cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1);
				}
				/*
				 * Chop the tail of the line. It is not important.
				 * strlimcpy(first_line, ctags_x, sizeof(first_line));
				 */
				strncpy(first_line, ctags_xid, sizeof(first_line));
				first_line[sizeof(first_line) - 1] = '\0';
				strlimcpy(prev, tag, sizeof(prev));
				entry_count = 0;
			} else {
				/* duplicate entry */
				if (first_line[0]) {
					char fid[MAXFIDLEN];
					const char *ctags_x = parse_xid(first_line, fid, NULL);

					if (!dynamic) {
						char path[MAXPATHLEN];

						snprintf(path, sizeof(path), "%s/%s/%d.%s", distpath, dirs[db], count, HTML);
						fileop = open_output_file(path, cflag);
						op = get_descripter(fileop);
						fputs_nl(gen_page_begin(tag, SUBDIR), op);
						fputs_nl(body_begin, op);
						fputs_nl(gen_list_begin(), op);
						fputs_nl(gen_list_body(srcdir, ctags_x, fid), op);
					}
					writing = 1;
					entry_count++;
					first_line[0] = 0;
				}
				if (!dynamic) {
					fputs_nl(gen_list_body(srcdir, ctags_x, fid), op);
				}
				entry_count++;
			}
		}
		if (db == GTAGS)
			definition_count = count;
		if (pclose(ip) != 0)
			die("'%s' failed.", strbuf_value(command));
		if (writing) {
			if (!dynamic) {
				fputs_nl(gen_list_end(), op);
				fputs_nl(body_end, op);
				fputs_nl(gen_page_end(), op);
				close_file(fileop);
				html_count++;
			}
			/*
			 * cache record: " <fid>\0<entry number>\0"
			 */
			strbuf_reset(tmp);
			strbuf_putc(tmp, ' ');
			strbuf_putn(tmp, count);
			strbuf_putc(tmp, '\0');
			strbuf_putn(tmp, entry_count);
			cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1);
		}
		if (first_line[0]) {
			char fid[MAXFIDLEN];
			const char *ctags_x = parse_xid(first_line, fid, NULL);
			const char *lno = nextelement(ctags_x);

			strbuf_reset(tmp);
			strbuf_puts_withterm(tmp, lno, ' ');
			strbuf_putc(tmp, '\0');
			strbuf_puts(tmp, fid);
			cache_put(db, prev, strbuf_value(tmp), strbuf_getlen(tmp) + 1);
		}
	}
	strbuf_close(sb);
	strbuf_close(tmp);
	strbuf_close(command);
	return definition_count;
}
Exemplo n.º 17
0
const char *
dbop3_next(DBOP *dbop) {
	int rc;
	char *key, *dat;

	/*
	 *	0: rowid
	 *	1: key
	 *	2: dat
	 *	3: flags
	 */
	for (;;) {
		/* Once it receives SQLITE_DONE, do not never return value */
		if (dbop->done)
			return NULL;
		rc = sqlite3_step(dbop->stmt);
		if (rc == SQLITE_DONE)
			goto finish;
		else if (rc == SQLITE_ROW) {
			dbop->readcount++;
			dbop->lastrowid = sqlite3_column_int64(dbop->stmt, 0);
			key = (char *)sqlite3_column_text(dbop->stmt, 1);
			dat = (char *)sqlite3_column_text(dbop->stmt, 2);
			/* skip meta records */
			if (!(dbop->openflags & DBOP_RAW)) {
				if (dbop->ioflags & DBOP_KEY && ismeta(key))
					continue;
				else if (ismeta(dat))
					continue;
			}
			if (dbop->ioflags & DBOP_KEY) {
				if (!strcmp(dbop->prev, key))
					continue;
				if (strlen(key) > MAXKEYLEN)
					die("primary key too long.");
				strlimcpy(dbop->prev, key, sizeof(dbop->prev));
			}
			if (dbop->ioflags & DBOP_PREFIX) {
				if (strncmp(key, dbop->key, dbop->keylen))
					goto finish;
			} else if (dbop->keylen) {
				if (strcmp(key, dbop->key)) 
					goto finish;
			}
			if (dbop->preg && regexec(dbop->preg, key, 0, 0, 0) != 0)
				continue;
			break;
		} else {
			die("dbop3_next: something is wrong (rc = %d).", rc);
		}
	}
	strbuf_clear(dbop->sb);
	strbuf_puts0(dbop->sb, (char *)sqlite3_column_text(dbop->stmt, 2));
	dbop->lastsize = strbuf_getlen(dbop->sb) - 1;
	dbop->lastflag = (char *)sqlite3_column_text(dbop->stmt, 3);
	if (dbop->lastflag)
		strbuf_puts(dbop->sb, dbop->lastflag);
	dbop->lastdat = strbuf_value(dbop->sb);
	if (dbop->lastflag)
		dbop->lastflag = dbop->lastdat + dbop->lastsize + 1;
	dbop->lastkey = key;
	dbop->lastkeysize = strlen(dbop->lastkey);
	if (dbop->ioflags & DBOP_KEY) {
		strlimcpy(dbop->prev, key, sizeof(dbop->prev));
		return key;
	}
	return dbop->lastdat;
finish:
	dbop->done = 1;
	dbop->lastdat = NULL;
	dbop->lastsize = 0;
	return dbop->lastdat;
}
Exemplo n.º 18
0
const char *
dbop3_first(DBOP *dbop, const char *name, regex_t *preg, int flags) {
	int rc;
	char *key;
	STRBUF *sql = strbuf_open_tempbuf();

	dbop->done = 0; 	/* This is turned on when it receives SQLITE_DONE. */
	strbuf_puts(sql, "select rowid, * from ");
	strbuf_puts(sql, dbop->tblname);
	if (name) {
		strbuf_puts(sql, " where key ");
		if (dbop->ioflags & DBOP_PREFIX) {
			/*
			 * In sqlite3, 'like' ignores case. 'glob' does not ignore case.
			 */
			strbuf_puts(sql, "glob '");
			strbuf_puts(sql, name);
			strbuf_puts(sql, "*'");
		} else {
			strbuf_puts(sql, "= '");
			strbuf_puts(sql, name);
			strbuf_puts(sql, "'");
		}
		strlimcpy(dbop->key, name, sizeof(dbop->key));
		dbop->keylen = strlen(name);
	}
	strbuf_puts(sql, " order by key");
	if (dbop->stmt) {
		rc = sqlite3_finalize(dbop->stmt);
		if (rc != SQLITE_OK)
			die("dbop3_finalize failed. (rc = %d)", rc);
		dbop->stmt = NULL;
	}
	rc = sqlite3_prepare_v2(dbop->db3, strbuf_value(sql), -1, &dbop->stmt, NULL);
	if (rc != SQLITE_OK)
		die("dbop3_first: sqlite3_prepare_v2 failed. (rc = %d)", rc);
	/*
	 *	0: rowid
	 *	1: key
	 *	2: dat
	 *	3: flags
	 */
	for (;;) {
		/* Once it receives SQLITE_DONE, do not never return value */
		if (dbop->done)
			return NULL;
		rc = sqlite3_step(dbop->stmt);
		if (rc == SQLITE_DONE)
			goto finish;
		else if (rc == SQLITE_ROW) {
			dbop->readcount++;
			dbop->lastrowid = sqlite3_column_int64(dbop->stmt, 0);
			key = (char *)sqlite3_column_text(dbop->stmt, 1);
			if (name) {
				if (dbop->ioflags & DBOP_PREFIX) {
					if (strncmp(key, dbop->key, dbop->keylen))
						goto finish;
				} else {
					if (strcmp(key, dbop->key)) 
						goto finish;
				}
				if (dbop->preg && regexec(dbop->preg, key, 0, 0, 0) != 0)
					continue;
			} else {
				/* skip meta records */
				if (ismeta(key) && !(dbop->openflags & DBOP_RAW))
					continue;
				if (dbop->preg && regexec(dbop->preg, key, 0, 0, 0) != 0)
					continue;
			}
			break;
		} else {
			die("dbop3_first: something is wrong (rc = %d).", rc);
		}
	}
	strbuf_clear(dbop->sb);
	strbuf_puts0(dbop->sb, (char *)sqlite3_column_text(dbop->stmt, 2));
	dbop->lastsize = strbuf_getlen(dbop->sb) - 1;
	dbop->lastflag = (char *)sqlite3_column_text(dbop->stmt, 3);
	if (dbop->lastflag)
		strbuf_puts(dbop->sb, dbop->lastflag);
	dbop->lastdat = strbuf_value(dbop->sb);
	if (dbop->lastflag)
		dbop->lastflag = dbop->lastdat + dbop->lastsize + 1;
	dbop->lastkey = key;
	dbop->lastkeysize = strlen(dbop->lastkey);
	strbuf_release_tempbuf(sql);
	if (flags & DBOP_KEY) {
		strlimcpy(dbop->prev, key, sizeof(dbop->prev));
		return key;
	}
	return dbop->lastdat;
finish:
	strbuf_release_tempbuf(sql);
	dbop->done = 1;
	dbop->lastdat = NULL;
	dbop->lastsize = 0;
	dbop->lastflag = NULL;
	return dbop->lastdat;
}
Exemplo n.º 19
0
/**
 * flush_pool: flush the pool and write is as compact format.
 *
 *	@param[in]	gtop	descripter of #GTOP
 *	@param[in]	s_fid
 */
static void
flush_pool(GTOP *gtop, const char *s_fid)
{
	struct sh_entry *entry;
	int header_offset;
	int i, last;

	if (s_fid == NULL && (s_fid = gpath_path2fid(gtop->cur_path, NULL)) == NULL)
		die("GPATH is corrupted.('%s' not found)", gtop->cur_path);
	/*
	 * Write records as compact format and free line number table
	 * for each entry in the pool.
	 */
	for (entry = strhash_first(gtop->path_hash); entry; entry = strhash_next(gtop->path_hash)) {
		VARRAY *vb = (VARRAY *)entry->value;
		int *lno_array = varray_assign(vb, 0, 0);
		const char *key = entry->name;

		/*
		 * extract method when class method definition.
		 *
		 * Ex: Class::method(...)
		 *
		 * key	= 'method'
		 * data = 'Class::method  103 ./class.cpp ...'
		 */
		if (gtop->flags & GTAGS_EXTRACTMETHOD) {
			if ((key = locatestring(entry->name, ".", MATCH_LAST)) != NULL)
				key++;
			else if ((key = locatestring(entry->name, "::", MATCH_LAST)) != NULL)
				key += 2;
			else
				key = entry->name;
		}
		/* Sort line number table */
		qsort(lno_array, vb->length, sizeof(int), compare_lineno); 

		strbuf_reset(gtop->sb);
		strbuf_puts(gtop->sb, s_fid);
		strbuf_putc(gtop->sb, ' ');
		if (gtop->format & GTAGS_COMPNAME) {
			strbuf_puts(gtop->sb, compress(entry->name, key));
		} else {
			strbuf_puts(gtop->sb, entry->name);
		}
		strbuf_putc(gtop->sb, ' ');
		header_offset = strbuf_getlen(gtop->sb);
		/*
		 * If GTAGS_COMPLINE flag is set, each line number is expressed as the
		 * difference from the previous line number except for the head.
		 * GTAGS_COMPLINE is set by default in format version 5.
		 */
		if (gtop->format & GTAGS_COMPLINE) {
			int cont = 0;

			last = 0;			/* line 0 doesn't exist */
			for (i = 0; i < vb->length; i++) {
				int n = lno_array[i];

				if (n == last)
					continue;
				if (last > 0 && n == last + 1) {
					if (!cont) {
						/*
						 * Don't use range expression at the head.
						 */
						if (strbuf_getlen(gtop->sb) == header_offset)
							strbuf_putn(gtop->sb, n);
						else
							cont = last;
					}
				} else {
					/*
					 * Range expression. ex: 10-2 means 10 11 12
					 */
					if (cont) {
						strbuf_putc(gtop->sb, '-');
						strbuf_putn(gtop->sb, last - cont);
						cont = 0;
					}
					if (strbuf_getlen(gtop->sb) > header_offset) {
						strbuf_putc(gtop->sb, ',');
						strbuf_putn(gtop->sb, n - last);
					} else {
						strbuf_putn(gtop->sb, n);
					}
					if (strbuf_getlen(gtop->sb) > DBOP_PAGESIZE / 4) {
						dbop_put(gtop->dbop, key, strbuf_value(gtop->sb));
						strbuf_setlen(gtop->sb, header_offset);
					}
				}
				last = n;
			}
			if (cont) {
				strbuf_putc(gtop->sb, '-');
				strbuf_putn(gtop->sb, last - cont);
			}
		} else {
			/*
			 * This code is to support older format (version 4).
			 */
			last = 0;			/* line 0 doesn't exist */
			for (i = 0; i < vb->length; i++) {
				int n = lno_array[i];

				if (n == last)
					continue;
				if (strbuf_getlen(gtop->sb) > header_offset)
					strbuf_putc(gtop->sb, ',');
				strbuf_putn(gtop->sb, n);
				if (strbuf_getlen(gtop->sb) > DBOP_PAGESIZE / 4) {
					dbop_put(gtop->dbop, key, strbuf_value(gtop->sb));
					strbuf_setlen(gtop->sb, header_offset);
				}
				last = n;
			}
		}
		if (strbuf_getlen(gtop->sb) > header_offset) {
			dbop_put(gtop->dbop, key, strbuf_value(gtop->sb));
		}
		/* Free line number table */
		varray_close(vb);
	}
}
Exemplo n.º 20
0
/*
 * Execute retrieval command.
 *
 *	i)	command		0: Find this C symbol
 *				1: Find this definition
 *				2: Find functions called by this function (not supported)
 *				3: Find functions calling this function
 *				4: Find this text string
 *				6: Find this egrep pattern
 *				7: Find this file
 *				8: Find files #including this file
 *	i)	arg		argument
 *
 * Unsupported command prints "cscope: 0 lines\n".
 */
static void
search(int com, char *arg)
{
	static STRBUF *sb;
	char buf[1024], *p;
	int count = 0, opt = 0;

	if (sb == NULL)
		sb = strbuf_open(1024 * 1024);
	else
		strbuf_reset(sb);
	/*
	 * Convert from cscope command to global command.
	 */
	switch (com) {
	case '0':		/* Find this C symbol */
	case '1':		/* Find this definition */
		break;
	case '2':		/* Find functions called by this function */
		/*
		 * <symbol>:<line number>:<path>
		 */
		for (p = arg; *p && *p != ':'; p++)
			;
		*p++ = '\0';
		context = p;
		opt = FROM_HERE;
		break;
	case '3':		/* Find functions calling this function */
		opt = 'r';
		break;
	case '4':		/* Find this text string */
		opt = 'g';
		strlimcpy(buf, quote_string(arg), sizeof(buf));
		arg = buf;
		break;
	case '5':		/* Change this text string */
		opt = NA;
		break;
	case '6':		/* Find this egrep pattern */
		opt = 'g';
		break;
	case '7':		/* Find this file */
		opt = 'P';
		break;
	case '8':		/* Find files #including this file */
		opt = 'g';
		arg = include_pattern(arg);
		break;
	}
	/*
	 * Execute global(1).
	 */
	if (opt == NA) {
		fprintf(stdout, "cscope: 0 lines\n");
		return;
	}
	if (com == '0') {
		count += execute_command(sb, com, 0, arg);
		count += execute_command(sb, com, (count > 0) ? 'r' : 's', arg);
	} else {
		count += execute_command(sb, com, opt, arg);
	}
	/*
	 * Output format:
	 * cscope: <n> lines
	 * ******************		... 1
	 * ******************		... 2
	 * ...
	 * ******************		... n
	 * 
	 * Example:
	 * cscope: 3 lines
	 * global/global.c main 158 main(int argc, char **argv)
	 * gozilla/gozilla.c main 155 main(int argc, char **argv)
	 * gscope/gscope.c main 108 main(int argc, char **argv)
	 */
	fprintf(stdout, "cscope: %d lines\n", count);
	if (count > 0)
		fwrite(strbuf_value(sb), 1, strbuf_getlen(sb), stdout);
	fflush(stdout);
}