/** * rewrite_string: execute rewrite against string * * @param[in] rewrite object * NULL: just print string * @param[in] string * @param[in] offset start point of the rewriting * @param[in] file descriptor */ const char * rewrite_string(REWRITE *rewrite, const char *string, int offset) { STATIC_STRBUF(sb); regmatch_t m; /* if rewrite object is NULL or does not match, just return the string. */ if (rewrite == NULL || rewrite->pattern == NULL) return string; if (regexec(&rewrite->reg, string + offset, 1, &m, 0) != 0) return string; strbuf_clear(sb); strbuf_nputs(sb, string, offset); string += offset; strbuf_nputs(sb, string, m.rm_so); if (rewrite->part[REWRITE_CENTER]) { strbuf_puts(sb, rewrite->part[REWRITE_CENTER]); } else { if (rewrite->part[REWRITE_LEFT]) strbuf_puts(sb, rewrite->part[REWRITE_LEFT]); strbuf_nputs(sb, string + m.rm_so, m.rm_eo - m.rm_so); if (rewrite->part[REWRITE_RIGHT]) strbuf_puts(sb, rewrite->part[REWRITE_RIGHT]); } strbuf_puts(sb, string + m.rm_eo); return (const char *)strbuf_value(sb); }
/** * makedirectories: make directories on the path like @XREF{mkdir,1} with the @OPTION{-p} option. * * @param[in] base base directory * @param[in] rest path from the base * @param[in] verbose 1: verbose mode, 0: not verbose mode * @return 0: success <br> * -1: base directory not found <br> * -2: permission error <br> * -3: cannot make directory */ int makedirectories(const char *base, const char *rest, int verbose) { STRBUF *sb; const char *p, *q; if (!test("d", base)) return -1; if (!test("drw", base)) return -2; sb = strbuf_open(0); strbuf_puts(sb, base); if (*rest == SEP) rest++; for (q = rest; *q;) { p = q; while (*q && *q != SEP) q++; strbuf_putc(sb, SEP); strbuf_nputs(sb, p, q - p); p = strbuf_value(sb); if (!test("d", p)) { if (verbose) fprintf(stderr, " Making directory '%s'.\n", p); if (mkdir(p, 0775) < 0) { strbuf_close(sb); return -3; } } if (*q == SEP) q++; } strbuf_close(sb); return 0; }
/** * dbop_put_tag: put a tag * * @param[in] dbop descripter * @param[in] name key * @param[in] data data */ void dbop_put_tag(DBOP *dbop, const char *name, const char *data) { #ifdef USE_SQLITE3 if (dbop->openflags & DBOP_SQLITE3) { int len; char fid[MAXFIDLEN], *q = fid; const char *p = data; /* extract fid */ while (*p && isdigit(*p)) *q++ = *p++; *q = '\0'; /* trim line */ len = strlen(data); if (data[len-1] == '\n') len--; if (data[len-1] == '\r') len--; if (data[len] == '\r' || data[len] == '\n') { STATIC_STRBUF(sb); strbuf_clear(sb); strbuf_nputs(sb, data, len); data = strbuf_value(sb); } dbop3_put(dbop, name, data, fid); return; } #endif dbop_put(dbop, name, data); return; }
/** * makedirectories: make directories on the path like @XREF{mkdir,1} with the @OPTION{-p} option. * * @param[in] base base directory * @param[in] rest path from the base * @param[in] verbose 1: verbose mode, 0: not verbose mode * @return 0: success <br> * -1: base directory not found <br> * -2: permission error <br> * -3: cannot make directory */ int makedirectories(const char *base, const char *rest, int verbose) { STRBUF *sb; const char *p, *q; if (!test("d", base)) return -1; if (!test("drw", base)) return -2; sb = strbuf_open(0); strbuf_puts(sb, base); if (*rest == SEP) rest++; for (q = rest; *q;) { p = q; while (*q && *q != SEP) q++; strbuf_putc(sb, SEP); strbuf_nputs(sb, p, q - p); p = strbuf_value(sb); if (!test("d", p)) { if (verbose) fprintf(stderr, " Making directory '%s'.\n", p); #if defined(_WIN32) && !defined(__CYGWIN__) if (mkdir(p) < 0) { #else if (mkdir(p, 0775) < 0) { #endif /* WIN32 */ strbuf_close(sb); return -3; } } if (*q == SEP) q++; } strbuf_close(sb); return 0; } /** * trimpath: trim path name */ const char * trimpath(const char *path) { if (*path == '.' && *(path + 1) == '/') path += 2; return path; }
/** * includelabel: procedure for tc= (or include=) * * @param[in] fp file pointer * @param[out] sb string buffer * @param[in] label record label * @param[in] level nest level for check * * This function may call itself (recursive) */ static void includelabel(FILE *fp, STRBUF *sb, const char *label, int level) { const char *savep, *p, *q; char *file; if (++level > allowed_nest_level) die("nested include= (or tc=) over flow."); /* * Label can include a '@' and a following path name. * Label: <label>[@<path>] */ if ((file = locatestring(label, "@", MATCH_FIRST)) != NULL) { *file++ = '\0'; if ((p = makepath_with_tilde(file)) == NULL) die("config file must be absolute path. (%s)", file); fp = fopen(p, "r"); if (fp == NULL) die("cannot open config file. (%s)", p); } if (!(savep = p = readrecord(fp, label))) die("label '%s' not found.", label); while ((q = locatestring(p, ":include=", MATCH_FIRST)) || (q = locatestring(p, ":tc=", MATCH_FIRST))) { STRBUF *inc = strbuf_open(0); strbuf_nputs(sb, p, q - p); q = locatestring(q, "=", MATCH_FIRST) + 1; for (; *q && *q != ':'; q++) strbuf_putc(inc, *q); includelabel(fp, sb, strbuf_value(inc), level); p = q; strbuf_close(inc); } strbuf_puts(sb, p); free((void *)savep); if (file) fclose(fp); }
/** * includelabel: procedure for @CODE{tc=} (or @CODE{include=}) * * @param[out] sb string buffer * @param[in] label record label * @param[in] level nest level for check */ static void includelabel(STRBUF *sb, const char *label, int level) { const char *savep, *p, *q; if (++level > allowed_nest_level) die("nested include= (or tc=) over flow."); if (!(savep = p = readrecord(label))) die("label '%s' not found.", label); while ((q = locatestring(p, ":include=", MATCH_FIRST)) || (q = locatestring(p, ":tc=", MATCH_FIRST))) { STRBUF *inc = strbuf_open(0); strbuf_nputs(sb, p, q - p); q = locatestring(q, "=", MATCH_FIRST) + 1; for (; *q && *q != ':'; q++) strbuf_putc(inc, *q); includelabel(sb, strbuf_value(inc), level); p = q; strbuf_close(inc); } strbuf_puts(sb, p); free((void *)savep); }
/** * getconfs: get property string * * @param[in] name property name * @param[out] sb string buffer (if not @VAR{NULL}) * @return 1: found, 0: not found */ int getconfs(const char *name, STRBUF *sb) { const char *p; char buf[MAXPROPLEN]; int all = 0; int exist = 0; if (!opened) die("configuration file not opened."); /* 'path' is reserved name for the current path of configuration file */ if (!strcmp(name, "path")) { if (config_path) strbuf_puts(sb, config_path); return 1; } if (!strcmp(name, "skip") || !strcmp(name, "gtags_parser") || !strcmp(name, "langmap")) all = 1; snprintf(buf, sizeof(buf), ":%s=", name); p = confline; while ((p = locatestring(p, buf, MATCH_FIRST)) != NULL) { if (exist && sb) strbuf_putc(sb, ','); exist = 1; for (p += strlen(buf); *p; p++) { if (*p == ':') break; if (*p == '\\' && *(p + 1) == ':') /* quoted character */ p++; if (sb) strbuf_putc(sb, *p); } if (!all) break; } /* * If 'bindir' and 'datadir' are not defined then * return system configuration value. */ if (!exist) { if (!strcmp(name, "bindir")) { strbuf_puts(sb, BINDIR); exist = 1; } else if (!strcmp(name, "datadir")) { #if defined(_WIN32) && !defined(__CYGWIN__) /* * Test if this directory exists, and if not, take the * directory relative to the binary. */ if (test("d", DATADIR)) strbuf_puts(sb, DATADIR); else { const char *name = strrchr(_pgmptr, '\\'); if (name) strbuf_nputs(sb, _pgmptr, name+1 - _pgmptr); strbuf_puts(sb, "..\\share"); } #else strbuf_puts(sb, DATADIR); #endif exist = 1; } else if (!strcmp(name, "localstatedir")) { strbuf_puts(sb, LOCALSTATEDIR); exist = 1; } else if (!strcmp(name, "sysconfdir")) { strbuf_puts(sb, SYSCONFDIR); exist = 1; } } return exist; }
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; }
/** * execute_command * * @param[in] xp xargs structure * @return !=NULL: file pointer <br> * ==NULL: end of argument * * This function constructs command line from the following, <br> * @STRONG{command}: @CODE{xp-\>command} <br> * @STRONG{argument}: each argument provider <br> * execute it on a pipe line, and return the file pointer. */ static FILE * execute_command(XARGS *xp) { int limit; STRBUF *comline = strbuf_open(0); int count = 0; int length; FILE *pipe = NULL; char *p, *meta_p; #if defined(_WIN32) && !defined(__CYGWIN__) /* * If the command starts with a quote, CMD.EXE requires the entire * command line to be quoted. */ if (*xp->command == '"') strbuf_putc(comline, '"'); #endif /* * Copy the part before '%s' of the command skeleton. * The '%s' in the skeleton is replaced with given arguments. */ meta_p = locatestring(xp->command, "%s", MATCH_FIRST); if (meta_p) { strbuf_nputs(comline, xp->command, meta_p - xp->command); limit = exec_line_limit(strlen(meta_p + 2)); } else { strbuf_puts(comline, xp->command); limit = exec_line_limit(0); } /* * Append arguments as many as possible. */ switch (xp->type) { case XARGS_FILE: for ( /* initial */ fseek(xp->ip, xp->fptr, SEEK_SET) ; /* continuation condition */ (LT_MAX && ((p = (strbuf_getlen(xp->path) > 0 ? strbuf_value(xp->path) : strbuf_fgets(xp->path, xp->ip, STRBUF_NOCRLF))) != NULL)) ; /* preparation */ strbuf_reset(xp->path) ) APPEND_ARGUMENT(p); xp->fptr = ftell(xp->ip); break; case XARGS_ARGV: for (; LT_MAX && xp->argc > 0; xp->argc--, xp->argv++) APPEND_ARGUMENT(xp->argv[0]) break; case XARGS_STRBUF: for (; LT_MAX && xp->curp < xp->endp; xp->curp += length + 1) APPEND_ARGUMENT(xp->curp) break; case XARGS_FIND: for (; LT_MAX && (p = repeat_find_read()) != NULL; repeat_find_next()) APPEND_ARGUMENT(p) break; } /* * Copy the left part of the command skeleton. */ if (meta_p) { strbuf_putc(comline, ' '); strbuf_puts(comline, meta_p + 2); } #if defined(_WIN32) && !defined(__CYGWIN__) if (*xp->command == '"') strbuf_putc(comline, '"'); #endif if (count > 0) { pipe = popen(strbuf_value(comline), "r"); if (pipe == NULL) die("cannot execute command '%s'.", strbuf_value(comline)); } strbuf_close(comline); return pipe; }