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