/** * 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); }
/** * 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; }