%{ #include #include #include #include #include #include #include #define DX 248 #define DY 248 #ifdef USED /* plan9port */ #define system system9 #define CC "9c" #define LD "9l" #else #define CC "8c" #define LD "8l" #endif char *newname; char *cmd; Fmt codefmt; int yylex(void); int yyparse(void); void yyerror(char*); void checkref(char*); void checkrefn(int); %} %union { char* s; int i; } %token NAME NEW OLD NUM EOF ERROR %token FN NAME %type index zindex newname command expr fileref value %type NUM %right '=' %right '?' ':' %left '|' %left '^' %left '&' %left EQ NE %right LSH RSH %left '<' '>' LE GE %left '+' '-' %left '*' '/' '%' %right POW %right '!' %% start: command EOF { cmd = $1; return 0; } index: '[' expr ',' expr ']' { $$ = smprint("%s, %s", $2, $4); } zindex: index | { $$ = "x, y"; } newname: NEW { $$ = "new"; } | NEW NAME { $$ = $2; } | NAME { $$ = $1; } command: newname zindex '=' expr { newname = $1; $$ = smprint("T = %s; *WIMAGE(%s, %s) = CLIP(T);", $4, $1, $2); } | expr { newname = "new"; $$ = smprint("T = %s; *WIMAGE(new, x,y) = CLIP(T);", $1); } expr: value | fileref | 'x' { $$ = "x"; } | 'y' { $$ = "y"; } | 'X' { $$ = "X"; } | 'Y' { $$ = "Y"; } | 'Z' { $$ = "Z"; } | "(" expr ")" { $$ = $2; } | FN "(" expr ")" { $$ = smprint("%s(%s)", $1, $3); } | '-' expr %prec '!' { $$ = smprint("-(%s)", $2); } | '!' expr { $$ = smprint("!(%s)", $2); } | expr '+' expr { $$ = smprint("(%s)+(%s)", $1, $3); } | expr '-' expr { $$ = smprint("(%s)-(%s)", $1, $3); } | expr '*' expr { $$ = smprint("(%s)*(%s)", $1, $3); } | expr '/' expr { $$ = smprint("DIV(%s, %s)", $1, $3); } | expr '%' expr { $$ = smprint("MOD(%s, %s)", $1, $3); } | expr '<' expr { $$ = smprint("(%s) < (%s)", $1, $3); } | expr '>' expr { $$ = smprint("(%s) > (%s)", $1, $3); } | expr LE expr { $$ = smprint("(%s) <= (%s)", $1, $3); } | expr GE expr { $$ = smprint("(%s) >= (%s)", $1, $3); } | expr EQ expr { $$ = smprint("(%s) == (%s)", $1, $3); } | expr NE expr { $$ = smprint("(%s) != (%s)", $1, $3); } | expr LSH expr { $$ = smprint("(%s) << (%s)", $1, $3); } | expr RSH expr { $$ = smprint("(%s) >> (%s)", $1, $3); } | expr '^' expr { $$ = smprint("(%s) ^ (%s)", $1, $3); } | expr '&' expr { $$ = smprint("(%s) & (%s)", $1, $3); } | expr '|' expr { $$ = smprint("(%s) | (%s)", $1, $3); } | expr '?' expr ':' expr { $$ = smprint("(%s) ? (%s) : (%s)", $1, $3, $5); } | expr POW expr { $$ = smprint("POW(%s, %s)", $1, $3); } fileref: NAME zindex { checkref($1); $$ = smprint("IMAGE(%s, %s)", $1, $2); } | "$" NUM zindex { checkrefn($2); $$ = smprint("IMAGE(OLD[%d-1], %s)", $2, $3); } | OLD zindex { checkrefn(1); $$ = smprint("IMAGE(old, %s)", $2); } value: NUM { $$ = smprint("%d", $1); } %% char *inp; #define follow(x, y) (*inp == x ? (inp++, y) : c) #define follow2(x, y, x1, y1) (*inp == x ? (inp++, y) : *inp == x1 ? (inp++, y1) : c) jmp_buf boomer; void kaboom(char *fmt, ...) { va_list arg; va_start(arg, fmt); vfprint(2, fmt, arg); va_end(arg); fprint(2, "\n"); longjmp(boomer, 1); } void yyerror(char *msg) { kaboom("%s", msg); } int yylex() { int c; while((c = *inp) != 0 && isspace(c)) inp++; if(c == 0) return EOF; inp++; switch(c){ case '+': case '-': case '/': case '%': case '?': case ':': case '|': case '^': case '&': case '$': case '[': case ']': case ',': case 'X': case 'Y': case 'Z': case '(': case ')': return c; case '*': return follow('*', POW); case '<': return follow2('=', LE, '<', LSH); case '>': return follow2('=', GE, '>', RSH); case '=': return follow('=', EQ); case '!': return follow('=', NE); } if(isdigit(c)){ int n = c - '0'; while((c = *inp) != 0 && isdigit(c)) { n = n * 10 + c - '0'; inp++; } yylval.i = n; return NUM; } if(islower(c)){ char buf[100]; char *p = buf; char *ep = buf+sizeof buf-1; *p++ = c; while(ppid != pid) ; if(w == nil){ fprint(2, "%s: wait not found\n", s); return -1; } if(w->msg && w->msg[0]) { fprint(2, "%s: failed\n", s); return -1; } return 0; } void show(Memimage*); void xquit(int argc, char **argv) { USED(argc); USED(argv); exits(0); } struct { char *name; char *path; Memimage *m; int ref; } *files; int nfiles; Memimage* namei(char *name, int warn) { int i; for(i=0; i nfiles) kaboom("no image $%d", n); files[n-1].ref++; } Memimage* readi(char *name) { int fd; Memimage *m, *m1; if((fd = open(name, OREAD)) < 0){ fprint(2, "open %s: %r\n", name); return nil; } m = readmemimage(fd); close(fd); if(m == nil){ fprint(2, "readmemimage: %r\n"); return nil; } if(m->chan != GREY8 || !eqrect(m->r, Rect(0, 0, DX, DY))){ m1 = allocmemimage(Rect(0, 0, DX, DY), GREY8); memfillcolor(m1, DBlack); memimagedraw(m1, m1->r, m, m->r.min, memopaque, ZP, S); freememimage(m); m = m1; } return m; } int writei(Memimage *m, char *name) { int fd; if((fd = create(name, OWRITE, 0666)) < 0){ fprint(2, "create %s: %r\n", name); return -1; } if(writememimage(fd, m) < 0){ fprint(2, "writememimage %s: %r\n", name); close(fd); return -1; } close(fd); return 0; } void xfiles(int argc, char **argv) { USED(argv); int i; if(argc != 1){ fprint(2, "usage: f\n"); return; } for(i=0; i 3){ fprint(2, "usage: r image [filename]\n"); return; } m = readi(argc == 3 ? argv[2] : argv[1]); iput(argv[1], m); } void xwrite(int argc, char **argv) { if(argc < 2 || argc > 3){ fprint(2, "usage: w image [filename]\n"); return; } Memimage *m = namei(argv[1], 1); if(m == nil) return; writei(m, argc == 3 ? argv[2] : argv[1]); } void xdisplay(int argc, char **argv) { int i; if(argc == 1){ if(nfiles > 0) show(files[nfiles-1].m); return; } for(i=1; i\n" "#include \n" "#include \n" "\n" "Memimage*\n" "READ(char *file)\n" "{\n" " Memimage *m;\n" " int fd = open(file, OREAD);\n" " if(fd < 0) sysfatal(\"open %s: %r\", file);\n" " m = readmemimage(fd);\n" " if(m == nil) sysfatal(\"readmemimage %s: %r\", file);\n" " return m;\n" "}\n\n" "void\n" "WRITE(Memimage *m, char *file)\n" "{\n" " int fd = create(file, OWRITE, 0666);\n" " if(fd < 0) sysfatal(\"create %s: %r\", file);\n" " if(writememimage(fd, m) < 0) sysfatal(\"writememimage %s: %r\", file);\n" "}\n\n" "int\n" "POW(int a, int b)\n" "{\n" " int t;\n" " if(b <= 0) return 1;\n" " if(b == 1) return a;\n" " t = POW(a, b/2);\n" " t *= t;\n" " if(b%2) t *= a;\n" " return t;\n" "}\n" "\n" "int\n" "DIV(int a, int b)\n" "{\n" " if(b == 0) return 0;\n" " return a/b;\n" "}\n" "\n" "int\n" "MOD(int a, int b)\n" "{\n" " if(b == 0) return 0;\n" " return a%b;\n" "}\n" "\n" "#define X 248\n" "#define Y 248\n" "#define Z 255\n" "\n" "uchar\n" "IMAGE(uchar *p, int x, int y)\n" "{\n" " if(x < 0 || y < 0 || x >= X || y >= Y) return 0;\n" " return p[y*X+x];\n" "}\n" "\n" "uchar*\n" "WIMAGE(uchar *p, int x, int y)\n" "{\n" " static uchar devnull;\n" " if(x < 0 || y < 0 || x >= X || y >= Y) return &devnull;\n" " return &p[y*X+x];\n" "}\n" "\n" "#define CLIP(x) ((x) < 0 ? 0 : (x) > 255 ? 255 : (x))\n" "\n" "void main(void) {\n" " int x, y, T;\n" ; int quiet; void runprog(char *name, char *cmd) { int i, fd, isnew; Memimage *m; if((fd = create("/tmp/pico-run.c", OWRITE, 0666)) < 0){ fprint(2, "create /tmp/pico-run.c: %r"); return; } write(fd, prolog, strlen(prolog)); fprint(fd, "\tuchar* OLD[%d+1]; USED(OLD);\n", nfiles); fprint(fd, "\tuchar* old = 0; USED(old);\n"); fprint(fd, "\tMemimage *M[%d+1];\n", nfiles); isnew = namei(name, 0) == 0; if(isnew){ fprint(fd, "\tMemimage *NEW = allocmemimage(Rect(0, 0, X, Y), GREY8);\n"); fprint(fd, "\tif(NEW == nil) sysfatal(\"allocmemimage: %%r\");\n"); fprint(fd, "\tuchar* %s = NEW->data->bdata;\n", name); } for(i=0; idata->bdata;\n", *files[i].name ? "uchar* " :"", files[i].name, *files[i].name ? " = " : "", i, i); if(strcmp(files[i].name, name) == 0) fprint(fd, "Memimage* NEW = M[%d];\n", i); } fprint(fd, "\tfor(x=0; x<%d; x++) for(y=0; y<%d; y++) {\n", DX, DY); fprint(fd, "\t\t%s\n", cmd); fprint(fd, "\t}"); fprint(fd, "\tWRITE(NEW, \"/tmp/pico-run.out.png\");\n"); fprint(fd, "\texits(0);\n}\n"); close(fd); if(system(CC " -o /tmp/pico-run.o /tmp/pico-run.c") < 0) goto cleanup; if(system(LD " -o /tmp/pico-run /tmp/pico-run.o") < 0) goto cleanup; for(i=0; i "); if((p = Brdline(&b, '\n')) == 0) break; p[Blinelen(&b)-1] = 0; while(*p != 0 && isspace(*p)) p++; if(*p == 0) goto reread; for(i=0; ir, displayed, nil, ZP); flushimage(display, 1); } void showloop(Memimage *m) { if(initdraw(0, 0, "pico") < 0){ fprint(2, "initdraw: %r\n"); return; } einit(Emouse|Ekeyboard); doresize(); if((displayed = allocimage(display, Rect(0, 0, DX, DY), GREY8, 0, DBlack)) == nil){ fprint(2, "allocimage: %r\n"); return; } if(loadimage(displayed, displayed->r, byteaddr(m, ZP), DX*DY) < 0){ fprint(2, "loadimage: %r\n"); return; } close(0); eresized(0); for(;;){ Event e; flushimage(display, 0); switch(eread(Emouse|Ekeyboard, &e)){ case Ekeyboard: if(e.kbdc == 'q') return; eresized(0); break; case Emouse: if(e.mouse.buttons&4) return; break; } } } void show(Memimage *m) { if(newwin() != 0) return; showloop(m); exits(0); }