/* * 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; }
/** * gtags_delete: delete records belong to set of fid. * * @param[in] gtop #GTOP structure * @param[in] deleteset bit array of fid */ void gtags_delete(GTOP *gtop, IDSET *deleteset) { const char *tagline; int fid; long id; #ifdef USE_SQLITE3 if (gtop->dbop->openflags & DBOP_SQLITE3) { STRBUF *where = strbuf_open(0); strbuf_puts(where, "("); for (id = idset_first(deleteset); id != END_OF_ID; id = idset_next(deleteset)) { strbuf_puts(where, "'"); strbuf_putn(where, id); strbuf_puts(where, "',"); } strbuf_unputc(where, ','); strbuf_puts(where, ")"); dbop_delete(gtop->dbop, strbuf_value(where)); strbuf_close(where); } else #endif for (tagline = dbop_first(gtop->dbop, NULL, NULL, 0); tagline; tagline = dbop_next(gtop->dbop)) { /* * Extract path from the tag line. */ fid = atoi(tagline); /* * If the file id exists in the deleteset, delete the tagline. */ if (idset_contains(deleteset, fid)) dbop_delete(gtop->dbop, NULL); } }
/* * load_alias: load alias value. * * [$HOME/.gozillarc] * +----------------------- * |a:http://www.gnu.org * |f = file:/usr/share/xxx.html * |www http://www.xxx.yyy/ */ static void load_alias(void) { FILE *ip; STRBUF *sb = strbuf_open(0); char *p; int flag = STRBUF_NOCRLF; struct sh_entry *ent; sh = strhash_open(10); if (!(p = get_home_directory())) goto end; if (!test("r", makepath(p, gozillarc, NULL))) #ifdef __DJGPP__ if (!test("r", makepath(p, dos_gozillarc, NULL))) #endif goto end; if (!(ip = fopen(makepath(p, gozillarc, NULL), "r"))) #ifdef __DJGPP__ if (!(ip = fopen(makepath(p, dos_gozillarc, NULL), "r"))) #endif goto end; while ((p = strbuf_fgets(sb, ip, flag)) != NULL) { char *name, *value; flag &= ~STRBUF_APPEND; if (*p == '#') continue; if (strbuf_unputc(sb, '\\')) { flag |= STRBUF_APPEND; continue; } while (*p && isblank(*p)) /* skip spaces */ p++; name = p; while (*p && isalnum(*p)) /* get name */ p++; *p++ = 0; while (*p && isblank(*p)) /* skip spaces */ p++; if (*p == '=' || *p == ':') { p++; while (*p && isblank(*p))/* skip spaces */ p++; } value = p; while (*p && !isblank(*p)) /* get value */ p++; *p = 0; ent = strhash_assign(sh, name, 1); if (ent->value) (void)free(ent->value); ent->value = check_strdup(value); } fclose(ip); end: strbuf_close(sb); }
/** * readrecord: read recoed indexed by label. * * @param[in] label label in config file * @return record or NULL * * Jobs: * - skip comment. * - append following line. * - format check. */ static const char * readrecord(FILE *fp, const char *label) { char *p; int flag = STRBUF_NOCRLF|STRBUF_SHARPSKIP; int count = 0; rewind(fp); while ((p = strbuf_fgets(ib, fp, flag)) != NULL) { count++; /* * ignore \<new line>. */ flag &= ~STRBUF_APPEND; if (*p == '\0') continue; if (strbuf_unputc(ib, '\\')) { flag |= STRBUF_APPEND; continue; } trim(p); for (;;) { const char *candidate; /* * pick up candidate. */ if ((candidate = strmake(p, "|:")) == NULL) die("invalid config file format (line %d).", count); if (!strcmp(label, candidate)) { if (!(p = locatestring(p, ":", MATCH_FIRST))) die("invalid config file format (line %d).", count); return check_strdup(p); } /* * locate next candidate. */ p += strlen(candidate); if (*p == ':') break; else if (*p == '|') p++; else die("invalid config file format (line %d).", count); } } /* * config line not found. */ return NULL; }
/** * openconf: load configuration file. * * @param[in] rootdir Project root directory * * Globals used (output): * confline: specified entry */ void openconf(const char *rootdir) { STRBUF *sb; if (opened) return; opened = 1; /* * if config file not found then return default value. */ if (!(config_path = configpath(rootdir))) confline = check_strdup(""); /* * if it is not an absolute path then assumed config value itself. */ else if (!isabspath(config_path)) { confline = check_strdup(config_path); if (!locatestring(confline, ":", MATCH_FIRST)) die("GTAGSCONF must be absolute path name."); } /* * else load value from config file. */ else { if (test("d", config_path)) die("config file '%s' is a directory.", config_path); if (!test("f", config_path)) die("config file '%s' not found.", config_path); if (!test("r", config_path)) die("config file '%s' is not readable.", config_path); if ((config_label = getenv("GTAGSLABEL")) == NULL) config_label = "default"; if (!(fp = fopen(config_path, "r"))) die("cannot open '%s'.", config_path); ib = strbuf_open(MAXBUFLEN); sb = strbuf_open(0); includelabel(fp, sb, config_label, 0); confline = check_strdup(strbuf_value(sb)); strbuf_close(ib); strbuf_close(sb); fclose(fp); } /* * make up required variables. */ sb = strbuf_open(0); strbuf_puts(sb, confline); strbuf_unputc(sb, ':'); if (!getconfs("langmap", NULL)) { strbuf_puts(sb, ":langmap="); strbuf_puts(sb, quote_chars(DEFAULTLANGMAP, ':')); } if (!getconfs("skip", NULL)) { strbuf_puts(sb, ":skip="); strbuf_puts(sb, DEFAULTSKIP); } strbuf_unputc(sb, ':'); strbuf_putc(sb, ':'); confline = check_strdup(strbuf_value(sb)); strbuf_close(sb); trim(confline); return; }
/* * prepare_skip: prepare skipping files. * * go) skip regular expression for skip files. * go) listarry[] skip list. * go) list_count count of skip list. */ static void prepare_skip(void) { char *skiplist; STRBUF *reg = strbuf_open(0); int reg_count = 0; char *p, *q; int flags = REG_EXTENDED|REG_NEWLINE; /* * load icase_path option. */ if (getconfb("icase_path")) flags |= REG_ICASE; #if defined(_WIN32) || defined(__DJGPP__) flags |= REG_ICASE; #endif /* * initialize common data. */ if (!list) list = strbuf_open(0); else strbuf_reset(list); list_count = 0; if (listarray) (void)free(listarray); listarray = (char **)0; /* * load skip data. */ if (!getconfs("skip", reg)) { strbuf_close(reg); return; } skiplist = check_strdup(strbuf_value(reg)); trim(skiplist); strbuf_reset(reg); /* * construct regular expression. */ strbuf_putc(reg, '('); /* ) */ /* skip files which start with '.' e.g. .cvsignore */ strbuf_puts(reg, "/\\.[^/]+$|"); strbuf_puts(reg, "/\\.[^/]+/|"); for (p = skiplist; p; ) { char *skipf = p; if ((p = locatestring(p, ",", MATCH_FIRST)) != NULL) *p++ = 0; if (*skipf == '/') { list_count++; strbuf_puts0(list, skipf); } else { reg_count++; strbuf_putc(reg, '/'); for (q = skipf; *q; q++) { if (isregexchar(*q)) strbuf_putc(reg, '\\'); strbuf_putc(reg, *q); } if (*(q - 1) != '/') strbuf_putc(reg, '$'); if (p) strbuf_putc(reg, '|'); } } strbuf_unputc(reg, '|'); strbuf_putc(reg, ')'); if (reg_count > 0) { int retval; /* * compile regular expression. */ skip = &skip_area; retval = regcomp(skip, strbuf_value(reg), flags); #ifdef DEBUG if (debug) fprintf(stderr, "skip regex: %s\n", strbuf_value(reg)); #endif if (retval != 0) die("cannot compile regular expression."); } else { skip = (regex_t *)0; } if (list_count > 0) { int i; listarray = (char **)check_malloc(sizeof(char *) * list_count); p = strbuf_value(list); #ifdef DEBUG if (debug) fprintf(stderr, "skip list: "); #endif for (i = 0; i < list_count; i++) { #ifdef DEBUG if (debug) { fprintf(stderr, "%s", p); if (i + 1 < list_count) fputc(',', stderr); } #endif listarray[i] = p; p += strlen(p) + 1; } #ifdef DEBUG if (debug) fputc('\n', stderr); #endif } strbuf_close(reg); free(skiplist); }
void literal_search(CONVERT *cv, const char *file) { struct words *c; int ccount; char *p; char *buf; struct stat stb; char *linep; long lineno; int f; if ((f = open(file, 0)) < 0) die("cannot open '%s'.", file); if (fstat(f, &stb) < 0) die("cannot fstat '%s'.", file); if (stb.st_size == 0) goto skip_empty_file; #ifdef HAVE_MMAP buf = mmap(0, stb.st_size, PROT_READ, MAP_SHARED, f, 0); if (buf == MAP_FAILED) die("mmap failed (%s).", file); #else #ifdef HAVE_ALLOCA buf = (char *)alloca(stb.st_size); #else buf = (char *)malloc(stb.st_size); #endif if (buf == NULL) die("short of memory."); if (read(f, buf, stb.st_size) < stb.st_size) die("read failed (%s).", file); #endif linep = p = buf; ccount = stb.st_size; lineno = 1; c = w; for (;;) { if (--ccount <= 0) break; nstate: if (ccomp(c->inp, *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto nstate; } else { c = c->fail; if (c==0) { c = w; istate: if (ccomp(c->inp , *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto istate; } } else goto nstate; } if (c->out) { while (*p++ != '\n') { if (--ccount <= 0) break; } if (Vflag) goto nomatch; succeed: if (cv->format == FORMAT_PATH) { convert_put_path(cv, file); goto finish; } else { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_nputs(sb, linep, p - linep); strbuf_unputc(sb, '\n'); strbuf_unputc(sb, '\r'); convert_put_using(cv, encoded_pattern, file, lineno, strbuf_value(sb), NULL); } nomatch: lineno++; linep = p; c = w; continue; } if (*p++ == '\n') { if (Vflag) goto succeed; else { lineno++; linep = p; c = w; } } } finish: #ifdef HAVE_MMAP munmap(buf, stb.st_size); #elif HAVE_ALLOCA #else free(buf); #endif skip_empty_file: close(f); }
/** * literal_search: execute literal search * * @param[in] cv CONVERT structure * @param[in] file file to search * @return 0: normal, -1: error */ int literal_search(CONVERT *cv, const char *file) { # define ccomp(a,b) (iflag ? lca(a)==lca(b) : a==b) # define lca(x) (isupper(x) ? tolower(x) : x) struct words *c; int ccount; char *p; char *buf; struct stat stb; char *linep; long lineno; int f; int count = 0; if ((f = open(file, O_BINARY)) < 0) { warning("cannot open '%s'.", file); return -1; } if (fstat(f, &stb) < 0) { warning("cannot fstat '%s'.", file); goto skip_empty_file; } if (stb.st_size == 0) goto skip_empty_file; #ifdef HAVE_MMAP buf = mmap(0, stb.st_size, PROT_READ, MAP_SHARED, f, 0); if (buf == MAP_FAILED) die("mmap failed (%s).", file); #elif _WIN32 { HANDLE hMap = CreateFileMapping((HANDLE)_get_osfhandle(f), NULL, PAGE_READONLY, 0, stb.st_size, NULL); if (hMap == NULL) die("CreateFileMapping failed (%s).", file); buf = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); if (buf == NULL) die("MapViewOfFile failed (%s).", file); #else #ifdef HAVE_ALLOCA buf = (char *)alloca(stb.st_size); #else buf = (char *)malloc(stb.st_size); #endif if (buf == NULL) die("short of memory."); if (read(f, buf, stb.st_size) < stb.st_size) die("read failed (%s).", file); #endif linep = p = buf; ccount = stb.st_size; lineno = 1; c = w; for (;;) { if (--ccount < 0) break; nstate: if (ccomp(c->inp, *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto nstate; } else { c = c->fail; if (c==0) { c = w; istate: if (ccomp(c->inp , *p)) { c = c->nst; } else if (c->link != 0) { c = c->link; goto istate; } } else goto nstate; } if (c->out) { while (*p++ != '\n') { if (--ccount < 0) break; } if (Vflag) goto nomatch; succeed: if (cv->format == FORMAT_PATH) { convert_put_path(cv, NULL, file); count++; goto finish; } else { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_nputs(sb, linep, p - linep); strbuf_unputc(sb, '\n'); strbuf_unputc(sb, '\r'); convert_put_using(cv, pattern, file, lineno, strbuf_value(sb), NULL); count++; } nomatch: lineno++; linep = p; c = w; continue; } if (*p++ == '\n' || ccount == 0) { if (Vflag) goto succeed; else { lineno++; linep = p; c = w; } } } finish: #ifdef HAVE_MMAP munmap(buf, stb.st_size); #elif _WIN32 UnmapViewOfFile(buf); CloseHandle(hMap); } #elif HAVE_ALLOCA #else free(buf); #endif skip_empty_file: close(f); return count; }