Exemple #1
0
/*
 * read-ahead strategy
 * on second block, read RAGAP blocks,
 * thereafter, read RAGAP ahead of current pos
 */
Off
dbufread(Iobuf *p, Dentry *d, Off a, Off ra, int uid)
{
	Off addr;

	if(a == 0)
		return 1;
	if(a == 1 && ra == 1) {
		while(ra < a+RAGAP) {
			ra++;
			addr = rel2abs(p, d, ra, 0, 0, uid);
			if(!addr)
				return 0;
			preread(p->dev, addr);
		}
		return ra+1;
	}
	if(ra == a+RAGAP) {
		addr = rel2abs(p, d, ra, 0, 0, uid);
		if(!addr)
			return 0;
		preread(p->dev, addr);
		return ra+1;
	}
	return ra;
}
Exemple #2
0
/*
 * normalize: normalize path name
 *
 *	i)	path	path name
 *	i)	root	root of project (must be end with a '/')
 *	i)	cwd	current directory
 *	o)	result	normalized path name
 *	i)	size	size of the result
 *	r)		==NULL: error
 *			!=NULL: result
 */
char *
normalize(const char *path, const char *root, const char *cwd, char *result, const int size)
{
    char *p, abs[MAXPATHLEN];

    if (normalize_pathname(path, result, size) == NULL)
        goto toolong;
    if (isabspath(path)) {
        if (strlen(result) > MAXPATHLEN)
            goto toolong;
        strcpy(abs, result);
    } else {
        if (rel2abs(result, cwd, abs, sizeof(abs)) == NULL)
            goto toolong;
    }
    /*
     * Remove the root part of path and insert './'.
     *      rootdir  /a/b/
     *      path     /a/b/c/d.c -> c/d.c -> ./c/d.c
     */
    p = locatestring(abs, root, MATCH_AT_FIRST);
    if (p == NULL)
        return NULL;
    strlimcpy(result, "./", size);
    strlimcpy(result + 2, p, size - 2);
    return result;
toolong:
    die("path name is too long.");
}
Exemple #3
0
static int
getdatablock(Fs *fs, Dentry *d, int32_t a)
{
	int32_t addr;

	if((addr = rel2abs(fs, d, a)) == 0)
		return -1;
	return getblocktag(fs, addr, Tfile, QPNONE);
}
Exemple #4
0
Iobuf*
dnodebuf(Iobuf *p, Dentry *d, Off a, int tag, int uid)
{
	Off addr;

	addr = rel2abs(p, d, a, tag, 0, uid);
	if(addr)
		return getbuf(p->dev, addr, Brd);
	return 0;
}
Exemple #5
0
Iobuf*
dnodebuf(Iobuf *p, Dentry *d, long a, int tag)
{
	long addr;

	addr = rel2abs(p, d, a, tag, 0);
	if(addr)
		return getbuf(p->dev, addr, Bread);
	return 0;
}
Exemple #6
0
static int
readdentry(Fs *fs, Dentry *d, int n, Dentry *e)
{
	int32_t addr, m;

	m = n/fs->kfs.DIRPERBUF;
	if((addr = rel2abs(fs, d, m)) <= 0)
		return addr;
	if(getblocktag(fs, addr, Tdir, d->qid.path) < 0)
		return -1;
	*e = *(Dentry*)(block+(n%fs->kfs.DIRPERBUF)*sizeof(Dentry));
	return 1;
}
Exemple #7
0
/*
 * same as dnodebuf but it calls putbuf(p)
 * to reduce interference.
 */
Iobuf*
dnodebuf1(Iobuf *p, Dentry *d, Off a, int tag, int uid)
{
	Off addr;
	Device *dev;

	dev = p->dev;
	addr = rel2abs(p, d, a, tag, 1, uid);
	if(addr)
		return getbuf(dev, addr, Brd);
	return 0;

}
Exemple #8
0
/*
 * same as dnodebuf but it calls putpuf(p)
 * to reduce interference.
 */
Iobuf*
dnodebuf1(Iobuf *p, Dentry *d, long a, int tag)
{
	long addr;
	Device dev;

	dev = p->dev;
	addr = rel2abs(p, d, a, tag, 1);
	if(addr)
		return getbuf(dev, addr, Bread);
	return 0;

}
Exemple #9
0
struct string_t *arb_rel2abs(char *path, char *base)
{
	size_t size = 100;
	char *buffer = (char*)malloc(size);
	if(!buffer)
		return NULL;
	
	if(rel2abs(path, base, buffer, size) == buffer)
	{
		struct string_t *string = malloc(sizeof(struct string_t));
		string->text = buffer;
		return string;
	}
	
	while(1)
	{
		size *= 2;
		
		char *new_buffer = (char*)realloc(buffer, size);
		if(!new_buffer)
		{
			free(buffer);
			return NULL;
		}
		
		buffer = new_buffer;
		
		if(rel2abs(path, base, buffer, size) == buffer)
		{
			struct string_t *string = malloc(sizeof(struct string_t));
			string->text = buffer;
			return string;
		}
		
		if(errno != ERANGE)
			return NULL;
	}
}
Exemple #10
0
void open_dialog(Vector2i pos, color_t color_index)
{
	size_t height = (color_index == CIDX_DEFAULT)  ? left_pos.y+2
		          : (color_index == CIDX_NEWCOLOR) ? delete_pos.y
		          : DIALOG_WINDOW_HEIGHT;
	cidx = color_index;

	if (pos.x + DIALOG_WINDOW_WIDTH >= MENU_WINDOW_WIDTH) {
		pos.x += DIALOG_WINDOW_WIDTH - MENU_WINDOW_WIDTH - 2;
	}
	dialog_pos = rel2abs(pos, menu_pos);

	dialogw = newwin(height, DIALOG_WINDOW_WIDTH, dialog_pos.y, dialog_pos.x);
	keypad(dialogw, TRUE);
	nodelay(dialogw, TRUE);
}
Exemple #11
0
/**
 * @details
 * normalize: normalize path name
 *
 *	@param[in]	path	path name
 *	@param[in]	root	root of project (@STRONG{must be end with a '/'})
 *	@param[in]	cwd	current directory
 *	@param[out]	result	normalized path name
 *	@param[in]	size	size of the @a result
 *	@return		==NULL: error <br>
 *			!=NULL: @a result
 *
 *	@note Calls die() if the result path name is too long (#MAXPATHLEN).
 */
char *
normalize(const char *path, const char *root, const char *cwd, char *result, const int size)
{
	char *p, abs[MAXPATHLEN];

	if (normalize_pathname(path, result, size) == NULL)
		goto toolong;
	if (isabspath(path)) {
		if (strlen(result) > MAXPATHLEN)
			goto toolong;
		strcpy(abs, result);
	} else {
		if (rel2abs(result, cwd, abs, sizeof(abs)) == NULL)
			goto toolong;
	}
	/*
	 * Remove the root part of path and insert './'.
	 *      rootdir  /a/b/
	 *      path     /a/b/c/d.c -> c/d.c -> ./c/d.c
	 */
	p = locatestring(abs, root, MATCH_AT_FIRST);
	if (p == NULL) {
		p = locatestring(root, abs, MATCH_AT_FIRST);
		/*
		 * abs == /usr/src should be considered to be equal to root == /usr/src/.
		 */
		if (p && !strcmp(p, "/"))
			result[0] = '\0';
		else
			return NULL;
	}
	strlimcpy(result, "./", size);
	strlimcpy(result + 2, p, size - 2);
	return result;
toolong:
	die("path name is too long.");
}
Exemple #12
0
int
main(int argc, char **argv)
{
	char c;
	const char *p, *browser = NULL, *definition = NULL;
	STRBUF *arg = strbuf_open(0);
	STRBUF *URL = strbuf_open(0);

	while (--argc > 0 && ((c = (++argv)[0][0]) == '-' || c == '+')) {
		if (argv[0][1] == '-') {
			if (!strcmp("--help", argv[0]))
				help();
			else if (!strcmp("--version", argv[0]))
				show_version++;
			else if (!strcmp("--quiet", argv[0])) {
				qflag++;
				vflag = 0;
			} else if (!strcmp("--verbose", argv[0])) {
				vflag++;
				qflag = 0;
			} else
				usage();
			continue;
		}
		if (c == '+') {
			linenumber = atoi(argv[0] + 1);
			continue;
		}
		p = argv[0] + 1;
		switch (*p) {
		case 'b':
			browser = argv[1];
			--argc; ++argv;
			break;
		case 'd':
			definition = argv[1];
			--argc; ++argv;
			break;
		case 'p':
			pflag++;
			break;
		case 'q':
			qflag++;
			setquiet();
			break;
		case 'v':
			vflag++;
			setverbose();
			break;
		default:
			usage();
		}
	}
	if (show_version)
		version(progname, vflag);
	/*
	 * Load aliases from .gozillarc.
	 */
	load_alias();

	/*
	 * Decide browser.
	 */
	if (!browser && getenv("BROWSER"))
		browser = getenv("BROWSER");
	if (!browser && alias("BROWSER"))
		browser = alias("BROWSER");
	/*
	 * In DOS & Windows, let the file: association handle it.
	 */
#if !(_WIN32 || __DJGPP__)
	if (!browser)
		browser = "mozilla";
#endif

	/*
	 * Replace alias name.
	 */
	if (definition == NULL) {
		if (argc == 0)
			usage();
		strbuf_puts(arg, argv[0]);
		/*
		 * Replace with alias value.
		 */
		if ((p = alias(strbuf_value(arg))) != NULL) {
			strbuf_reset(arg);
			strbuf_puts(arg, p);
		}
	}
	/*
	 * Get URL.
	 */
	{
		char *argument = strbuf_value(arg);

		/*
		 * Protocol (xxx://...)
		 */
		if (!definition && isprotocol(argument)) {
			strbuf_puts(URL, argument);
		} else {
			const char *HTMLdir = NULL;

			if (setupdbpath(0) == 0) {
				cwd = get_cwd();
				root = get_root();
				dbpath = get_dbpath();
				HTMLdir = locate_HTMLdir();
			} 
			/*
			 * Make a URL of hypertext from the argument.
			 */
			if (HTMLdir != NULL) {
				if (definition)
					getdefinitionURL(definition, HTMLdir, URL);
				else
					getURL(argument, HTMLdir, URL);
			}
			/*
			 * Make a file URL.
			 */
			else if (test("fr", argument) || test("dr", argument)) {
				char cwd[MAXPATHLEN];
				char result[MAXPATHLEN];

				if (getcwd(cwd, sizeof(cwd)) == NULL)
					die("cannot get current directory.");
				if (rel2abs(argument, cwd, result, sizeof(result)) == NULL)
					die("rel2abs failed.");
				strbuf_puts(URL, "file://");
				strbuf_puts(URL, result);
			} else {
				die_with_code(1, "file '%s' not found.", argument);
			}
		}
	}
	if (pflag) {
		fprintf(stdout, "%s\n", strbuf_value(URL));
		if (vflag)
			fprintf(stdout, "using browser '%s'.\n", browser);
		exit(0);
	}
	/*
	 * Show URL's page.
	 */
	show_page_by_url(browser, strbuf_value(URL));
	exit(0);
}
Exemple #13
0
int
fffiles( char *name, char **buf )
{
	char	pathbuf[ NFILEN ], tmpnam[ NFILEN ] ;
	char	pathbufs[ NFILEN ], ff_namee[ NFILEN ] ;
	char	*cp, *dirpart, *nampart, *buffer ;
	int		n, len, size, dirpartlen, nampartlen, l ;
	HANDLE	hFind ;
	WIN32_FIND_DATA	find ;
	TCHAR	findPath[ MAX_PATH ], unicode[ MAX_PATH ] ;
#ifdef HOMEDIR
	char	*home;
	int	homelen;
#endif

#ifndef _WIN32_WCE
	if (name[1] == ':' && name[2] == '\0') {
	  return -1;
	}
#endif

#ifdef HOMEDIR
	if (name[0] == '~' && (name[1]=='/' || name[1]=='\\') &&
	    (home = getenv("HOME"))) {
		homelen = strlen(home)-1;
		strncpy(pathbuf, home, sizeof(pathbuf));
		pathbuf[NFILEN-1] = '\0';
		strncat(pathbuf, &name[1], sizeof(pathbuf)-strlen(pathbuf)-1);
	} else {
		home = NULL;
		homelen = 0;
		strncpy(pathbuf, name, sizeof(pathbuf));
		pathbuf[NFILEN-1] = '\0';
    	}
#else
	strncpy(pathbuf, name, sizeof(pathbuf));
	pathbuf[NFILEN-1] = '\0';
#endif
	dirpart = NULL ;
	for ( cp = pathbuf ; *cp ; cp ++ ) {
		if ( *cp == '/' ) {
			*cp = '\\' ;
			dirpart = cp ;
		} else if ( *cp == '\\' ) {
			dirpart = cp ;
		} else if ( dirpart == NULL && *cp == ':' ) {
			dirpart = cp ;
		}
	}
	if ( dirpart ) {
		*++dirpart = '\0' ;
		dirpartlen = dirpart - pathbuf ;
	} else {
		strcpy( pathbuf, ".\\" ) ;	/* 90.05.30  by A.Shirahashi */
		dirpartlen = 0 ;
	}
#ifdef	HOMEDIR
	nampart = name + dirpartlen - homelen;
#else
	nampart = name + dirpartlen;
#endif
	nampartlen = strlen( nampart ) ;

	buffer = malloc( MALLOC_STEP ) ;
	if ( buffer == NULL ) {
		return -1 ;
	}
	size = MALLOC_STEP ;
	len = 0 ;
	n = 0 ;

	(VOID) strcat( pathbuf, "*.*" ) ;
	strcpy( pathbufs, pathbuf ) ;
#ifdef KANJI
	bufetos( pathbufs, strlen(pathbufs) + 1 ) ;
#endif
	/* Convert the search path to UNICODE and get absolute path */
	sjis2unicode( (LPBYTE) pathbufs, unicode, sizeof unicode ) ;
	rel2abs( findPath, g_szCurDir, unicode ) ;
	/* Find first file */
	hFind = FindFirstFile( findPath, &find ) ;
	if ( hFind == INVALID_HANDLE_VALUE ) {
		*buf = buffer ;
		buffer[0] = '\0' ;
		return 0 ;
	}
	do {
		if ( !lstrcmp( find.cFileName, TEXT(".") ) ) {
			continue ;
		} else if ( !lstrcmp( find.cFileName, TEXT("..") ) ) {
			continue ;
		}
		unicode2sjis( find.cFileName, (LPBYTE) ff_namee, sizeof ff_namee ) ;
#ifdef KANJI
		bufstoe( ff_namee, strlen(ff_namee) + 1 ) ;
#endif
		if ( strnicmp( nampart, ff_namee, nampartlen ) ) {
			continue ;		/* no-case-sensitive comparison */
		}
		strncpy( tmpnam, pathbuf, dirpartlen ) ;
		strcpy( tmpnam + dirpartlen, ff_namee ) ;
		if ( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
			strcat( tmpnam, "\\" ) ;
		}
		l = strlen(tmpnam) + 1 ;
		/* 90.05.30  by A.Shirahashi */
		if ( l > 5 && (stricmp( &tmpnam[l-5], ".OBJ" ) == 0 ||
						stricmp( &tmpnam[l-5], ".EXE" ) == 0 ||
						stricmp( &tmpnam[l-5], ".COM" ) == 0 ) ) {
			/* 90.05.30  by A.Shirahashi */
			continue ;
		}
		if ( l + len >= size ) {
			/* make room for double null */
			if ( ( buffer = realloc( buffer, size += MALLOC_STEP ) ) == NULL ) {
			        FindClose(hFind);
				return -1 ;
			}
		}
		/* 90.06.08  by A.Shirahashi: to */
		/* 00.12.28  by amura.. contributed by sahf */
#ifdef HOMEDIR
		if(home) {
			strcpy(buffer+len, "~");
			strcat(buffer+len, tmpnam+homelen+1);
			l -= homelen;
		} else
#endif
		strcpy( buffer + len, tmpnam ) ;
		len += l ;
		n ++ ;
	} while ( FindNextFile( hFind, &find ) ) ;

	FindClose(hFind);
	*buf = buffer ;
	buffer[len] = '\0' ;
	return n ;
}
Exemple #14
0
    // create a path that is relative to the given base directory
    // path and base will first be resolved against cwd to make them absolute
    std::string abs2rel(const std::string& uri, const std::string& base, const std::string& cwd)
    {

      std::string absolute_uri = rel2abs(uri, cwd);
      std::string absolute_base = rel2abs(base, cwd);

      size_t proto = 0;
      // check if we have a protocol
      if (uri[proto] && Prelexer::is_alpha(uri[proto])) {
        // skip over all alphanumeric characters
        while (uri[proto] && Prelexer::is_alnum(uri[proto++])) {}
        // then skip over the mandatory colon
        if (proto && uri[proto] == ':') ++ proto;
      }

      // distinguish between windows absolute paths and valid protocols
      // we assume that protocols must at least have two chars to be valid
      if (proto && uri[proto++] == '/' && proto > 3) return uri;

      #ifdef _WIN32
        // absolute link must have a drive letter, and we know that we
        // can only create relative links if both are on the same drive
        if (absolute_base[0] != absolute_uri[0]) return absolute_uri;
      #endif

      std::string stripped_uri = "";
      std::string stripped_base = "";

      size_t index = 0;
      size_t minSize = std::min(absolute_uri.size(), absolute_base.size());
      for (size_t i = 0; i < minSize; ++i) {
        #ifdef FS_CASE_SENSITIVE
          if (absolute_uri[i] != absolute_base[i]) break;
        #else
          // compare the charactes in a case insensitive manner
          // windows fs is only case insensitive in ascii ranges
          if (tolower(absolute_uri[i]) != tolower(absolute_base[i])) break;
        #endif
        if (absolute_uri[i] == '/') index = i + 1;
      }
      for (size_t i = index; i < absolute_uri.size(); ++i) {
        stripped_uri += absolute_uri[i];
      }
      for (size_t i = index; i < absolute_base.size(); ++i) {
        stripped_base += absolute_base[i];
      }

      size_t left = 0;
      size_t directories = 0;
      for (size_t right = 0; right < stripped_base.size(); ++right) {
        if (stripped_base[right] == '/') {
          if (stripped_base.substr(left, 2) != "..") {
            ++directories;
          }
          else if (directories > 1) {
            --directories;
          }
          else {
            directories = 0;
          }
          left = right + 1;
        }
      }

      std::string result = "";
      for (size_t i = 0; i < directories; ++i) {
        result += "../";
      }
      result += stripped_uri;

      return result;
    }
Exemple #15
0
int
main(int argc, char **argv)
{
	const char *av = NULL;
	int db;
	int optchar;
	int option_index = 0;
	int status = 0;

	/*
	 * get path of following directories.
	 *	o current directory
	 *	o root of source tree
	 *	o dbpath directory
	 *
	 * if GTAGS not found, exit with an error message.
	 */
	status = setupdbpath(0);
	if (status == 0) {
		cwd = get_cwd();
		root = get_root();
		dbpath = get_dbpath();
	}
	/*
	 * Setup GTAGSCONF and GTAGSLABEL environment variable
	 * according to the --gtagsconf and --gtagslabel option.
	 */
	preparse_options(argc, argv);
	/*
	 * Open configuration file.
	 */
	openconf(root);
	setenv_from_config();
	logging_arguments(argc, argv);
	while ((optchar = getopt_long(argc, argv, "acde:EifFgGIlL:MnoOpPqrsS:tTuvVx", long_options, &option_index)) != EOF) {
		switch (optchar) {
		case 0:
			break;
		case 'a':
			aflag++;
			break;
		case 'c':
			cflag++;
			setcom(optchar);
			break;
		case 'd':
			dflag++;
			break;
		case 'e':
			av = optarg;
			break;
		case 'E':
			Gflag = 0;
			break;
		case 'f':
			fflag++;
			xflag++;
			setcom(optchar);
			break;
		case 'F':
			Tflag = 0;
			break;
		case 'g':
			gflag++;
			setcom(optchar);
			break;
		case 'G':
			Gflag++;
			break;
		case 'i':
			iflag++;
			break;
		case 'I':
			Iflag++;
			setcom(optchar);
			break;
		case 'l':
			Sflag++;
			scope = ".";
			break;
		case 'L':
			file_list = optarg;
			break;
		case 'M':
			Mflag++;
			iflag = 0;
			break;
		case 'n':
			nflag++;
			if (optarg) {
				if (!strcmp(optarg, "sort"))
					nofilter |= SORT_FILTER;
				else if (!strcmp(optarg, "path"))
					nofilter |= PATH_FILTER;
			} else {
				nofilter = BOTH_FILTER;
			}
			break;
		case 'o':
			oflag++;
			break;
		case 'O':
			Oflag++;
			break;
		case 'p':
			pflag++;
			setcom(optchar);
			break;
		case 'P':
			Pflag++;
			setcom(optchar);
			break;
		case 'q':
			qflag++;
			setquiet();
			break;
		case 'r':
			rflag++;
			break;
		case 's':
			sflag++;
			break;
		case 'S':
			Sflag++;
			scope = optarg;
			break;
		case 't':
			tflag++;
			break;
		case 'T':
			Tflag++;
			break;
		case 'u':
			uflag++;
			setcom(optchar);
			break;
		case 'v':
			vflag++;
			setverbose();
			break;
		case 'V':
			Vflag++;
			break;
		case 'x':
			xflag++;
			break;
		case OPT_USE_COLOR:
			if (optarg) {
				if (!strcmp(optarg, "never"))
					use_color = 0;
				else if (!strcmp(optarg, "always"))
					use_color = 1;
				else if (!strcmp(optarg, "auto"))
					use_color = 2;
				else
					die_with_code(2, "unknown color type.");
			} else {
				use_color = 2;
			}
			break;
		case OPT_ENCODE_PATH:
			encode_chars = optarg;
			break;
		case OPT_FROM_HERE:
			{
			char *p = optarg;
			const char *usage = "usage: global --from-here=lineno:path.";

			context_lineno = p;
			while (*p && isdigit(*p))
				p++;
			if (*p != ':')
				die_with_code(2, usage);
			*p++ = '\0';
			if (!*p)
				die_with_code(2, usage);
			context_file = p;
			}
			break;
		case OPT_GTAGSCONF:
		case OPT_GTAGSLABEL:
			/* These options are already parsed in preparse_options() */
			break;
		case OPT_MATCH_PART:
			if (!strcmp(optarg, "first"))
				match_part = MATCH_PART_FIRST;
			else if (!strcmp(optarg, "last"))
				match_part = MATCH_PART_LAST;
			else if (!strcmp(optarg, "all"))
				match_part = MATCH_PART_ALL;
			else
				die_with_code(2, "unknown part type for the --match-part option.");
			break;
		case OPT_PATH_CONVERT:
			do_path = 1;
			if (!strcmp("absolute", optarg))
				convert_type = PATH_ABSOLUTE;
			else if (!strcmp("relative", optarg))
				convert_type = PATH_RELATIVE;
			else if (!strcmp("through", optarg))
				convert_type = PATH_THROUGH;
			else
				die("Unknown path type.");
			break;
		case OPT_PATH_STYLE:
			path_style = optarg;
			break;
		case OPT_RESULT:
			if (!strcmp(optarg, "ctags-x"))
				format = FORMAT_CTAGS_X;
			else if (!strcmp(optarg, "ctags-xid"))
				format = FORMAT_CTAGS_XID;
			else if (!strcmp(optarg, "ctags"))
				format = FORMAT_CTAGS;
			else if (!strcmp(optarg, "ctags-mod"))
				format = FORMAT_CTAGS_MOD;
			else if (!strcmp(optarg, "path"))
				format = FORMAT_PATH;
			else if (!strcmp(optarg, "grep"))
				format = FORMAT_GREP;
			else if (!strcmp(optarg, "cscope"))
				format = FORMAT_CSCOPE;
			else
				die_with_code(2, "unknown format type for the --result option.");
			break;
		case OPT_SINGLE_UPDATE:
			single_update = optarg;
			break;
		default:
			usage();
			break;
		}
	}
	if (qflag)
		vflag = 0;
	if (show_version)
		version(av, vflag);
	if (show_help)
		help();
	if (dbpath == NULL)
		die_with_code(-status, gtags_dbpath_error);
	/*
	 * decide format.
	 * The --result option is given to priority more than the -t and -x option.
	 */
	if (format == 0) {
		if (tflag) { 			/* ctags format */
			format = FORMAT_CTAGS;
		} else if (xflag) {		/* print details */
			format = FORMAT_CTAGS_X;
		} else {			/* print just a file name */
			format = FORMAT_PATH;
		}
	}
	/*
	 * GTAGSBLANKENCODE will be used in less(1).
	 */
	switch (format) {
	case FORMAT_CTAGS_X:
	case FORMAT_CTAGS_XID:
		if (encode_chars == NULL && getenv("GTAGSBLANKENCODE"))
			encode_chars = " \t";
		break;
	}
	if (encode_chars) {
		if (strlen(encode_chars) > 255)
			die("too many encode chars.");
		if (strchr(encode_chars, '/') || strchr(encode_chars, '.'))
			warning("cannot encode '/' and '.' in the path. Ignored.");
		set_encode_chars((unsigned char *)encode_chars);
	}
	if (getenv("GTAGSTHROUGH"))
		Tflag++;
	if (use_color) {
#if defined(_WIN32) && !defined(__CYGWIN__)
		if (!(getenv("ANSICON") || LoadLibrary("ANSI32.dll")) && use_color == 2)
			use_color = 0;
#endif
		if (use_color == 2 && !isatty(1))
			use_color = 0;
		if (Vflag)
			use_color = 0;
	}
	argc -= optind;
	argv += optind;
	/*
	 * Path filter
	 */
	if (do_path) {
		/*
		 * This code is needed for globash.rc.
		 * This code extract path name from tag line and
		 * replace it with the relative or the absolute path name.
		 *
		 * By default, if we are in src/ directory, the output
		 * should be converted like follows:
		 *
		 * main      10 ./src/main.c  main(argc, argv)\n
		 * main      22 ./libc/func.c   main(argc, argv)\n
		 *		v
		 * main      10 main.c  main(argc, argv)\n
		 * main      22 ../libc/func.c   main(argc, argv)\n
		 *
		 * Similarly, the --path-convert=absolute option specified, then
		 *		v
		 * main      10 /prj/xxx/src/main.c  main(argc, argv)\n
		 * main      22 /prj/xxx/libc/func.c   main(argc, argv)\n
		 */
		STRBUF *ib = strbuf_open(MAXBUFLEN);
		CONVERT *cv;
		char *ctags_x;

		if (argc < 3)
			die("global --path-convert: 3 arguments needed.");
		cv = convert_open(convert_type, FORMAT_CTAGS_X, argv[0], argv[1], argv[2], stdout, NOTAGS);
		while ((ctags_x = strbuf_fgets(ib, stdin, STRBUF_NOCRLF)) != NULL)
			convert_put(cv, ctags_x);
		convert_close(cv);
		strbuf_close(ib);
		exit(0);
	}
	/*
	 * At first, we pickup pattern from -e option. If it is not found
	 * then use argument which is not option.
	 */
	if (!av) {
		av = *argv;
		/*
		 * global -g pattern [files ...]
		 *           av      argv
		 */
		if (gflag && av)
			argv++;
	}
	if (single_update) {
		if (command == 0) {
			uflag++;
			command = 'u';
		} else if (command != 'u') {
			;	/* ignored */
		}
	}
	/*
	 * only -c, -u, -P and -p allows no argument.
	 */
	if (!av) {
		switch (command) {
		case 'c':
		case 'u':
		case 'p':
		case 'P':
			break;
		case 'f':
			if (file_list)
				break;
		default:
			usage();
			break;
		}
	}
	/*
	 * -u and -p cannot have any arguments.
	 */
	if (av) {
		switch (command) {
		case 'u':
		case 'p':
			usage();
		default:
			break;
		}
	}
	if (tflag)
		xflag = 0;
	if (nflag > 1)
		nosource = 1;	/* to keep compatibility */
	if (print0)
		set_print0();
	if (cflag && match_part == 0)
		match_part = MATCH_PART_ALL;
	/*
	 * remove leading blanks.
	 */
	if (!Iflag && !gflag && av)
		for (; *av == ' ' || *av == '\t'; av++)
			;
	if (cflag && !Pflag && av && isregex(av))
		die_with_code(2, "only name char is allowed with -c option.");
	/*
	 * print dbpath or rootdir.
	 */
	if (pflag) {
		fprintf(stdout, "%s\n", (rflag) ? root : dbpath);
		exit(0);
	}
	/*
	 * incremental update of tag files.
	 */
	if (uflag) {
		STRBUF	*sb = strbuf_open(0);
		char *gtags_path = usable("gtags");

		if (!gtags_path)
			die("gtags command not found.");
		if (chdir(root) < 0)
			die("cannot change directory to '%s'.", root);
#if defined(_WIN32) && !defined(__CYGWIN__)
		/*
		 * Get around CMD.EXE's weird quoting rules by sticking another
		 * perceived whitespace in front (also works with Take Command).
		 */
		strbuf_putc(sb, ';');
#endif
		strbuf_puts(sb, quote_shell(gtags_path));
		strbuf_puts(sb, " -i");
		if (vflag)
			strbuf_puts(sb, " -v");
		if (single_update) {
			if (!isabspath(single_update)) {
				static char regular_path_name[MAXPATHLEN];

				if (rel2abs(single_update, cwd, regular_path_name, sizeof(regular_path_name)) == NULL)
					die("rel2abs failed.");
				single_update = regular_path_name;
			}
			strbuf_puts(sb, " --single-update ");
			strbuf_puts(sb, quote_shell(single_update));
		}
		strbuf_putc(sb, ' ');
		strbuf_puts(sb, quote_shell(dbpath));
		if (system(strbuf_value(sb)))
			exit(1);
		strbuf_close(sb);
		exit(0);
	}
	/*
	 * decide tag type.
	 */
	if (context_file) {
		if (isregex(av))
			die_with_code(2, "regular expression is not allowed with the --from-here option.");
		db = decide_tag_by_context(av, context_file, atoi(context_lineno));
	} else {
		if (dflag)
			db = GTAGS;
		else if (rflag && sflag)
			db = GRTAGS + GSYMS;
		else
			db = (rflag) ? GRTAGS : ((sflag) ? GSYMS : GTAGS);
	}
	/*
	 * complete function name
	 */
	if (cflag) {
		if (Iflag)
			completion_idutils(dbpath, root, av);
		else if (Pflag)
			completion_path(dbpath, av);
		else
			completion(dbpath, root, av, db);
		exit(0);
	}
	/*
	 * make local prefix.
	 * local prefix must starts with './' and ends with '/'.
	 */
	if (Sflag) {
		STRBUF *sb = strbuf_open(0);
		static char buf[MAXPATHLEN];
		const char *path = scope;
	
		/*
		 * normalize the path of scope directory.
		 */
		if (!test("d", path))
			die("'%s' not found or not a directory.", scope);
		if (!isabspath(path))
			path = makepath(cwd, path, NULL);
		if (realpath(path, buf) == NULL)
			die("cannot get real path of '%s'.", scope);
		if (!in_the_project(buf))
			die("'%s' is out of the source project.", scope);
		scope = buf;
		/*
		 * make local prefix.
		 */
		strbuf_putc(sb, '.');
		if (strcmp(root, scope) != 0) {
			const char *p = scope + strlen(root);
			if (*p != '/')
				strbuf_putc(sb, '/');
			strbuf_puts(sb, p);
		}
		strbuf_putc(sb, '/');
		localprefix = check_strdup(strbuf_value(sb));
		strbuf_close(sb);
#ifdef DEBUG
		fprintf(stderr, "root=%s\n", root);
		fprintf(stderr, "cwd=%s\n", cwd);
		fprintf(stderr, "localprefix=%s\n", localprefix);
#endif
	}
	/*
	 * convert the file-list path into an absolute path.
	 */
	if (file_list && strcmp(file_list, "-") && !isabspath(file_list)) {
		static char buf[MAXPATHLEN];

		if (realpath(file_list, buf) == NULL)
			die("'%s' not found.", file_list);
		file_list = buf;
	}
	/*
	 * decide path conversion type.
	 */
	if (nofilter & PATH_FILTER)
		type = PATH_THROUGH;
	else if (aflag)
		type = PATH_ABSOLUTE;
	else
		type = PATH_RELATIVE;
	if (path_style) {
		if (!strcmp(path_style, "relative"))
			type = PATH_RELATIVE;
		else if (!strcmp(path_style, "absolute"))
			type = PATH_ABSOLUTE;
		else if (!strcmp(path_style, "through"))
			type = PATH_THROUGH;
		else if (!strcmp(path_style, "shorter"))
			type = PATH_SHORTER;
		else if (!strcmp(path_style, "abslib")) {
			type = PATH_RELATIVE;
			abslib++;
		} else
			die("invalid path style.");
	}
	/*
	 * exec lid(idutils).
	 */
	if (Iflag) {
		chdir(root);
		idutils(av, dbpath);
	}
	/*
	 * search pattern (regular expression).
	 */
	else if (gflag) {
		chdir(root);
		grep(av, argv, dbpath);
	}
	/*
	 * locate paths including the pattern.
	 */
	else if (Pflag) {
		chdir(root);
		pathlist(av, dbpath);
	}
	/*
	 * parse source files.
	 */
	else if (fflag) {
		chdir(root);
		parsefile(argv, cwd, root, dbpath, db);
	}
	/*
	 * tag search.
	 */
	else {
		tagsearch(av, cwd, root, dbpath, db);
	}
	return 0;
}