📄 global.c
字号:
/* * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 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 <config.h>#endif#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <ctype.h>#include <stdio.h>#ifdef STDC_HEADERS#include <stdlib.h>#endif#ifdef HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "getopt.h"#include "global.h"#include "regex.h"#include "const.h"static void usage(void);static void help(void);static void setcom(int);int main(int, char **);void makefilter(STRBUF *);FILE *openfilter(void);void closefilter(FILE *);void completion(const char *, const char *, const char *);void idutils(const char *, const char *);void grep(const char *);void pathlist(const char *, const char *);void parsefile(int, char **, const char *, const char *, const char *, int);static int exec_parser(const char *, STRBUF *, const char *, const char *, FILE *);void printtag(FILE *, const char *);int search(const char *, const char *, const char *, int);void ffformat(char *, int, const char *);STRBUF *sortfilter; /* sort filter */STRBUF *pathfilter; /* path convert filter */const char *localprefix; /* local prefix */int aflag; /* [option] */int cflag; /* command */int fflag; /* command */int gflag; /* command */int Gflag; /* [option] */int iflag; /* [option] */int Iflag; /* command */int lflag; /* [option] */int nflag; /* [option] */int oflag; /* [option] */int pflag; /* command */int Pflag; /* command */int qflag; /* [option] */int rflag; /* [option] */int sflag; /* [option] */int tflag; /* [option] */int Tflag; /* [option] */int uflag; /* command */int vflag; /* [option] */int xflag; /* [option] */int show_version;int show_help;int show_filter; /* undocumented command */int debug;const char *extra_options;static voidusage(void){ if (!qflag) fputs(usage_const, stderr); exit(2);}static voidhelp(void){ fputs(usage_const, stdout); fputs(help_const, stdout); exit(0);}static struct option const long_options[] = { {"absolute", no_argument, NULL, 'a'}, {"completion", no_argument, NULL, 'c'}, {"regexp", required_argument, NULL, 'e'}, {"file", no_argument, NULL, 'f'}, {"local", no_argument, NULL, 'l'}, {"nofilter", no_argument, NULL, 'n'}, {"grep", no_argument, NULL, 'g'}, {"basic-regexp", no_argument, NULL, 'G'}, {"ignore-case", no_argument, NULL, 'i'}, {"idutils", optional_argument, NULL, 'I'}, {"other", no_argument, NULL, 'o'}, {"print-dbpath", no_argument, NULL, 'p'}, {"path", no_argument, NULL, 'P'}, {"quiet", no_argument, NULL, 'q'}, {"reference", no_argument, NULL, 'r'}, {"rootdir", no_argument, NULL, 'r'}, {"symbol", no_argument, NULL, 's'}, {"tags", no_argument, NULL, 't'}, {"through", no_argument, NULL, 'T'}, {"update", no_argument, NULL, 'u'}, {"verbose", no_argument, NULL, 'v'}, {"cxref", no_argument, NULL, 'x'}, /* long name only */ {"debug", no_argument, &debug, 1}, {"version", no_argument, &show_version, 1}, {"help", no_argument, &show_help, 1}, {"filter", no_argument, &show_filter, 1}, { 0 }};static int command;static voidsetcom(c) int c;{ if (command == 0) command = c; else if (command != c) usage();}intmain(argc, argv) int argc; char *argv[];{ const char *av = NULL; int count; int db; int optchar; int option_index = 0; char cwd[MAXPATHLEN+1]; /* current directory */ char root[MAXPATHLEN+1]; /* root of source tree */ char dbpath[MAXPATHLEN+1]; /* dbpath directory */ const char *gtags; while ((optchar = getopt_long(argc, argv, "ace:ifgGIlnopPqrstTuvx", long_options, &option_index)) != EOF) { switch (optchar) { case 0: if (!strcmp("idutils", long_options[option_index].name)) extra_options = optarg; break; case 'a': aflag++; break; case 'c': cflag++; setcom(optchar); break; case 'e': av = optarg; break; case 'f': fflag++; xflag++; setcom(optchar); break; case 'l': lflag++; break; case 'n': nflag++; break; case 'g': gflag++; setcom(optchar); break; case 'G': Gflag++; break; case 'i': iflag++; break; case 'I': Iflag++; setcom(optchar); 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 't': tflag++; break; case 'T': Tflag++; break; case 'u': uflag++; setcom(optchar); break; case 'v': vflag++; break; case 'x': xflag++; break; default: usage(); break; } } if (qflag) vflag = 0; if (show_help) help(); argc -= optind; argv += optind; /* * At first, we pickup pattern from -e option. If it is not found * then use argument which is not option. */ if (!av) av = (argc > 0) ? *argv : NULL; if (show_version) version(av, vflag); /* * invalid options. */ if (sflag && rflag) die_with_code(2, "both of -s and -r are not allowed."); /* * only -c, -u, -P and -p allows no argument. */ if (!av && !show_filter) { switch (command) { case 'c': case 'u': case 'p': case 'P': break; default: usage(); break; } } /* * -u and -p cannot have any arguments. */ if (av) { switch (command) { case 'u': case 'p': usage(); default: break; } } if (fflag) lflag = 0; if (tflag) xflag = 0; /* * remove leading blanks. */ if (!Iflag && !gflag && av) for (; *av == ' ' || *av == '\t'; av++) ; if (cflag && av && isregex(av)) die_with_code(2, "only name char is allowed with -c option."); /* * get path of following directories. * o current directory * o root of source tree * o dbpath directory * * if GTAGS not found, getdbpath doesn't return. */ getdbpath(cwd, root, dbpath, (pflag && vflag)); if (Iflag && !test("f", makepath(root, "ID", NULL))) die("You must have id-utils's index at the root of source tree."); /* * print dbpath or rootdir. */ if (pflag) { fprintf(stdout, "%s\n", (rflag) ? root : dbpath); exit(0); } /* * incremental update of tag files. */ gtags = usable("gtags"); if (!gtags) die("gtags command not found."); gtags = strdup(gtags); if (!gtags) die("short of memory."); if (uflag) { STRBUF *sb = strbuf_open(0); if (chdir(root) < 0) die("cannot change directory to '%s'.", root); strbuf_puts(sb, gtags); strbuf_puts(sb, " -i"); if (vflag) strbuf_putc(sb, 'v'); strbuf_putc(sb, ' '); strbuf_puts(sb, dbpath); if (system(strbuf_value(sb))) exit(1); strbuf_close(sb); exit(0); } /* * complete function name */ if (cflag) { completion(dbpath, root, av); exit(0); } /* * make local prefix. */ if (lflag) { char *p = cwd + strlen(root); STRBUF *sb = strbuf_open(0); /* * getdbpath() assure follows. * cwd != "/" and cwd includes root. */ strbuf_putc(sb, '.'); if (*p) strbuf_puts(sb, p); strbuf_putc(sb, '/'); localprefix = strdup(strbuf_value(sb)); if (!localprefix) die("short of memory."); strbuf_close(sb); } else { localprefix = NULL; } /* * make sort filter. */ { int unique = 0; const char *sort; /* * We cannot depend on the command PATH, because global(1) * might be called from WWW server. Since usable() looks for * the command in BINDIR directory first, gnusort need not * be in command PATH. */ sort = usable("gnusort"); if (!sort) die("gnusort not found."); sortfilter = strbuf_open(0); strbuf_puts(sortfilter, sort); if (sflag) { strbuf_puts(sortfilter, " -u"); unique = 1; } if (tflag) /* ctags format */ strbuf_puts(sortfilter, " -k 1,1 -k 2,2 -k 3,3n"); else if (fflag) strbuf_setlen(sortfilter, 0); else if (xflag) /* print details */ strbuf_puts(sortfilter, " -k 1,1 -k 3,3 -k 2,2n"); else if (!unique) /* print just a file name */ strbuf_puts(sortfilter, " -u"); } /* * make path filter. */ pathfilter = strbuf_open(0); strbuf_puts(pathfilter, gtags); if (aflag) /* absolute path name */ strbuf_puts(pathfilter, " --absolute"); else /* relative path name */ strbuf_puts(pathfilter, " --relative"); if (xflag || tflag) strbuf_puts(pathfilter, " --cxref"); strbuf_putc(pathfilter, ' '); strbuf_puts(pathfilter, root); strbuf_putc(pathfilter, ' '); strbuf_puts(pathfilter, cwd); /* * print filter. */ if (show_filter) { STRBUF *sb = strbuf_open(0); makefilter(sb); fprintf(stdout, "%s\n", strbuf_value(sb)); strbuf_close(sb); exit(0); } /* * exec lid(id-utils). */ if (Iflag) { chdir(root); idutils(av, dbpath); exit(0); } /* * grep the pattern in a source tree. */ if (gflag) { chdir(root); grep(av); exit(0); } /* * locate the path including the pattern in a source tree. */ if (Pflag) { chdir(root); pathlist(dbpath, av); exit(0); } db = (rflag) ? GRTAGS : ((sflag) ? GSYMS : GTAGS); /* * print function definitions. */ if (fflag) { parsefile(argc, argv, cwd, root, dbpath, db); exit(0); } /* * search in current source tree. */ count = search(av, root, dbpath, db); /* * search in library path. */ if (getenv("GTAGSLIBPATH") && (count == 0 || Tflag) && !lflag && !rflag) { STRBUF *sb = strbuf_open(0); char libdbpath[MAXPATHLEN+1]; char *p, *lib; strbuf_puts(sb, getenv("GTAGSLIBPATH")); p = strbuf_value(sb); while (p) { lib = p; if ((p = locatestring(p, PATHSEP, MATCH_FIRST)) != NULL) *p++ = 0; if (!gtagsexist(lib, libdbpath, sizeof(libdbpath), 0)) continue; if (!strcmp(dbpath, libdbpath)) continue; if (!test("f", makepath(libdbpath, dbname(db), NULL))) continue; strbuf_reset(pathfilter); strbuf_puts(pathfilter, gtags); if (aflag) /* absolute path name */ strbuf_puts(pathfilter, " --absolute"); else /* relative path name */ strbuf_puts(pathfilter, " --relative"); if (xflag || tflag) strbuf_puts(pathfilter, " --cxref"); strbuf_putc(pathfilter, ' '); strbuf_puts(pathfilter, lib); strbuf_putc(pathfilter, ' '); strbuf_puts(pathfilter, cwd); count = search(av, lib, libdbpath, db); if (count > 0 && !Tflag) { strlimcpy(dbpath, libdbpath, sizeof(dbpath)); break; } } strbuf_close(sb); } if (vflag) { if (count) { if (count == 1) fprintf(stderr, "%d object located", count); if (count > 1) fprintf(stderr, "%d objects located", count); } else { fprintf(stderr, "'%s' not found", av); } if (!Tflag) fprintf(stderr, " (using '%s').\n", makepath(dbpath, dbname(db), NULL)); } strbuf_close(sortfilter); strbuf_close(pathfilter); return 0;}/* * makefilter: make filter string. * * o) filter buffer */voidmakefilter(sb) STRBUF *sb;{ if (!nflag) { strbuf_puts(sb, strbuf_value(sortfilter)); if (strbuf_getlen(sortfilter) && strbuf_getlen(pathfilter)) strbuf_puts(sb, " | "); strbuf_puts(sb, strbuf_value(pathfilter)); }}/* * openfilter: open output filter. * * gi) pathfilter * gi) sortfilter * r) file pointer for output filter */FILE *openfilter(void){ FILE *op; STRBUF *sb = strbuf_open(0); makefilter(sb); if (strbuf_getlen(sb) == 0) op = stdout; else op = popen(strbuf_value(sb), "w"); strbuf_close(sb); return op;}voidclosefilter(op) FILE *op;{ if (op != stdout) if (pclose(op) != 0) die("terminated abnormally.");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -