1: #ifndef lint 2: static char sccsid[] = "@(#)n4.c 4.1 6/7/82"; 3: #endif lint 4: 5: #include "tdef.h" 6: extern 7: #include "d.h" 8: extern 9: #include "v.h" 10: #ifdef NROFF 11: extern 12: #include "tw.h" 13: #endif 14: #include "sdef.h" 15: /* 16: troff4.c 17: 18: number registers, conversion, arithmetic 19: */ 20: 21: extern int inchar[LNSIZE], *pinchar; /* XXX */ 22: extern struct s *frame; 23: 24: extern int ascii; 25: extern int cbuf[NC]; 26: extern int *cp; 27: extern int r[NN]; 28: extern int *vlist; 29: extern int inc[NN]; 30: extern int fmt[NN]; 31: extern int ch; 32: extern int lgf; 33: extern int pl; 34: extern int lastl; 35: extern int ralss; 36: extern int totout; 37: extern int nrbits; 38: extern int nonumb; 39: extern int vflag; 40: extern int noscale; 41: extern int dfact; 42: extern int dfactd; 43: extern int po; 44: extern int nform; 45: extern int ll; 46: extern int in; 47: extern int font; 48: extern int bdtab[]; 49: extern int lss; 50: extern int pts; 51: extern int fi; 52: extern int res; 53: extern int cwidth; 54: extern int dotT; 55: extern int ev; 56: extern int ne; 57: extern int ad, admod; 58: extern int print; 59: extern int ls; 60: extern int nel, un; 61: extern int xxx; 62: int regcnt = NNAMES; 63: 64: setn() 65: { 66: register i,j; 67: int f; 68: 69: f = nform = 0; 70: if((i=getch() & CMASK) == '+')f = 1; 71: else if(i == '-')f = -1; 72: else ch = i; 73: if((i=getsn()) == 0)return; 74: if((i & 0177) == '.')switch(i>>BYTE){ 75: case 's': i = pts & 077; break; 76: case 'v': i = lss; break; 77: case 'f': i = font + 1; break; 78: case 'p': i = pl; break; 79: case 't': i = findt1(); break; 80: case 'o': i = po; break; 81: case 'l': i = ll; break; 82: case 'i': i = in; break; 83: case '$': i = frame->nargs; break; 84: case 'A': i = ascii; break; 85: case 'c': i = v.cd; break; 86: case 'n': i = lastl; break; 87: case 'a': i = ralss; break; 88: case 'h': i = dip->hnl; break; 89: case 'd': 90: if(dip != d)i = dip->dnl; else i = v.nl; 91: break; 92: case 'u': i = fi; break; 93: case 'j': i = ad + 2*admod; break; 94: case 'w': i = width(*(pinchar-1)); break; /* XXX */ 95: case 'x': i = nel; break; 96: case 'y': i = un; break; 97: case 'T': i = dotT; break; /*-Tterm used in nroff*/ 98: case 'V': i = VERT; break; 99: case 'H': i = HOR; break; 100: case 'k': i = ne; break; 101: case 'P': i = print; break; 102: case 'L': i = ls; break; 103: case 'R': i = NN - regcnt; break; 104: case 'z': i = dip->curd; 105: cbuf[0] = i & BMASK; 106: cbuf[1] = (i >> BYTE) & BMASK; 107: cbuf[2] = 0; 108: cp = cbuf; 109: return; 110: #ifndef NROFF 111: case 'b': i = bdtab[font]; break; 112: #endif 113: 114: default: 115: goto s0; 116: } 117: else{ 118: s0: 119: if((j=findr(i)) == -1)i = 0; 120: else{ 121: i = (vlist[j] = (vlist[j] + inc[j]*f)); 122: nform = fmt[j]; 123: } 124: } 125: setn1(i); 126: cp = cbuf; 127: } 128: setn1(i) 129: int i; 130: { 131: extern int wrc(); 132: 133: cp = cbuf; 134: nrbits = 0; 135: fnumb(i,wrc); 136: *cp = 0; 137: cp = cbuf; 138: } 139: findr(i) 140: int i; 141: { 142: register j; 143: static int numerr; 144: 145: if(i == 0)return(-1); 146: for(j=0;j<NN;j++){ 147: if(i == r[j])break; 148: } 149: if(j != NN)return(j); 150: for(j=0; j<NN; j++){ 151: if(r[j] == 0){ 152: r[j] = i; 153: regcnt++; 154: break; 155: } 156: } 157: if(j==NN){ 158: if(!numerr)prstrfl("Too many number registers.\n"); 159: if(++numerr > 1)done2(04); else edone(04); 160: } 161: return(j); 162: } 163: fnumb(i,f) 164: int i, (*f)(); 165: { 166: register j; 167: 168: j = 0; 169: if(i < 0){ 170: j = (*f)('-' | nrbits); 171: i = -i; 172: } 173: switch(nform){ 174: default: 175: case '1': 176: case 0: return(decml(i,f) + j); 177: case 'i': 178: case 'I': return(roman(i,f) + j); 179: case 'a': 180: case 'A': return(abc(i,f) + j); 181: } 182: } 183: decml(i,f) 184: int i, (*f)(); 185: { 186: register j,k; 187: 188: k = 0; 189: nform--; 190: if((j=i/10) || (nform > 0))k = decml(j,f); 191: return(k + (*f)((i%10 + '0') | nrbits)); 192: } 193: roman(i,f) 194: int i, (*f)(); 195: { 196: 197: if(!i)return((*f)('0' | nrbits)); 198: if(nform == 'i')return(roman0(i,f,"ixcmz","vldw")); 199: else return(roman0(i,f,"IXCMZ","VLDW")); 200: } 201: roman0(i,f,onesp,fivesp) 202: int i, (*f)(); 203: char *onesp, *fivesp; 204: { 205: register q, rem, k; 206: 207: k = 0; 208: if(!i)return(0); 209: k = roman0(i/10,f,onesp+1,fivesp+1); 210: q = (i=i%10)/5; 211: rem = i%5; 212: if(rem == 4){ 213: k += (*f)(*onesp | nrbits); 214: if(q)i = *(onesp+1); 215: else i = *fivesp; 216: return(k += (*f)(i | nrbits)); 217: } 218: if(q)k += (*f)(*fivesp | nrbits); 219: while(--rem >= 0) 220: k += (*f)(*onesp | nrbits); 221: return(k); 222: } 223: abc(i,f) 224: int i, (*f)(); 225: { 226: if(!i)return((*f)('0' | nrbits)); 227: else return(abc0(i-1,f)); 228: } 229: abc0(i,f) 230: int i, (*f)(); 231: { 232: register j, k; 233: 234: k = 0; 235: if(j=i/26)k = abc0(j-1,f); 236: return(k + (*f)((i%26 + nform) | nrbits)); 237: } 238: wrc(i) 239: int i; 240: { 241: if(cp >= &cbuf[NC])return(0); 242: *cp++ = i; 243: return(1); 244: } 245: atoi(){ 246: extern long atoi0(); 247: 248: return((int)atoi0()); 249: } 250: long atoi0() 251: { 252: register ii, k, cnt; 253: long i, acc; 254: extern long ckph(); 255: 256: i = 0; acc = 0; 257: nonumb = 0; 258: cnt = -1; 259: a0: 260: cnt++; 261: switch((ii=getch()) & CMASK){ 262: default: 263: ch = ii; 264: if(cnt)break; 265: case '+': 266: i = ckph(); 267: if(nonumb)break; 268: acc += i; 269: goto a0; 270: case '-': 271: i = ckph(); 272: if(nonumb)break; 273: acc -= i; 274: goto a0; 275: case '*': 276: i = ckph(); 277: if(nonumb)break; 278: acc *= i; 279: goto a0; 280: case '/': 281: i = ckph(); 282: if(nonumb)break; 283: if(i == 0){ 284: prstrfl("Divide by zero.\n"); 285: acc = 0; 286: }else acc /= i; 287: goto a0; 288: case '%': 289: i = ckph(); 290: if(nonumb)break; 291: acc %= i; 292: goto a0; 293: case '&': /*and*/ 294: i = ckph(); 295: if(nonumb)break; 296: if((acc > 0) && (i > 0))acc = 1; else acc = 0; 297: goto a0; 298: case ':': /*or*/ 299: i = ckph(); 300: if(nonumb)break; 301: if((acc > 0) || (i > 0))acc = 1; else acc = 0; 302: goto a0; 303: case '=': 304: if(((ii=getch()) & CMASK) != '=')ch = ii; 305: i = ckph(); 306: if(nonumb){acc = 0; break;} 307: if(i == acc)acc = 1; 308: else acc = 0; 309: goto a0; 310: case '>': 311: k = 0; 312: if(((ii=getch()) & CMASK) == '=')k++; else ch =ii; 313: i = ckph(); 314: if(nonumb){acc = 0; break;} 315: if(acc > (i - k))acc = 1; else acc = 0; 316: goto a0; 317: case '<': 318: k = 0; 319: if(((ii=getch()) & CMASK) == '=')k++; else ch =ii; 320: i = ckph(); 321: if(nonumb){acc = 0; break;} 322: if(acc < (i + k))acc = 1; else acc = 0; 323: goto a0; 324: case ')': break; 325: case '(': 326: acc = atoi0(); 327: goto a0; 328: } 329: return(acc); 330: } 331: long ckph(){ 332: register i; 333: long j; 334: extern long atoi0(); 335: extern long atoi1(); 336: 337: if(((i = getch()) & CMASK) == '(')j = atoi0(); 338: else{ 339: ch = i; 340: j = atoi1(); 341: } 342: return(j); 343: } 344: long atoi1() 345: { 346: register i, j, digits; 347: long acc; 348: int neg, abs, field; 349: 350: neg = abs = field = digits = 0; 351: acc = 0; 352: a0: 353: switch((i = getch()) & CMASK){ 354: default: 355: ch = i; 356: break; 357: case '+': 358: goto a0; 359: case '-': 360: neg = 1; 361: goto a0; 362: case '|': 363: abs = 1 + neg; 364: neg = 0; 365: goto a0; 366: } 367: a1: 368: while(((j = ((i = getch()) & CMASK) - '0') >= 0) && (j <= 9)){ 369: field++; 370: digits++; 371: acc = 10*acc + j; 372: } 373: if((i & CMASK) == '.'){ 374: field++; 375: digits = 0; 376: goto a1; 377: } 378: ch = i; 379: if(!field)goto a2; 380: switch((i = getch()) & CMASK){ 381: case 'u': 382: i = j = 1; 383: break; 384: case 'v': /*VSs - vert spacing*/ 385: j = lss; 386: i = 1; 387: break; 388: case 'm': /*Ems*/ 389: j = EM; 390: i = 1; 391: break; 392: case 'n': /*Ens*/ 393: j = EM; 394: #ifndef NROFF 395: i = 2; 396: #endif 397: #ifdef NROFF 398: i = 1; /*Same as Ems in NROFF*/ 399: #endif 400: break; 401: case 'p': /*Points*/ 402: j = INCH; 403: i = 72; 404: break; 405: case 'i': /*Inches*/ 406: j = INCH; 407: i = 1; 408: break; 409: case 'c': /*Centimeters*/ 410: j = INCH*50; 411: i = 127; 412: break; 413: case 'P': /*Picas*/ 414: j = INCH; 415: i = 6; 416: break; 417: default: 418: j = dfact; 419: ch = i; 420: i = dfactd; 421: } 422: if(neg) acc = -acc; 423: if(!noscale){ 424: acc = (acc*j)/i; 425: } 426: if((field != digits) && (digits > 0))while(digits--)acc /= 10; 427: if(abs){ 428: if(dip != d)j = dip->dnl; else j = v.nl; 429: if(!vflag)j = v.hp = sumhp(); /* XXX */ 430: if(abs == 2)j = -j; 431: acc -= j; 432: } 433: a2: 434: nonumb = !field; 435: return(acc); 436: } 437: caserr(){ 438: register i,j; 439: 440: lgf++; 441: while(!skip() && (i=getrq()) ){ 442: for(j=NNAMES; j<NN; j++){ /*NNAMES predefined names*/ 443: if(i == r[j])break; 444: } 445: if(j!=NN){ 446: r[j]=vlist[j]=inc[j]=fmt[j]=0; 447: regcnt--; 448: } 449: } 450: } 451: casenr(){ 452: register i, j; 453: 454: lgf++; 455: skip(); 456: if((i = findr(getrq())) == -1)goto rtn; 457: skip(); 458: j = inumb(&vlist[i]); 459: if(nonumb)goto rtn; 460: vlist[i] = j; 461: skip(); 462: j = atoi(); 463: if(nonumb)goto rtn; 464: inc[i] = j; 465: rtn: 466: return; 467: } 468: caseaf(){ 469: register i, j, k; 470: 471: lgf++; 472: if(skip() || !(i = getrq()) || skip())return; 473: k = 0; 474: if(!alph(j=getch())){ 475: ch = j; 476: while(((j = getch() & CMASK) >= '0') && 477: (j <= '9'))k++; 478: } 479: if(!k)k=j; 480: fmt[findr(i)] = k & BMASK; 481: } 482: vnumb(i) 483: int *i; 484: { 485: vflag++; 486: dfact = lss; 487: res = VERT; 488: return(inumb(i)); 489: } 490: hnumb(i) 491: int *i; 492: { 493: dfact = EM; 494: res = HOR; 495: return(inumb(i)); 496: } 497: inumb(n) 498: int *n; 499: { 500: register i, j, f; 501: 502: f = 0; 503: if(n){ 504: if((j = (i = getch()) & CMASK) == '+')f = 1; 505: else if(j == '-')f = -1; 506: else ch = i; 507: } 508: i = atoi(); 509: if(n && f)i = *n + f*i; 510: i = quant(i,res); 511: vflag = 0; 512: res = dfactd = dfact = 1; 513: if(nonumb)i = 0; 514: return(i); 515: } 516: quant(n,m) 517: int n, m; 518: { 519: register i, neg; 520: 521: neg = 0; 522: if(n<0){ 523: neg++; 524: n = -n; 525: } 526: i = n/m; 527: if((n - m*i) > (m/2))i += 1; 528: i *= m; 529: if(neg)i = -i; 530: return(i); 531: }