int picolCommandSet(struct picolInterp *i, int argc, char **argv, void *pd) { if (argc != 3) return picolArityErr(i, argv[0]); picolSetVar(i, argv[1], argv[2]); picolSetResult(i, argv[2]); return PICOL_OK; }
int picolCommandMath(struct picolInterp *i, int argc, char **argv, void *pd) { char buf[64]; int a, b, c; if (argc != 3) return picolArityErr(i, argv[0]); a = atoi(argv[1]); b = atoi(argv[2]); if (argv[0][0] == '+') c = a + b; else if (argv[0][0] == '-') c = a - b; else if (argv[0][0] == '*') c = a * b; else if (argv[0][0] == '/') c = a / b; else if (argv[0][0] == '>' && argv[0][1] == '\0') c = a > b; else if (argv[0][0] == '>' && argv[0][1] == '=') c = a >= b; else if (argv[0][0] == '<' && argv[0][1] == '\0') c = a < b; else if (argv[0][0] == '<' && argv[0][1] == '=') c = a <= b; else if (argv[0][0] == '=' && argv[0][1] == '=') c = a == b; else if (argv[0][0] == '!' && argv[0][1] == '=') c = a != b; else c = 0; /* I hate warnings */ sniprintf(buf, 64, "%d", c); picolSetResult(i, buf); return PICOL_OK; }
int picolCommandCallProc(struct picolInterp *i, int argc, char **argv, void *pd) { char **x=pd, *alist=x[0], *body=x[1], *p=strdup(alist), *tofree; struct picolCallFrame *cf = malloc(sizeof(*cf)); int arity = 0, done = 0, errcode = PICOL_OK; char errbuf[1024]; cf->vars = NULL; cf->parent = i->callframe; i->callframe = cf; tofree = p; while(1) { char *start = p; while(*p != ' ' && *p != '\0') p++; if (*p != '\0' && p == start) { p++; continue; } if (p == start) break; if (*p == '\0') done=1; else *p = '\0'; if (++arity > argc-1) goto arityerr; picolSetVar(i,start,argv[arity]); p++; if (done) break; } free(tofree); if (arity != argc-1) goto arityerr; errcode = picolEval(i,body); if (errcode == PICOL_RETURN) errcode = PICOL_OK; picolDropCallFrame(i); /* remove the called proc callframe */ return errcode; arityerr: snprintf(errbuf,1024,"Proc '%s' called with wrong arg num",argv[0]); picolSetResult(i,errbuf); picolDropCallFrame(i); /* remove the called proc callframe */ return PICOL_ERR; }
int picolRegisterCommand(struct picolInterp *i, char *name, picolCmdFunc f, void *privdata) { struct picolCmd *c = picolGetCommand(i,name); char errbuf[1024]; if (c) { snprintf(errbuf,1024,"Command '%s' already defined",name); picolSetResult(i,errbuf); return PICOL_ERR; } c = malloc(sizeof(*c)); c->name = strdup(name); c->func = f; c->privdata = privdata; c->next = i->commands; i->commands = c; return PICOL_OK; }
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; }
int picolErr(picolInterp *i, char* str) { picolSetResult(i,str); return PICOL_ERR; }
int picolSetFmtResult(picolInterp* i, char* fmt, int result) { char buf[32]; mysnprintf(buf,sizeof(buf),fmt,result); return picolSetResult(i,buf); }
int picolCommandReturn(struct picolInterp *i, int argc, char **argv, void *pd) { if (argc != 1 && argc != 2) return picolArityErr(i, argv[0]); picolSetResult(i, (argc == 2) ? argv[1] : ""); return PICOL_RETURN; }
/* 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; }
/* ACTUAL COMMANDS! */ int picolArityErr(struct picolInterp *i, char *name) { char buf[1024]; snprintf(buf,1024,"Wrong number of args for %s",name); picolSetResult(i,buf); return PICOL_ERR; }