1*19573Smckusick /* 2*19573Smckusick * Copyright (c) 1979 Regents of the University of California. 3*19573Smckusick * All rights reserved. The Berkeley software License Agreement 4*19573Smckusick * specifies the terms and conditions for redistribution. 5*19573Smckusick */ 6*19573Smckusick 7*19573Smckusick #ifndef lint 8*19573Smckusick static char sccsid[] = "@(#)ey4.c 5.1 (Berkeley) 04/29/85"; 9*19573Smckusick #endif not lint 10*19573Smckusick 11*19573Smckusick # include "ey.h" 12*19573Smckusick 13*19573Smckusick output(){ /* print the output for the states */ 14*19573Smckusick 15*19573Smckusick int i, j, k, c; 16*19573Smckusick 17*19573Smckusick settab(); 18*19573Smckusick arrset("yyact"); 19*19573Smckusick 20*19573Smckusick for( i=0; i<nstate; ++i ){ /* output the stuff for state i */ 21*19573Smckusick nolook = (tystate[i]==0); 22*19573Smckusick closure(i); 23*19573Smckusick /* output actions */ 24*19573Smckusick aryfil( temp1, nterms+1, 0 ); 25*19573Smckusick for( j=0; j<cwset; ++j ){ /* look at the items */ 26*19573Smckusick c = *( wsets[j].pitem ); 27*19573Smckusick if( c>0 && c<NTBASE && temp1[c]==0 ) temp1[c] = go2(i,c); 28*19573Smckusick } 29*19573Smckusick 30*19573Smckusick if( i == 1 ) temp1[1] = ACCEPTCODE; 31*19573Smckusick 32*19573Smckusick /* now, we have the shifts; look at the reductions */ 33*19573Smckusick 34*19573Smckusick lastred = 0; 35*19573Smckusick for( j=0; j<cwset; ++j ){ 36*19573Smckusick c = *( wsets[j].pitem ); 37*19573Smckusick if( c<=0 ){ /* reduction */ 38*19573Smckusick lastred = -c; 39*19573Smckusick for( k=1; k<=nterms; ++k ){ 40*19573Smckusick if( ((wsets[j].ws[k>>4])&(1<<(k&017))) != 0 ) { 41*19573Smckusick if( temp1[k] == 0 ) temp1[k] = c; 42*19573Smckusick else if( temp1[k]<0 ){ /* reduce/reduce conflict */ 43*19573Smckusick settty(); 44*19573Smckusick fprintf( cout , "\n%d: reduce/reduce conflict (red'ns %d and %d ) on %s", 45*19573Smckusick i, -temp1[k], lastred, symnam(k) ); 46*19573Smckusick if( -temp1[k] > lastred ) temp1[k] = -lastred; 47*19573Smckusick ++zzrrconf; 48*19573Smckusick settab(); 49*19573Smckusick } 50*19573Smckusick else { /* potential shift/reduce conflict */ 51*19573Smckusick switch( precftn( lastred, k ) ) { 52*19573Smckusick 53*19573Smckusick case 0: /* precedence does not apply */ 54*19573Smckusick 55*19573Smckusick settty(); 56*19573Smckusick fprintf( cout , "\n%d: shift/reduce conflict (shift %d, red'n %d) on %s", i, 57*19573Smckusick temp1[k], lastred, symnam(k) ); 58*19573Smckusick ++zzsrconf; 59*19573Smckusick settab(); 60*19573Smckusick /* resolve in favor of shifting, so remove from reduce set */ 61*19573Smckusick wsets[j].ws[k>>4] &=~ (1<<(k&017)); 62*19573Smckusick break; 63*19573Smckusick 64*19573Smckusick case 1: /* reduce */ 65*19573Smckusick 66*19573Smckusick temp1[k] = -lastred; 67*19573Smckusick break; 68*19573Smckusick 69*19573Smckusick case 2: /* error, binary operator */ 70*19573Smckusick 71*19573Smckusick temp1[k] = ERRCODE; 72*19573Smckusick break; 73*19573Smckusick 74*19573Smckusick case 3: /* shift ... leave the entry alone */ 75*19573Smckusick 76*19573Smckusick break; 77*19573Smckusick } 78*19573Smckusick } 79*19573Smckusick } 80*19573Smckusick } 81*19573Smckusick } 82*19573Smckusick } 83*19573Smckusick wract(i); 84*19573Smckusick } 85*19573Smckusick 86*19573Smckusick settab(); 87*19573Smckusick arrdone(); 88*19573Smckusick 89*19573Smckusick /* now, output the pointers to the action array */ 90*19573Smckusick /* also output the info about reductions */ 91*19573Smckusick prred(); 92*19573Smckusick } 93*19573Smckusick 94*19573Smckusick prred(){ /* print the information about the actions and the reductions */ 95*19573Smckusick int index, i; 96*19573Smckusick 97*19573Smckusick arrset("yypact"); 98*19573Smckusick index = 1; /* position in the output table */ 99*19573Smckusick 100*19573Smckusick for( i=0; i<nstate; ++i ){ 101*19573Smckusick if( tystate[i]>0 ){ /* the state is real */ 102*19573Smckusick temp1[i] = index; 103*19573Smckusick arrval( index ); 104*19573Smckusick index += tystate[i]; 105*19573Smckusick } 106*19573Smckusick else { 107*19573Smckusick arrval( temp1[-tystate[i]] ); 108*19573Smckusick } 109*19573Smckusick } 110*19573Smckusick 111*19573Smckusick arrdone(); 112*19573Smckusick 113*19573Smckusick arrset("yyr1"); 114*19573Smckusick for( i=1; i<nprod; ++i ) arrval( *prdptr[i] - NTBASE ); 115*19573Smckusick arrdone(); 116*19573Smckusick 117*19573Smckusick arrset("yyr2"); 118*19573Smckusick for( i=1; i<nprod; ++i ) arrval( ( prdptr[i+1]-prdptr[i]-2 ) ); 119*19573Smckusick arrdone(); 120*19573Smckusick 121*19573Smckusick } 122*19573Smckusick 123*19573Smckusick go2(i,c){ /* do a goto on the closure state, not worrying about lookaheads */ 124*19573Smckusick if( c<NTBASE ) return( amem[ apstate[i]+c ] ); 125*19573Smckusick else return( amem[ apstate[i] + c - NTBASE + nterms ] ); 126*19573Smckusick } 127*19573Smckusick 128*19573Smckusick int pkdebug = 0; 129*19573Smckusick apack(p, n ) int *p;{ /* pack state i from temp1 into amem */ 130*19573Smckusick _REGISTER k, l, off; 131*19573Smckusick int j; 132*19573Smckusick 133*19573Smckusick /* find the spot */ 134*19573Smckusick 135*19573Smckusick j = n; 136*19573Smckusick for( off = 0; off <= j && p[off] == 0; ++off ) ; 137*19573Smckusick if( off > j ){ /* no actions */ 138*19573Smckusick return(0); 139*19573Smckusick } 140*19573Smckusick j -= off; 141*19573Smckusick for( k=0; k<actsiz; ++k ){ 142*19573Smckusick for( l=0; l<=j; ++l ){ 143*19573Smckusick if( p[off+l] != 0 ){ 144*19573Smckusick if( p[off+l] != amem[k+l] && amem[k+l] != 0 ) goto nextk; 145*19573Smckusick } 146*19573Smckusick } 147*19573Smckusick if( pkdebug ){ settty(); fprintf( cout , "off = %d, k = %d\n", off, k ); } 148*19573Smckusick /* we have found an acceptable k */ 149*19573Smckusick for( l=0; l<=j; ++l ){ 150*19573Smckusick if( p[off+l] ){ 151*19573Smckusick if( k+l >= actsiz ) error("action table overflow"); 152*19573Smckusick if( k+l >= memact ) memact = k+l; 153*19573Smckusick amem[k+l] = p[off+l]; 154*19573Smckusick } 155*19573Smckusick } 156*19573Smckusick if( pkdebug ){ 157*19573Smckusick for( k=0; k<memact; k+=10){ 158*19573Smckusick fprintf( cout , "\t"); 159*19573Smckusick for( l=0; l<=9; ++l ) fprintf( cout , "%d ", amem[k+l] ); 160*19573Smckusick fprintf( cout , "\n"); 161*19573Smckusick } 162*19573Smckusick } 163*19573Smckusick return(k-off); 164*19573Smckusick 165*19573Smckusick nextk: ; 166*19573Smckusick } 167*19573Smckusick error("no space in action table"); 168*19573Smckusick } 169*19573Smckusick 170*19573Smckusick go2out(){ /* output the gotos for the nontermninals */ 171*19573Smckusick int i, j, k, best, offset, count, cbest, times; 172*19573Smckusick 173*19573Smckusick settab(); 174*19573Smckusick arrset("yygo"); 175*19573Smckusick offset = 1; 176*19573Smckusick 177*19573Smckusick for( i=1; i<=nnonter; ++i ) { 178*19573Smckusick go2gen(i); 179*19573Smckusick 180*19573Smckusick /* find the best one to make default */ 181*19573Smckusick 182*19573Smckusick temp2[i] = offset; 183*19573Smckusick 184*19573Smckusick best = -1; 185*19573Smckusick times = 0; 186*19573Smckusick 187*19573Smckusick for( j=0; j<=nstate; ++j ){ /* is j the most frequent */ 188*19573Smckusick if( tystate[j] == 0 ) continue; 189*19573Smckusick if( tystate[j] == best ) continue; 190*19573Smckusick 191*19573Smckusick /* is tystate[j] the most frequent */ 192*19573Smckusick 193*19573Smckusick count = 0; 194*19573Smckusick cbest = tystate[j]; 195*19573Smckusick 196*19573Smckusick for( k=j; k<=nstate; ++k ) if( tystate[k]==cbest ) ++count; 197*19573Smckusick 198*19573Smckusick if( count > times ){ 199*19573Smckusick best = cbest; 200*19573Smckusick times = count; 201*19573Smckusick } 202*19573Smckusick } 203*19573Smckusick 204*19573Smckusick /* best is now the default entry */ 205*19573Smckusick 206*19573Smckusick zzgobest += (times-1)*2; 207*19573Smckusick settab(); 208*19573Smckusick for( j=0; j<=nstate; ++j ){ 209*19573Smckusick if( tystate[j] != 0 && tystate[j]!=best ){ 210*19573Smckusick arrval( j ); 211*19573Smckusick arrval( tystate[j] ); 212*19573Smckusick offset += 2; 213*19573Smckusick zzgoent += 2; 214*19573Smckusick } 215*19573Smckusick } 216*19573Smckusick 217*19573Smckusick /* now, the default */ 218*19573Smckusick 219*19573Smckusick zzgoent += 2; 220*19573Smckusick arrval( -1 ); 221*19573Smckusick arrval( best ); 222*19573Smckusick offset += 2; 223*19573Smckusick 224*19573Smckusick } 225*19573Smckusick 226*19573Smckusick arrdone(); 227*19573Smckusick 228*19573Smckusick arrset("yypgo"); 229*19573Smckusick for( i=1; i<=nnonter; ++i ) arrval( temp2[i] ); 230*19573Smckusick arrdone(); 231*19573Smckusick 232*19573Smckusick } 233*19573Smckusick 234*19573Smckusick int g2debug = 0; 235*19573Smckusick go2gen(c){ /* output the gotos for nonterminal c */ 236*19573Smckusick 237*19573Smckusick int i, work, cc; 238*19573Smckusick struct item *p, *q; 239*19573Smckusick 240*19573Smckusick /* first, find nonterminals with gotos on c */ 241*19573Smckusick 242*19573Smckusick aryfil( temp1, nnonter+1, 0 ); 243*19573Smckusick temp1[c] = 1; 244*19573Smckusick 245*19573Smckusick work = 1; 246*19573Smckusick while( work ){ 247*19573Smckusick work = 0; 248*19573Smckusick for( i=0; i<nprod; ++i ){ 249*19573Smckusick if( (cc=prdptr[i][1]-NTBASE) >= 0 ){ /* cc is a nonterminal */ 250*19573Smckusick if( temp1[cc] != 0 ){ /* cc has a goto on c */ 251*19573Smckusick cc = *prdptr[i]-NTBASE; /* thus, the left side of production i does too */ 252*19573Smckusick if( temp1[cc] == 0 ){ 253*19573Smckusick work = 1; 254*19573Smckusick temp1[cc] = 1; 255*19573Smckusick } 256*19573Smckusick } 257*19573Smckusick } 258*19573Smckusick } 259*19573Smckusick } 260*19573Smckusick 261*19573Smckusick /* now, we have temp1[c] = 1 if a goto on c in closure of cc */ 262*19573Smckusick 263*19573Smckusick if( g2debug ){ 264*19573Smckusick settty(); 265*19573Smckusick fprintf( cout , "%s: gotos on ", nontrst[c].name ); 266*19573Smckusick for( i=0; i<=nnonter; ++i ) if( temp1[i]) fprintf( cout , "%s ", nontrst[i].name); 267*19573Smckusick fprintf( cout , "\n"); 268*19573Smckusick } 269*19573Smckusick 270*19573Smckusick /* now, go through and put gotos into tystate */ 271*19573Smckusick 272*19573Smckusick aryfil( tystate, nstate, 0 ); 273*19573Smckusick settty(); 274*19573Smckusick fprintf( cout , "\nnonterminal %s\n", nontrst[c].name ); 275*19573Smckusick for( i=0; i<nstate; ++i ){ 276*19573Smckusick q = pstate[i+1]; 277*19573Smckusick for( p=pstate[i]; p<q; ++p ){ 278*19573Smckusick if( (cc= *p->pitem) >= NTBASE ){ 279*19573Smckusick if( temp1[cc -= NTBASE] ){ /* goto on c is possible */ 280*19573Smckusick tystate[i] = amem[indgo[i]+c]; 281*19573Smckusick break; 282*19573Smckusick } 283*19573Smckusick } 284*19573Smckusick } 285*19573Smckusick if( tystate[i] ) fprintf( cout , "\t%d\t%d\n", i, tystate[i]); 286*19573Smckusick } 287*19573Smckusick } 288*19573Smckusick 289*19573Smckusick precftn(r,t){ /* decide a shift/reduce conflict by precedence. 290*19573Smckusick Returns 0 if action is 'do nothing',1 if action is reduce, 291*19573Smckusick 2 if the action is 'error,binary operator' 292*19573Smckusick and 3 if the action is 'reduce'. */ 293*19573Smckusick 294*19573Smckusick int lp,lt; 295*19573Smckusick lp = levprd[r]; 296*19573Smckusick lt = trmlev[t]; 297*19573Smckusick if ((lt==0)||((lp&03)==0))return(0); 298*19573Smckusick if((lt>>3) == (lp>>3)){ 299*19573Smckusick return(lt&03); 300*19573Smckusick } 301*19573Smckusick if((lt>>3) > (lp>>3)) return(3); 302*19573Smckusick return(1); 303*19573Smckusick } 304*19573Smckusick 305*19573Smckusick int cdebug = 0; /* debug for common states */ 306*19573Smckusick wract(i){ /* output state i */ 307*19573Smckusick /* temp1 has the actions, lastred the default */ 308*19573Smckusick int p, p0, p1, size; 309*19573Smckusick int ntimes, tred, count, j, k; 310*19573Smckusick struct item *q0, *q1; 311*19573Smckusick 312*19573Smckusick /* find the best choice for lastred */ 313*19573Smckusick 314*19573Smckusick lastred = 0; 315*19573Smckusick ntimes = 0; 316*19573Smckusick stateflags[i] = 0; 317*19573Smckusick /***** UCB MOD - full state spec if shift on error *****/ 318*19573Smckusick if (temp1[2] > 0) 319*19573Smckusick stateflags[i] |= NEEDSREDUCE; 320*19573Smckusick else for( j=1; j<=nterms; ++j ){ 321*19573Smckusick /* find the entry on which the greatest number of reductions are done */ 322*19573Smckusick if( temp1[j] >= 0 ) continue; 323*19573Smckusick if( temp1[j]+lastred == 0 ) continue; 324*19573Smckusick /* count the number of appearances of temp1[j] */ 325*19573Smckusick count = 0; 326*19573Smckusick tred = -temp1[j]; 327*19573Smckusick for( p=1; p<=nterms; ++p ){ 328*19573Smckusick if( temp1[p]+tred == 0 ) ++count; 329*19573Smckusick } 330*19573Smckusick if( count >ntimes ){ 331*19573Smckusick lastred = tred; 332*19573Smckusick ntimes = count; 333*19573Smckusick } 334*19573Smckusick } 335*19573Smckusick 336*19573Smckusick /* clear out entries in temp1 which equal lastred */ 337*19573Smckusick /* ie, make the most frequent reduction into the default reduction */ 338*19573Smckusick for( p=1; p<= nterms; ++p ) if( temp1[p]+lastred == 0 )temp1[p]=0; 339*19573Smckusick 340*19573Smckusick /* write out the state */ 341*19573Smckusick 342*19573Smckusick /* first, check for equality with another state */ 343*19573Smckusick /* see if there is a nonterminal with all dots before it, */ 344*19573Smckusick /* and no reductions in the state */ 345*19573Smckusick /* this is done by checking if all items are the same non-terminal */ 346*19573Smckusick p0 = 0; 347*19573Smckusick q1 = pstate[i+1]; 348*19573Smckusick for( q0=pstate[i]; q0<q1; ++q0 ){ 349*19573Smckusick if( (p1= *(q0->pitem) ) < NTBASE ) goto standard; 350*19573Smckusick if( p0 == 0 ) p0 = p1; 351*19573Smckusick else if( p0 != p1 ) goto standard; 352*19573Smckusick } 353*19573Smckusick stateflags[i] |= SINGLE_NT | pempty[p0 - NTBASE]; 354*19573Smckusick 355*19573Smckusick /* now, all items have dots before p0 */ 356*19573Smckusick if( cdebug ){ 357*19573Smckusick settty(); 358*19573Smckusick fprintf( cout , "state %d, pre-nonterminal %s\n",i,nontrst[p0-NTBASE].name); 359*19573Smckusick } 360*19573Smckusick 361*19573Smckusick for( j=0; j<i; ++j ){ 362*19573Smckusick /* 363*19573Smckusick * check that the states have the same shift lookaheads. 364*19573Smckusick */ 365*19573Smckusick if( apstate[i] != apstate[j] ) 366*19573Smckusick continue; 367*19573Smckusick if (cdebug) 368*19573Smckusick fprintf(cout, "states %d and %d have same shift lookaheads\n",i,j); 369*19573Smckusick 370*19573Smckusick /* 371*19573Smckusick * Check that state has one item, and that the item matches. 372*19573Smckusick */ 373*19573Smckusick if ((stateflags[j] & SINGLE_NT) == 0 || *(pstate[j]->pitem) != p0) 374*19573Smckusick continue; 375*19573Smckusick 376*19573Smckusick /* 377*19573Smckusick * Check that enumeration and reduce lookaheads are the same. 378*19573Smckusick */ 379*19573Smckusick if ((stateflags[i]&(GENLAMBDA|NEEDSREDUCE)) == (GENLAMBDA|NEEDSREDUCE)) { 380*19573Smckusick /* 381*19573Smckusick * p0 derives lambda. 382*19573Smckusick * state[i] needs full reduce lookahead 383*19573Smckusick * state[j] has full reduce lookahead 384*19573Smckusick */ 385*19573Smckusick if ((stateflags[j] & NEEDSREDUCE) == 0) 386*19573Smckusick error("state %d does not need full reduce", j); 387*19573Smckusick if (lambdarule < 0) 388*19573Smckusick error("missing lambda rule definition in state %d", i); 389*19573Smckusick if (lookstate[j] == 0) 390*19573Smckusick error("state %d lookahead was not saved", j); 391*19573Smckusick /* must check lookaheads */ 392*19573Smckusick for (k = 0; k < tbitset; ++k) 393*19573Smckusick if (lastate[lookstate[j]].lset[k] != wsets[lambdarule].ws[k]) 394*19573Smckusick /* cannot merge states */ goto nextj; 395*19573Smckusick } 396*19573Smckusick 397*19573Smckusick /* we have a match with state j ! */ 398*19573Smckusick 399*19573Smckusick if( cdebug ){ 400*19573Smckusick settty(); 401*19573Smckusick fprintf( cout , "state %d matches state %d\n", i, j); 402*19573Smckusick } 403*19573Smckusick tystate[i] = -j; 404*19573Smckusick zzacsave += tystate[j]; 405*19573Smckusick zznsave++; 406*19573Smckusick wrstate(i); 407*19573Smckusick /* merged, so no need for future consideration */ 408*19573Smckusick stateflags[i] = 0; 409*19573Smckusick return; 410*19573Smckusick 411*19573Smckusick nextj: ; 412*19573Smckusick } 413*19573Smckusick 414*19573Smckusick 415*19573Smckusick standard: 416*19573Smckusick tystate[i] = 2; 417*19573Smckusick wrstate(i); 418*19573Smckusick if ((stateflags[i] & (SINGLE_NT|NEEDSREDUCE|GENLAMBDA)) == 419*19573Smckusick (SINGLE_NT|NEEDSREDUCE|GENLAMBDA)) { 420*19573Smckusick if (savedlook + 1 >= maxlastate) { 421*19573Smckusick settty(); 422*19573Smckusick fprintf(cout, 423*19573Smckusick "Warning: _maxlastate too small (%d), state packing impared\n", 424*19573Smckusick maxlastate); 425*19573Smckusick /* cannot consider future merger with this state */ 426*19573Smckusick stateflags[i] = 0; 427*19573Smckusick } else { 428*19573Smckusick if( cdebug ){ 429*19573Smckusick settty(); 430*19573Smckusick fprintf( cout , "save lookahead for state %d\n", i); 431*19573Smckusick } 432*19573Smckusick lookstate[i] = savedlook; 433*19573Smckusick for (k = 0; k < tbitset; ++k) 434*19573Smckusick lastate[savedlook].lset[k] = wsets[lambdarule].ws[k]; 435*19573Smckusick savedlook++; 436*19573Smckusick } 437*19573Smckusick } 438*19573Smckusick 439*19573Smckusick size = 0; 440*19573Smckusick for( p0=1; p0<=nterms; ++p0 ) 441*19573Smckusick if( (p1=temp1[p0])!=0 ) { 442*19573Smckusick /***** UCB MOD - test actions are negative of symbol to be tested 443*19573Smckusick this speeds up the parser as it is easy to check for 444*19573Smckusick *****/ 445*19573Smckusick arrval( -trmset[p0].value ); 446*19573Smckusick if( p1 < 0 ) arrval( REDUCACT - p1 ); 447*19573Smckusick else if( p1 == ACCEPTCODE ) arrval( ACCEPTACT ); 448*19573Smckusick else if( p1 == ERRCODE ) arrval( ERRACT ); 449*19573Smckusick else arrval( SHIFTACT + p1 ); 450*19573Smckusick size += 2; 451*19573Smckusick } 452*19573Smckusick if( lastred ) arrval( REDUCACT + lastred ); 453*19573Smckusick else arrval( ERRACT ); 454*19573Smckusick tystate[i] = size+1; /* store entry size in tystate */ 455*19573Smckusick zzacent += (size+1); 456*19573Smckusick return; 457*19573Smckusick } 458*19573Smckusick 459*19573Smckusick wrstate(i){ /* writes state i */ 460*19573Smckusick int j0,j1,s; 461*19573Smckusick struct item *pp, *qq; 462*19573Smckusick settty(); 463*19573Smckusick fprintf( cout , "\nstate %d\n",i); 464*19573Smckusick qq = pstate[i+1]; 465*19573Smckusick for( pp=pstate[i]; pp<qq; ++pp) fprintf( cout , "\t%s\n", writem(pp)); 466*19573Smckusick 467*19573Smckusick /* check for state equal to another */ 468*19573Smckusick 469*19573Smckusick if( tystate[i] <= 0 ){ 470*19573Smckusick fprintf( cout , "\n\tsame as %d\n\n", -tystate[i] ); 471*19573Smckusick return; 472*19573Smckusick } 473*19573Smckusick 474*19573Smckusick for( j0=1; j0<=nterms; ++j0 ) if( (j1=temp1[j0]) != 0 ){ 475*19573Smckusick fprintf( cout , "\n\t%s ", symnam(j0) ); 476*19573Smckusick if( j1>0 ){ /* shift, error, or accept */ 477*19573Smckusick if( j1 == ACCEPTCODE ) fprintf( cout , "accept" ); 478*19573Smckusick else if( j1 == ERRCODE ) fprintf( cout , "error" ); 479*19573Smckusick else fprintf( cout , "shift %d", j1 ); 480*19573Smckusick } 481*19573Smckusick else fprintf( cout , "reduce %d",-j1 ); 482*19573Smckusick } 483*19573Smckusick 484*19573Smckusick /* output the final production */ 485*19573Smckusick 486*19573Smckusick if( lastred ) fprintf( cout , "\n\t. reduce %d\n\n", lastred ); 487*19573Smckusick else fprintf( cout , "\n\t. error\n\n" ); 488*19573Smckusick 489*19573Smckusick ret: 490*19573Smckusick settab(); 491*19573Smckusick } 492