📄 catalog.c
字号:
}}staticPARAM_TYPE parse_literal(parser, lit, lit_type) struct parser *parser; int lit; enum literal_type lit_type;{ enum { no, yes_begin, yes_middle } skipping = yes_begin; FILE *fp = parser->fp; param_init(parser); for (;;) { int c = getc(fp); if (c == lit) break; switch (c) { case '\0': error(parser, E_NUL_CHAR); break; case EOF: if (ferror(fp)) error(parser, E_GETC); error(parser, E_EOF_LITERAL); return LITERAL_PARAM; case '\n': parser->newline_count += 1; /* fall through */ case ' ': if (lit_type == MINIMUM_LITERAL) { if (skipping == no) { param_char(parser, ' '); skipping = yes_middle; } } else param_char(parser, c); break; default: if (lit_type == MINIMUM_LITERAL) { if (!parser->minimum_data[c]) error(parser, E_MINIMUM_DATA); else { skipping = no; param_char(parser, c); } } else param_char(parser, c); break; } } if (skipping == yes_middle) param_chop(parser); return LITERAL_PARAM;}staticPARAM_TYPE parse_name(parser, first_char) struct parser *parser; int first_char;{ FILE *fp = parser->fp; param_init(parser); param_char(parser, first_char); for (;;) { int c = getc(fp); switch (c) { case '\0': error(parser, E_NUL_CHAR); break; case EOF: if (ferror(fp)) error(parser, E_GETC); goto done; case '\n': parser->newline_count += 1; goto done; case ' ': case '\t': goto done; case '"': case '\'': ungetc(c, fp); goto done; default: param_char(parser, c); } } done: return NAME_PARAM;}staticVOID param_grow(parser) struct parser *parser;{ if (parser->param_alloc == 0) { parser->param_alloc = 256; parser->param = xmalloc(parser->param_alloc); } else { parser->param_alloc *= 2; parser->param = xrealloc(parser->param, parser->param_alloc); }}staticconst char *param_save(parser) struct parser *parser;{ char *s = alloc_bytes(parser->cat, parser->param_length + 1); memcpy(s, parser->param, parser->param_length); s[parser->param_length] = '\0'; return s;}staticchar *alloc_bytes(catalog, n) struct catalog *catalog; SIZE_T n;{ char *tem; if (n > catalog->block_spare) { struct string_block *block; SIZE_T block_size = n > BLOCK_SIZE ? n : BLOCK_SIZE; block = (struct string_block *)xmalloc(sizeof(struct string_block) + block_size); block->next = catalog->blocks; catalog->blocks = block; catalog->block_ptr = (char *)(block + 1); catalog->block_spare = block_size; } tem = catalog->block_ptr; catalog->block_ptr += n; catalog->block_spare -= n; return tem;}/* Return 1 if the current parameter is equal to key. */staticint param_equal(parser, key) struct parser *parser; const char *key;{ const char *param = parser->param; SIZE_T param_length = parser->param_length; for (; param_length > 0; param++, param_length--, key++) { unsigned char c; if (*key == '\0') return 0; c = *param; if (islower(c)) c = toupper(c); if (c != (unsigned char)*key) return 0; } return *key == '\0';}/* Return 0 if it was a duplicate. */staticint hash_table_add(table, s, system_id, file_index) struct hash_table *table; const char *s; const char *system_id; int file_index;{ SIZE_T i; struct hash_table_entry *p; if (table->size > 0) { i = hash_table_start_index(table, s); while (table->v[i] != 0) { if (strcmp(table->v[i]->key, s) == 0) return 0; if (i == 0) i = table->size; i--; } } if (table->used >= table->used_limit) { SIZE_T j; struct hash_table_entry **old_table = table->v; SIZE_T old_size = table->size; if (old_size == 0) { table->size = HASH_TABLE_INITIAL_SIZE; table->used_limit = table->size/2; } else { if (old_size > HASH_TABLE_MAX_SIZE/2) { if (old_size == HASH_TABLE_MAX_SIZE) return 0; /* FIXME: give an error? */ table->size = HASH_TABLE_MAX_SIZE; table->used_limit = HASH_TABLE_MAX_SIZE - 1; } else { table->size = (old_size << 1); table->used_limit = table->size/2; } } table->v = (struct hash_table_entry **)xmalloc(sizeof(struct hash_table_entry *) * table->size); for (j = 0; j < table->size; j++) table->v[j] = 0; for (j = 0; j < old_size; j++) if (old_table[j]) { SIZE_T k = hash_table_start_index(table, old_table[j]->key); while (table->v[k] != 0) { if (k == 0) k = table->size; k--; } table->v[k] = old_table[j]; } if (old_table) free((UNIV)old_table); i = hash_table_start_index(table, s); while (table->v[i] != 0) { if (i == 0) i = table->size; i--; } } p = (struct hash_table_entry *)xmalloc(sizeof(struct hash_table_entry)); p->key = s; p->system_id = system_id; p->file_index = file_index; table->v[i] = p; table->used += 1; return 1;}staticstruct hash_table_entry *hash_table_lookup(table, s) struct hash_table *table; const char *s;{ if (table->size > 0) { SIZE_T i; i = hash_table_start_index(table, s); while (table->v[i] != 0) { if (strcmp(table->v[i]->key, s) == 0) return table->v[i]; if (i == 0) i = table->size; i--; } } return 0;}staticstruct hash_table_entry *hash_table_lookup_subst(table, subst_table, s) struct hash_table *table; const char *subst_table; const char *s;{ SIZE_T i; for (i = 0; i < table->size; i++) { struct hash_table_entry *p = table->v[i]; if (p && subst_equal(subst_table, s, p->key)) return p; } return 0;}staticVOID hash_table_init(p) struct hash_table *p;{ p->v = 0; p->size = 0; p->used = 0; p->used_limit = 0;}staticVOID hash_table_delete(p) struct hash_table *p;{ if (p->v) { SIZE_T i; for (i = 0; i < p->size; i++) if (p->v[i]) free(p->v[i]); free(p->v); }}staticSIZE_T hash_table_start_index(p, s) struct hash_table *p; const char *s;{ unsigned long h = 0; while (*s) h = (h << 5) + h + (unsigned char)*s++; return (h & (p->size - 1));}/* s1 has already been substituted; s2 has not */staticint subst_equal(subst_table, s1, s2) const char *subst_table; const char *s1; const char *s2;{ for (; *s1 == subst_table[(unsigned char)*s2]; s1++, s2++) if (*s1 == '\0') return 1; return 0;}staticVOID error(parser, err) struct parser *parser; enum catalog_error err;{ (*parser->cat->error_handler)(parser->filename, parser->newline_count + 1, err, (err >= FIRST_SYSTEM_ERROR ? CATALOG_SYSTEM_ERROR : 0), (err >= FIRST_SYSTEM_ERROR ? errno : 0));}#ifdef MAINstatic const char *program_name;#include "getopt.h"static VOID usage P((void));static VOID out_of_memory P((void));static VOID handle_catalog_error P((const char *filename, unsigned long lineno, int error_number, unsigned flags, int sys_errno));int main(argc, argv) int argc; char **argv;{ int entity_flag = 0; enum catalog_decl_type entity_type = CATALOG_NO_DECL; char *public_id = 0; char *name = 0; int exit_status; int opt; CATALOG catalog; int i; const char *file; const char *system_id; program_name = argv[0]; while ((opt = getopt(argc, argv, "edl")) != EOF) switch (opt) { case 'e': entity_flag = 1; entity_type = CATALOG_ENTITY_DECL; break; case 'd': entity_flag = 1; entity_type = CATALOG_DOCTYPE_DECL; break; case 'l': entity_flag = 1; entity_type = CATALOG_LINKTYPE_DECL; break; case '?': usage(); } if (argc - optind < 2) usage(); if (entity_flag) name = argv[optind]; else public_id = argv[optind]; catalog = catalog_create(handle_catalog_error); for (i = optind + 1; i < argc; i++) catalog_load_file(catalog, argv[i]); if (catalog_lookup_entity(catalog, public_id, name, entity_type, (char *)0, &system_id, &file)) { exit_status = 0; fprintf(stderr, "%s (%s)\n", system_id, file); } else { fprintf(stderr, "not found\n"); exit_status = 1; } catalog_delete(catalog); return exit_status;}staticVOID usage(){ fprintf(stderr, "usage: %s [-e] [-d] [-l] id file ...\n", program_name); exit(1);}staticVOID handle_catalog_error(filename, lineno, error_number, flags, sys_errno) const char *filename; unsigned long lineno; int error_number; unsigned flags; int sys_errno;{ fprintf(stderr, "%s:", program_name); if (flags & CATALOG_SYSTEM_ERROR) { putc(' ', stderr); fprintf(stderr, catalog_error_text(error_number), filename); putc('\n', stderr); } else fprintf(stderr, "%s:%lu: %s\n", filename, lineno, catalog_error_text(error_number)); fflush(stderr);}UNIV xmalloc(n) SIZE_T n;{ UNIV p = malloc(n); if (!p) out_of_memory(); return p;}UNIV xrealloc(p, n) UNIV p; SIZE_T n;{ p = realloc(p, n); if (!p) out_of_memory(); return p;}staticVOID out_of_memory(){ fprintf(stderr, "%s: out of memory\n", program_name); exit(1);}#endif /* MAIN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -