/* * 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); }
/** * gtags_first: return first record * * @param[in] gtop #GTOP structure * @param[in] pattern tag name <br> * - may be regular expression * - may be @VAR{NULL} * @param[in] flags #GTOP_PREFIX: prefix read <br> * #GTOP_KEY: read key only <br> * #GTOP_PATH: read path only <br> * #GTOP_NOREGEX: don't use regular expression. <br> * #GTOP_IGNORECASE: ignore case distinction. <br> * #GTOP_BASICREGEX: use basic regular expression. <br> * #GTOP_NOSORT: don't sort * @return record */ GTP * gtags_first(GTOP *gtop, const char *pattern, int flags) { int dbflags = 0; int regflags = 0; char prefix[IDENTLEN]; static regex_t reg; regex_t *preg = ® const char *key = NULL; const char *tagline; /* Settlement for last time if any */ if (gtop->path_hash) { strhash_close(gtop->path_hash); gtop->path_hash = NULL; } if (gtop->path_array) { free(gtop->path_array); gtop->path_array = NULL; } gtop->flags = flags; if (flags & GTOP_PREFIX && pattern != NULL) dbflags |= DBOP_PREFIX; if (flags & GTOP_KEY) dbflags |= DBOP_KEY; if (!(flags & GTOP_BASICREGEX)) regflags |= REG_EXTENDED; if (flags & GTOP_IGNORECASE) regflags |= REG_ICASE; /* * Get key and compiled regular expression for dbop_xxxx(). */ if (flags & GTOP_NOREGEX) { key = pattern; preg = NULL; } else if (pattern == NULL || !strcmp(pattern, ".*")) { /* * Since the regular expression '.*' matches to any record, * we take sequential read method. */ key = NULL; preg = NULL; } else if (isregex(pattern) && regcomp(preg, pattern, regflags) == 0) { const char *p; /* * If the pattern include '^' + some non regular expression * characters like '^aaa[0-9]', we take prefix read method * with the non regular expression part as the prefix. */ if (!(flags & GTOP_IGNORECASE) && *pattern == '^' && *(p = pattern + 1) && !isregexchar(*p)) { int i = 0; while (*p && !isregexchar(*p) && i < IDENTLEN) prefix[i++] = *p++; prefix[i] = '\0'; key = prefix; dbflags |= DBOP_PREFIX; } else { key = NULL; } } else { key = pattern; preg = NULL; } /* * If GTOP_PATH is set, at first, we collect all path names in a pool and * sort them. gtags_first() and gtags_next() returns one of the pool. */ if (gtop->flags & GTOP_PATH) { struct sh_entry *entry; char *p; const char *cp; unsigned long i; gtop->path_hash = strhash_open(HASHBUCKETS); /* * Pool path names. * * fid path name * +-------------------------- * |100 ./aaa/a.c * |105 ./aaa/b.c * ... */ for (tagline = dbop_first(gtop->dbop, key, preg, dbflags); tagline != NULL; tagline = dbop_next(gtop->dbop)) { VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop); /* extract file id */ p = locatestring(tagline, " ", MATCH_FIRST); if (p == NULL) die("Illegal tag record. '%s'\n", tagline); *p = '\0'; entry = strhash_assign(gtop->path_hash, tagline, 1); /* new entry: get path name and set. */ if (entry->value == NULL) { cp = gpath_fid2path(tagline, NULL); if (cp == NULL) die("GPATH is corrupted.(file id '%s' not found)", tagline); entry->value = strhash_strdup(gtop->path_hash, cp, 0); } } /* * Sort path names. * * fid path name path_array (sort) * +-------------------------- +---+ * |100 ./aaa/a.c <-------* | * |105 ./aaa/b.c <-------* | * ... ... */ gtop->path_array = (char **)check_malloc(gtop->path_hash->entries * sizeof(char *)); i = 0; for (entry = strhash_first(gtop->path_hash); entry != NULL; entry = strhash_next(gtop->path_hash)) gtop->path_array[i++] = entry->value; if (i != gtop->path_hash->entries) die("Something is wrong. 'i = %lu, entries = %lu'" , i, gtop->path_hash->entries); if (!(gtop->flags & GTOP_NOSORT)) qsort(gtop->path_array, gtop->path_hash->entries, sizeof(char *), compare_path); gtop->path_count = gtop->path_hash->entries; gtop->path_index = 0; if (gtop->path_index >= gtop->path_count) return NULL; gtop->gtp.path = gtop->path_array[gtop->path_index++]; return >op->gtp; } else if (gtop->flags & GTOP_KEY) { for (gtop->gtp.tag = dbop_first(gtop->dbop, key, preg, dbflags); gtop->gtp.tag != NULL; gtop->gtp.tag = dbop_next(gtop->dbop)) { VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop); break; } return gtop->gtp.tag ? >op->gtp : NULL; } else { if (gtop->vb == NULL) gtop->vb = varray_open(sizeof(GTP), 200); else varray_reset(gtop->vb); if (gtop->segment_pool == NULL) gtop->segment_pool = pool_open(); else pool_reset(gtop->segment_pool); if (gtop->path_hash == NULL) gtop->path_hash = strhash_open(HASHBUCKETS); else strhash_reset(gtop->path_hash); tagline = dbop_first(gtop->dbop, key, preg, dbflags); if (tagline == NULL) return NULL; /* * Dbop_next() wil read the same record again. */ dbop_unread(gtop->dbop); /* * Read a tag segment with sorting. */ segment_read(gtop); return >op->gtp_array[gtop->gtp_index++]; } }
/** * gtags_open: open global tag. * * @param[in] dbpath dbpath directory * @param[in] root root directory (needed when compact format) * @param[in] db #GTAGS, #GRTAGS, #GSYMS * @param[in] mode #GTAGS_READ: read only <br> * #GTAGS_CREATE: create tag <br> * #GTAGS_MODIFY: modify tag * @param[in] flags #GTAGS_COMPACT: compact format * @return #GTOP structure * * @note when error occurred, @NAME{gtags_open()} doesn't return. */ GTOP * gtags_open(const char *dbpath, const char *root, int db, int mode, int flags) { GTOP *gtop; char tagfile[MAXPATHLEN]; int dbmode; gtop = (GTOP *)check_calloc(sizeof(GTOP), 1); gtop->db = db; gtop->mode = mode; gtop->openflags = flags; /* * Open tag file allowing duplicate records. */ switch (gtop->mode) { case GTAGS_READ: dbmode = 0; break; case GTAGS_CREATE: dbmode = 1; break; case GTAGS_MODIFY: dbmode = 2; break; default: assert(0); } /* * GRTAGS and GSYMS are virtual tag file. They are included in a real GRTAGS file. * In fact, GSYMS doesn't exist now. * * GRTAGS: tags which belongs to GRTAGS, and are defined in GTAGS. * GSYMS: tags which belongs to GRTAGS, and is not defined in GTAGS. */ strlimcpy(tagfile, makepath(dbpath, dbname(db == GSYMS ? GRTAGS : db), NULL), sizeof(tagfile)); gtop->dbop = dbop_open(tagfile, dbmode, 0644, DBOP_DUP|DBOP_SORTED_WRITE); if (gtop->dbop == NULL) { if (dbmode == 1) die("cannot make %s.", dbname(db)); die("%s not found.", dbname(db)); } if (gtop->mode == GTAGS_READ && db != GTAGS) { const char *gtags = makepath(dbpath, dbname(GTAGS), NULL); int format_version; gtop->gtags = dbop_open(gtags, 0, 0, 0); if (gtop->gtags == NULL) die("GTAGS not found."); format_version = dbop_getversion(gtop->dbop); if (format_version > upper_bound_version) die("%s seems new format. Please install the latest GLOBAL.", gtags); else if (format_version < lower_bound_version) die("%s seems older format. Please remake tag files.", gtags); } if (gtop->mode == GTAGS_CREATE) { /* * Decide format. */ gtop->format = 0; gtop->format_version = new_format_version; /* * GRTAGS and GSYSM always use compact format. * GTAGS uses compact format only when the -c option specified. */ if (gtop->db == GRTAGS || gtop->db == GSYMS || gtop->openflags & GTAGS_COMPACT) { gtop->format |= GTAGS_COMPACT; gtop->format |= GTAGS_COMPLINE; } else { /* standard format */ gtop->format |= GTAGS_COMPRESS; } gtop->format |= GTAGS_COMPNAME; if (gtop->format & GTAGS_COMPACT) dbop_putoption(gtop->dbop, COMPACTKEY, NULL); if (gtop->format & GTAGS_COMPRESS) { dbop_putoption(gtop->dbop, COMPRESSKEY, DEFAULT_ABBREVIATION); abbrev_open(DEFAULT_ABBREVIATION); } if (gtop->format & GTAGS_COMPLINE) dbop_putoption(gtop->dbop, COMPLINEKEY, NULL); if (gtop->format & GTAGS_COMPNAME) dbop_putoption(gtop->dbop, COMPNAMEKEY, NULL); dbop_putversion(gtop->dbop, gtop->format_version); } else { /* * recognize format version of GTAGS. 'format version record' * is saved as a META record in GTAGS and GRTAGS. * if 'format version record' is not found, it's assumed * version 1. */ const char *p; /* * check format version. */ gtop->format_version = dbop_getversion(gtop->dbop); if (gtop->format_version > upper_bound_version) die("%s seems new format. Please install the latest GLOBAL.", tagfile); else if (gtop->format_version < lower_bound_version) die("%s seems older format. Please remake tag files.", tagfile); gtop->format = 0; if (dbop_getoption(gtop->dbop, COMPACTKEY) != NULL) gtop->format |= GTAGS_COMPACT; if ((p = dbop_getoption(gtop->dbop, COMPRESSKEY)) != NULL) { abbrev_open(p); gtop->format |= GTAGS_COMPRESS; } if (dbop_getoption(gtop->dbop, COMPLINEKEY) != NULL) gtop->format |= GTAGS_COMPLINE; if (dbop_getoption(gtop->dbop, COMPNAMEKEY) != NULL) gtop->format |= GTAGS_COMPNAME; } if (gpath_open(dbpath, dbmode) < 0) { if (dbmode == 1) die("cannot create GPATH."); else die("GPATH not found."); } if (gtop->mode != GTAGS_READ) gtop->sb = strbuf_open(0); /* This buffer is used for working area. */ /* * Stuff for compact format. */ if (gtop->format & GTAGS_COMPACT) { assert(root != NULL); strlimcpy(gtop->root, root, sizeof(gtop->root)); if (gtop->mode != GTAGS_READ) gtop->path_hash = strhash_open(HASHBUCKETS); } return gtop; }
/** * gtags_first: return first record * * @param[in] gtop #GTOP structure * @param[in] pattern tag name <br> * - may be regular expression * - may be @VAR{NULL} * @param[in] flags #GTOP_PREFIX: prefix read <br> * #GTOP_KEY: read key only <br> * #GTOP_PATH: read path only <br> * #GTOP_NOREGEX: don't use regular expression. <br> * #GTOP_IGNORECASE: ignore case distinction. <br> * #GTOP_BASICREGEX: use basic regular expression. <br> * #GTOP_NOSORT: don't sort * @return record */ GTP * gtags_first(GTOP *gtop, const char *pattern, int flags) { int regflags = 0; static regex_t reg; const char *tagline; STATIC_STRBUF(regex); strbuf_clear(regex); gtop->preg = ® gtop->key = NULL; gtop->prefix = NULL; gtop->flags = flags; gtop->dbflags = 0; gtop->readcount = 1; /* Settlement for last time if any */ if (gtop->path_hash) { strhash_close(gtop->path_hash); gtop->path_hash = NULL; } if (gtop->path_array) { free(gtop->path_array); gtop->path_array = NULL; } if (flags & GTOP_KEY) gtop->dbflags |= DBOP_KEY; if (!(flags & GTOP_BASICREGEX)) regflags |= REG_EXTENDED; /* * decide a read method */ if (pattern == NULL) gtop->preg = NULL; else if (pattern[0] == 0) return NULL; else if (!strcmp(pattern, ".*") || !strcmp(pattern, "^.*$") || !strcmp(pattern, "^") || !strcmp(pattern, "$") || !strcmp(pattern, "^.*") || !strcmp(pattern, ".*$")) { /* * Since these regular expressions match to any record, * we take sequential read method. */ gtop->preg = NULL; } else if (flags & GTOP_IGNORECASE) { regflags |= REG_ICASE; if (!isregex(pattern) || flags & GTOP_NOREGEX) { gtop->prefix = get_prefix(pattern, flags); if (gtop->openflags & GTAGS_DEBUG) if (gtop->prefix != NULL) fprintf(stderr, "Using prefix: %s\n", gtop->prefix); if (gtop->prefix == NULL) die("gtags_first: impossible (1)."); strbuf_putc(regex, '^'); strbuf_puts(regex, pattern); if (!(flags & GTOP_PREFIX)) strbuf_putc(regex, '$'); } else if (*pattern == '^' && (gtop->prefix = get_prefix(pattern, flags)) != NULL) { if (gtop->openflags & GTAGS_DEBUG) fprintf(stderr, "Using prefix: %s\n", gtop->prefix); strbuf_puts(regex, pattern); } else { strbuf_puts(regex, pattern); } } else { if (!isregex(pattern) || flags & GTOP_NOREGEX) { if (flags & GTOP_PREFIX) gtop->dbflags |= DBOP_PREFIX; gtop->key = pattern; gtop->preg = NULL; } else if (*pattern == '^' && (gtop->key = get_prefix(pattern, flags)) != NULL) { if (gtop->openflags & GTAGS_DEBUG) fprintf(stderr, "Using prefix: %s\n", gtop->key); gtop->dbflags |= DBOP_PREFIX; gtop->preg = NULL; } else { strbuf_puts(regex, pattern); } } if (gtop->prefix) { if (gtop->key) die("gtags_first: impossible (2)."); gtop->key = gtop->prefix; gtop->dbflags |= DBOP_PREFIX; } if (strbuf_getlen(regex) > 0) { if (gtop->preg == NULL) die("gtags_first: impossible (3)."); if (regcomp(gtop->preg, strbuf_value(regex), regflags) != 0) die("invalid regular expression."); } /* * If GTOP_PATH is set, at first, we collect all path names in a pool and * sort them. gtags_first() and gtags_next() returns one of the pool. */ if (gtop->flags & GTOP_PATH) { struct sh_entry *entry; char *p; const char *cp; unsigned long i; gtop->path_hash = strhash_open(HASHBUCKETS); /* * Pool path names. * * fid path name * +-------------------------- * |100 ./aaa/a.c * |105 ./aaa/b.c * ... */ again0: for (tagline = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags); tagline != NULL; tagline = dbop_next(gtop->dbop)) { VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop); /* extract file id */ p = locatestring(tagline, " ", MATCH_FIRST); if (p == NULL) die("Invalid tag record. '%s'\n", tagline); *p = '\0'; entry = strhash_assign(gtop->path_hash, tagline, 1); /* new entry: get path name and set. */ if (entry->value == NULL) { cp = gpath_fid2path(tagline, NULL); if (cp == NULL) die("GPATH is corrupted.(file id '%s' not found)", tagline); entry->value = strhash_strdup(gtop->path_hash, cp, 0); } } if (gtop->prefix && gtags_restart(gtop)) goto again0; /* * Sort path names. * * fid path name path_array (sort) * +-------------------------- +---+ * |100 ./aaa/a.c <-------* | * |105 ./aaa/b.c <-------* | * ... ... */ gtop->path_array = (char **)check_malloc(gtop->path_hash->entries * sizeof(char *)); i = 0; for (entry = strhash_first(gtop->path_hash); entry != NULL; entry = strhash_next(gtop->path_hash)) gtop->path_array[i++] = entry->value; if (i != gtop->path_hash->entries) die("Something is wrong. 'i = %lu, entries = %lu'" , i, gtop->path_hash->entries); if (!(gtop->flags & GTOP_NOSORT)) qsort(gtop->path_array, gtop->path_hash->entries, sizeof(char *), compare_path); gtop->path_count = gtop->path_hash->entries; gtop->path_index = 0; if (gtop->path_index >= gtop->path_count) return NULL; gtop->gtp.path = gtop->path_array[gtop->path_index++]; return >op->gtp; } else if (gtop->flags & GTOP_KEY) { again1: for (gtop->gtp.tag = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags); gtop->gtp.tag != NULL; gtop->gtp.tag = dbop_next(gtop->dbop)) { VIRTUAL_GRTAGS_GSYMS_PROCESSING(gtop); break; } if (gtop->gtp.tag == NULL) { if (gtop->prefix && gtags_restart(gtop)) goto again1; } return gtop->gtp.tag ? >op->gtp : NULL; } else { if (gtop->vb == NULL) gtop->vb = varray_open(sizeof(GTP), 200); else varray_reset(gtop->vb); if (gtop->segment_pool == NULL) gtop->segment_pool = pool_open(); else pool_reset(gtop->segment_pool); if (gtop->path_hash == NULL) gtop->path_hash = strhash_open(HASHBUCKETS); else strhash_reset(gtop->path_hash); again2: tagline = dbop_first(gtop->dbop, gtop->key, gtop->preg, gtop->dbflags); if (tagline == NULL) { if (gtop->prefix && gtags_restart(gtop)) goto again2; return NULL; } /* * Dbop_next() wil read the same record again. */ dbop_unread(gtop->dbop); /* * Read a tag segment with sorting. */ segment_read(gtop); return >op->gtp_array[gtop->gtp_index++]; } }