1File: SYMT.C Page 1 1 /* 2 Copyright 1981 3 Alcyon Corporation 4 8716 Production Ave. 5 San Diego, Ca. 92121 6 */ 7 8 #include "as68.h" 9 10 /* symbol table and misc routines*/ 11 12 int errno; 13 char *ermsg[]; 14 char tfilname[]; 15 char initfnam[]; 16 char ldfn[]; 17 char tlab1[]; 18 int stdofd; 19 int ftudp; 20 int poslab; 21 22 /*output it for beginning of statement*/ 23 opitb() 24 { 25 stbuf[0].itty = ITBS; /*beginning of statement*/ 26 stbuf[0].itop = (fchr!=EOLC) ? absln : absln-1; 27 stbuf[1].itty = ITSY; /*label entry*/ 28 stbuf[1].itop.ptrw2 = lblpt; /*pointer to symbol or 0*/ 29 30 /*put opcode in it buffer*/ 31 stbuf[2].itty = ITSY; 32 stbuf[2].itrl = modelen; /*mode of instr(byte, word, long)*/ 33 stbuf[2].itop.ptrw2 = opcpt; /*pointer to opcode in main table*/ 34 stbuf[3].itty = ITCN; 35 stbuf[3].itrl = rlflg; /*relocation base*/ 36 stbuf[3].itop = loctr; /*pass1 location counter*/ 37 itwc = ITOP1; /*next available slot-currently 4*/ 38 pitw = &stbuf[ITOP1].itty; /*init the pointer*/ 39 } 40 41 /* 42 * get an input term (symbol, constant, or special character) 43 * call with: 44 * the first character in fchr 45 * returns: 46 * item type in itype 47 * item value in ival if item is a constant or special character 48 * if it is a symbol it is placed at the end of the main table 49 50 * meaning of state table: 51 52 * currently getting: symbol(0) constant(1) beginning(2) 53 54 * next char: 55 * digit(0) 0 1 1 56 57 * letter(3) 0 3 0 58 59 * special char(6) 3 3 3 1File: SYMT.C Page 2 60 61 * contents of the state table is the next state. processing stops when 62 * state 3 is encountered. state 2 is the beginning state. 63 */ 64 int sttbl[] {0,1,1,0,3,0,3,3,3}; /*state table for parser*/ 65 66 gterm(constpc) 67 int constpc; 68 { 69 register smode, i; 70 register char *p; 71 register int tmode; 72 register char *j; 73 long num; 74 char istr[80]; 75 76 /* if(fchr == '\'' || fchr == '"') */ /* Fucking Whitesmith's */ 77 if(fchr == 047 || fchr == 042) 78 if(astring()) /*maybe ascii string*/ 79 return; 80 smode = 2; /*beginning state*/ 81 i = 0; 82 p = istr; 83 84 /*loop to put item on istr*/ 85 while(fchr>=' ') { /*until a control char*/ 86 if(smode==2 && fchr=='.') 87 tmode = 3; 88 else if(isalpha(fchr) || fchr=='~' || fchr=='_' || (fchr=='$'&&i)) 89 tmode=3; 90 else if(isdigit(fchr)) 91 tmode=0; 92 else 93 tmode = 6; 94 tmode = sttbl[tmode+smode]; /*new state*/ 95 if(tmode==3) break; /*end of item*/ 96 smode = tmode; 97 *p++ = fchr; /*save character*/ 98 i++; 99 fchr=gchr(); 100 } 101 102 /* end of item*/ 103 switch(smode) { 104 105 case 0: /*symbol*/ 106 *p = '\0'; /*end of symbol*/ 107 itype = ITSY; /*symbol*/ 108 pack(istr,lmte); /*put symbol at end of main table*/ 109 j = lemt(sirt,FALSE); 110 if(istr[0]!='~' && !poslab && (j->flags&(SYEQ|SYER))==SYEQ) { 111 itype = (j->flags&SYRM) ? ITRM : ITCN; /* [vlh] */ 112 ival = j->vl1; 113 reloc = ((j->flags)&SYRO) ? TEXT : ((j->flags)&SYRA) ? DATA : 114 ((j->flags)&SYBS) ? BSS : ABS; 115 } 116 return; 117 118 case 1: /*constant*/ 1File: SYMT.C Page 3 119 if(!constant(&num,istr,i)) { 120 uerr(17); /*illegal constant*/ 121 num = 0; 122 } 123 ival = num; 124 itype = ITCN; 125 reloc = ABS; 126 return; 127 128 case 2: /*just a special char*/ 129 switch(fchr) { 130 131 case '*': /*location counter*/ 132 if(starmul) { /*multiply*/ 133 starmul = 0; 134 goto specsy; 135 } 136 refpc++; /*referenced pgm ctr*/ 137 reloc = rlflg; /*relocation of location counter*/ 138 ival = loctr; 139 itype = (constpc) ? ITCN : ITPC; 140 break; 141 142 143 case '$': /*hex constant*/ 144 oconst(16); 145 return; 146 147 case '@': /*octal const*/ 148 oconst(8); 149 return; 150 151 case '%': /*binary const*/ 152 oconst(2); 153 return; 154 155 case '#': 156 immed[opdix]++; 157 goto specsy; 158 159 case '(': 160 indir[opdix]++; 161 plevel++; 162 goto specsy; 163 164 case ')': 165 plevel--; 166 goto specsy; 167 168 default: 169 specsy: 170 itype = ITSP; /*return special char*/ 171 ival = fchr; 172 } 173 if(fchr != EOLC) 174 fchr=gchr(); /*get next char*/ 175 if((ival=='>' && fchr=='>') || (ival=='<' && fchr=='<')) 176 fchr=gchr(); /*shift op, ignore second char*/ 177 return; 1File: SYMT.C Page 4 178 179 default: 180 abort(); /*not possible*/ 181 } 182 } 183 184 /*check for an ascii string enclosed in single quotes*/ 185 186 astring() 187 { 188 register char delim; 189 190 /* if(fchr != '\'' && fchr != '"') *//*valid delimiter*/ 191 if(fchr != 047 && fchr != 042) 192 return; 193 delim = fchr; 194 if(equflg || (itype==ITSP && ival.wd2=='#')) { /*immediate operand*/ 195 if(astr1(delim)) { 196 fchr = gchr(); 197 if(fchr!=delim) 198 xerr(19); 199 fchr=gchr(); 200 } 201 return((equflg) ? 1 : 0); 202 } 203 while(astr1(delim)) { 204 itype = ITSP; 205 ival = ','; /*separate by commas*/ 206 reloc = ABS; 207 opitoo(); 208 } 209 return(0); 210 } 211 212 astr1(adelim) 213 { 214 register delim,i,retv; 215 register long l; 216 217 delim = adelim; 218 i = 0; l = 0; 219 retv = 1; 220 while((fchr=gchr()) != EOF) { 221 if(fchr==delim) { 222 fchr = gchr(); 223 if(fchr != delim) { 224 retv = 0; /*end of string*/ 225 break; 226 } 227 } 228 if(fchr == EOLC) { 229 xerr(19); 230 retv = 0; /*end of string*/ 231 break; 232 } 233 l = (l<<8) | fchr; 234 if(++i >= modelen) { 235 if((fchr=gchr()) == delim) { 236 fchr = gchr(); 1File: SYMT.C Page 5 237 retv = 0; /*end of string*/ 238 } 239 else 240 peekc = fchr; /*next char in string*/ 241 break; /*filled one bucket*/ 242 } 243 } 244 while(i < modelen) { 245 l =<< 8; 246 i++; 247 } 248 itype = ITCN; 249 ival = l; 250 reloc = ABS; 251 if(!equflg) 252 opitoo(); /*output one operand*/ 253 return(retv); 254 } 255 256 /*get constant given radix*/ 257 oconst(ardx) 258 { 259 register trdx,j; 260 register long i; 261 262 switch (ardx) { /* radix as power of 2 */ 263 case 16 : trdx = 4; break; 264 case 8 : trdx = 3; break; 265 case 2 : trdx = 1; break; 266 default : 267 rpterr("invalid radix in oconst"); 268 abort(); 269 } 270 i=0; 271 while(1) { 272 fchr=gchr(); 273 j=fchr; 274 if(isdigit(j)) 275 j =- '0'; 276 else if((j=tolower(j))>='a' && j<='f') 277 j = j-'a'+10; 278 else 279 break; /*not valid numeric char*/ 280 if(j>=0 && j=10) 307 return(0); 308 l = (l<<3) + (l<<1) + j; /* l = l*10 + j*/ 309 } 310 *pnum = l; 311 return(1); 312 } 313 314 /* 315 * method for looking up entries in the main table 316 * 317 * Note: The entry to be looked up must be placed at the end 318 * of the main table. The global cell 'lmte'(last main 319 * entry) points to the next available entry in the main 320 * table. The address of an initial reference table must 321 * also be provided. 322 * 323 * 1) Compute the hash code for the symbol and add it to the base address 324 * of the initial reference table given as input. Thus, two words are 325 * accessed which define the chain on which the symbol must be if it 326 * is in the table at all. 327 * 328 * 2) Alter the table link of the last symbol in the chain so that it 329 * points to the symbol being looked up. Note that the symbol to be 330 * looked up is always placed at the end of the main table before 331 * calling the lookup routine. This essentially adds one more element 332 * to the end of the chain, namely the symbol to be looked up. 333 * 334 * 3) Now start at the first symbol in the chain and follow the chain 335 * looking for a symbol equal to the smbol being looked up. It is 336 * guaranteed that such a symbol will be found because it is always 337 * the last symbol on the chain. 338 * 339 * 4) When the symbol is found, check to see if it is the last symbol 340 * on the chain. If not, the symbol being looked for is in the table 341 * and has been found. If it is the last symbol, the symbol being 342 * looked up is not in the table. 343 * 344 * 5) In the case the looked up symbol is not found, it is usually added 345 * to the end of the table. This is done simply b changing the 346 * initial reference table entry which points to the previous 347 * last symbol on the chain so that is now points to the symbol at the 348 * end of the main table. In case the symbol just looked up is not to 349 * be added to the main table then no action is needed . This means 350 * that the table link of the last symbol on a chain may point any- 351 * where. 352 * 353 * look up entry in the main table 354 * call with: 1File: SYMT.C Page 7 355 * address of initial reference table 356 * entry to be looked up at the end of the main table 357 * returns: 358 * a pointer to the entry. if this pointer is equal to 359 * lmte then the symbol was not previously in the table. 360 */ 361 362 char *lemt(airt,oplook) 363 char **airt; 364 int oplook; /* if true then looking in opcode table */ 365 { 366 register char *mtpt; 367 register int *p1, *p2; 368 register int i, j; 369 370 if (oplook) { /* [vlh] get rid of preceding '.', to lowercase */ 371 if (lmte->name[0]=='.') { 372 lmte->name[NAMELEN-1] = NULL; /* in case of '.' */ 373 j = 1; 374 } 375 else j = 0; 376 for (i=0; jname[i] = tolower(lmte->name[j]); 378 } 379 380 pirt = airt + hash(); /*hashed ptr to irt*/ 381 mtpt = pirt->irfe; /*pointer to first entry in chain*/ 382 if(!mtpt) /*empty chain*/ 383 mtpt = lmte; /*start at end of main table*/ 384 else 385 (pirt->irle)->tlnk = lmte; /*last entry in chain is new symbol*/ 386 387 /*loop to locate entry in main table*/ 388 lemtl: 389 p1 = &mtpt->name[0]; 390 p2 = &lmte->name[0]; 391 i = NAMELEN/(sizeof i); 392 while(i) { 393 if(*p1++ != *p2++) { 394 mtpt = mtpt->tlnk; /*go to next entry in chain*/ 395 goto lemtl; 396 } 397 i--; 398 } 399 return(mtpt); 400 } 401 402 /* compute a hash code for the last entry in the main table*/ 403 /* returns the hash code*/ 404 hash() 405 { 406 register int i; 407 register ht1; 408 register char *p; 409 410 ht1 = 0; 411 p = &lmte->name[0]; 412 for(i=0; iirle = lmte; /*pointer to last entry in chain*/ 426 if(pirt->irfe == 0) /*first entry in chain*/ 427 pirt->irfe = lmte; 428 lmte =+ STESIZE; /*bump last main table entry pointer*/ 429 if(lmte>=emte) { /*main table overflow*/ 430 if(sbrk(STESIZE*ICRSZMT) == -1){ /*get more memory*/ 431 rpterr("symbol table overflow\n"); 432 endit(); 433 } 434 else { 435 emte =+ STESIZE*ICRSZMT; /*move end of main table*/ 436 cszmt =+ ICRSZMT; 437 } 438 } 439 } 440 441 /* 442 * make an entry in the main table for a directive 443 * call with: 444 * pointer to string containing directive name 445 * address of routine to handle directive in pass one 446 * address of routine to handle directive in pass two 447 */ 448 mdemt(mdstr,dirnum) 449 char *mdstr; 450 { 451 register char *mdept; 452 453 pack(mdstr,lmte); /*pack name at end of main table*/ 454 mdept=lemt(oirt,TRUE); /*look up in opcode table*/ 455 if(mdept != lmte) { /*best not be there already*/ 456 uerr(5); 457 abort(); 458 return; 459 } 460 mmte(); /*make main table entry*/ 461 mdept->flags =| OPDR|SYIN; /*directive*/ 462 mdept->vl1 = dirnum; /*directive #*/ 463 } 464 465 /* 466 * pack a string into an entry in the main table 467 * call with: 468 * pointer to the string 469 * pointer to desired entry in the main table 470 */ 471 pack(apkstr,apkptr) 472 char *apkstr, *apkptr; 1File: SYMT.C Page 9 473 { 474 register i; 475 register char *pkstr, *pkptr; 476 477 pkstr = apkstr; 478 pkptr = apkptr; 479 i = NAMELEN; 480 while(*pkstr && i) { 481 *pkptr++ = *pkstr++; 482 i--; 483 } 484 while(i--) 485 *pkptr++ = '\0'; /*pad with nulls*/ 486 } 487 488 /* function to get characters for source file*/ 489 int xcol = 0; /* Column Counter */ 490 int spcnt = 0; /* Space count for tab expansion */ 491 gchr() 492 { 493 register chr1; 494 495 if(peekc) { 496 chr1 = peekc; 497 peekc = 0; 498 if(chr1 != SOH) 499 xcol--; 500 } 501 else if (spcnt) 502 { 503 spcnt--; 504 return(' '); 505 } 506 else 507 { 508 gchr1: 509 if(sbuflen<=0){ /*nothing on input buffer*/ 510 sbuflen=read(ifn,sbuf,512); /*read in source*/ 511 if(sbuflen<=0) 512 return(EOF); /*end of file*/ 513 psbuf = sbuf; 514 } 515 chr1 = *psbuf++; 516 sbuflen--; 517 } 518 if (chr1 == SOH) /*preprocessor flag*/ 519 goto gchr1; /*ignore it*/ 520 if(chr1 == EOLC) { /*end of line*/ 521 xcol = -1; /* Clear column counter */ 522 if(!p2flg) /*pass 1 only*/ 523 absln++; 524 } 525 if(chr1=='\t') /*convert tabs to spaces*/ 526 { 527 spcnt += 7 - (xcol&7); /* This many spaces */ 528 xcol += spcnt; /* New column number */ 529 chr1 = ' '; 530 } 531 xcol++; 1File: SYMT.C Page 10 532 return(chr1); 533 } 534 535 /* 536 * write out intermediate text for one statement 537 * call with 538 * the it for the statement in stbuf 539 */ 540 wostb() 541 { 542 register int woix; 543 register short *itwo; 544 register int i; 545 546 if(stbuf[0].itty != ITBS) abort(); /*not beginning of stmt*/ 547 itwo = &stbuf; 548 woix = stbuf[0].itrl & 0377; /*unsigned byte*/ 549 while(woix--) { 550 for(i=0; i<(sizeof stbuf[0])/(sizeof *itwo); i++) { 551 doitwr(*itwo++); 552 } 553 } 554 /* debug(); //call debug package*/ 555 } 556 557 doitwr(word) 558 short word; 559 { 560 short i; 561 562 if( pitix < itbuf || pitix > &itbuf[ITBSZ] ) { 563 printf("doitwr: it buffer botch\n"); 564 endit(); 565 } 566 if( pitix >= &itbuf[ITBSZ]) { 567 if(write(itfn,itbuf,ITBSZ*(sizeof i)) != ITBSZ*(sizeof i)) { 568 rpterr("it write error errno=%o\n",errno); 569 endit(); 570 } 571 pitix = itbuf; 572 } 573 *pitix++ = word; 574 } 575 576 /* 577 * user source error 578 * call with: 579 * number to indicate reason for error 580 * types the error number and the line number on which 581 * the error occured. 582 */ 583 uerr(errn) 584 { 585 if(p2flg) { /*pass 2 gets two ampersands*/ 586 in_err++; /* [vlh] instrlen <- pass1 estimation */ 587 printf("&& %d: %s\n",p2absln,ermsg[errn-1]); 588 } 589 else 590 printf("& %d: %s\n",(fchr==EOLC)?absln-1:absln,ermsg[errn-1]); 1File: SYMT.C Page 11 591 nerror++; 592 } 593 /* 594 * user error that causes the statement to be abandoned 595 * call with: 596 * error number 597 */ 598 xerr(xern) 599 { 600 uerr(xern); /*type error message*/ 601 if(!p2flg) /*pass one*/ 602 igrst(); /*pass rest of source*/ 603 } 604 605 /* abort the assembly*/ 606 abort() 607 { 608 rpterr("as68 abort\n"); 609 nerror++; 610 endit(); 611 } 612 613 /*ignore rest of statement*/ 614 igrst() 615 { 616 while(fchr!=EOLC && fchr!=EOF) /*until end of line*/ 617 fchr=gchr(); 618 while((fchr=gchr())==EOLC) ; /*ignore null lines*/ 619 } 620 621 /*ignore blanks after a label*/ 622 ligblk() 623 { 624 if(fchr == EOF) return; 625 igblk(); 626 if(fchr==EOLC) { 627 fchr=gchr(); 628 ligblk(); 629 } 630 } 631 632 rubout() 633 { 634 nerror = -1; 635 endit(); 636 } 637 638 /* exit from the assembler*/ 639 endit() 640 { 641 LASTCHTFN = itfnc; 642 unlink(tfilname); /*delete temporary files*/ 643 LASTCHTFN = trbfnc; 644 unlink(tfilname); 645 LASTCHTFN = dafnc; 646 unlink(tfilname); 647 LASTCHTFN = drbfnc; 648 unlink(tfilname); 649 if(nerror != -1) { /*not rubout*/ 1File: SYMT.C Page 12 650 if(ftudp) 651 putchar('\n'); 652 } 653 if(nerror > 0) { 654 fprintf(stderr,"& %d errors\n",nerror); 655 } 656 if (initflg) 657 unlink(ldfn); /* [vlh] get rid of empty .o file */ 658 exit(nerror!=0); 659 } 660 661 /* 662 * open files 663 * call with: 664 * pointer to name of file to open 665 * flag for how to open 666 * 0 => read 667 * 1 => write 668 */ 669 openfi(pname,hflag) 670 char *pname; 671 { 672 register fd; 673 674 fd = (hflag==1) ? creat(pname,0666,1) : open(pname,hflag,1); 675 if(fd < 0) { /*open failed*/ 676 rpterr("can't open %s errno=%o\n",pname,errno); 677 endit(); 678 } 679 return(fd); 680 } 681 682 /* get a temp file for the intermediate text*/ 683 char lastfile = 'A'; 684 gettempf() 685 { 686 register i,j; 687 register char *p; 688 689 LASTCHTFN = lastfile++; /* Creat temp name */ 690 if((j=creat(tfilname,0600,1)) >= 0) 691 return(j); /* File created OK */ 692 rpterr("Unable to open temporary file\n"); 693 endit(); 694 } 695 696 /* move label name from lbt to main table entry pointed to by lmte*/ 697 setname() 698 { 699 register i; 700 register int *p1, *p2; 701 702 p1 = &lmte->name[0]; 703 for(p2 = &lbt[0]; p2 < &lbt[NAMELEN]; ) { 704 *p1++ = *p2; 705 *p2++ = 0; 706 } 707 } 708 1File: SYMT.C Page 13 709 /* get the initialized main table and initial reference tables from*/ 710 /* the initialize file*/ 711 getsymtab() 712 { 713 long j; /* length for read / write */ 714 register char **p; 715 register struct symtab *p1; 716 register char *p2; 717 register fd,i; 718 719 if((fd=open(initfnam,0,1)) < 0) { 720 rerr: 721 printf("& Unable to read init file: %s\n", initfnam); 722 endit(); 723 } 724 if(read(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) { 725 goto rerr; 726 } 727 728 if(read(fd,oirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) 729 goto rerr; 730 731 if(read(fd,&j,(sizeof j)) != (sizeof j)) /* Read Count */ 732 goto rerr; /* Y-U-K!!! */ 733 734 if((i=read(fd,bmte,(int)j)) != j) /* Read table */ 735 goto rerr; 736 737 if((i%STESIZE) != 0) 738 goto rerr; 739 740 lmte = bmte + i; 741 p2 = bmte-1; 742 for(p=sirt; p<&sirt[SZIRT]; p++) { 743 if(*p) 744 *p =+ (long)p2; 745 } 746 for(p=oirt; p<&oirt[SZIRT]; p++) { 747 if(*p) 748 *p =+ (long)p2; 749 } 750 for(p1=bmte; p1tlnk) 752 p1->tlnk =+ (long)p2; 753 } 754 close(fd); 755 } 756 757 /* write the initialization file*/ 758 putsymtab() 759 { 760 long j; 761 register char **p; 762 register struct symtab *p1; 763 register char *p2; 764 register fd,i; 765 766 if((fd=creat(initfnam,0644,1))<0) { 767 printf("& Cannot create init: %s\n", initfnam); 1File: SYMT.C Page 14 768 return; 769 } 770 /* 771 * change all pointers so that they are relative to the beginning 772 * of the symbol table 773 */ 774 p2 = bmte-1; 775 for(p=sirt; p<&sirt[SZIRT]; p++) { 776 if(*p) 777 *p =- (long)p2; 778 } 779 for(p=oirt; p<&oirt[SZIRT]; p++) { 780 if(*p) 781 *p =- (long)p2; 782 } 783 for(p1=bmte; p1tlnk) 785 p1->tlnk =- (long)p2; 786 } 787 788 if(write(fd,sirt,SZIRT*(sizeof sirt[0])) != SZIRT*(sizeof sirt[0])) { 789 goto werr; 790 } 791 792 if(write(fd,oirt,SZIRT*(sizeof oirt[0])) != SZIRT*(sizeof oirt[0])) 793 goto werr; 794 795 i = lmte - bmte; /*length of current main table*/ 796 if((i % STESIZE) != 0) { 797 goto werr; 798 } 799 j = i; 800 if(write(fd,&j,(sizeof j)) != (sizeof j)) /* Y-U-K!! */ 801 goto werr; 802 803 if(write(fd,bmte,i) != i) { 804 werr: 805 printf("& Write error on init file: %s\n",initfnam); 806 return; 807 } 808 close(fd); 809 } 810 811 /* print an error on file descriptor 2*/ 812 /* used for errors with disasterous consequences*/ 813 rpterr(ptch,x1,x2,x3,x4,x5,x6) 814 char *ptch; 815 { 816 if(prtflg==0) /* Check for paging output */ 817 page(); /* Perform page checks */ 818 fprintf(stderr,"& %d: ",absln); 819 fprintf(stderr,ptch,x1,x2,x3,x4,x5,x6); 820 } 821 822 /* set the file name for the relocatable object file (sourcefile.o)*/ 823 setldfn(ap) 824 char *ap; 825 { 826 register char *p1,*p2; 1File: SYMT.C Page 15 827 828 p1 = ap; 829 p2 = ldfn; 830 while(*p1) { 831 *p2++ = *p1++; 832 } 833 if(*(p2-2) != '.') { /*not name.?*/ 834 *p2++ = '.'; 835 *p2++ = 'o'; 836 } 837 else { /* is name.? */ 838 *(p2-1) = 'o'; 839 } 840 *p2 = '\0'; 841 } 842 843 savelab() 844 { 845 register int *p1, *p2; 846 847 p2 = &lmte->name[0]; 848 for(p1= &tlab1[0]; p1 < &tlab1[NAMELEN]; ) 849 *p1++ = *p2++; 850 }