diff options
Diffstat (limited to 'pic/for.c')
-rw-r--r-- | pic/for.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/pic/for.c b/pic/for.c new file mode 100644 index 0000000000000..9323aecae54a7 --- /dev/null +++ b/pic/for.c @@ -0,0 +1,107 @@ +/* + * Changes by Gunnar Ritter, Freiburg i. Br., Germany, October 2005. + * + * Derived from Plan 9 v4 /sys/src/cmd/pic/ + * + * Copyright (C) 2003, Lucent Technologies Inc. and others. + * All Rights Reserved. + * + * Distributed under the terms of the Lucent Public License Version 1.02. + */ + +/* Sccsid @(#)for.c 1.3 (gritter) 10/18/05 */ +#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) + FATAL("for loop nested too deep"); + 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) + FATAL("forstk popped too far"); + } 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; + } +} |