Esempio n. 1
0
/**
 * args_read: read path From args.
 *
 *	@return		path (@VAR{NULL}: end of argument)
 */
const char *
args_read(void)
{
	const char *p;
	STATIC_STRBUF(sb);

	strbuf_clear(sb);
	switch (type) {
	case ARGS_NOP:
		p = NULL;
		break;
	case ARGS_ARGS:
		p = *argslist++;
		break;
	case ARGS_FILELIST:
		p = strbuf_fgets(sb, ip, STRBUF_NOCRLF);
		break;
	case ARGS_GFIND:
		p = gfind_read(gp);
		break;
	case ARGS_BOTH:
		if (*argslist != NULL)
			p = *argslist++;
		else
			p = strbuf_fgets(sb, ip, STRBUF_NOCRLF);
		break;
	default:
		die("args_read: invalid type.");
	}
	return p;
}
Esempio n. 2
0
/**
 * completion_path: print candidate path list.
 *
 *	@param[in]	dbpath	dbpath directory
 *	@param[in]	prefix	prefix of primary key
 */
void
completion_path(const char *dbpath, const char *prefix)
{
	GFIND *gp;
	const char *localprefix = "./";
	DBOP *dbop = dbop_open(NULL, 1, 0600, DBOP_RAW);
	const char *path;
	int prefix_length;
	int target = GPATH_SOURCE;
	int flags = (match_part == MATCH_PART_LAST) ? MATCH_LAST : MATCH_FIRST;

	if (dbop == NULL)
		die("cannot open temporary file.");
	if (prefix && *prefix == 0)	/* In the case global -c '' */
		prefix = NULL;
	prefix_length = (prefix == NULL) ? 0 : strlen(prefix);
	if (oflag)
		target = GPATH_BOTH;
	if (Oflag)
		target = GPATH_OTHER;
	if (iflag || getconfb("icase_path"))
		flags |= IGNORE_CASE;
#if _WIN32 || __DJGPP__
	else if (!Mflag)
		flags |= IGNORE_CASE;
#endif
	gp = gfind_open(dbpath, localprefix, target);
	while ((path = gfind_read(gp)) != NULL) {
		path++;					/* skip '.'*/
		if (prefix == NULL) {
			dbop_put(dbop, path + 1, "");
		} else if (match_part == MATCH_PART_ALL) {
			const char *p = path;

			while ((p = locatestring(p, prefix, flags)) != NULL) {
				dbop_put(dbop, p, "");
				p += prefix_length;
			}
		} else {
			const char *p = locatestring(path, prefix, flags);
			if (p != NULL) {
				dbop_put(dbop, p, "");
			}
		}
	}
	gfind_close(gp);
	for (path = dbop_first(dbop, NULL, NULL, DBOP_KEY); path != NULL; path = dbop_next(dbop)) {
		fputs(path, stdout);
		fputc('\n', stdout);
	}
	dbop_close(dbop);
}
Esempio n. 3
0
/**
 * get a path from input stream.
 *
 * @note Each path name must start with @CODE{"./"}.
 */
static const char *
getpath(void)
{
	static const char *buff;

	if (!retry) {
		/* skip README or ChangeLog unless the -o option specified. */
		do {
			buff = gfind_read(gp);
		} while (buff && gp->type == GPATH_OTHER && !other_files);
	}
	retry = 0;
	return buff;
}
Esempio n. 4
0
/**
 * gfind_open: start iterator using GPATH.
 *
 *	@param[in]	dbpath  dbpath
 *	@param[in]	local   local prefix,
 *			if NULL specified, it assumes "./";
 *	@param[in]      target  GPATH_SOURCE: only source file,
 *			GPATH_OTHER: only other file,
 *			GPATH_BOTH: source file + other file
 *	@param[in]	flags	GPATH_NEARSORT
 *	@return		GFIND structure
 */
GFIND *
gfind_open(const char *dbpath, const char *local, int target, int flags)
{
	GFIND *gfind = (GFIND *)check_calloc(sizeof(GFIND), 1);

	gfind->dbop = dbop_open(makepath(dbpath, dbname(GPATH), NULL), 0, 0, 0);
	if (gfind->dbop == NULL)
		die("GPATH not found.");
	gfind->path = NULL;
	gfind->prefix = check_strdup(local ? local : "./");
	gfind->first = 1;
	gfind->eod = 0;
	gfind->target = target;
	gfind->type = GPATH_SOURCE;
	gfind->flags = flags;
	gfind->path_array = NULL;
	gfind->version = dbop_getversion(gfind->dbop);
	if (gfind->version > support_version)
		die("GPATH seems new format. Please install the latest GLOBAL.");
	else if (gfind->version < support_version)
		die("GPATH seems older format. Please remake tag files."); 
	/*
	 * Nearness sort.
	 * In fact, this timing of sort is not good for performance.
	 * Reconsideration is needed later.
	 */
	if (gfind->flags & GPATH_NEARSORT) {
		const char *path = NULL;
		VARRAY *varray = varray_open(sizeof(char *), 100);
		POOL *pool = pool_open();
		while ((path = gfind_read(gfind)) != NULL) {
			char **a = varray_append(varray);
			*a = pool_strdup(pool, path, 0);
		}
		if ((nearbase = get_nearbase_path()) == NULL)
			die("cannot get nearbase path.");
		qsort(varray_assign(varray, 0, 0), varray->length, sizeof(char *), compare_nearpath);
		gfind->path_array = varray;
		gfind->pool = pool;
		gfind->index = 0;
	}
	return gfind;
}
Esempio n. 5
0
/**
 * makehtml: make html files
 *
 *	@param[in]	total	number of files.
 */
static void
makehtml(int total)
{
	GFIND *gp;
	FILE *anchor_stream;
	const char *path;
	int count = 0;

	/*
	 * Create anchor stream for anchor_load().
	 */
	anchor_stream = tmpfile();
#if defined(_WIN32) && !defined(__CYGWIN__)
	/*
	 * tmpfile is created in the root, which user's can't write on Vista+.
	 * Use _tempnam and open it directly.
	 */
	if (anchor_stream == NULL) {
		char *name = _tempnam(tmpdir, "htags");
		anchor_stream = fopen(name, "w+bD");
		free(name);
	}
#endif
	gp = gfind_open(dbpath, NULL, other_files ? GPATH_BOTH : GPATH_SOURCE, 0);
	while ((path = gfind_read(gp)) != NULL) {
		if (gp->type == GPATH_OTHER)
			fputc(' ', anchor_stream);
		fputs(path, anchor_stream);
		fputc('\n', anchor_stream);
	}
	gfind_close(gp);
	/*
	 * Prepare anchor stream for anchor_load().
	 */
	anchor_prepare(anchor_stream);
	/*
	 * For each path in GPATH, convert the path into HTML file.
	 */
	gp = gfind_open(dbpath, NULL, other_files ? GPATH_BOTH : GPATH_SOURCE, 0);
	while ((path = gfind_read(gp)) != NULL) {
		char html[MAXPATHLEN];

		if (gp->type == GPATH_OTHER && !other_files)
			continue;
		/*
		 * load tags belonging to the path.
		 * The path must be start "./".
		 */
		anchor_load(path);
		/*
		 * inform the current path name to lex() function.
		 */
		save_current_path(path);
		count++;
		path += 2;		/* remove './' at the head */
		message(" [%d/%d] converting %s", count, total, path);
		snprintf(html, sizeof(html), "%s/%s/%s.%s", distpath, SRCS, path2fid(path), HTML);
		src2html(path, html, gp->type == GPATH_OTHER);
	}
	gfind_close(gp);
}
Esempio n. 6
0
/*
 * pathlist: print candidate path list.
 *
 *	i)	dbpath
 */
void
pathlist(const char *pattern, const char *dbpath)
{
	GFIND *gp;
	CONVERT *cv;
	const char *path, *p;
	regex_t preg;
	int count;
	int target = GPATH_SOURCE;

	if (oflag)
		target = GPATH_BOTH;
	if (Oflag)
		target = GPATH_OTHER;
	if (pattern) {
		int flags = 0;
		char edit[IDENTLEN];

		if (!Gflag)
			flags |= REG_EXTENDED;
		if (iflag || getconfb("icase_path"))
			flags |= REG_ICASE;
#ifdef _WIN32
		flags |= REG_ICASE;
#endif /* _WIN32 */
		/*
		 * We assume '^aaa' as '^/aaa'.
		 */
		if (*pattern == '^' && *(pattern + 1) != '/') {
			snprintf(edit, sizeof(edit), "^/%s", pattern + 1);
			pattern = edit;
		}
		if (regcomp(&preg, pattern, flags) != 0)
			die("invalid regular expression.");
	}
	if (!localprefix)
		localprefix = "./";
	cv = convert_open(type, format, root, cwd, dbpath, stdout);
	count = 0;

	gp = gfind_open(dbpath, localprefix, target);
	while ((path = gfind_read(gp)) != NULL) {
		/*
		 * skip localprefix because end-user doesn't see it.
		 */
		p = path + strlen(localprefix) - 1;
		if (pattern) {
			int result = regexec(&preg, p, 0, 0, 0);

			if ((!Vflag && result != 0) || (Vflag && result == 0))
				continue;
		} else if (Vflag)
			continue;
		if (format == FORMAT_PATH)
			convert_put_path(cv, path);
		else
			convert_put_using(cv, "path", path, 1, " ", gp->dbop->lastdat);
		count++;
	}
	gfind_close(gp);
	convert_close(cv);
	if (pattern)
		regfree(&preg);
	if (vflag) {
		switch (count) {
		case 0:
			fprintf(stderr, "file not found");
			break;
		case 1:
			fprintf(stderr, "1 file located");
			break;
		default:
			fprintf(stderr, "%d files located", count);
			break;
		}
		fprintf(stderr, " (using '%s').\n", makepath(dbpath, dbname(GPATH), NULL));
	}
}
Esempio n. 7
0
int
main(int argc, char **argv)
{
    char dbpath[MAXPATHLEN];
    char cwd[MAXPATHLEN];
    STRBUF *sb = strbuf_open(0);
    int optchar;
    int option_index = 0;
    STATISTICS_TIME *tim;

    /*
     * Setup GTAGSCONF and GTAGSLABEL environment variable
     * according to the --gtagsconf and --gtagslabel option.
     */
    preparse_options(argc, argv);
    /*
     * Get the project root directory.
     */
    if (!vgetcwd(cwd, MAXPATHLEN))
        die("cannot get current directory.");
    canonpath(cwd);
    /*
     * Load configuration file.
     */
    openconf(cwd);
    configuration();
    setenv_from_config();
    {
        char *env = getenv("GTAGS_OPTIONS");
        if (env && *env)
            argv = prepend_options(&argc, argv, env);
    }
    logging_arguments(argc, argv);
    while ((optchar = getopt_long(argc, argv, "cd:f:iIn:oOqvwse", long_options, &option_index)) != EOF) {
        switch (optchar) {
        case 0:
            /* already flags set */
            break;
        case OPT_CONFIG:
            show_config = 1;
            if (optarg)
                config_name = optarg;
            break;
        case OPT_GTAGSCONF:
        case OPT_GTAGSLABEL:
            /* These options are already parsed in preparse_options() */
            break;
        case OPT_SINGLE_UPDATE:
            iflag++;
            single_update = optarg;
            break;
        case OPT_ACCEPT_DOTFILES:
            set_accept_dotfiles();
            break;
        case 'c':
            cflag++;
            break;
        case 'd':
            dump_target = optarg;
            break;
        case 'f':
            file_list = optarg;
            break;
        case 'i':
            iflag++;
            break;
        case 'I':
            Iflag++;
            break;
        case 'o':
            /*
             * Though the -o(--omit-gsyms) was removed, this code
             * is left for compatibility.
             */
            break;
        case 'O':
            Oflag++;
            break;
        case 'q':
            qflag++;
            setquiet();
            break;
        case 'w':
            wflag++;
            break;
        case 'v':
            vflag++;
            setverbose();
            break;
        default:
            usage();
            break;
        }
    }
    if (qflag)
        vflag = 0;
    if (show_version)
        version(NULL, vflag);
    if (show_help)
        help();

    argc -= optind;
    argv += optind;

    /* If dbpath is specified, -O(--objdir) option is ignored. */
    if (argc > 0)
        Oflag = 0;
    if (show_config) {
        openconf(setupdbpath(0) == 0 ? get_root() : NULL);
        if (config_name)
            printconf(config_name);
        else
            fprintf(stdout, "%s\n", getconfline());
        exit(0);
    } else if (dump_target) {
        /*
         * Dump a tag file.
         */
        DBOP *dbop = NULL;
        const char *dat = 0;
        int is_gpath = 0;

        if (!test("f", dump_target))
            die("file '%s' not found.", dump_target);
        if ((dbop = dbop_open(dump_target, 0, 0, DBOP_RAW)) == NULL)
            die("file '%s' is not a tag file.", dump_target);
        /*
         * The file which has a NEXTKEY record is GPATH.
         */
        if (dbop_get(dbop, NEXTKEY))
            is_gpath = 1;
        for (dat = dbop_first(dbop, NULL, NULL, 0); dat != NULL; dat = dbop_next(dbop)) {
            const char *flag = is_gpath ? dbop_getflag(dbop) : "";

            if (*flag)
                printf("%s\t%s\t%s\n", dbop->lastkey, dat, flag);
            else
                printf("%s\t%s\n", dbop->lastkey, dat);
        }
        dbop_close(dbop);
        exit(0);
    } else if (Iflag) {
#define REQUIRED_MKID_VERSION "4.5"
        char *p;

        if (!usable("mkid"))
            die("mkid not found.");
        if (read_first_line("mkid --version", sb))
            die("mkid cannot executed.");
        p = strrchr(strbuf_value(sb), ' ');
        if (p == NULL)
            die("invalid version string of mkid: %s", strbuf_value(sb));
        switch (check_version(p + 1, REQUIRED_MKID_VERSION)
#ifdef _WIN32
                || strcmp(p + 1, "3.2.99") == 0
#endif
               )  {
        case 1:
            break;	/* OK */
        case 0:
            die("mkid version %s or later is required.", REQUIRED_MKID_VERSION);
        default:
            die("invalid version string of mkid: %s", strbuf_value(sb));
        }
    }

    /*
     * If 'gtags.files' exists, use it as a file list.
     * If the file_list other than "-" is given, it must be readable file.
     */
    if (file_list == NULL && test("f", GTAGSFILES))
        file_list = GTAGSFILES;
    if (file_list && strcmp(file_list, "-")) {
        if (test("d", file_list))
            die("'%s' is a directory.", file_list);
        else if (!test("f", file_list))
            die("'%s' not found.", file_list);
        else if (!test("r", file_list))
            die("'%s' is not readable.", file_list);
    }
    /*
     * Regularize the path name for single updating (--single-update).
     */
    if (single_update) {
        static char regular_path_name[MAXPATHLEN];
        char *p = single_update;

        if (!test("f", p))
            die("'%s' not found.", p);
#if _WIN32 || __DJGPP__
        for (; *p; p++)
            if (*p == '\\')
                *p = '/';
        p = single_update;
#define LOCATEFLAG MATCH_AT_FIRST|IGNORE_CASE
#else
#define LOCATEFLAG MATCH_AT_FIRST
#endif
        if (isabspath(p)) {
            char *q = locatestring(p, cwd, LOCATEFLAG);

            if (q && *q == '/')
                snprintf(regular_path_name, MAXPATHLEN, "./%s", q + 1);
            else
                die("path '%s' is out of the project.", p);

        } else {
            if (p[0] == '.' && p[1] == '/')
                snprintf(regular_path_name, MAXPATHLEN, "%s", p);
            else
                snprintf(regular_path_name, MAXPATHLEN, "./%s", p);
        }
        single_update = regular_path_name;
    }
    /*
     * Decide directory (dbpath) in which gtags make tag files.
     *
     * Gtags create tag files at current directory by default.
     * If dbpath is specified as an argument then use it.
     * If the -i option specified and both GTAGS and GRTAGS exists
     * at one of the candidate directories then gtags use existing
     * tag files.
     */
    if (iflag) {
        if (argc > 0)
            realpath(*argv, dbpath);
        else if (!gtagsexist(cwd, dbpath, MAXPATHLEN, vflag))
            strlimcpy(dbpath, cwd, sizeof(dbpath));
    } else {
        if (argc > 0)
            realpath(*argv, dbpath);
        else if (Oflag) {
            char *objdir = getobjdir(cwd, vflag);

            if (objdir == NULL)
                die("Objdir not found.");
            strlimcpy(dbpath, objdir, sizeof(dbpath));
        } else
            strlimcpy(dbpath, cwd, sizeof(dbpath));
    }
    if (iflag && (!test("f", makepath(dbpath, dbname(GTAGS), NULL)) ||
                  !test("f", makepath(dbpath, dbname(GRTAGS), NULL)) ||
                  !test("f", makepath(dbpath, dbname(GPATH), NULL)))) {
        if (wflag)
            warning("GTAGS, GRTAGS or GPATH not found. -i option ignored.");
        iflag = 0;
    }
    if (!test("d", dbpath))
        die("directory '%s' not found.", dbpath);
    if (vflag)
        fprintf(stderr, "[%s] Gtags started.\n", now());
    /*
     * initialize parser.
     */
    if (vflag && gtags_parser)
        fprintf(stderr, " Using plug-in parser.\n");
    parser_init(langmap, gtags_parser);
    if (vflag && file_list)
        fprintf(stderr, " Using '%s' as a file list.\n", file_list);
    /*
     * Start statistics.
     */
    init_statistics();
    /*
     * incremental update.
     */
    if (iflag) {
        /*
         * Version check. If existing tag files are old enough
         * gtagsopen() abort with error message.
         */
        GTOP *gtop = gtags_open(dbpath, cwd, GTAGS, GTAGS_MODIFY, 0);
        gtags_close(gtop);
        /*
         * GPATH is needed for incremental updating.
         * Gtags check whether or not GPATH exist, since it may be
         * removed by mistake.
         */
        if (!test("f", makepath(dbpath, dbname(GPATH), NULL)))
            die("Old version tag file found. Please remake it.");
        (void)incremental(dbpath, cwd);
        print_statistics(statistics);
        exit(0);
    }
    /*
     * create GTAGS and GRTAGS
     */
    createtags(dbpath, cwd);
    /*
     * create idutils index.
     */
    if (Iflag) {
        FILE *op;
        GFIND *gp;
        const char *path;

        tim = statistics_time_start("Time of creating ID");
        if (vflag)
            fprintf(stderr, "[%s] Creating indexes for idutils.\n", now());
        strbuf_reset(sb);
        /*
         * Since idutils stores the value of PWD in ID file, we need to
         * force idutils to follow our style.
         */
#if _WIN32 || __DJGPP__
        strbuf_puts(sb, "mkid --files0-from=-");
#else
        strbuf_sprintf(sb, "PWD=%s mkid --files0-from=-", quote_shell(cwd));
#endif
        if (vflag)
            strbuf_puts(sb, " -v");
        strbuf_sprintf(sb, " --file=%s/ID", quote_shell(dbpath));
        if (vflag) {
#ifdef __DJGPP__
            if (is_unixy())	/* test for 4DOS as well? */
#endif
                strbuf_puts(sb, " 1>&2");
        } else {
            strbuf_puts(sb, " >" NULL_DEVICE);
#ifdef __DJGPP__
            if (is_unixy())	/* test for 4DOS as well? */
#endif
                strbuf_puts(sb, " 2>&1");
        }
        if (debug)
            fprintf(stderr, "executing mkid like: %s\n", strbuf_value(sb));
        op = popen(strbuf_value(sb), "w");
        if (op == NULL)
            die("cannot execute '%s'.", strbuf_value(sb));
        gp = gfind_open(dbpath, NULL, GPATH_BOTH);
        while ((path = gfind_read(gp)) != NULL) {
            fputs(path, op);
            fputc('\0', op);
        }
        gfind_close(gp);
        if (pclose(op) != 0)
            die("terminated abnormally '%s' (errno = %d).", strbuf_value(sb), errno);
        if (test("f", makepath(dbpath, "ID", NULL)))
            if (chmod(makepath(dbpath, "ID", NULL), 0644) < 0)
                die("cannot chmod ID file.");
        statistics_time_end(tim);
    }
    if (vflag)
        fprintf(stderr, "[%s] Done.\n", now());
    closeconf();
    strbuf_close(sb);
    print_statistics(statistics);

    return 0;
}