int cnumb(void) { int c, n; c = *f.charp++; if(c == '<') { n = f.nextiter; if(n >= 0) { f.nextiter = n+f.diriter; if(n == f.lastiter) { f.nextiter = -1; f.lastiter = -1; } do { c = *f.charp++; } while (c != '>'); return n; } n = cnumb(); if(*f.charp++ != '-') { cdiag("- expected", f.charp[-1]); return 0; } c = cnumb(); if(*f.charp++ != '>') { cdiag("> expected", f.charp[-1]); return 0; } f.lastiter = c; f.diriter = 1; if(n > c) f.diriter = -1; f.nextiter = n+f.diriter; return n; } if(!isascii(c) || !isdigit(c)) { cdiag("number expected", c); return 0; } n = 0; while(isascii(c) && isdigit(c)) { n = n*10 + (c-'0'); c = *f.charp++; } f.charp--; return n; }
/* * Get nation argument. * If @arg is not empty, use it * Else prompt for input using @prompt. * If no input is provided, return NULL. * If the argument identifies a country, return its getnatp() value. * Else complain and return NULL. * Caution: this function doesn't care for lack of contact. */ struct natstr * natargp(char *arg, char *prompt) { char buf[1024]; int n; struct natstr *np; arg = getstarg(arg, prompt, buf); if (!arg || !*arg) return NULL; if (isdigit(*arg)) n = atoi(arg); else { n = cnumb(arg); if (n == M_NOTUNIQUE) { pr("Country '%s' is ambiguous\n", arg); return NULL; } } np = getnatp(n); if (!np || np->nat_stat == STAT_UNUSED) { pr("Country '%s' doesn't exist.\n", arg); return NULL; } return np; }
/* * Search table @type for an element matching @name, return its index. * Accepts EF_BAD, but of course never finds anything then. * Return M_NOTFOUND if there are no matches, M_NOTUNIQUE if there are * several. */ int ef_elt_byname(int type, char *name) { switch (type) { case EF_BAD: return M_NOTFOUND; case EF_NATION: return cnumb(name); case EF_SECTOR_CHR: return sct_typematch(name); case EF_SHIP_CHR: return stmtch(name, mchr, offsetof(struct mchrstr, m_name), sizeof(mchr[0])); case EF_LAND_CHR: return stmtch(name, lchr, offsetof(struct lchrstr, l_name), sizeof(lchr[0])); case EF_PLANE_CHR: return stmtch(name, plchr, offsetof(struct plchrstr, pl_name), sizeof(plchr[0])); case EF_NUKE_CHR: return stmtch(name, nchr, offsetof(struct nchrstr, n_name), sizeof(nchr[0])); case EF_ITEM: return stmtch(name, ichr, offsetof(struct ichrstr, i_name), sizeof(ichr[0])); case EF_PRODUCT: return stmtch(name, pchr, offsetof(struct pchrstr, p_sname), sizeof(pchr[0])); case EF_TABLE: return stmtch(name, empfile, offsetof(struct empfile, name), sizeof(empfile[0])); default: if (ef_cadef(type) == symbol_ca) return stmtch(name, ef_ptr(type, 0), offsetof(struct symbol, name), sizeof(struct symbol)); } return M_NOTFOUND; }
Device* config(void) { int c, m; Device *d; char *icp; if(f.error) return devnone; d = malloc(sizeof(Device)); c = *f.charp++; switch(c) { default: cdiag("unknown type", c); return devnone; case '(': /* (d+) one or multiple cat */ case '[': /* [d+] one or multiple interleave */ case '{': /* {d+} a mirrored device and optional mirrors */ return config1(c); case 'f': /* fd fake worm */ d->type = Devfworm; d->fw.fw = config(); break; case 'n': d->type = Devnone; break; case 'w': /* w[#.]#[.#] wren [ctrl] unit [lun] */ case 'r': /* r# worm side */ case 'l': /* l# labelled-worm side */ icp = f.charp; d->type = Devwren; d->wren.ctrl = 0; d->wren.targ = cnumb(); d->wren.lun = 0; m = *f.charp; if(m == '.') { f.charp++; d->wren.lun = cnumb(); m = *f.charp; if(m == '.') { f.charp++; d->wren.ctrl = d->wren.targ; d->wren.targ = d->wren.lun; d->wren.lun = cnumb(); } } if(f.nextiter >= 0) f.charp = icp-1; if(c == 'r') /* worms are virtual and not uniqued */ d->type = Devworm; else if(c == 'l') d->type = Devlworm; else map(d); /* subject wrens to optional mapping */ break; case 'o': /* o ro part of last cw */ if(f.lastcw == 0) { cdiag("no cw to match", c); return devnone; } return f.lastcw->cw.ro; case 'j': /* DD jukebox */ d->type = Devjuke; d->j.j = config(); d->j.m = config(); break; case 'c': /* cache/worm */ d->type = Devcw; d->cw.c = config(); d->cw.w = config(); d->cw.ro = malloc(sizeof(Device)); d->cw.ro->type = Devro; d->cw.ro->ro.parent = d; f.lastcw = d; break; case 'p': /* pd#.# partition base% size% */ d->type = Devpart; d->part.d = config(); d->part.base = cnumb(); c = *f.charp++; if(c != '.') cdiag("dot expected", c); d->part.size = cnumb(); break; case 'x': /* xD swab a device's metadata */ d->type = Devswab; d->swab.d = config(); break; } d->dlink = f.devlist; f.devlist = d; return d; }