1 #ifndef lint 2 static char sccsid[] = "@(#)n4.c 4.1 06/07/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 } 532