?? myutil.c
字號:
for(c = 0; c < lp_max_mod; c++) { for(d = 0; d < lp_modules[c]->modvars_len; d++) { printf("%s::%s\n", lp_modules[c]->name, lp_modules[c]->modvars[d].name); } }}void dummy (struct lp_block *b) { fprintf(stderr, "*** error: %s cannot be declared at top-level.\n", b->name); exit(1);}struct lp_list *lp_list_add(struct lp_list *l, struct lp_value *v){ int c, newlen; for(c = 0; c < l->values_len; c++) { if(!l->values[c]) goto done; } newlen = 2 * c * sizeof(struct lp_value *); l->values = realloc(l->values, newlen); bzero(l->values + c, newlen / 2); l->values_len *= 2; done: l->values_pop++; l->values[c] = v; return l;}/* maps a modtype and parameter name to a nonnegative numeric * representation. -1 returned on error */int lp_param_name(int m, char *n){ int c = 0; if(!RANGE(m,0,lp_max_mod)) return -1; if(!n) return -1; while((c < lp_modules[m]->modvars_len) && strcmp(lp_modules[m]->modvars[c].name, n)) c++; if(c >= lp_modules[m]->modvars_len) { return -1; } else { return c; }}int lp_mod_name(char *n) { int c = 0; if(!n) return -1; while((c < lp_max_mod) && strcmp(lp_modules[c]->name, n)) c++; if(c >= lp_max_mod) { return -1; } else { return c; }}/* get the base type of name */char *lp_lookup_base_type(char *name, int *n) { int c; for(c = 0; c < lp_typetbl_len; c++) { if(lp_typetbl[c]) { if(!strcmp(name, lp_typetbl[c]->sub)) { if(lp_typetbl[c]->super) { return lp_lookup_base_type(lp_typetbl[c]->super, n); } else { break; } } } } if(n) *n = c; return name;}char *lp_lookup_type(char *name, int *n) { int c; for(c = 0; c < lp_typetbl_len; c++) { if(lp_typetbl[c]) { if(!strcmp(name, lp_typetbl[c]->sub)) { if(n) *n = c; return lp_typetbl[c]->super; } } } return 0;}/* find the specification for name or return 0 if it doesn't exist. * New "wildcard" behavior: if name is null, return the first * spec in the typetbl with non-zero parent -- i.e. only * match a user-provided spec, not a builtin type! */struct lp_block *lp_lookup_spec(char *name) { int c; for(c = 0; c < lp_typetbl_len; c++) if(lp_typetbl[c]) { if(!name) { if(lp_typetbl[c]->super) { return lp_typetbl[c]->spec; } } else if(!strcmp(name, lp_typetbl[c]->sub)) { return lp_typetbl[c]->spec; } } return 0;}struct lp_tlt *lp_new_tl_topo(struct lp_topospec *t, char *source_file){ struct lp_tlt *result = calloc(1, sizeof(*result)); result->source_file = source_file; result->what = TLT_TOPO; result->it.topo = t; lp_add_tlt(result); return result;}struct lp_tlt *lp_new_tl_inst(struct lp_inst *i, char *source_file){ struct lp_tlt *result = calloc(1, sizeof(*result)); result->source_file = source_file; result->what = TLT_INST; result->it.inst = i; lp_add_tlt(result); return result;}struct lp_tlt *lp_new_tl_block(struct lp_block *b, char *source_file){ struct lp_tlt *result = calloc(1, sizeof(*result)); result->source_file = source_file; result->what = TLT_BLOCK; result->it.block = b; lp_add_tlt(result); return result;}void lp_add_tlt(struct lp_tlt *tlt) { int c; int found = 0; for(c = 0; c < lp_tlts_len; c++) { if(!lp_tlts[c]) { found = c; break; } } if(!found) { int newlen = lp_tlts_len ? 2 * lp_tlts_len : 2; int zerocnt = lp_tlts_len ? lp_tlts_len : 2; int newsize = newlen * sizeof(struct lp_tlts *); zerocnt *= sizeof(struct lp_tlts *); lp_tlts = realloc(lp_tlts, newsize); memset(lp_tlts + lp_tlts_len, 0, zerocnt); found = lp_tlts_len; lp_tlts_len = newlen; } lp_tlts[c] = tlt;}int lp_add_type(char *newt, char *parent) { int c; int newlen; struct lp_subtype *st = calloc(1, sizeof(*st)); st->super = strdup(parent); st->sub = strdup(newt); if(!lp_lookup_type(newt,0)) { for(c = 0; c < lp_typetbl_len; c++) if(!lp_typetbl[c]) { goto done; } newlen = lp_typetbl_len ? 2 * lp_typetbl_len : 2; lp_typetbl = realloc(lp_typetbl, newlen * sizeof(int *)); bzero(lp_typetbl + c, c * sizeof(int *)); lp_typetbl_len = newlen; } else return -1; done: lp_typetbl[c] = st; return 0;}int lp_add_param(struct lp_param ***b, int *plen, struct lp_param *p){ int c; /* look for dupe params */ for(c = 0; c < *plen; c++) { if(!(*b)[c]) continue; if(!strcmp((*b)[c]->name, p->name)) { fprintf(stderr, "*** error: redefined %s\n", p->name); return -1; } } for(c = 0; c < *plen; c++) { if(!(*b)[c]) { (*b)[c] = p; break; } } if(c == *plen) { /* didn't find a free slot -- double the array */ int newlen = 2 * (*plen) + 1; (*b) = realloc((*b), newlen * sizeof(int *)); bzero((int *)(*b) + *plen, ((*plen) + 1) * sizeof(int*)); (*b)[(*plen)] = p; *plen = newlen; } return 0;}/* copy all of the params in parent not defined in child into * child */int lp_setup_subtype(struct lp_block *parent, struct lp_block *child){ int c, d; for(c = 0; c < parent->params_len; c++) { int found = 0; for(d = 0; d < child->params_len; d++) { if(!strcmp(child->params[d]->name, parent->params[c]->name)) { found = 1; } } if(!found) { lp_add_param(&child->params, &child->params_len, parent->params[c]); } } return 0;}void lp_init_typetbl(void) { int c; lp_typetbl = calloc(lp_max_mod, sizeof(struct subtype *)); for(c = 0; c < lp_max_mod; c++) { lp_typetbl[c] = malloc(sizeof(struct lp_subtype)); bzero(lp_typetbl[c], sizeof(struct lp_subtype)); lp_typetbl[c]->sub = strdup(lp_modules[c]->name); } lp_typetbl_len = lp_max_mod;}void lp_release_typetbl(void) { int c; for(c = 0; c < lp_typetbl_len; c++) { if(!lp_typetbl[c]) continue; if(lp_typetbl[c]->spec) destroy_block(lp_typetbl[c]->spec); if(lp_typetbl[c]->sub) free(lp_typetbl[c]->sub); if(lp_typetbl[c]->super) free(lp_typetbl[c]->super); free(lp_typetbl[c]); } free(lp_typetbl);}/* splits s into a trailing number (i) and the leading part */int dumb_split(char *s, char **t, int *i) { int c = strlen(s) - 1; while(c && isdigit(s[c])) c--; if(!c) return -1; c++; (*i) = atoi(&s[c]); *t = strdup(s); (*t)[c] = 0; return 0;}/* separate 'foo:bar' into 'foo' and 'bar' */int dumb_split2(char *s, char **s1, char **s2) { int c = 0; (*s1) = strdup(s); while(s[c] && (s[c] != ':')) c++; (*s1)[c] = 0; if(s[c]) (*s2) = strdup(s + c + 1); else return -1; return 0;}static int param_override(struct lp_block *b, char *pname, char *pval) { int c; for(c = 0; c < b->params_len; c++) { if(!b->params[c]) continue; if(!strcmp(b->params[c]->name, pname)) { switch(b->params[c]->v->t) { case I: b->params[c]->v->v.i = atoi(pval); break; case D: b->params[c]->v->v.d = atof(pval); break; case S: free(b->params[c]->v->v.s); b->params[c]->v->v.s = strdup(pval); return 0; break; default: ddbg_assert(0); } return -1; } } return -1;} int range_match(char *range, char *name) { char *base1, *base2, *base3; char r1[128], r2[128]; int i1, i2, i3; if(!strcmp(range, name)) { return 1; } if(!strcmp(range, "*")) return 1; if(sscanf(range, "%s .. %s", r1, r2) != 2) { char *prefix; int junk; dumb_split(name, &prefix, &junk); /* i.e. driver* matches driver2 and driver and driver2344 but not * driverqux */ if((strlen(range) == ( strlen(prefix) + 1)) && !strncmp(range,prefix,strlen(prefix)) && (range[strlen(prefix)] == '*')) return 1; return 0; } dumb_split(r1, &base1, &i1); dumb_split(r2, &base2, &i2); if(strcmp(base1, base2) || (i1 < 0) || (i2 < i1)) { fprintf(stderr, "*** error: bad range \"%s .. %s\"\n", r1, r2); return 0; } dumb_split(name, &base3, &i3); if(!strcmp(base3, base2) && (i3 >= i1) && (i3 <= i2)) { return 1; } else { return 0; }}/* instantiate a component with overrides * tname type to instantiate, * cname name of instantiated component * loader is the module loader function for tname */int *lp_override_inst(struct lp_block *spec, char *cname, lp_modloader_t loader, char **overrides, int overrides_len){ int c, d; struct lp_block *spec_copy; char *p1, *p2; int *result; spec_copy = copy_block(spec); for(c = 0; c < overrides_len; c += 3) { if(range_match(overrides[c], cname)) { /* overrides[c+2] could be an int, a real, a string or a list or * a block. need parser to deal with lists and blocks * reasonably so we aren't going to deal with them here */ if(!dumb_split2(overrides[c+1], &p1, &p2)) { /* descend hierarchy */ for(d = 0; d < spec_copy->params_len; d++) { if(!spec_copy->params[d]) continue; if(!strcmp(p1, spec_copy->params[d]->name)) { if(spec_copy->params[d]->v->t != BLOCK) { fprintf(stderr, "*** error: tried to recurse through non-block parameter.\n"); return 0; } else { param_override(spec_copy->params[d]->v->v.b, p2, overrides[c+2]); } } } } else { param_override(spec_copy, overrides[c+1], overrides[c+2]); } } } if(!check_types(spec_copy)) { result = loader(spec_copy, 0); } // XXX don't leak (segfaults) // destroy_block(spec_copy); return result; }extern void libparamparse(void);extern void libparamlex(void);int lp_loadfile(FILE *in, struct lp_tlt ***tlts, int *tlts_len, char *infile, char **cli_overrides, int cli_overrides_len) { char *lp_sp; char *dirc; char *dir; int stdout_save; int devnull; top_file = 0; lp_lineno = 1; dirc = strdup(infile); dir = dirname(dirc); lp_filename = infile; lp_cwd = dir; libparamin = in; overrides = cli_overrides; overrides_len = cli_overrides_len; // do the searchpath lp_sp = getenv("LP_PATH"); if(lp_sp) { char *p = lp_sp; char *colon; lp_searchpath = calloc(LP_MAX_SP, sizeof(char*)); while(*p) { colon = strchr(p, ':'); if(colon) { char *next; *colon = 0; next = colon+1; lp_searchpath[lp_searchpath_len++] = strdup(p); p = next; } else { lp_searchpath[lp_searchpath_len++] = strdup(p); break; } } } // this creates a fresh array every time its run so caller // is responsible for freeing it lp_tlts = 0; lp_tlts_len = 0; fflush(stdout); stdout_save = dup(1); devnull = open("/dev/null", O_RDONLY); dup2(devnull, 1); libparamparse(); fflush(stdout); dup2(stdout_save, 1); close(devnull); close(stdout_save); if(tlts) { *tlts = lp_tlts; } if(tlts_len) { *tlts_len = lp_tlts_len; } return 0;}#define LP_STACK_MAX 32intlp_loadparams(void *it, struct lp_block *b, struct lp_mod *m) { int c; int needed = 0; int param_stack[LP_STACK_MAX]; int stack_ptr = 0; // index of first free slot // XXX not static size char *paramvec = calloc(m->modvars_len, sizeof(char)); // This is pretty gross; there should be a better solution. // dirname() munges its operand. Its result may also be a static // buffer somewhere, hence the 2 copies. char *tmp = strdup(b->source_file); lp_cwd = strdup(dirname(tmp)); // free(tmp); for(c = 0; c < b->params_len; c++) { int pnum, deps; if(!b->params[c]) continue; TOP: pnum = lp_param_name(lp_mod_name(m->name), b->params[c]->name); // Don't initialize things more than once. // Should warn here, probably. if(BIT_TEST(paramvec, pnum)) continue; if(stack_ptr > 0) { for(c = 0; c < b->params_len; c++) { if(lp_param_name(lp_mod_name(m->name), b->params[c]->name) == needed) goto FOUND; } break; } FOUND: deps = m->param_deps[pnum](paramvec); if(deps > -1) { ddbg_assert(stack_ptr < LP_STACK_MAX); param_stack[stack_ptr++] = c; needed = deps; continue; } else { switch(PTYPE(b->params[c])) { case I: ((lp_paramloader_int)m->param_loaders[pnum])(it, IVAL(b->params[c])); break; case D: ((lp_paramloader_double)m->param_loaders[pnum])(it, DVAL(b->params[c])); break; case S: ((lp_paramloader_string)m->param_loaders[pnum])(it, SVAL(b->params[c])); break; case LIST: ((lp_paramloader_list)m->param_loaders[pnum])(it, LVAL(b->params[c])); break; case BLOCK: default: ((lp_paramloader_block)m->param_loaders[pnum])(it, BVAL(b->params[c])); break; } } BIT_SET(paramvec, pnum); if(stack_ptr > 0) { c = param_stack[--stack_ptr]; goto TOP; } } for(c = 0; c < m->modvars_len; c++) { if(m->modvars[c].req && !BIT_TEST(paramvec,c)) { fprintf(stderr, "*** error: in %s spec -- missing required parameter %s\n", m->name, m->modvars[c].name); break; } } free(paramvec); return 0; // ???}char *lp_search_path(char *cwd, char *name){ char *cand = calloc(LP_PATH_MAX, sizeof(char)); struct stat s; int i; if(name[0] == '/') if(stat(name, &s)) goto fail; snprintf(cand, LP_PATH_MAX, "%s/%s", cwd, name); if(!stat(cand, &s)) goto succ; for(i = 0; i < lp_searchpath_len; i++) { snprintf(cand, LP_PATH_MAX, "%s/%s", lp_searchpath[i], name); if(!stat(cand, &s)) { goto succ; } } fail: free(cand); return 0; succ: return cand;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -