/* * Copyright (c) 2005 Tama Communications Corporation * * This file is part of GNU GLOBAL. * * GNU GLOBAL 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 2, or (at your option) * any later version. * * GNU GLOBAL 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "abs2rel.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). */ /* * put_converting: convert path into relative or absolute and print. * * i) raw output from global(1) * i) format (defined in tagsort.h) * i) fileid 1: add fid to the head of line, 0: do nothing */ static STRBUF *abspath; static char basedir[MAXPATHLEN+1]; static int start_point; static void set_base_directory(const char *root, const char *cwd) { abspath = strbuf_open(MAXPATHLEN); strbuf_puts(abspath, root); strbuf_unputc(abspath, '/'); start_point = strbuf_getlen(abspath); if (strlen(cwd) > MAXPATHLEN) die("current directory name too long."); strlimcpy(basedir, cwd, sizeof(basedir)); /* leave abspath unclosed. */ } static void put_converting(const char *tagline, int type, int format, int fileid, FILE *op) { char buf[MAXPATHLEN+1]; char *path, *p; /* * print until path name. */ if (format == FORMAT_PATH) { path = (char *)tagline; } else { /* FORMAT_CTAGS, FORMAT_CTAGS_X */ int savec = 0; /* * Move to the head of path name. * * Don't use split() function, since we must support * following both format: * ctags: main ./main.c 20 * ctags -x: main 20 ./main.c main() */ /* skip tag name */ for (p = (char *)tagline; *p && !isspace((unsigned char)*p); p++) ; /* skip blanks (and line number) */ for (; *p && *p != '.'; p++) ; path = p; /* * The --fileid option specified, put file id to the head * of the output like follows. * * 120@main 32 ./main.c main(int argc, char **argv) * ~~~ ~~~~~~~~~ * ^ | * +---------------------+ * * Global.cgi script generated by htags(1) refers it to * generate anchor. */ if (fileid) { for (; *p && !isspace((unsigned char)*p); p++) ; savec = *p; *p = '\0'; fputs(gpath_path2fid(path, NULL), op); *p = savec; putc('@', op); } for (p = (char *)tagline; *p && p < path; p++) (void)putc(*p, op); } if (*path++ == '\0') return; /* * make absolute path. */ strbuf_setlen(abspath, start_point); for (p = path; *p && !isspace((unsigned char)*p); p++) strbuf_putc(abspath, *p); /* * put path with converting. */ if (type == PATH_ABSOLUTE) { (void)fputs(strbuf_value(abspath), op); } else { const char *a = strbuf_value(abspath); const char *b = basedir; #if defined(_WIN32) || defined(__DJGPP__) /* skip drive char in 'c:/usr/bin' */ while (*a != '/') a++; while (*b != '/') b++; #endif if (!abs2rel(a, b, buf, sizeof(buf))) die("abs2rel failed. (path=%s, base=%s).", a, b); (void)fputs(buf, op); } /* * print the rest of the record. */ (void)fputs(p, op); } /* * pathconvert: convert path into relative or absolute and print. * * i) type PATH_ABSOLUTE, PATH_RELATIVE * i) format tag record format * i) fileid append fileid at the head of the line * i) root root directory of source tree * i) cwd current directory * i) dbpath dbpath directory * i) ip input file * i) op output file */ void pathconvert(int type, int format, int fileid, const char *root, const char *cwd, const char *dbpath, FILE *ip, FILE *op) { STRBUF *ib = strbuf_open(MAXBUFLEN); const char *ctags_x; set_base_directory(root, cwd); if (gpath_open(dbpath, 0) < 0) die("GPATH not found."); while ((ctags_x = strbuf_fgets(ib, ip, 0)) != NULL) put_converting(ctags_x, type, format, fileid, op); gpath_close(); strbuf_close(ib); }