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