/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * troff4.c * * number registers, conversion, arithmetic */ #include "tdef.h"#include "fns.h"#include "ext.h" int regcnt = NNAMES;int falsef = 0; /* on if inside false branch of if */ #define NHASHSIZE 128 /* must be 2**n */#define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1)Numtab *nhash[NHASHSIZE]; Numtab *numtabp = NULL;#define NDELTA 400int ncnt = 0; void setn(void){ int i, j, f; Tchar ii; Uchar *p; char buf[NTM]; /* for \n(.S */ f = nform = 0; if ((i = cbits(ii = getach())) == '+') f = 1; else if (i == '-') f = -1; else if (ii) /* don't put it back if it's already back (thanks to jaap) */ ch = ii; if (falsef) f = 0; if ((i = getsn()) == 0) return; p = unpair(i); if (p[0] == '.') switch (p[1]) { case 's': i = pts; break; case 'v': i = lss; break; case 'f': i = font; break; case 'p': i = pl; break; case 't': i = findt1(); break; case 'o': i = po; break; case 'l': i = ll; break; case 'i': i = in; break; case '$': i = frame->nargs; break; case 'A': i = ascii; break; case 'c': i = numtabp[CD].val; break; case 'n': i = lastl; break; case 'a': i = ralss; break; case 'h': i = dip->hnl; break; case 'd': if (dip != d) i = dip->dnl; else i = numtabp[NL].val; break; case 'u': i = fi; break; case 'j': i = ad + 2 * admod; break; case 'w': i = widthp; break; case 'x': i = nel; break; case 'y': i = un; break; case 'T': i = dotT; break; /* -Tterm used in nroff */ case 'V': i = VERT; break; case 'H': i = HOR; break; case 'k': i = ne; break; case 'P': i = print; break; case 'L': i = ls; break; case 'R': /* maximal # of regs that can be addressed */ i = 255*256 - regcnt; break; case 'z': p = unpair(dip->curd); *pbp++ = p[1]; /* watch order */ *pbp++ = p[0]; return; case 'b': i = bdtab[font]; break; case 'F': cpushback(cfname[ifi]); return; case 'S': buf[0] = j = 0; for( i = 0; tabtab[i] != 0 && i < NTAB; i++) { if (i > 0) buf[j++] = ' '; sprintf(&buf[j], "%d", tabtab[i] & TABMASK); j = strlen(buf); if ( tabtab[i] & RTAB) sprintf(&buf[j], "uR"); else if (tabtab[i] & CTAB) sprintf(&buf[j], "uC"); else sprintf(&buf[j], "uL"); j += 2; } cpushback(buf); return; default: goto s0; } else {s0: if ((j = findr(i)) == -1) i = 0; else { i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f; nform = numtabp[j].fmt; } } setn1(i, nform, (Tchar) 0);} Tchar numbuf[25];Tchar *numbufp; int wrc(Tchar i){ if (numbufp >= &numbuf[24]) return(0); *numbufp++ = i; return(1);} /* insert into input number i, in format form, with size-font bits bits */void setn1(int i, int form, Tchar bits){ numbufp = numbuf; nrbits = bits; nform = form; fnumb(i, wrc); *numbufp = 0; pushback(numbuf);} void prnumtab(Numtab *p){ int i; for (i = 0; i < ncnt; i++) if (p) if (p[i].r != 0) fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val); else fprintf(stderr, "slot %d empty\n", i); else fprintf(stderr, "slot %d empty\n", i);} void nnspace(void){ ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA; numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab)); if (numtabp == NULL) { ERROR "not enough memory for registers (%d)", ncnt WARN; exit(1); } numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab, sizeof(numtab)); if (numtabp == NULL) { ERROR "Cannot initialize registers" WARN; exit(1); }} void grownumtab(void){ ncnt += NDELTA; numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab)); if (numtabp == NULL) { ERROR "Too many number registers (%d)", ncnt WARN; done2(04); } else { memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab), 0, NDELTA * sizeof(Numtab)); nrehash(); }} void nrehash(void){ Numtab *p; int i; for (i=0; i<NHASHSIZE; i++) nhash[i] = 0; for (p=numtabp; p < &numtabp[ncnt]; p++) p->link = 0; for (p=numtabp; p < &numtabp[ncnt]; p++) { if (p->r == 0) continue; i = NHASH(p->r); p->link = nhash[i]; nhash[i] = p; }} void nunhash(Numtab *rp){ Numtab *p; Numtab **lp; if (rp->r == 0) return; lp = &nhash[NHASH(rp->r)]; p = *lp; while (p) { if (p == rp) { *lp = p->link; p->link = 0; return; } lp = &p->link; p = p->link; }} int findr(int i){ Numtab *p; int h = NHASH(i); if (i == 0) return(-1);a0: for (p = nhash[h]; p; p = p->link) if (i == p->r) return(p - numtabp); for (p = numtabp; p < &numtabp[ncnt]; p++) { if (p->r == 0) { p->r = i; p->link = nhash[h]; nhash[h] = p; regcnt++; return(p - numtabp); } } grownumtab(); goto a0;} int usedr(int i) /* returns -1 if nr i has never been used */{ Numtab *p; if (i == 0) return(-1); for (p = nhash[NHASH(i)]; p; p = p->link) if (i == p->r) return(p - numtabp); return -1;} int fnumb(int i, int (*f)(Tchar)){ int j; j = 0; if (i < 0) { j = (*f)('-' | nrbits); i = -i; } switch (nform) { default: case '1': case 0: return decml(i, f) + j; case 'i': case 'I': return roman(i, f) + j; case 'a': case 'A': return abc(i, f) + j; }} int decml(int i, int (*f)(Tchar)){ int j, k; k = 0; nform--; if ((j = i / 10) || (nform > 0)) k = decml(j, f); return(k + (*f)((i % 10 + '0') | nrbits));} int roman(int i, int (*f)(Tchar)){ if (!i) return((*f)('0' | nrbits)); if (nform == 'i') return(roman0(i, f, "ixcmz", "vldw")); else return(roman0(i, f, "IXCMZ", "VLDW"));} int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp){ int q, rem, k; if (!i) return(0); k = roman0(i / 10, f, onesp + 1, fivesp + 1); q = (i = i % 10) / 5; rem = i % 5; if (rem == 4) { k += (*f)(*onesp | nrbits); if (q) i = *(onesp + 1); else i = *fivesp; return(k += (*f)(i | nrbits)); } if (q) k += (*f)(*fivesp | nrbits); while (--rem >= 0) k += (*f)(*onesp | nrbits); return(k);} int abc(int i, int (*f)(Tchar)){ if (!i) return((*f)('0' | nrbits)); else return(abc0(i - 1, f));} int abc0(int i, int (*f)(Tchar)){ int j, k; k = 0; if (j = i / 26) k = abc0(j - 1, f); return(k + (*f)((i % 26 + nform) | nrbits));} long atoi0(void){ int c, k, cnt; Tchar ii; long i, acc; acc = 0; nonumb = 0; cnt = -1;a0: cnt++; ii = getch(); c = cbits(ii); switch (c) { default: ch = ii; if (cnt) break; case '+': i = ckph(); if (nonumb) break; acc += i; goto a0; case '-': i = ckph(); if (nonumb) break; acc -= i; goto a0; case '*': i = ckph(); if (nonumb) break; acc *= i; goto a0; case '/': i = ckph(); if (nonumb) break; if (i == 0) { flusho(); ERROR "divide by zero." WARN; acc = 0; } else acc /= i; goto a0; case '%': i = ckph(); if (nonumb) break; acc %= i; goto a0; case '&': /*and*/ i = ckph(); if (nonumb) break; if ((acc > 0) && (i > 0)) acc = 1; else acc = 0; goto a0; case ':': /*or*/ i = ckph(); if (nonumb) break; if ((acc > 0) || (i > 0)) acc = 1; else acc = 0; goto a0; case '=': if (cbits(ii = getch()) != '=') ch = ii; i = ckph(); if (nonumb) { acc = 0; break; } if (i == acc) acc = 1; else acc = 0; goto a0; case '>': k = 0; if (cbits(ii = getch()) == '=')Lines 1–500 of 837. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* * troff4.c * * number registers, conversion, arithmetic */ #include "tdef.h" #include "fns.h" #include "ext.h" int regcnt = NNAMES; int falsef = 0; /* on if inside false branch of if */ #define NHASHSIZE 128 /* must be 2**n */ #define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1) Numtab *nhash[NHASHSIZE]; Numtab *numtabp = NULL; #define NDELTA 400 int ncnt = 0; void setn(void) { int i, j, f; Tchar ii; Uchar *p; char buf[NTM]; /* for \n(.S */ f = nform = 0; if ((i = cbits(ii = getach())) == '+') f = 1; else if (i == '-') f = -1; else if (ii) /* don't put it back if it's already back (thanks to jaap) */ ch = ii; if (falsef) f = 0; if ((i = getsn()) == 0) return; p = unpair(i); if (p[0] == '.') switch (p[1]) { case 's': i = pts; break; case 'v': i = lss; break; case 'f': i = font; break; case 'p': i = pl; break; case 't': i = findt1(); break; case 'o': i = po; break; case 'l': i = ll; break; case 'i': i = in; break; case '$': i = frame->nargs; break; case 'A': i = ascii; break; case 'c': i = numtabp[CD].val; break; case 'n': i = lastl; break; case 'a': i = ralss; break; case 'h': i = dip->hnl; break; case 'd': if (dip != d) i = dip->dnl; else i = numtabp[NL].val; break; case 'u': i = fi; break; case 'j': i = ad + 2 * admod; break; case 'w': i = widthp; break; case 'x': i = nel; break; case 'y': i = un; break; case 'T': i = dotT; break; /* -Tterm used in nroff */ case 'V': i = VERT; break; case 'H': i = HOR; break; case 'k': i = ne; break; case 'P': i = print; break; case 'L': i = ls; break; case 'R': /* maximal # of regs that can be addressed */ i = 255*256 - regcnt; break; case 'z': p = unpair(dip->curd); *pbp++ = p[1]; /* watch order */ *pbp++ = p[0]; return; case 'b': i = bdtab[font]; break; case 'F': cpushback(cfname[ifi]); return; case 'S': buf[0] = j = 0; for( i = 0; tabtab[i] != 0 && i < NTAB; i++) { if (i > 0) buf[j++] = ' '; sprintf(&buf[j], "%d", tabtab[i] & TABMASK); j = strlen(buf); if ( tabtab[i] & RTAB) sprintf(&buf[j], "uR"); else if (tabtab[i] & CTAB) sprintf(&buf[j], "uC"); else sprintf(&buf[j], "uL"); j += 2; } cpushback(buf); return; default: goto s0; } else { s0: if ((j = findr(i)) == -1) i = 0; else { i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f; nform = numtabp[j].fmt; } } setn1(i, nform, (Tchar) 0); } Tchar numbuf[25]; Tchar *numbufp; int wrc(Tchar i) { if (numbufp >= &numbuf[24]) return(0); *numbufp++ = i; return(1); } /* insert into input number i, in format form, with size-font bits bits */ void setn1(int i, int form, Tchar bits) { numbufp = numbuf; nrbits = bits; nform = form; fnumb(i, wrc); *numbufp = 0; pushback(numbuf); } void prnumtab(Numtab *p) { int i; for (i = 0; i < ncnt; i++) if (p) if (p[i].r != 0) fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val); else fprintf(stderr, "slot %d empty\n", i); else fprintf(stderr, "slot %d empty\n", i); } void nnspace(void) { ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA; numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab)); if (numtabp == NULL) { ERROR "not enough memory for registers (%d)", ncnt WARN; exit(1); } numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab, sizeof(numtab)); if (numtabp == NULL) { ERROR "Cannot initialize registers" WARN; exit(1); } } void grownumtab(void) { ncnt += NDELTA; numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab)); if (numtabp == NULL) { ERROR "Too many number registers (%d)", ncnt WARN; done2(04); } else { memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab), 0, NDELTA * sizeof(Numtab)); nrehash(); } } void nrehash(void) { Numtab *p; int i; for (i=0; i<NHASHSIZE; i++) nhash[i] = 0; for (p=numtabp; p < &numtabp[ncnt]; p++) p->link = 0; for (p=numtabp; p < &numtabp[ncnt]; p++) { if (p->r == 0) continue; i = NHASH(p->r); p->link = nhash[i]; nhash[i] = p; } } void nunhash(Numtab *rp) { Numtab *p; Numtab **lp; if (rp->r == 0) return; lp = &nhash[NHASH(rp->r)]; p = *lp; while (p) { if (p == rp) { *lp = p->link; p->link = 0; return; } lp = &p->link; p = p->link; } } int findr(int i) { Numtab *p; int h = NHASH(i); if (i == 0) return(-1); a0: for (p = nhash[h]; p; p = p->link) if (i == p->r) return(p - numtabp); for (p = numtabp; p < &numtabp[ncnt]; p++) { if (p->r == 0) { p->r = i; p->link = nhash[h]; nhash[h] = p; regcnt++; return(p - numtabp); } } grownumtab(); goto a0; } int usedr(int i) /* returns -1 if nr i has never been used */ { Numtab *p; if (i == 0) return(-1); for (p = nhash[NHASH(i)]; p; p = p->link) if (i == p->r) return(p - numtabp); return -1; } int fnumb(int i, int (*f)(Tchar)) { int j; j = 0; if (i < 0) { j = (*f)('-' | nrbits); i = -i; } switch (nform) { default: case '1': case 0: return decml(i, f) + j; case 'i': case 'I': return roman(i, f) + j; case 'a': case 'A': return abc(i, f) + j; } } int decml(int i, int (*f)(Tchar)) { int j, k; k = 0; nform--; if ((j = i / 10) || (nform > 0)) k = decml(j, f); return(k + (*f)((i % 10 + '0') | nrbits)); } int roman(int i, int (*f)(Tchar)) { if (!i) return((*f)('0' | nrbits)); if (nform == 'i') return(roman0(i, f, "ixcmz", "vldw")); else return(roman0(i, f, "IXCMZ", "VLDW")); } int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp) { int q, rem, k; if (!i) return(0); k = roman0(i / 10, f, onesp + 1, fivesp + 1); q = (i = i % 10) / 5; rem = i % 5; if (rem == 4) { k += (*f)(*onesp | nrbits); if (q) i = *(onesp + 1); else i = *fivesp; return(k += (*f)(i | nrbits)); } if (q) k += (*f)(*fivesp | nrbits); while (--rem >= 0) k += (*f)(*onesp | nrbits); return(k); } int abc(int i, int (*f)(Tchar)) { if (!i) return((*f)('0' | nrbits)); else return(abc0(i - 1, f)); } int abc0(int i, int (*f)(Tchar)) { int j, k; k = 0; if (j = i / 26) k = abc0(j - 1, f); return(k + (*f)((i % 26 + nform) | nrbits)); } long atoi0(void) { int c, k, cnt; Tchar ii; long i, acc; acc = 0; nonumb = 0; cnt = -1; a0: cnt++; ii = getch(); c = cbits(ii); switch (c) { default: ch = ii; if (cnt) break; case '+': i = ckph(); if (nonumb) break; acc += i; goto a0; case '-': i = ckph(); if (nonumb) break; acc -= i; goto a0; case '*': i = ckph(); if (nonumb) break; acc *= i; goto a0; case '/': i = ckph(); if (nonumb) break; if (i == 0) { flusho(); ERROR "divide by zero." WARN; acc = 0; } else acc /= i; goto a0; case '%': i = ckph(); if (nonumb) break; acc %= i; goto a0; case '&': /*and*/ i = ckph(); if (nonumb) break; if ((acc > 0) && (i > 0)) acc = 1; else acc = 0; goto a0; case ':': /*or*/ i = ckph(); if (nonumb) break; if ((acc > 0) || (i > 0)) acc = 1; else acc = 0; goto a0; case '=': if (cbits(ii = getch()) != '=') ch = ii; i = ckph(); if (nonumb) { acc = 0; break; } if (i == acc) acc = 1; else acc = 0; goto a0; case '>': k = 0; if (cbits(ii = getch()) == '=')