version 1.1.1.1, 2017/08/22 12:33:54
|
version 1.1.1.2, 2021/03/17 19:50:23
|
Line 48
|
Line 48
|
#include "conf/conf.h" |
#include "conf/conf.h" |
#include "conf/cf-parse.tab.h" |
#include "conf/cf-parse.tab.h" |
#include "lib/string.h" |
#include "lib/string.h" |
|
#include "lib/hash.h" |
|
|
struct keyword { |
struct keyword { |
byte *name; |
byte *name; |
Line 57 struct keyword {
|
Line 58 struct keyword {
|
|
|
#include "conf/keywords.h" |
#include "conf/keywords.h" |
|
|
#define KW_HASH_SIZE 64 | /* Could be defined by Bison in cf-parse.tab.h, inteferes with SYM hash */ |
static struct keyword *kw_hash[KW_HASH_SIZE]; | #ifdef SYM |
static int kw_hash_inited; | #undef SYM |
| #endif |
|
|
#define SYM_HASH_SIZE 128 |
|
|
|
struct sym_scope { | static uint cf_hash(byte *c); |
struct sym_scope *next; /* Next on scope stack */ | |
struct symbol *name; /* Name of this scope */ | |
int active; /* Currently entered */ | |
}; | |
static struct sym_scope *conf_this_scope; | |
|
|
static int cf_hash(byte *c); | #define KW_KEY(n) n->name |
static inline struct symbol * cf_get_sym(byte *c, uint h0); | #define KW_NEXT(n) n->next |
| #define KW_EQ(a,b) !strcmp(a,b) |
| #define KW_FN(k) cf_hash(k) |
| #define KW_ORDER 8 /* Fixed */ |
|
|
|
#define SYM_KEY(n) n->name, n->scope->active |
|
#define SYM_NEXT(n) n->next |
|
#define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2 |
|
#define SYM_FN(k,s) cf_hash(k) |
|
#define SYM_ORDER 6 /* Initial */ |
|
|
|
#define SYM_REHASH sym_rehash |
|
#define SYM_PARAMS /8, *1, 2, 2, 6, 20 |
|
|
|
|
|
HASH_DEFINE_REHASH_FN(SYM, struct symbol) |
|
|
|
HASH(struct keyword) kw_hash; |
|
|
|
|
|
static struct sym_scope *conf_this_scope; |
|
|
linpool *cfg_mem; |
linpool *cfg_mem; |
|
|
int (*cf_read_hook)(byte *buf, unsigned int max, int fd); |
int (*cf_read_hook)(byte *buf, unsigned int max, int fd); |
Line 84 static struct include_file_stack *ifs_head;
|
Line 100 static struct include_file_stack *ifs_head;
|
#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd); |
#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max, ifs->fd); |
#define YY_NO_UNPUT |
#define YY_NO_UNPUT |
#define YY_FATAL_ERROR(msg) cf_error(msg) |
#define YY_FATAL_ERROR(msg) cf_error(msg) |
|
#define YY_USER_ACTION ifs->chno += yyleng; ifs->toklen = yyleng; |
|
|
static void cf_include(char *arg, int alen); |
static void cf_include(char *arg, int alen); |
static int check_eof(void); |
static int check_eof(void); |
Line 179 else: {
|
Line 196 else: {
|
yytext[yyleng-1] = 0; |
yytext[yyleng-1] = 0; |
yytext++; |
yytext++; |
} |
} |
unsigned int h = cf_hash(yytext); | |
struct keyword *k = kw_hash[h & (KW_HASH_SIZE-1)]; | struct keyword *k = HASH_FIND(kw_hash, KW, yytext); |
while (k) | if (k) |
| { |
| if (k->value > 0) |
| return k->value; |
| else |
{ |
{ |
if (!strcmp(k->name, yytext)) | cf_lval.i = -k->value; |
{ | return ENUM; |
if (k->value > 0) | |
return k->value; | |
else | |
{ | |
cf_lval.i = -k->value; | |
return ENUM; | |
} | |
} | |
k=k->next; | |
} |
} |
cf_lval.s = cf_get_sym(yytext, h); | } |
| |
| cf_lval.s = cf_get_symbol(yytext); |
return SYM; |
return SYM; |
} |
} |
|
|
Line 224 else: {
|
Line 238 else: {
|
|
|
{WHITE}+ |
{WHITE}+ |
|
|
\n ifs->lino++; | \n ifs->lino++; ifs->chno = 0; |
|
|
# BEGIN(COMMENT); |
# BEGIN(COMMENT); |
|
|
Line 234 else: {
|
Line 248 else: {
|
|
|
<COMMENT>\n { |
<COMMENT>\n { |
ifs->lino++; |
ifs->lino++; |
|
ifs->chno = 0; |
BEGIN(INITIAL); |
BEGIN(INITIAL); |
} |
} |
|
|
<COMMENT>. |
<COMMENT>. |
|
|
<CCOMM>\*\/ BEGIN(INITIAL); |
<CCOMM>\*\/ BEGIN(INITIAL); |
<CCOMM>\n ifs->lino++; | <CCOMM>\n ifs->lino++; ifs->chno = 0; |
<CCOMM>\/\* cf_error("Comment nesting not supported"); |
<CCOMM>\/\* cf_error("Comment nesting not supported"); |
<CCOMM><<EOF>> cf_error("Unterminated comment"); |
<CCOMM><<EOF>> cf_error("Unterminated comment"); |
<CCOMM>. |
<CCOMM>. |
Line 257 else: {
|
Line 272 else: {
|
|
|
%% |
%% |
|
|
static int | static uint |
cf_hash(byte *c) |
cf_hash(byte *c) |
{ |
{ |
unsigned int h = 13; | uint h = 13 << 24; |
|
|
while (*c) |
while (*c) |
h = (h * 37) + *c++; | h = h + (h >> 2) + (h >> 5) + ((uint) *c++ << 24); |
return h; |
return h; |
} |
} |
|
|
Line 428 check_eof(void)
|
Line 443 check_eof(void)
|
} |
} |
|
|
static struct symbol * |
static struct symbol * |
cf_new_sym(byte *c, uint h0) | cf_new_symbol(byte *c) |
{ |
{ |
uint h = h0 & (SYM_HASH_SIZE-1); | struct symbol *s; |
struct symbol *s, **ht; | |
int l; | |
|
|
if (!new_config->sym_hash) | uint l = strlen(c); |
new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *)); | |
ht = new_config->sym_hash; | |
l = strlen(c); | |
if (l > SYM_MAX_LEN) |
if (l > SYM_MAX_LEN) |
cf_error("Symbol too long"); |
cf_error("Symbol too long"); |
|
|
s = cfg_alloc(sizeof(struct symbol) + l); |
s = cfg_alloc(sizeof(struct symbol) + l); |
s->next = ht[h]; |
|
ht[h] = s; |
|
s->scope = conf_this_scope; |
s->scope = conf_this_scope; |
s->class = SYM_VOID; |
s->class = SYM_VOID; |
s->def = NULL; |
s->def = NULL; |
s->aux = 0; |
s->aux = 0; |
strcpy(s->name, c); |
strcpy(s->name, c); |
return s; |
|
} |
|
|
|
static struct symbol * | if (!new_config->sym_hash.data) |
cf_find_sym(struct config *cfg, byte *c, uint h0) | HASH_INIT(new_config->sym_hash, new_config->pool, SYM_ORDER); |
{ | |
uint h = h0 & (SYM_HASH_SIZE-1); | |
struct symbol *s, **ht; | |
|
|
if (ht = cfg->sym_hash) | HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s); |
{ | |
for(s = ht[h]; s; s=s->next) | |
if (!strcmp(s->name, c) && s->scope->active) | |
return s; | |
} | |
if (ht = cfg->sym_fallback) | |
{ | |
/* We know only top-level scope is active */ | |
for(s = ht[h]; s; s=s->next) | |
if (!strcmp(s->name, c) && s->scope->active) | |
return s; | |
} | |
|
|
return NULL; | return s; |
} |
} |
|
|
static inline struct symbol * |
|
cf_get_sym(byte *c, uint h0) |
|
{ |
|
return cf_find_sym(new_config, c, h0) ?: cf_new_sym(c, h0); |
|
} |
|
|
|
/** |
/** |
* cf_find_symbol - find a symbol by name |
* cf_find_symbol - find a symbol by name |
* @cfg: specificed config |
* @cfg: specificed config |
Line 494 cf_get_sym(byte *c, uint h0)
|
Line 480 cf_get_sym(byte *c, uint h0)
|
struct symbol * |
struct symbol * |
cf_find_symbol(struct config *cfg, byte *c) |
cf_find_symbol(struct config *cfg, byte *c) |
{ |
{ |
return cf_find_sym(cfg, c, cf_hash(c)); | struct symbol *s; |
| |
| if (cfg->sym_hash.data && |
| (s = HASH_FIND(cfg->sym_hash, SYM, c, 1))) |
| return s; |
| |
| if (cfg->fallback && |
| cfg->fallback->sym_hash.data && |
| (s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, 1))) |
| return s; |
| |
| return NULL; |
} |
} |
|
|
/** |
/** |
Line 509 cf_find_symbol(struct config *cfg, byte *c)
|
Line 506 cf_find_symbol(struct config *cfg, byte *c)
|
struct symbol * |
struct symbol * |
cf_get_symbol(byte *c) |
cf_get_symbol(byte *c) |
{ |
{ |
return cf_get_sym(c, cf_hash(c)); | return cf_find_symbol(new_config, c) ?: cf_new_symbol(c); |
} |
} |
|
|
struct symbol * |
struct symbol * |
Line 522 cf_default_name(char *template, int *counter)
|
Line 519 cf_default_name(char *template, int *counter)
|
for(;;) |
for(;;) |
{ |
{ |
bsprintf(buf, template, ++(*counter)); |
bsprintf(buf, template, ++(*counter)); |
s = cf_get_sym(buf, cf_hash(buf)); | s = cf_get_symbol(buf); |
if (s->class == SYM_VOID) |
if (s->class == SYM_VOID) |
return s; |
return s; |
if (!perc) |
if (!perc) |
Line 553 cf_define_symbol(struct symbol *sym, int type, void *d
|
Line 550 cf_define_symbol(struct symbol *sym, int type, void *d
|
{ |
{ |
if (sym->scope == conf_this_scope) |
if (sym->scope == conf_this_scope) |
cf_error("Symbol already defined"); |
cf_error("Symbol already defined"); |
sym = cf_new_sym(sym->name, cf_hash(sym->name)); | sym = cf_new_symbol(sym->name); |
} |
} |
sym->class = type; |
sym->class = type; |
sym->def = def; |
sym->def = def; |
Line 563 cf_define_symbol(struct symbol *sym, int type, void *d
|
Line 560 cf_define_symbol(struct symbol *sym, int type, void *d
|
static void |
static void |
cf_lex_init_kh(void) |
cf_lex_init_kh(void) |
{ |
{ |
struct keyword *k; | HASH_INIT(kw_hash, &root_pool, KW_ORDER); |
|
|
for(k=keyword_list; k->name; k++) | struct keyword *k; |
{ | for (k=keyword_list; k->name; k++) |
unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1); | HASH_INSERT(kw_hash, KW, k); |
k->next = kw_hash[h]; | |
kw_hash[h] = k; | |
} | |
kw_hash_inited = 1; | |
} |
} |
|
|
/** |
/** |
Line 585 cf_lex_init_kh(void)
|
Line 578 cf_lex_init_kh(void)
|
void |
void |
cf_lex_init(int is_cli, struct config *c) |
cf_lex_init(int is_cli, struct config *c) |
{ |
{ |
if (!kw_hash_inited) | if (!kw_hash.data) |
cf_lex_init_kh(); |
cf_lex_init_kh(); |
|
|
ifs_head = ifs = push_ifs(NULL); |
ifs_head = ifs = push_ifs(NULL); |
Line 642 cf_pop_scope(void)
|
Line 635 cf_pop_scope(void)
|
conf_this_scope->active = 0; |
conf_this_scope->active = 0; |
conf_this_scope = conf_this_scope->next; |
conf_this_scope = conf_this_scope->next; |
ASSERT(conf_this_scope); |
ASSERT(conf_this_scope); |
} |
|
|
|
struct symbol * |
|
cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos) |
|
{ |
|
for(;;) |
|
{ |
|
if (!sym) |
|
{ |
|
if (*pos >= SYM_HASH_SIZE) |
|
return NULL; |
|
sym = cf->sym_hash[(*pos)++]; |
|
} |
|
else |
|
sym = sym->next; |
|
if (sym && sym->scope->active) |
|
return sym; |
|
} |
|
} |
} |
|
|
/** |
/** |