diff options
Diffstat (limited to 'src/cmd/svgpic/for.c')
-rw-r--r-- | src/cmd/svgpic/for.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/cmd/svgpic/for.c b/src/cmd/svgpic/for.c new file mode 100644 index 00000000..cece48b5 --- /dev/null +++ b/src/cmd/svgpic/for.c @@ -0,0 +1,95 @@ +#include <stdio.h> +#include <stdlib.h> +#include "pic.h" +#include "y.tab.h" + +#define SLOP 1.001 + +typedef struct { + char *var; /* index variable */ + double to; /* limit */ + double by; + int op; /* operator */ + char *str; /* string to push back */ +} For; + +For forstk[10]; /* stack of for loops */ +For *forp = forstk; /* pointer to current top */ + +void setfval(char *, double); +void nextfor(void); + +void forloop(char *var, double from, double to, int op, + double by, char *str) /* set up a for loop */ +{ + dprintf("# for %s from %g to %g by %c %g \n", + var, from, to, op, by); + if (++forp >= forstk+10) + ERROR "for loop nested too deep" FATAL; + forp->var = var; + forp->to = to; + forp->op = op; + forp->by = by; + forp->str = str; + setfval(var, from); + nextfor(); + unput('\n'); +} + +void nextfor(void) /* do one iteration of a for loop */ +{ + /* BUG: this should depend on op and direction */ + if (getfval(forp->var) > SLOP * forp->to) { /* loop is done */ + free(forp->str); + if (--forp < forstk) + ERROR "forstk popped too far" FATAL; + } else { /* another iteration */ + pushsrc(String, "\nEndfor\n"); + pushsrc(String, forp->str); + } +} + +void endfor(void) /* end one iteration of for loop */ +{ + struct symtab *p = lookup(forp->var); + + switch (forp->op) { + case '+': + case ' ': + p->s_val.f += forp->by; + break; + case '-': + p->s_val.f -= forp->by; + break; + case '*': + p->s_val.f *= forp->by; + break; + case '/': + p->s_val.f /= forp->by; + break; + } + nextfor(); +} + +char *ifstat(double expr, char *thenpart, char *elsepart) +{ + dprintf("if %g then <%s> else <%s>\n", expr, thenpart, elsepart? elsepart : ""); + if (expr) { + unput('\n'); + pushsrc(Free, thenpart); + pushsrc(String, thenpart); + unput('\n'); + if (elsepart) + free(elsepart); + return thenpart; /* to be freed later */ + } else { + free(thenpart); + if (elsepart) { + unput('\n'); + pushsrc(Free, elsepart); + pushsrc(String, elsepart); + unput('\n'); + } + return elsepart; + } +} |