int b_enum(int argc, char **argv, Shbltin_t *context) { bool pflag = false, iflag = false; int i, n; ssize_t sz = -1; Namval_t *np, *tp, *mp; Namarr_t *ap; char *cp; const char *sp; struct Enum *ep; Shell_t *shp = context->shp; struct { Optdisc_t opt; Namval_t *np; } optdisc; if (cmdinit(argc, argv, context, ERROR_NOTIFY)) return -1; while ((n = optget(argv, enum_usage))) { switch (n) { case 'p': { pflag = true; break; } case 'i': { iflag = true; break; } case ':': { errormsg(SH_DICT, 2, "%s", opt_info.arg); break; } case '?': { errormsg(SH_DICT, ERROR_usage(2), "%s", opt_info.arg); __builtin_unreachable(); } default: { break; } } } argv += opt_info.index; argc -= opt_info.index; if (error_info.errors || argc != 1) { error(ERROR_USAGE | 2, "%s", optusage(NULL)); return 1; } while ((cp = *argv++)) { np = nv_open(cp, shp->var_tree, NV_VARNAME | NV_NOADD); if (!np || !(ap = nv_arrayptr(np)) || ap->fun || ap->nelem < 2) { error(ERROR_exit(1), "%s must name an array containing at least two elements", cp); } n = stktell(shp->stk); sfprintf(shp->stk, "%s.%s%c", NV_CLASS, np->nvname, 0); tp = nv_open(stkptr(shp->stk, n), shp->var_tree, NV_VARNAME); if (pflag) { sh_outenum(shp, sfstdout, tp); continue; } stkseek(shp->stk, n); n = ap->nelem; i = 0; nv_onattr(tp, NV_UINT16); nv_putval(tp, (char *)&i, NV_INTEGER); nv_putsub(np, NULL, 0L, ARRAY_SCAN); do { sz += strlen(nv_getval(np)); } while (nv_nextsub(np)); ep = calloc(1, sizeof(struct Enum)); if (!ep) { error(ERROR_system(1), "out of space"); __builtin_unreachable(); } ep->nelem = n; mp = nv_namptr(ep->node, 0); mp->nvshell = shp; nv_setsize(mp, 10); nv_onattr(mp, NV_UINT16); ep->iflag = iflag; ep->values = malloc(n * sizeof(*ep->values)); nv_putsub(np, NULL, 0L, ARRAY_SCAN); i = 0; do { sp = nv_getval(np); ep->values[i++] = strdup(sp); } while (nv_nextsub(np)); assert(n == i); ep->namfun.dsize = sizeof(struct Enum); ep->namfun.disc = &ENUM_disc; ep->namfun.type = tp; nv_onattr(tp, NV_RDONLY); nv_disc(tp, &ep->namfun, DISC_OP_FIRST); memset(&optdisc, 0, sizeof(optdisc)); optdisc.opt.infof = enuminfo; optdisc.np = tp; nv_addtype(tp, enum_type, &optdisc, sizeof(optdisc)); nv_onattr(np, NV_LTOU | NV_UTOL); } nv_open(0, shp->var_tree, 0); return error_info.errors != 0; }
static void genvalue(Sfio_t *out, Shclass_t *sp, int indent, Namval_t *npar) { Shfield_t *fp = sp->fields; Namval_t *np, **nodes= (Namval_t**)(sp+1); register int i,isarray; if(out) { sfwrite(out,"(\n",2); indent++; } for(i=0; i < sp->nelem; i++,fp++) { #if 0 /* handle recursive case */ #endif if(!(np=nodes[i]) && out) np = sh_newnode(fp,npar); if(np) { isarray=0; if(nv_isattr(np,NV_ARRAY)) { isarray=1; if(array_elem(nv_arrayptr(np))==0) isarray=2; else nv_putsub(np,(char*)0,ARRAY_SCAN); } sfnputc(out,'\t',indent); sfputr(out,fp->name,(isarray==2?'\n':'=')); if(isarray) { if(isarray==2) continue; sfwrite(out,"(\n",2); sfnputc(out,'\t',++indent); } while(1) { char *fmtq; if(isarray) { sfprintf(out,"[%s]",sh_fmtq(nv_getsub(np))); sfputc(out,'='); } if(!(fmtq=nv_getval(np)) || !(fmtq=sh_fmtq(fmtq))) fmtq = ""; sfputr(out,fmtq,'\n'); if(!nv_nextsub(np)) break; sfnputc(out,'\t',indent); } if(isarray) { sfnputc(out,'\t',--indent); sfwrite(out,")\n",2); } } } if(out) { if(indent>1) sfnputc(out,'\t',indent-1); sfputc(out,')'); } }
int b_enum(int argc, char** argv, Shbltin_t *context) #endif { bool pflag=false, iflag=false; int i,n; ssize_t sz = -1; Namval_t *np, *tp, *mp; Namarr_t *ap; char *cp,*sp; struct Enum *ep; Shell_t *shp = context->shp; struct { Optdisc_t opt; Namval_t *np; } optdisc; cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY); for (;;) { switch (optget(argv, enum_usage)) { case 'p': pflag = true; continue; case 'i': iflag = true; continue; case '?': error(ERROR_USAGE|4, "%s", opt_info.arg); break; case ':': error(2, "%s", opt_info.arg); break; } break; } argv += opt_info.index; if (error_info.errors) { error(ERROR_USAGE|2, "%s", optusage(NiL)); return 1; } if(!*argv) sh_outenum(shp,sfstdout,(Namval_t*)0); while(cp = *argv++) { if(!(np = nv_open(cp, shp->var_tree, NV_VARNAME|NV_NOADD)) || !(ap=nv_arrayptr(np)) || ap->fun || (sz=ap->nelem) < 2) error(ERROR_exit(1), "%s must name an array containing at least two elements",cp); n = stktell(shp->stk); sfprintf(shp->stk,"%s.%s%c",NV_CLASS,np->nvname,0); tp = nv_open(stkptr(shp->stk,n), shp->var_tree, NV_VARNAME); if(pflag) { sh_outenum(shp,sfstdout,tp); continue; } stkseek(shp->stk,n); n = sz; i = 0; nv_onattr(tp, NV_UINT16); nv_putval(tp, (char*)&i, NV_INTEGER); nv_putsub(np, (char*)0, 0L, ARRAY_SCAN); do { sz += strlen(nv_getval(np)); } while(nv_nextsub(np)); sz += n*sizeof(char*); if(!(ep = newof(0,struct Enum,1,sz))) error(ERROR_system(1), "out of space"); mp = nv_namptr(ep->node,0); mp->nvshell = shp; nv_setsize(mp,10); nv_onattr(mp, NV_UINT16); ep->iflag = iflag; ep->nelem = n; cp = (char*)&ep->values[n+1]; nv_putsub(np, (char*)0, 0L, ARRAY_SCAN); ep->values[n] = 0; i = 0; do { ep->values[i++] = cp; sp = nv_getval(np); n = strlen(sp); memcpy(cp,sp,n+1); cp += n+1; } while(nv_nextsub(np)); ep->hdr.dsize = sizeof(struct Enum)+sz; ep->hdr.disc = &ENUM_disc; ep->hdr.type = tp; nv_onattr(tp, NV_RDONLY); nv_disc(tp, &ep->hdr,NV_FIRST); memset(&optdisc,0,sizeof(optdisc)); optdisc.opt.infof = enuminfo; optdisc.np = tp; nv_addtype(tp, enum_type, &optdisc.opt, sizeof(optdisc)); nv_onattr(np,NV_LTOU|NV_UTOL); } nv_open(0,shp->var_tree,0); return error_info.errors != 0; }