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