/*
* Copyright (c) 2005, 2006 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 .
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#ifdef STDC_HEADERS
#include
#endif
#include "abs2rel.h"
#include "checkalloc.h"
#include "die.h"
#include "format.h"
#include "gparam.h"
#include "gpathop.h"
#include "pathconvert.h"
#include "strbuf.h"
#include "strlimcpy.h"
/*
* Path filter for the output of global(1).
*/
static const char *
convert_pathname(CONVERT *cv, const char *path)
{
static char buf[MAXPATHLEN+1];
const char *a, *b;
/*
* print without conversion.
*/
if (cv->type == PATH_THROUGH)
return path;
/*
* make absolute path name.
* 'path + 1' means skipping "." at the head.
*/
strbuf_setlen(cv->abspath, cv->start_point);
strbuf_puts(cv->abspath, path + 1);
/*
* print path name with converting.
*/
switch (cv->type) {
case PATH_ABSOLUTE:
path = strbuf_value(cv->abspath);
break;
case PATH_RELATIVE:
a = strbuf_value(cv->abspath);
b = cv->basedir;
#if defined(_WIN32) || defined(__DJGPP__)
while (*a != '/')
a++;
while (*b != '/')
b++;
#endif
if (!abs2rel(a, b, buf, sizeof(buf)))
die("abs2rel failed. (path=%s, base=%s).", a, b);
path = buf;
break;
default:
die("unknown path type.");
break;
}
return (const char *)path;
}
/*
* 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;
}
/*
* convert_put: convert path into relative or absolute and print.
*
* i) cv CONVERT structure
* i) tagline output record
*/
void
convert_put(CONVERT *cv, const char *tagline)
{
char *tagnextp = NULL;
int tagnextc = 0;
char *tag = NULL, *lineno = NULL, *path, *rest = NULL;
/*
* parse tag line.
* Don't use split() function not to destroy line image.
*/
if (cv->format == FORMAT_PATH) {
path = (char *)tagline;
} else {
char *p = (char *)tagline;
/*
* tag name
*/
tag = p;
for (; *p && !isspace(*p); p++)
;
if (*p == '\0')
die("illegal ctags-x format (line number not found).");
tagnextp = p;
tagnextc = *p;
*p++ = '\0';
/* skip blanks */
for (; *p && isspace(*p); p++)
;
if (*p == '\0')
die("illegal ctags-x format (line number not found).");
/*
* line number
*/
lineno = p;
for (; *p && !isspace(*p); p++)
;
if (*p == '\0')
die("illegal ctags-x format (path name not found).");
*p++ = '\0';
/* skip blanks */
for (; *p && isspace(*p); p++)
;
if (*p == '\0')
die("illegal ctags-x format (path name not found).");
/*
* path name
*/
path = p;
for (; *p && !isspace(*p); p++)
;
if (*p == '\0')
die("illegal ctags-x format (line image not found).");
*p++ = '\0';
rest = p;
}
switch (cv->format) {
case FORMAT_PATH:
fputs(convert_pathname(cv, path), cv->op);
break;
case FORMAT_CTAGS:
fputs(tag, cv->op);
fputc('\t', cv->op);
fputs(convert_pathname(cv, path), cv->op);
fputc('\t', cv->op);
fputs(lineno, cv->op);
break;
case FORMAT_CTAGS_XID:
fputs(gpath_path2fid(path, NULL), cv->op);
fputc(' ', cv->op);
/* PASS THROUGH */
case FORMAT_CTAGS_X:
/*
* print until path name.
*/
*tagnextp = tagnextc;
fputs(tagline, cv->op);
fputc(' ', cv->op);
/*
* print path name and the rest.
*/
fputs(convert_pathname(cv, path), cv->op);
fputc(' ', cv->op);
fputs(rest, cv->op);
break;
case FORMAT_GREP:
fputs(convert_pathname(cv, path), cv->op);
fputc(':', cv->op);
fputs(lineno, cv->op);
fputc(':', cv->op);
fputs(rest, cv->op);
break;
case FORMAT_CSCOPE:
fputs(convert_pathname(cv, path), cv->op);
fputc(' ', cv->op);
fputs(tag, cv->op);
fputc(' ', cv->op);
fputs(lineno, cv->op);
fputc(' ', cv->op);
for (; *rest && isspace(*rest); rest++)
;
fputs(rest, cv->op);
break;
default:
die("unknown format type.");
}
(void)fputc('\n', cv->op);
}
/*
* convert_put_using: convert path into relative or absolute and print.
*
* i) cv CONVERT structure
* i) tag tag name
* i) path path name
* i) lineno line number
* i) line line image
*/
void
convert_put_using(CONVERT *cv, const char *tag, const char *path, int lineno, const char *rest)
{
switch (cv->format) {
case FORMAT_PATH:
fputs(convert_pathname(cv, path), cv->op);
break;
case FORMAT_CTAGS:
fputs(tag, cv->op);
fputc('\t', cv->op);
fputs(convert_pathname(cv, path), cv->op);
fputc('\t', cv->op);
fprintf(cv->op, "%d", lineno);
break;
case FORMAT_CTAGS_XID:
fputs(gpath_path2fid(path, NULL), cv->op);
fputc(' ', cv->op);
/* PASS THROUGH */
case FORMAT_CTAGS_X:
fprintf(cv->op, "%-16s %4d %-16s %s",
tag, lineno, convert_pathname(cv, path), rest);
break;
case FORMAT_GREP:
fputs(convert_pathname(cv, path), cv->op);
fputc(':', cv->op);
fprintf(cv->op, "%d", lineno);
fputc(':', cv->op);
fputs(rest, cv->op);
break;
case FORMAT_CSCOPE:
fputs(convert_pathname(cv, path), cv->op);
fputc(' ', cv->op);
fputs(tag, cv->op);
fputc(' ', cv->op);
fprintf(cv->op, "%d", lineno);
fputc(' ', cv->op);
for (; *rest && isspace(*rest); rest++)
;
fputs(rest, cv->op);
break;
default:
die("unknown format type.");
}
(void)fputc('\n', cv->op);
}
void
convert_close(CONVERT *cv)
{
strbuf_close(cv->abspath);
gpath_close();
free(cv);
}