#include <stdio.h> #include "pico.h" #include "pico2.h" #include "y.tab.h" extern struct SRC src[MANY]; extern short CURSCRATCH, CUROLD; extern char faster, frameb, metheus; extern int DEF_LL, DEF_NL; #define NNODE 8000 Node nodearray[NNODE]; int nalloc=0; Node * Index(k) Node *k; { switch(k->type) { case ACOMMA: if (commacount(k) == 2) return new(OADD, new(OMUL, k->right, VR(&DEF_LL), Z), k->left, Z); break; case COMP: return new(ODIV, sumchans(k->left), NR(3), Z); } return k; } Node * ncopy(n) Node *n; { if (n == Z) return n; n = new(n->type, ncopy(n->left), ncopy(n->right), n->other); if (n->type == CONDI) n->other = ncopy(n->other); return n; } int spare; Node * modulo(p, q) Node *p, *q; { Node *tmp1, *tmp2; if (p->type == OCOMMA || p->type == ACOMMA) yyerror("lefthand-side of modulo is a composite"); tmp1 = new(OASS, VR(&spare), ncopy(p), Z); tmp2 = new(OSUB, VR(&spare), new(OMUL, new(ODIV, VR(&spare), ncopy(q), Z), ncopy(q), Z), Z); return new(OCOMMA, tmp1, new(CONDI, tmp2, VR(&spare), q), Z); } Node * divide(p, q) Node *p, *q; { Node *tmp = ncopy(q); extern Node zero; return new(CONDI, new(ODIV, p, q, Z), &zero, tmp); } int fixspot; /* encodes the assignment of a composite to a composite */ Node * fixit(n, m) Node *n, *m; { Node *tmp1 = new(OASS, VR(&fixspot), ncopy(m), Z); Node *tmp2 = ncopy(n->left->left); /* r */ Node *tmp3 = ncopy(n->left->right->left); /* g */ Node *tmp4 = ncopy(n->left->right->right); /* b */ Node *low = new(OAND, VR(&fixspot), NR(255), Z); Node *med = new(OLSH, notnew(OAND, VR(&fixspot), NR(255<<8)), new(OMINUS, NR(8), Z, Z), Z); Node *hig = new(OLSH, VR(&fixspot), new(OMINUS, NR(16), Z, Z), Z); Node *tmp5 = new(OASS, tmp2, low, Z); Node *tmp6 = new(OASS, tmp3, med, Z); Node *tmp7 = new(OASS, tmp4, hig, Z); Node *tmp8 = new(OCOMMA, tmp5, tmp6, Z); Node *tmp9 = new(OCOMMA, tmp7, tmp8, Z); return new(OCOMMA, tmp1, tmp9, Z); } Node * catch(what, n, m) int what; Node *n, *m; { switch (what) { case DIVV: return divide(n, m); case MODU: return modulo(n, m); case OASS: if (n->type == COMP) { if (m->type == CONDI) return fixit(n, m); else return new(OCOMMA, par(what, n->left, m->left), Z, Z); } default: return new(what, n, m, Z); } } Node * new(type, left, right, oth) Node *left, *right, *oth; { register Node *n; if (nalloc >= NNODE) yyerror("NNODE too small; recompile pico"); n = nodearray+nalloc++; n->type = type; n->left = left; n->right = right; n->other = oth; return n; } Node * sumchans(n) Node *n; { if (n == Z || n->type != ACOMMA) return n; return new(OADD, sumchans(n->left), sumchans(n->right), Z); } Node * cast(n) Node *n; { if (n == Z || n->type != ACOMMA) return n; return new(ODIV, sumchans(n->left), NR(3), Z); } #define Par(side) par(what, n1->side, n2->side) Node * par(what, n1, n2) int what; Node *n1, *n2; { if (n1 == Z || n2 == Z) return Z; if (n1->type != ACOMMA || n2->type != ACOMMA) return catch(what, ncopy(n1), ncopy(n2)); if (what == OASS) return new(OCOMMA, Par(left), Par(right), Z); else return new(ACOMMA, Par(left), Par(right), Z); } Node * promote(m) Node *m; { Node *n; if (m->type == CONDI) return new(CONDI, promote(m->left), promote(m->right), m->other); if (m->type == COMP) return m; n = new(ACOMMA, ncopy(m), ncopy(m), Z); n = new(ACOMMA, ncopy(m), n, Z); return new(COMP, n, Z, Z); } Node * disp(what, n, e) int what; Node *n, *e; { if (n == Z) return Z; if (n->type != ACOMMA) return catch(what, ncopy(n), ncopy(e)); return new(OCOMMA, disp(what, n->left, e), disp(what, n->right, e), Z); } Node * notnew(what, n1, n2) int what; Node *n1, *n2; { int how = 0; if (n1->type == COMP) how += 1; if (n2->type == COMP) how += 2; switch (how) { case 1: n2 = promote(n2); /* fall through */ case 0: return catch(what, n1, n2); case 2: if (what == OASS) return catch(what, n1, new(ODIV, sumchans(n2->left), NR(3), Z)); n1 = promote(n1); /* fall through */ case 3: if (what == OASS) return catch(what, n1, n2); /* else: */ return new(COMP, par(what, n1->left, n2->left), Z, Z); } } Node * threechans(q, r) struct SRC *q; Node *r; { Node *n; if (q->nchan >= 3) { n = new(ACOMMA, DOLGRN(q, r), DOLBLU(q, r), Z); n = new(ACOMMA, DOLRED(q, r), n, Z); return new(COMP, n, Z, Z); } else return DOLRED(q, r); } SNode * nsup(n, x, y, i) Node *n, *x, *y; char i; { SNode *tmp; tmp = (SNode *) Emalloc(sizeof(SNode)); tmp->n = n; tmp->x = x; tmp->y = y; tmp->i = i; return tmp; } Node * splatter(n) SNode *n; { extern int ramlyank(), fblyank(), metlyank(); if (metheus) return new(CCALL, new(ACOMMA, n->x, n->y, Z), Z, metlyank); else if (frameb) return new(CCALL, new(ACOMMA, n->x, n->y, Z), Z, fblyank); } Node * weird(n, m) SNode *n; Node *m; { Node *tmp; if (m == Z) return n->n; tmp = notnew(OASS, n->n, m); if (n->i != CURSCRATCH || (!frameb && !metheus) || (faster && notafunc() && metheus) || (faster && Old->nchan==1 && notafunc() && frameb)) return tmp; else return new(OCOMMA, tmp, splatter(n), Z); } Node * getx(n) Node *n; { if (n == Z) return AREG(XREG); if (n->type == ACOMMA) { if (commacount(n) == 2) return n->left; else yyerror("bad index"); } return modulo(n, VR(&DEF_LL)); } Node * gety(n) Node *n; { if (n == Z) return AREG(YREG); if (n->type == ACOMMA) { if (commacount(n) == 2) return n->right; else yyerror("bad index"); } return divide(n, VR(&DEF_LL)); } SNode * super(a, b, t) Node *b; { Node *tmp; Node *n = (b == Z)? DII: Index(b); switch (t) { case RGB: tmp = threechans(&src[a], n); break; case BW: if (src[a].nchan == 1) tmp = DOLRED((&src[a]), n); else tmp = cast(threechans(&src[a], n)); break; case RCHAN: tmp = DOLRED((&src[a]), n); break; case GCHAN: tmp = DOLGRN((&src[a]), n); break; case BCHAN: tmp = DOLBLU((&src[a]), n); break; } if (b == Z) return nsup(tmp, AREG(XREG), AREG(YREG), a); else return nsup(tmp, getx(b), gety(b), a); }