int picolCondition(picolInterp *i, char* str) { if(str) { char buf[MAXSTR], buf2[MAXSTR]; int rc; rc = picolSubst(i,str); if(rc != PICOL_OK) return rc; //mysnprintf(buf, MAXSTR, "Condi: (%s) ->(%s)\n",str,i->result); //dbg_send_str3(buf, 1); mystrncpy(buf2,i->result, MAXSTR); /* ------- try whether the format suits [expr]... */ mystrncpy(buf,"llength ", MAXSTR); LAPPEND(buf,i->result); //dbg_send_str3(buf, 1); rc = picolEval(i,buf); if(rc != PICOL_OK) return rc; #if 0 if(EQ(i->result,"3")) { FOREACH(buf,cp,buf2) argv[a++] = mystrdup(buf); if(picolGetCmd(i,argv[1])) { /* defined operator in center */ mystrncpy(buf,argv[1], MAXSTR); /* translate to Polish :) */ LAPPEND(buf,argv[0]); /* e.g. {1 > 2} -> {> 1 2} */ LAPPEND(buf,argv[2]); rc = picolEval(i, buf); return rc; } } /* .. otherwise, check for inequality to zero */ #endif if(*str == '!') {mystrncpy(buf, "== 0 ", MAXSTR); str++;} /* allow !$x */ else mystrncpy(buf, "!= 0 ", MAXSTR); mystrncat(buf, str, MAXSTR); return picolEval(i, buf); // todo: compare without eval } else return picolErr(i, "NULL condition"); }
int main(int argc, char **argv) { struct picolInterp interp; picolInitInterp(&interp); picolRegisterCoreCommands(&interp); if (argc == 1) { while(1) { char clibuf[1024]; int retcode; printf("picol> "); fflush(stdout); if (fgets(clibuf,1024,stdin) == NULL) return 0; retcode = picolEval(&interp,clibuf); if (interp.result[0] != '\0') printf("[%d] %s\n", retcode, interp.result); } } else if (argc == 2) { char buf[1024*16]; FILE *fp = fopen(argv[1],"r"); if (!fp) { perror("open"); exit(1); } buf[fread(buf,1,1024*16,fp)] = '\0'; fclose(fp); if (picolEval(&interp,buf) != PICOL_OK) printf("%s\n", interp.result); } return 0; }
int picol_main(int argc, char **argv) { static struct picolInterp interp; picolInitInterp(&interp); picolRegisterCoreCommands(&interp); if (1) { while (1) { static char clibuf[256]; int retcode; iprintf("picol> "); fflush(stdout); interpreter_readline(clibuf, sizeof(clibuf)); retcode = picolEval(&interp, clibuf); if (interp.result[0] != '\0') iprintf("[%d] %s\n", retcode, interp.result); } } #if 0 else if (argc == 2) { char buf[1024 * 16]; FILE *fp = fopen(argv[1], "r"); if (!fp) { perror("open"); return 1; } buf[fread(buf, 1, 1024 * 16, fp)] = '\0'; fclose(fp); if (picolEval(&interp, buf) != PICOL_OK) iprintf("%s\n", interp.result); } #endif return 0; }
int picolCommandIf(struct picolInterp *i, int argc, char **argv, void *pd) { int retcode; if (argc != 3 && argc != 5) return picolArityErr(i,argv[0]); if ((retcode = picolEval(i,argv[1])) != PICOL_OK) return retcode; if (atoi(i->result)) return picolEval(i,argv[2]); else if (argc == 5) return picolEval(i,argv[4]); return PICOL_OK; }
int picolCommandWhile(struct picolInterp *i, int argc, char **argv, void *pd) { if (argc != 3) return picolArityErr(i,argv[0]); while(1) { int retcode = picolEval(i,argv[1]); if (retcode != PICOL_OK) return retcode; if (atoi(i->result)) { if ((retcode = picolEval(i,argv[2])) == PICOL_CONTINUE) continue; else if (retcode == PICOL_OK) continue; else if (retcode == PICOL_BREAK) return PICOL_OK; else return retcode; } else { 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 picolCallProc(picolInterp *i, int argc, char **argv) { if(i->level>MAXRECURSION) return picolErr(i,"too many nested evaluations (infinite loop?)"); picolCmd *c = picolGetCmd(i,argv[0]); if(!c) return PICOL_ERR; void *pd = c->privdata; if(!pd) return PICOL_ERR; char **x=pd; char *alist=x[0], *body=x[1]; char buf[MAXSTR]; picolCallFrame *cf = mycalloc(1,sizeof(*cf)); int a = 0, done = 0, errcode = PICOL_ERR; #ifndef __arm__ if(!cf) {printf("could not allocate callframe\n"); exit(1);} #else extern void print1(char *str); if(!cf) {dbg_send_str3("could not allocate callframe", 1); return PICOL_ERR;} #endif cf->parent = i->callframe; i->callframe = cf; i->level++; char *p = mystrdup(alist); 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(EQ(start,"args") && done) { dbg_send_hex2("eq", p - alist); picolSetVar(i,start,picolList1(buf,argc-a-1,argv+a+1)); a = argc-1; break; } if (++a > argc-1) break; picolSetVar(i,start,argv[a]); p++; if (done) break; } if (a == argc-1) errcode = picolEval(i,body); else errcode = picolErr1(i,"wrong # args for '%s'",argv[0]); if (errcode == PICOL_RETURN) errcode = PICOL_OK; i->callframe = cf->parent; myfree(cf); i->level--; return errcode; }
uint16_t pcl_load(picolInterp *i, uint32_t addr) { uint8_t *ptr = (uint8_t*)addr; dbg_send_hex2("pcl_load.addr", (uint32_t)ptr); int32_t fsz = (int32_t)flash_fsz1(); uint32_t len = 0; uint16_t rc = PICOL_OK; char buf[MAXSTR]; if(!fsz) return rc; while(1) { dbg_send_int2("pcl_load.fsz", fsz); while((ptr[0] == 0x0A) && (fsz > 0)) { ptr++; fsz--; } len = pcl_get_chunksz(ptr, fsz); dbg_send_int2("pcl_load.len", len); if(len == 0) break; if(len >= sizeof(buf)) { dbg_send_int2("chunk too big", len); dbg_send_int2("fsz", fsz); dbg_send_int2("ptr", (int32_t)(ptr - addr)); break; } mymemcpy(buf, ptr, len); buf[len] = 0; dbg_send_str3(buf, 1); //pcl_exec(buf); dbg_send_str3(buf, 1); rc = picolEval(i, buf); dbg_send_int2("pcl_load_eval_result", rc); if(rc != PICOL_OK) { dbg_send_str3("pcl_load error", 1); dbg_send_str3(i->result, 1); break; } ptr += len + 1; fsz -= len + 1; if(fsz <= 0) break; } dbg_send_int2("pcl_load.fsz", fsz); return rc; }
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; }