1*2155Seric # include "stdio.h" 2*2155Seric # include "seven/types.h" 3*2155Seric # include "seven/macros.h" 4*2155Seric # include "fatal.h" 5*2155Seric 6*2155Seric SCCSID(@(#)vc.c 4.1); 7*2155Seric USXALLOC(); 8*2155Seric 9*2155Seric /* 10*2155Seric * The symbol table size is set to a limit of forty keywords per input 11*2155Seric * file. Should this limit be changed it should also be changed in the 12*2155Seric * Help file. 13*2155Seric */ 14*2155Seric 15*2155Seric # define SYMSIZE 40 16*2155Seric # define PARMSIZE 10 17*2155Seric # define NSLOTS 32 18*2155Seric 19*2155Seric # define USD 1 20*2155Seric # define DCL 2 21*2155Seric # define ASG 4 22*2155Seric 23*2155Seric # define EQ '=' 24*2155Seric # define NEQ '!' 25*2155Seric # define GT '>' 26*2155Seric # define LT '<' 27*2155Seric # define DELIM " \t" 28*2155Seric # define TRUE 1 29*2155Seric # define FALSE 0 30*2155Seric 31*2155Seric char Ctlchar ':'; 32*2155Seric 33*2155Seric struct symtab { 34*2155Seric int usage; 35*2155Seric char name[PARMSIZE]; 36*2155Seric char *value; 37*2155Seric int lenval; 38*2155Seric }; 39*2155Seric struct symtab Sym[SYMSIZE]; 40*2155Seric 41*2155Seric struct { 42*2155Seric char chr; 43*2155Seric }; 44*2155Seric 45*2155Seric int Skiptabs; 46*2155Seric int Repall; 47*2155Seric 48*2155Seric /* 49*2155Seric * Delflag is used to indicate when text is to be skipped. It is decre- 50*2155Seric * mented whenever an if condition is false, or when an if occurs 51*2155Seric * within a false if/end statement. It is decremented whenever an end is 52*2155Seric * encountered and the Delflag is greater than zero. Whenever Delflag 53*2155Seric * is greater than zero text is skipped. 54*2155Seric */ 55*2155Seric 56*2155Seric int Delflag; 57*2155Seric 58*2155Seric /* 59*2155Seric * Ifcount keeps track of the number of ifs and ends. Each time 60*2155Seric * an if is encountered Ifcount is incremented and each time an end is 61*2155Seric * encountered it is decremented. 62*2155Seric */ 63*2155Seric 64*2155Seric int Ifcount; 65*2155Seric int Lineno; 66*2155Seric 67*2155Seric char *Repflag; 68*2155Seric char *Linend; 69*2155Seric int Silent; 70*2155Seric 71*2155Seric 72*2155Seric /* 73*2155Seric * The main program reads a line of text and sends it to be processed 74*2155Seric * if it is a version control statement. If it is a line of text and 75*2155Seric * the Delflag is equal to zero, it is written to the standard output. 76*2155Seric */ 77*2155Seric 78*2155Seric main(argc, argv) 79*2155Seric int argc; 80*2155Seric char *argv[]; 81*2155Seric { 82*2155Seric register char *lineptr, *p; 83*2155Seric register int i; 84*2155Seric char line[512]; 85*2155Seric extern int Fflags; 86*2155Seric 87*2155Seric Fflags = FTLCLN | FTLMSG | FTLEXIT; 88*2155Seric setsig(); 89*2155Seric for(i = 1; i< argc; i++) { 90*2155Seric p = argv[i]; 91*2155Seric if (p[0] == '-') 92*2155Seric switch (p[1]) { 93*2155Seric case 's': 94*2155Seric Silent = 1; 95*2155Seric break; 96*2155Seric case 't': 97*2155Seric Skiptabs = 1; 98*2155Seric break; 99*2155Seric case 'a': 100*2155Seric Repall = 1; 101*2155Seric break; 102*2155Seric case 'c': 103*2155Seric Ctlchar = p[2]; 104*2155Seric break; 105*2155Seric } 106*2155Seric else { 107*2155Seric p[size(p) - 1] = '\n'; 108*2155Seric asgfunc(p); 109*2155Seric } 110*2155Seric } 111*2155Seric while (fgets(line,sizeof(line),stdin) != NULL) { 112*2155Seric lineptr = line; 113*2155Seric Lineno++; 114*2155Seric 115*2155Seric if (Repflag != 0) { 116*2155Seric free(Repflag); 117*2155Seric Repflag = 0; 118*2155Seric } 119*2155Seric 120*2155Seric if (Skiptabs) { 121*2155Seric for (p = lineptr; *p; p++) 122*2155Seric if (*p == '\t') 123*2155Seric break; 124*2155Seric if (*p++ == '\t') 125*2155Seric lineptr = p; 126*2155Seric } 127*2155Seric 128*2155Seric if (lineptr[0] != Ctlchar) { 129*2155Seric if (lineptr[0] == '\\' && lineptr[1] == Ctlchar) 130*2155Seric for (p = &lineptr[1]; *lineptr++ = *p++; ) 131*2155Seric ; 132*2155Seric if(Delflag == 0) { 133*2155Seric if (Repall) 134*2155Seric repfunc(line); 135*2155Seric else 136*2155Seric fputs(line,stdout); 137*2155Seric } 138*2155Seric continue; 139*2155Seric } 140*2155Seric 141*2155Seric lineptr++; 142*2155Seric 143*2155Seric if (imatch("if ", lineptr)) 144*2155Seric iffunc(&lineptr[3]); 145*2155Seric else if (imatch("end", lineptr)) 146*2155Seric endfunc(); 147*2155Seric else if (Delflag == 0) { 148*2155Seric if (imatch("asg ", lineptr)) 149*2155Seric asgfunc(&lineptr[4]); 150*2155Seric else if (imatch("dcl ", lineptr)) 151*2155Seric dclfunc(&lineptr[4]); 152*2155Seric else if (imatch("err", lineptr)) 153*2155Seric errfunc(&lineptr[3]); 154*2155Seric else if (imatch("msg", lineptr)) 155*2155Seric msgfunc(&lineptr[3]); 156*2155Seric else if (lineptr[0] == Ctlchar) 157*2155Seric repfunc(&lineptr[1]); 158*2155Seric else if (imatch("on", lineptr)) 159*2155Seric Repall = 1; 160*2155Seric else if (imatch("off", lineptr)) 161*2155Seric Repall = 0; 162*2155Seric else if (imatch("ctl ", lineptr)) 163*2155Seric Ctlchar = lineptr[4]; 164*2155Seric else error("unknown command on line %d (901)",Lineno); 165*2155Seric } 166*2155Seric } 167*2155Seric for(i = 0; Sym[i].usage != 0 && i<SYMSIZE; i++) { 168*2155Seric if ((Sym[i].usage&USD) == 0) 169*2155Seric warn("`%s' never used (902)\n",Sym[i].name); 170*2155Seric if ((Sym[i].usage&DCL) == 0) 171*2155Seric warn("`%s' never declared (903)\n", Sym[i].name); 172*2155Seric if ((Sym[i].usage&ASG) == 0) 173*2155Seric warn("`%s' never assigned a value (920)\n", Sym[i].name); 174*2155Seric } 175*2155Seric if (Ifcount > 0) 176*2155Seric error("`if' with no matching `end' (904)"); 177*2155Seric exit(0); 178*2155Seric } 179*2155Seric 180*2155Seric 181*2155Seric /* 182*2155Seric * Asgfunc accepts a pointer to a line picks up a keyword name, an 183*2155Seric * equal sign and a value and calls putin to place it in the symbol table. 184*2155Seric */ 185*2155Seric 186*2155Seric asgfunc(aptr) 187*2155Seric register char *aptr; 188*2155Seric { 189*2155Seric register char *end, *aname; 190*2155Seric char *avalue; 191*2155Seric 192*2155Seric aptr = replace(aptr); 193*2155Seric NONBLANK(aptr); 194*2155Seric aname = aptr; 195*2155Seric end = Linend; 196*2155Seric aptr = findstr(aptr,"= \t"); 197*2155Seric if (*aptr == ' ' || *aptr == '\t') { 198*2155Seric *aptr++ = '\0'; 199*2155Seric aptr = findch(aptr,'='); 200*2155Seric } 201*2155Seric if (aptr == end) 202*2155Seric error("syntax on line %d (917)",Lineno); 203*2155Seric *aptr++ = '\0'; 204*2155Seric avalue = getid(aptr); 205*2155Seric chksize(aname); 206*2155Seric putin(aname, avalue); 207*2155Seric } 208*2155Seric 209*2155Seric 210*2155Seric /* 211*2155Seric * Dclfunc accepts a pointer to a line and picks up keywords 212*2155Seric * separated by commas. It calls putin to put each keyword in the 213*2155Seric * symbol table. It returns when it sees a newline. 214*2155Seric */ 215*2155Seric 216*2155Seric dclfunc(dptr) 217*2155Seric register char *dptr; 218*2155Seric { 219*2155Seric register char *end, *dname; 220*2155Seric int i; 221*2155Seric 222*2155Seric dptr = replace(dptr); 223*2155Seric end = Linend; 224*2155Seric NONBLANK(dptr); 225*2155Seric while (dptr < end) { 226*2155Seric dname = dptr; 227*2155Seric dptr = findch(dptr,','); 228*2155Seric *dptr++ = '\0'; 229*2155Seric chksize(dname); 230*2155Seric if (Sym[i = lookup(dname)].usage&DCL) 231*2155Seric error("`%s' declared twice on line %d (905)", 232*2155Seric dname, Lineno); 233*2155Seric else 234*2155Seric Sym[i].usage =| DCL; 235*2155Seric NONBLANK(dptr); 236*2155Seric } 237*2155Seric } 238*2155Seric 239*2155Seric 240*2155Seric /* 241*2155Seric * Errfunc calls fatal which stops the process. 242*2155Seric */ 243*2155Seric 244*2155Seric errfunc(eptr) 245*2155Seric char *eptr; 246*2155Seric { 247*2155Seric warn("ERROR:%s\n",replace(eptr)); 248*2155Seric error("err statement on line %d (915)", Lineno); 249*2155Seric } 250*2155Seric 251*2155Seric 252*2155Seric /* 253*2155Seric * Endfunc indicates an end has been found by decrementing the if count 254*2155Seric * flag. If because of a previous if statement, text was being skipped, 255*2155Seric * Delflag is also decremented. 256*2155Seric */ 257*2155Seric 258*2155Seric endfunc() 259*2155Seric { 260*2155Seric if (--Ifcount < 0) 261*2155Seric error("`end' without matching `if' on line %d (910)",Lineno); 262*2155Seric if (Delflag > 0) 263*2155Seric Delflag--; 264*2155Seric return; 265*2155Seric } 266*2155Seric 267*2155Seric 268*2155Seric /* 269*2155Seric * Msgfunc accepts a pointer to a line and prints that line on the 270*2155Seric * diagnostic output. 271*2155Seric */ 272*2155Seric 273*2155Seric msgfunc(mptr) 274*2155Seric char *mptr; 275*2155Seric { 276*2155Seric warn("Message(%d):%s\n", Lineno, replace(mptr)); 277*2155Seric } 278*2155Seric 279*2155Seric 280*2155Seric repfunc(s) 281*2155Seric char *s; 282*2155Seric { 283*2155Seric fprintf(stdout,"%s\n",replace(s)); 284*2155Seric } 285*2155Seric 286*2155Seric 287*2155Seric /* 288*2155Seric * Iffunc and the three functions following it, door, doand, and exp 289*2155Seric * are responsible for parsing and interperting the condition in the 290*2155Seric * if statement. The BNF used is as follows: 291*2155Seric * <iffunc> ::= [ "not" ] <door> EOL 292*2155Seric * <door> ::= <doand> | <doand> "|" <door> 293*2155Seric * <doand>::= <exp> | <exp> "&" <doand> 294*2155Seric * <exp>::= "(" <door> ")" | <value> <operator> <value> 295*2155Seric * <operator>::= "=" | "!=" | "<" | ">" 296*2155Seric * And has precedence over or. If the condition is false the Delflag 297*2155Seric * is bumped to indicate that lines are to be skipped. 298*2155Seric * An external variable, sptr is used for processing the line in 299*2155Seric * iffunc, door, doand, exp, getid. 300*2155Seric * Iffunc accepts a pointer to a line and sets sptr to that line. The 301*2155Seric * rest of iffunc, door, and doand follow the BNF exactly. 302*2155Seric */ 303*2155Seric 304*2155Seric char *sptr; 305*2155Seric 306*2155Seric iffunc(iptr) 307*2155Seric char *iptr; 308*2155Seric { 309*2155Seric register int value, not; 310*2155Seric 311*2155Seric Ifcount++; 312*2155Seric if (Delflag > 0) 313*2155Seric Delflag++; 314*2155Seric 315*2155Seric else { 316*2155Seric sptr = replace(iptr); 317*2155Seric NONBLANK(sptr); 318*2155Seric if (imatch("not ", sptr)) { 319*2155Seric not = FALSE; 320*2155Seric sptr =+ 4; 321*2155Seric } 322*2155Seric else not = TRUE; 323*2155Seric 324*2155Seric value = door(); 325*2155Seric if( *sptr != 0) 326*2155Seric error("syntax on line %d (918)",Lineno); 327*2155Seric 328*2155Seric if (value != not) 329*2155Seric Delflag++; 330*2155Seric } 331*2155Seric 332*2155Seric return; 333*2155Seric } 334*2155Seric 335*2155Seric 336*2155Seric door() 337*2155Seric { 338*2155Seric int value; 339*2155Seric value = doand(); 340*2155Seric NONBLANK(sptr); 341*2155Seric while (*sptr=='|') { 342*2155Seric sptr++; 343*2155Seric value =| doand(); 344*2155Seric NONBLANK(sptr); 345*2155Seric } 346*2155Seric return(value); 347*2155Seric } 348*2155Seric 349*2155Seric 350*2155Seric doand() 351*2155Seric { 352*2155Seric int value; 353*2155Seric value = exp(); 354*2155Seric NONBLANK(sptr); 355*2155Seric while (*sptr=='&') { 356*2155Seric sptr++; 357*2155Seric value =& exp(); 358*2155Seric NONBLANK(sptr); 359*2155Seric } 360*2155Seric return(value); 361*2155Seric } 362*2155Seric 363*2155Seric 364*2155Seric /* 365*2155Seric * After exp checks for parentheses, it picks up a value by calling getid, 366*2155Seric * picks up an operator and calls getid to pick up the second value. 367*2155Seric * Then based on the operator it calls either numcomp or equal to see 368*2155Seric * if the exp is true or false and returns the correct value. 369*2155Seric */ 370*2155Seric 371*2155Seric exp() 372*2155Seric { 373*2155Seric register char op, save; 374*2155Seric register int value; 375*2155Seric char *id1, *id2, next; 376*2155Seric 377*2155Seric NONBLANK(sptr); 378*2155Seric if(*sptr == '(') { 379*2155Seric sptr++; 380*2155Seric value = door(); 381*2155Seric NONBLANK(sptr); 382*2155Seric if (*sptr == ')') { 383*2155Seric sptr++; 384*2155Seric return(value); 385*2155Seric } 386*2155Seric else error("parenthesis error on line %d (911)",Lineno); 387*2155Seric } 388*2155Seric 389*2155Seric id1 = getid(sptr); 390*2155Seric if (op = *sptr) 391*2155Seric *sptr++ = '\0'; 392*2155Seric if (op == NEQ && (next = *sptr++) == '\0') 393*2155Seric --sptr; 394*2155Seric id2 = getid(sptr); 395*2155Seric save = *sptr; 396*2155Seric *sptr = '\0'; 397*2155Seric 398*2155Seric if(op ==LT || op == GT) { 399*2155Seric value = numcomp(id1, id2); 400*2155Seric if ((op == GT && value == 1) || (op == LT && value == -1)) 401*2155Seric value = TRUE; 402*2155Seric else value = FALSE; 403*2155Seric } 404*2155Seric 405*2155Seric else if (op==EQ || (op==NEQ && next==EQ)) { 406*2155Seric value = equal(id1, id2); 407*2155Seric if ( op == NEQ) 408*2155Seric value = !value; 409*2155Seric } 410*2155Seric 411*2155Seric else error("invalid operator on line %d (912)", Lineno); 412*2155Seric *sptr = save; 413*2155Seric return(value); 414*2155Seric } 415*2155Seric 416*2155Seric 417*2155Seric /* 418*2155Seric * Getid picks up a value off a line and returns a pointer to the value. 419*2155Seric */ 420*2155Seric 421*2155Seric getid(gptr) 422*2155Seric register char *gptr; 423*2155Seric { 424*2155Seric register char c, *id; 425*2155Seric 426*2155Seric NONBLANK(gptr); 427*2155Seric id = gptr; 428*2155Seric gptr = findstr(gptr,DELIM); 429*2155Seric if (*gptr) 430*2155Seric *gptr++ = '\0'; 431*2155Seric NONBLANK(gptr); 432*2155Seric sptr = gptr; 433*2155Seric return(id); 434*2155Seric } 435*2155Seric 436*2155Seric 437*2155Seric /* 438*2155Seric * Numcomp accepts two pointers to strings of digits and calls numck 439*2155Seric * to see if the strings contain only digits. It returns -1 if 440*2155Seric * the first is less than the second, 1 if the first is greater than the 441*2155Seric * second and 0 if the two are equal. 442*2155Seric */ 443*2155Seric 444*2155Seric numcomp(id1, id2) 445*2155Seric register char *id1, *id2; 446*2155Seric { 447*2155Seric int k1, k2; 448*2155Seric 449*2155Seric numck(id1); 450*2155Seric numck(id2); 451*2155Seric while (*id1 == '0') 452*2155Seric id1++; 453*2155Seric while (*id2 == '0') 454*2155Seric id2++; 455*2155Seric if ((k1 = size(id1)) > (k2 = size(id2))) 456*2155Seric return(1); 457*2155Seric else if (k1 < k2) 458*2155Seric return(-1); 459*2155Seric else while(*id1 != '\0') { 460*2155Seric if(*id1 > *id2) 461*2155Seric return(1); 462*2155Seric else if(*id1 < *id2) 463*2155Seric return(-1); 464*2155Seric id1++; 465*2155Seric id2++; 466*2155Seric } 467*2155Seric return(0); 468*2155Seric } 469*2155Seric 470*2155Seric 471*2155Seric /* 472*2155Seric * Numck accepts a pointer to a string and checks to see if they are 473*2155Seric * all digits. If they're not it calls fatal, otherwise it returns. 474*2155Seric */ 475*2155Seric 476*2155Seric numck(nptr) 477*2155Seric register char *nptr; 478*2155Seric { 479*2155Seric for (; *nptr != '\0'; nptr++) 480*2155Seric if (!numeric(*nptr)) 481*2155Seric error("non-numerical value on line %d (914)",Lineno); 482*2155Seric return; 483*2155Seric } 484*2155Seric 485*2155Seric 486*2155Seric /* 487*2155Seric * Replace accepts a pointer to a line and scans the line for a keyword 488*2155Seric * enclosed in control characters. If it doesn't find one it returns 489*2155Seric * a pointer to the begining of the line. Otherwise, it calls 490*2155Seric * lookup to find the keyword. 491*2155Seric * It rewrites the line substituting the value for the 492*2155Seric * keyword enclosed in control characters. It then continues scanning 493*2155Seric * the line until no control characters are found and returns a pointer to 494*2155Seric * the begining of the new line. 495*2155Seric */ 496*2155Seric 497*2155Seric # define INCR(int) if (++int==NSLOTS) error(subrng,Lineno) 498*2155Seric char *subrng "out of space [line %d] (916)"; 499*2155Seric 500*2155Seric replace(ptr) 501*2155Seric char *ptr; 502*2155Seric { 503*2155Seric char *slots[NSLOTS]; 504*2155Seric int i,j,newlen; 505*2155Seric register char *s, *t, *p; 506*2155Seric 507*2155Seric for (s=ptr; *s++!='\n';); 508*2155Seric *(--s) = '\0'; 509*2155Seric Linend = s; 510*2155Seric i = -1; 511*2155Seric for (p=ptr; *(s=findch(p,Ctlchar)); p=t) { 512*2155Seric *s++ = '\0'; 513*2155Seric INCR(i); 514*2155Seric slots[i] = p; 515*2155Seric if (*(t=findch(s,Ctlchar))==0) 516*2155Seric error("unmatched `%c' on line %d (907)",Ctlchar,Lineno); 517*2155Seric *t++ = '\0'; 518*2155Seric INCR(i); 519*2155Seric slots[i] = Sym[j = lookup(s)].value; 520*2155Seric Sym[j].usage =| USD; 521*2155Seric } 522*2155Seric INCR(i); 523*2155Seric slots[i] = p; 524*2155Seric if (i==0) return(ptr); 525*2155Seric newlen = 0; 526*2155Seric for (j=0; j<=i; j++) 527*2155Seric newlen =+ (size(slots[j])-1); 528*2155Seric t = Repflag = alloc(++newlen); 529*2155Seric for (j=0; j<=i; j++) 530*2155Seric t = ecopy(slots[j],t); 531*2155Seric Linend = t; 532*2155Seric return(Repflag); 533*2155Seric } 534*2155Seric 535*2155Seric 536*2155Seric /* 537*2155Seric * Lookup accepts a pointer to a keyword name and searches the symbol 538*2155Seric * table for the keyword. It returns its index in the table if its there, 539*2155Seric * otherwise it puts the keyword in the table. 540*2155Seric */ 541*2155Seric 542*2155Seric lookup(lname) 543*2155Seric char *lname; 544*2155Seric { 545*2155Seric register int i; 546*2155Seric register char *t; 547*2155Seric register struct symtab *s; 548*2155Seric 549*2155Seric t = lname; 550*2155Seric while ((i.chr = *t++) && 551*2155Seric ((i.chr>='A' && i.chr<='Z') || (i.chr>='a' && i.chr<='z') || 552*2155Seric (i.chr!= *lname && i.chr>='0' && i.chr<='9'))); 553*2155Seric if (i.chr) 554*2155Seric error("invalid keyword name on line %d (909)",Lineno); 555*2155Seric 556*2155Seric for(i =0; Sym[i].usage != 0 && i<SYMSIZE; i++) 557*2155Seric if (equal(lname, Sym[i].name)) return(i); 558*2155Seric s = &Sym[i]; 559*2155Seric if (s->usage == 0) { 560*2155Seric copy(lname,s->name); 561*2155Seric copy("",(s->value = alloc(s->lenval = 1))); 562*2155Seric return(i); 563*2155Seric } 564*2155Seric error("out of space (906)"); 565*2155Seric } 566*2155Seric 567*2155Seric 568*2155Seric /* 569*2155Seric * Putin accepts a pointer to a keyword name, and a pointer to a value. 570*2155Seric * It puts this information in the symbol table by calling lookup. 571*2155Seric * It returns the index of the name in the table. 572*2155Seric */ 573*2155Seric 574*2155Seric putin(pname, pvalue) 575*2155Seric char *pname; 576*2155Seric char *pvalue; 577*2155Seric { 578*2155Seric register int i; 579*2155Seric register struct symtab *s; 580*2155Seric 581*2155Seric s = &Sym[i = lookup(pname)]; 582*2155Seric free(s->value); 583*2155Seric s->lenval = size(pvalue); 584*2155Seric copy(pvalue, (s->value = alloc(s->lenval))); 585*2155Seric s->usage =| ASG; 586*2155Seric return(i); 587*2155Seric } 588*2155Seric 589*2155Seric 590*2155Seric chksize(s) 591*2155Seric char *s; 592*2155Seric { 593*2155Seric if (size(s) > PARMSIZE) 594*2155Seric error("keyword name too long on line %d (908)",Lineno); 595*2155Seric } 596*2155Seric 597*2155Seric 598*2155Seric findch(astr,match) 599*2155Seric char *astr, match; 600*2155Seric { 601*2155Seric register char *s, *t, c; 602*2155Seric char *temp; 603*2155Seric 604*2155Seric for (s=astr; (c = *s) && c!=match; s++) 605*2155Seric if (c=='\\') { 606*2155Seric if (s[1]==0) 607*2155Seric error("syntax on line %d (919)",Lineno); 608*2155Seric else { 609*2155Seric for (t = (temp=s) + 1; *s++ = *t++;); 610*2155Seric s = temp; 611*2155Seric } 612*2155Seric } 613*2155Seric return(s); 614*2155Seric } 615*2155Seric 616*2155Seric 617*2155Seric ecopy(s1,s2) 618*2155Seric char *s1, *s2; 619*2155Seric { 620*2155Seric register char *r1, *r2; 621*2155Seric 622*2155Seric r1 = s1; 623*2155Seric r2 = s2; 624*2155Seric while (*r2++ = *r1++); 625*2155Seric return(--r2); 626*2155Seric } 627*2155Seric 628*2155Seric 629*2155Seric error(arg) 630*2155Seric { 631*2155Seric fatal(sprintf(Error,"%r",&arg)); 632*2155Seric } 633*2155Seric 634*2155Seric 635*2155Seric findstr(astr,pat) 636*2155Seric char *astr, *pat; 637*2155Seric { 638*2155Seric register char *s, *t, c; 639*2155Seric char *temp; 640*2155Seric 641*2155Seric for (s=astr; (c = *s) && any(c,pat)==0; s++) 642*2155Seric if (c=='\\') { 643*2155Seric if (s[1]==0) 644*2155Seric error("syntax on line %d (919)",Lineno); 645*2155Seric else { 646*2155Seric for (t = (temp=s) + 1; *s++ = *t++;); 647*2155Seric s = temp; 648*2155Seric } 649*2155Seric } 650*2155Seric return(s); 651*2155Seric } 652*2155Seric 653*2155Seric 654*2155Seric warn(arg) 655*2155Seric { 656*2155Seric if (!Silent) 657*2155Seric fprintf(stderr,"%r",&arg); 658*2155Seric } 659