int picolEval2(picolInterp *i, const char *t, int mode) { /*----------- EVAL! */ /* mode==0: subst only, mode==1: full eval */ picolParser p; char buf[MAXSTR], tmp[MAXSTR], sep = 0; if(mode == 0) sep = ' '; uint32_t len; int rc = PICOL_OK; picolList args; args.size = 0; picolSetResult(i, ""); picolInitParser(&p, t); while(1) { picolGetToken(i, &p); //___print_token(&p); if (p.type == PT_EOF) break; len = p.end - p.start + 1; mystrncpy(tmp, p.start, len); //___print_list(&args); if (p.type == PT_SEP) { continue; } else if (p.type == PT_VAR) { picolVar *v = picolGetVar(i,tmp); if (v && !v->val) v = picolGetGlobalVar(i,tmp); if(!v) return picolErr(i,"no such variable"); picolListAppend(&args, v->val, buf, sep); //___print_list(&args); continue; } else if (p.type == PT_CMD) { rc = picolEval(i,tmp); if (rc != PICOL_OK) break; picolListAppend(&args, i->result, buf, sep); continue; } /* We have a complete command + args. Call it! */ else if (p.type == PT_EOL) { picolCmd *c; //args.size -= 1; if(mode==0) { /* do a quasi-subst only */ rc = picolSetResult(i, buf); goto err; /* not an error, if rc == PICOL_OK */ } if (args.size) { if ((c = picolGetCmd(i,args.table[0])) == NULL) { rc = picolErr(i,"invalid command name"); goto err; } rc = c->func(i,args.size,args.table); if (rc != PICOL_OK) goto err; args.size = 0; continue; } args.size = 0; continue; } else picolListAppend(&args, tmp, buf, sep); } err: return rc; }
/* EVAL! */ int picolEval(struct picolInterp *i, char *t) { struct picolParser p; int argc = 0, j; char **argv = NULL; int retcode = PICOL_OK; picolSetResult(i, ""); picolInitParser(&p, t); while (1) { char *t; int tlen; int prevtype = p.type; picolGetToken(&p); if (p.type == PT_EOF) break; tlen = p.end - p.start + 1; if (tlen < 0) tlen = 0; t = my_malloc(tlen + 1); memcpy(t, p.start, tlen); t[tlen] = '\0'; if (p.type == PT_VAR) { struct picolVar *v = picolGetVar(i, t); if (!v) { iprintf("No such variable '%s'", t); free(t); // picolSetResult(i, errbuf); retcode = PICOL_ERR; goto err; } free(t); t = strdup(v->val); } else if (p.type == PT_CMD) { retcode = picolEval(i, t); free(t); if (retcode != PICOL_OK) goto err; t = strdup(i->result); } else if (p.type == PT_ESC) { /* XXX: escape handling missing! */ } else if (p.type == PT_SEP) { prevtype = p.type; free(t); continue; } /* We have a complete command + args. Call it! */ if (p.type == PT_EOL) { struct picolCmd *c; free(t); prevtype = p.type; if (argc) { if ((c = picolGetCommand(i, argv[0])) == NULL) { iprintf("No such command '%s'", argv[0]); // picolSetResult(i, errbuf); retcode = PICOL_ERR; goto err; } retcode = c->func(i, argc, argv, c->privdata); if (retcode != PICOL_OK) goto err; } /* Prepare for the next command */ for (j = 0; j < argc; j++) free(argv[j]); free(argv); argv = NULL; argc = 0; continue; } /* We have a new token, append to the previous or as new arg? */ if (prevtype == PT_SEP || prevtype == PT_EOL) { argv = realloc(argv, sizeof(char*) * (argc + 1)); argv[argc] = t; argc++; } else { /* Interpolation */ int oldlen = strlen(argv[argc - 1]), tlen = strlen(t); argv[argc - 1] = realloc(argv[argc - 1], oldlen + tlen + 1); memcpy(argv[argc - 1] + oldlen, t, tlen); argv[argc - 1][oldlen + tlen] = '\0'; free(t); } prevtype = p.type; } err: for (j = 0; j < argc; j++) free(argv[j]); free(argv); return retcode; }