|
|
1.1 ! root 1: /* ! 2: * static char dis_utls_ID[] = "@(#)dis_utls.c 1.25 12/15/83"; ! 3: */ ! 4: #define DEBUG ! 5: #include <stdio.h> ! 6: #include <ar.h> ! 7: #include "dis.h" ! 8: #include "filehdr.h" ! 9: #include "ldfcn.h" ! 10: #include "sgs.h" ! 11: #include "scnhdr.h" ! 12: #include "linenum.h" ! 13: #include "syms.h" ! 14: #include "structs.h" ! 15: #ifdef OLIST ! 16: #include "olist_defs.h" ! 17: #endif ! 18: ! 19: #ifndef OLIST ! 20: #define TOOL "dis" ! 21: #endif ! 22: /* ! 23: * The following #define is necessary so that the disassembler ! 24: * will run on UNIX 370 3.0 and UNIX 370 4.0 (printf was changed). ! 25: * ! 26: */ ! 27: #ifndef UNIX ! 28: #define UNIX 3 ! 29: #endif ! 30: ! 31: #define FUNC_NM 0 /* for line_nums func, indicates the */ ! 32: /* line number entry value for the */ ! 33: /* beginning of a function */ ! 34: #define BADADDR -1L /* used by the resynchronization */ ! 35: /* function to indicate that a restart */ ! 36: /* candidate has not been found */ ! 37: ! 38: #ifdef OLIST ! 39: extern struct files *curfile; ! 40: extern char linebuf[]; ! 41: #endif ! 42: ! 43: /* ! 44: * This structure is used for storing data needed for the looking up ! 45: * of symbols for labels or functions. It consists of a pointer to a ! 46: * structure describing a symbol table entry, and a pointer to another ! 47: * structure of its own type (a forward linked list will be created). ! 48: */ ! 49: ! 50: struct SYMLINK { ! 51: SYMENT *element; ! 52: struct SYMLINK *next; ! 53: }; ! 54: ! 55: /* ! 56: * To look up labels, a linked list of 'struct SYMLINK' will be ! 57: * searched. 'num_labels' will be set to the number of label ! 58: * entries that exist, and 'head_ptr' will point to the head ! 59: * of this list. ! 60: */ ! 61: ! 62: static int num_labels = 0; ! 63: static struct SYMLINK *head_ptr; ! 64: #ifdef OLIST ! 65: static int firsttime = 1; ! 66: #endif ! 67: ! 68: /* ! 69: * To store the names and addresses of all the functions in the symbol ! 70: * table, SYMLINK is used so that all symbol information is collected ! 71: * for flexname purposes. ! 72: * In the previous version, only the name and address of the symbol ! 73: * was saved. ! 74: */ ! 75: ! 76: ! 77: extern unsigned short num_funcs; ! 78: static struct SYMLINK *func_ptr; ! 79: ! 80: /* ! 81: * To store the name of each section and associate it with its section ! 82: * number, an array of pointers is used. ! 83: */ ! 84: ! 85: static char **section; ! 86: ! 87: /* ! 88: * The following declarations provide space for the current ! 89: * lint number entry and the number of line numbers that have ! 90: * been read ! 91: */ ! 92: static LINENO line_ent; ! 93: static unsigned short lnno_cnt; ! 94: ! 95: FUNCLIST *currfunc; ! 96: ! 97: /* ! 98: * build_labels () ! 99: * ! 100: * Construct an array containing all the label entries in the ! 101: * symbol table. (This will be a forward linked structure.) ! 102: * Then construct an array containing each section name, ! 103: * associating the section name with its section number by its ! 104: * index. This is needed in looking up the labels. ! 105: */ ! 106: ! 107: build_labels() ! 108: { ! 109: /* the following items are from _extn.c */ ! 110: extern FILHDR filhdr; ! 111: extern LDFILE *f_ptr, ! 112: *symb; ! 113: extern char *fname; ! 114: extern int trace, ! 115: Lflag, ! 116: save_Lflag; ! 117: SCNHDR sect_hdr; ! 118: LDFILE *sect_ptr; ! 119: unsigned short j; ! 120: long limit; ! 121: struct SYMLINK *current; ! 122: char *calloc(); ! 123: SYMENT sym_ent; ! 124: SYMENT *sym_ptr = &sym_ent; ! 125: long sym_cnt; ! 126: ! 127: if ((filhdr.f_flags & F_LSYMS) || (filhdr.f_symptr == NULL)) { ! 128: printf("\nfile %s has been stripped of labels\n",fname); ! 129: /* if labels are stripped off save the value of Lflag */ ! 130: save_Lflag = Lflag; ! 131: Lflag = -1; ! 132: return; ! 133: } ! 134: ! 135: limit = filhdr.f_nsyms; /* # of symbol table entries */ ! 136: ! 137: /* ! 138: * Allocate for link structure of first element. ! 139: */ ! 140: ! 141: if ((head_ptr = (struct SYMLINK *) calloc(1,sizeof(struct SYMLINK))) == NULL) { ! 142: fprintf( stderr, "memory allocation failure on call to calloc"); ! 143: exit(0); ! 144: } ! 145: ! 146: current = head_ptr; /* point to first entry */ ! 147: ! 148: /* ! 149: * Allocate for symbol structure of first element. ! 150: */ ! 151: ! 152: if ((current->element = (SYMENT *) calloc(1,SYMESZ)) == NULL) { ! 153: fprintf( stderr, "memory allocation failure on call to calloc"); ! 154: exit(0); ! 155: } ! 156: ! 157: /* ! 158: * initialize all needed for get_sym() ! 159: */ ! 160: ! 161: ldtbseek(symb); ! 162: ! 163: /* ! 164: * Search the whole symbol table looking for elements ! 165: * with a storage class of label (C_LABEL) ! 166: */ ! 167: ! 168: for( sym_cnt = 0; sym_cnt < limit; sym_cnt++ ) { ! 169: if (ldtbread( symb, sym_cnt, sym_ptr ) == FAILURE) ! 170: { ! 171: fprintf( stderr, "%s%s: %s: cannot read symbol table\n", ! 172: SGS, TOOL, fname ); ! 173: exit(1); ! 174: } ! 175: if (trace > 0) { ! 176: printf("\nsym name %s\tsec # %d\tstor cl %d\n", ! 177: sym_ptr->n_name, ! 178: sym_ptr->n_scnum, ! 179: sym_ptr->n_sclass); ! 180: } ! 181: if (sym_ptr->n_sclass == C_LABEL) { ! 182: ! 183: /* if it's a label add it to the list */ ! 184: ! 185: #ifdef FLEXNAMES ! 186: current->element->n_zeroes=sym_ptr->n_zeroes; ! 187: current->element->n_offset=sym_ptr->n_offset; ! 188: #else ! 189: strcpy(current->element->n_name,sym_ptr->n_name); ! 190: #endif ! 191: current->element->n_value = sym_ptr->n_value; ! 192: current->element->n_scnum = sym_ptr->n_scnum; ! 193: current->element->n_type = sym_ptr->n_type; ! 194: current->element->n_sclass = sym_ptr->n_sclass; ! 195: current->element->n_numaux = sym_ptr->n_numaux; ! 196: ! 197: /* ! 198: * Obtain space for another link structure. ! 199: */ ! 200: ! 201: if ((current->next = (struct SYMLINK *) calloc(1,sizeof(struct SYMLINK))) == NULL) { ! 202: fprintf( stderr, "memory allocation failure on call to calloc"); ! 203: exit(0); ! 204: } ! 205: ! 206: current = current->next; ! 207: ! 208: /* ! 209: * Obtain space for another symbol element. ! 210: */ ! 211: ! 212: if ((current->element = (SYMENT *) calloc(1,SYMESZ)) == NULL) { ! 213: fprintf( stderr, "memory allocation failure on call to calloc"); ! 214: exit(0); ! 215: } ! 216: num_labels++; ! 217: } ! 218: sym_cnt += sym_ptr->n_numaux; ! 219: } ! 220: current->next = NULL; ! 221: ! 222: sect_ptr = NULL; ! 223: sect_ptr = ldaopen(fname,f_ptr); ! 224: ! 225: /* ! 226: * now build an array to store the pointers to the names of ! 227: * each section. First allocate a pointer for each section. ! 228: */ ! 229: ! 230: if ((section = (char **) calloc(filhdr.f_nscns + 1, sizeof(section))) == NULL) { ! 231: fprintf( stderr, "memory allocation failure on call to calloc"); ! 232: exit(0); ! 233: } ! 234: ! 235: /* ! 236: * now have section[0] point to a block of memory big enough to ! 237: * hold all the section names (their size has 1 added to ! 238: * account for a trailing '\0'). ! 239: */ ! 240: ! 241: if ((*section = calloc ( filhdr.f_nscns + 1, (sizeof(sect_hdr.s_name)+1))) == NULL) { ! 242: fprintf( stderr, "memory allocation failure on call to calloc"); ! 243: exit(0); ! 244: } ! 245: ! 246: /* ! 247: * now read and assign the section names. One will note that ! 248: * the allocated memory for the first name is not used. This ! 249: * does not cause us to run out of space, though, since '1' ! 250: * was added above in allocating space. ! 251: */ ! 252: ! 253: for (j = 1; j < filhdr.f_nscns; j++) { ! 254: ldshread(sect_ptr, j, §_hdr); ! 255: section[j] = section[j-1] + sizeof(sect_hdr.s_name) + 1; ! 256: sprintf(section[j],"%-.8s",sect_hdr.s_name); ! 257: } ! 258: ldaclose(sect_ptr); ! 259: } ! 260: ! 261: /* ! 262: * compoff (lng, temp) ! 263: * ! 264: * This routine will compute the location to which control is to be ! 265: * transferred. 'lng' is the number indicating the jump amount ! 266: * (already in proper form, meaning masked and negated if necessary) ! 267: * and 'temp' is a character array which already has the actual ! 268: * jump amount. The result computed here will go at the end of 'temp'. ! 269: * (This is a great routine for people that don't like to compute in ! 270: * hex arithmetic.) ! 271: */ ! 272: ! 273: compoff(lng, temp) ! 274: long lng; ! 275: char *temp; ! 276: { ! 277: extern int oflag; /* from _extn.c */ ! 278: extern long loc; /* from _extn.c */ ! 279: ! 280: lng += loc; ! 281: if (oflag) ! 282: sprintf(temp,"%s <%lo>",temp,lng); ! 283: else ! 284: sprintf(temp,"%s <%lx>",temp,lng); ! 285: } ! 286: /* ! 287: * convert (num, temp, flag) ! 288: * ! 289: * Convert the passed number to either hex or octal, depending on ! 290: * the oflag, leaving the result in the supplied string array. ! 291: * If LEAD is specified, preceed the number with '0' or '0x' to ! 292: * indicate the base (used for information going to the mnemonic ! 293: * printout). NOLEAD will be used for all other printing (for ! 294: * printing the offset, object code, and the second byte in two ! 295: * byte immediates, displacements, etc.) and will assure that ! 296: * there are leading zeros. ! 297: */ ! 298: ! 299: convert(num,temp,flag) ! 300: unsigned num; ! 301: char temp[]; ! 302: int flag; ! 303: ! 304: { ! 305: extern int oflag; /* in _extn.c */ ! 306: ! 307: #if UNIX < 4 ! 308: #ifdef B16 ! 309: if (flag == NOLEAD) ! 310: (oflag) ? sprintf(temp,"%03o",num): ! 311: sprintf(temp,"%02x",num); ! 312: #else ! 313: if (flag == NOLEAD) ! 314: (oflag) ? sprintf(temp,"%06o",num): ! 315: sprintf(temp,"%04x",num); ! 316: #endif /* B16 */ ! 317: #else ! 318: #ifdef B16 ! 319: if (flag == NOLEAD) ! 320: (oflag) ? sprintf(temp,"%.3o",num): ! 321: sprintf(temp,"%.2x",num); ! 322: #else ! 323: if (flag == NOLEAD) ! 324: (oflag) ? sprintf(temp,"%.6o",num): ! 325: sprintf(temp,"%.4x",num); ! 326: #endif /* B16 */ ! 327: #endif /* UNIX < 4 */ ! 328: if (flag == LEAD) ! 329: (oflag) ? sprintf(temp,"0%o",num): ! 330: sprintf(temp,"0x%x",num); ! 331: } ! 332: /* ! 333: * dis_data () ! 334: * ! 335: * the routine to disassemble a data section, ! 336: * which consists of just dumping it with byte offsets ! 337: */ ! 338: ! 339: dis_data( sectp ) ! 340: SCNLIST *sectp; ! 341: ! 342: { ! 343: extern SCNHDR scnhdr; /* from _extn.c */ ! 344: extern int oflag; /* from _extn.c */ ! 345: extern int trace; /* from _extn.c */ ! 346: extern short aflag; /* from _extn.c */ ! 347: extern long loc; /* from _extn.c */ ! 348: extern char mneu[]; /* from _extn.c */ ! 349: extern char object[];/* from _extn.c */ ! 350: extern unsigned short cur2bytes; /* from _extn.c */ ! 351: extern LDFILE *f_ptr; ! 352: extern char *fname; ! 353: ! 354: LDFILE *d_ptr; ! 355: short count; ! 356: long last_addr; ! 357: ! 358: scnhdr = sectp->shdr; ! 359: d_ptr = ldaopen( fname, f_ptr ); ! 360: ldsseek( d_ptr, sectp->scnum ); ! 361: ! 362: /* Blank out mneu so the printline routine won't print extraneous ! 363: * garbage. ! 364: */ ! 365: ! 366: sprintf(mneu,""); ! 367: if (scnhdr.s_nlnno != 0){ ! 368: fprintf(stderr,"\n%sdis: QUIRK--data section has line number entries",SGS); ! 369: printf("\n Are you sure this was a data section?!\n"); ! 370: } ! 371: ! 372: if (trace > 0){ ! 373: printf("\ntrace: section name %s\n",scnhdr.s_name); ! 374: printf("\ntrace: section size %x\n",scnhdr.s_size); ! 375: } ! 376: ! 377: for (loc = aflag? scnhdr.s_paddr: 0, last_addr = loc + scnhdr.s_size; ! 378: loc < last_addr; printline()) { ! 379: /* if -da flag specified, actual adress will be printed ! 380: if -d flag specified, offset within section will be printed */ ! 381: printf("\t"); ! 382: prt_offset(); ! 383: #ifdef B16 ! 384: for (count=0; (count<6) && (loc<last_addr); count++) ! 385: getbyte(d_ptr); ! 386: #endif ! 387: #ifdef MC68 ! 388: for (count=0; (count<8) && (loc<last_addr); count+=2) ! 389: get2bytes(d_ptr); ! 390: #endif ! 391: #ifdef N3B ! 392: for (count=0; (count<8) && (loc<last_addr); count+=2) ! 393: get2bytes(d_ptr); ! 394: #endif ! 395: #ifdef M32 ! 396: for (count=0; (count<8) && (loc<last_addr); count+=2) ! 397: /* bytes of data are swapped so they must be swapped back */ ! 398: getswapb2(d_ptr); ! 399: #endif /* M32 */ ! 400: } ! 401: ! 402: } ! 403: #if U3B | N3B | U3B5 | M32 ! 404: /* ! 405: * dfpconv(fpword1, fpword2, fpdoub, fpshort) ! 406: * ! 407: * This routine will convert the 2 longs (64 bit) "fpword1 fpword2" double ! 408: * precision floating point representation of a number into its decimal ! 409: * equivalent. The result will be stored in *fpdoub. The routine will ! 410: * return a value indicating what type of floating point number was ! 411: * converted. ! 412: * *NOTE* The conversion routine will calculate a decimal value ! 413: * if the disassembler is to run native mode on the 3B. ! 414: * If the 3B disassembler is to be run on a DEC processor ! 415: * (pdp11 or vax) the routine will store the exponent in ! 416: * *fpshort. The mantissa will be stored in the form: ! 417: * "T.fraction" where "T" is the implied bit and the ! 418: * fraction is of radix 2. The mantissa will be stored ! 419: * in *fpdoub. This is due to the difference in range ! 420: * of floating point numbers between the 3B and DEC ! 421: * processors. ! 422: */ ! 423: dfpconv(fpword1, fpword2, fpdoub, fpshort) ! 424: long fpword1, fpword2; ! 425: double *fpdoub; ! 426: short *fpshort; ! 427: { ! 428: unsigned short exponent; ! 429: short leadbit, signbit; ! 430: double dtemp, dec2exp, mantissa; ! 431: long ltemp; ! 432: ! 433: exponent = (unsigned short)((fpword1>>20) & 0x7ffL); ! 434: /* exponent is bits 1-11 of the double */ ! 435: ! 436: ltemp = fpword1 & 0xfffffL; /* first 20 bits of mantissa */ ! 437: mantissa = ((double)ltemp * TWO_32) + (double)fpword2; ! 438: /* mantissa is bits 12-63 of the double */ ! 439: ! 440: signbit = (short)((fpword1>>31) & 0x1L); ! 441: /* sign bit (1-negative, 0-positive) is bit 0 of double */ ! 442: ! 443: leadbit = 1; ! 444: /* implied bit to the left of the decimal point */ ! 445: ! 446: if (exponent==2047) ! 447: if (mantissa) ! 448: return(NOTANUM); ! 449: else ! 450: return((signbit)? NEGINF: INFINITY); ! 451: ! 452: if (exponent==0) ! 453: if (mantissa) ! 454: /* This is a denormalized number. The implied bit to ! 455: * the left of the decimal point is 0. ! 456: */ ! 457: leadbit = 0; ! 458: else ! 459: return((signbit)? NEGZERO: ZERO); ! 460: ! 461: /* ! 462: * Convert the 52 bit mantissa into "I.fraction" where ! 463: * "I" is the implied bit. The 52 bits are divided by ! 464: * 2 to the 52rd power to transform the mantissa into a ! 465: * fraction. Then the implied bit is added on. ! 466: */ ! 467: dtemp = (double)(leadbit + (mantissa/TWO_52)); ! 468: ! 469: #if U3B | U3B5 ! 470: /* Calculate 2 raised to the (exponent-BIAS) power and ! 471: * store it in a double. ! 472: */ ! 473: if (exponent < DBIAS) ! 474: for(dec2exp=1; exponent < DBIAS; ++exponent) ! 475: dec2exp /= 2; ! 476: else ! 477: for(dec2exp=1; exponent > DBIAS; --exponent) ! 478: dec2exp *= 2; ! 479: ! 480: /* Multiply "I.fraction" by 2 raised to the (exponent-BIAS) ! 481: * power to obtain the decimal floating point number. ! 482: */ ! 483: *fpdoub = dtemp *dec2exp; ! 484: ! 485: if (signbit) ! 486: *fpdoub = -(*fpdoub); ! 487: return(FPNUM); ! 488: #else ! 489: *fpshort = exponent - DBIAS; ! 490: *fpdoub = ((signbit)? (-dtemp): dtemp); ! 491: return(FPBIGNUM); ! 492: #endif /* U3B | U3B5 */ ! 493: } ! 494: #endif /* U3B | N3B | U3B5 | M32 */ ! 495: ! 496: /* ! 497: * getbyte (ptr) ! 498: * ! 499: * read a byte, mask it, then return the result in 'curbyte'. ! 500: * The getting of all single bytes is done here. The 'getbyte[s]' ! 501: * routines are the only place where the global variable 'loc' ! 502: * is incremented. ! 503: */ ! 504: int ! 505: getbyte(ptr) ! 506: LDFILE *ptr; ! 507: ! 508: { ! 509: extern long loc; /* from _extn.c */ ! 510: extern unsigned short curbyte; /* from _extn.c */ ! 511: extern char object[]; /* from _extn.c */ ! 512: char temp[NCPS+1]; ! 513: char byte; ! 514: ! 515: if ( FREAD(&byte,sizeof(byte),1,ptr) == NULL){ ! 516: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL); ! 517: exit(4); ! 518: } ! 519: loc++; ! 520: curbyte = byte & 0377; ! 521: convert(curbyte, temp, NOLEAD); ! 522: sprintf(object,"%s%s ",object,temp); ! 523: } ! 524: /* ! 525: * lookbyte (ptr) ! 526: * ! 527: * read a byte, mask it, then return the result in 'curbyte'. ! 528: * The byte is not immediately placed into the string object[]. ! 529: * is incremented. ! 530: */ ! 531: ! 532: int ! 533: lookbyte(ptr) ! 534: LDFILE *ptr; ! 535: ! 536: { ! 537: extern long loc; /* from _extn.c */ ! 538: extern unsigned short curbyte; /* from _extn.c */ ! 539: char byte; ! 540: ! 541: if ( FREAD(&byte,sizeof(byte),1,ptr) == NULL){ ! 542: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL); ! 543: exit(4); ! 544: } ! 545: loc++; ! 546: curbyte = byte & 0377; ! 547: } ! 548: ! 549: /* ! 550: * get2bytes(ptr) ! 551: * ! 552: * This routine will get 2 bytes, print them in the object file ! 553: * and place the result in 'cur2bytes'. ! 554: */ ! 555: ! 556: int ! 557: get2bytes(ptr) ! 558: LDFILE *ptr; ! 559: { ! 560: extern long loc; /* from _extn.c */ ! 561: extern unsigned short cur2bytes; /* from _extn.c */ ! 562: extern char object[]; /* from _extn.c */ ! 563: char temp[NCPS+1]; ! 564: extern int trace; ! 565: ! 566: if ( FREAD(&cur2bytes,sizeof(cur2bytes),1,ptr) == NULL){ ! 567: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL); ! 568: exit(4); ! 569: } ! 570: loc += 2; ! 571: convert( (cur2bytes & 0xffff), temp, NOLEAD); ! 572: sprintf(object,"%s%s ",object, temp); ! 573: if (trace > 1) ! 574: printf("\nin get2bytes object<%s>\n",object); ! 575: } ! 576: #ifdef M32 ! 577: /* ! 578: * getswapb2(ptr) ! 579: * ! 580: * This routine is used only for m32 and m32a. It will get and ! 581: * swap 2 bytes, print them in the object file and place the ! 582: * result in 'cur2bytes'. ! 583: */ ! 584: ! 585: int ! 586: getswapb2(ptr) ! 587: LDFILE *ptr; ! 588: { ! 589: extern long loc; /* from _extn.c */ ! 590: extern unsigned short cur2bytes; /* from _extn.c */ ! 591: extern char object[]; /* from _extn.c */ ! 592: char temp[NCPS+1]; ! 593: extern int trace; ! 594: ! 595: if ( FREAD(&cur2bytes,sizeof(cur2bytes),1,ptr) == NULL){ ! 596: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL); ! 597: exit(4); ! 598: } ! 599: loc += 2; ! 600: /* swap the 2 bytes contained in 'cur2bytes' */ ! 601: cur2bytes = ((cur2bytes>>8) & (unsigned short)0x00ff) | ! 602: ((cur2bytes<<8) & (unsigned short)0xff00); ! 603: convert( (cur2bytes & 0xffff), temp, NOLEAD); ! 604: sprintf(object,"%s%s ",object, temp); ! 605: if (trace > 1) ! 606: printf("\nin getswapb2 object<%s>\n",object); ! 607: } ! 608: #endif ! 609: /* ! 610: * get4bytes(ptr) ! 611: * ! 612: * This routine will bet 4 bytes, print them in the object and ! 613: * place the results in 'cur4bytes'. ! 614: */ ! 615: ! 616: get4bytes(ptr) ! 617: LDFILE *ptr; ! 618: { ! 619: extern long loc; /* from _extn.c */ ! 620: #ifdef AR32WR ! 621: extern unsigned long cur4bytes; /* from _extn.c */ ! 622: #else ! 623: extern long cur4bytes; ! 624: #endif ! 625: extern unsigned short cur2bytes; /* from _extn.c */ ! 626: extern char object[]; /* from _extn.c */ ! 627: char temp[NCPS+1]; ! 628: unsigned send; ! 629: extern int trace; /* in _extn.c */ ! 630: #ifdef AR32WR ! 631: unsigned long tempvax; ! 632: #endif ! 633: ! 634: if ( FREAD(&cur4bytes,sizeof(cur4bytes),1,ptr) == NULL){ ! 635: fprintf(stderr,"\n%s%s: premature EOF\n",SGS,TOOL); ! 636: exit(4); ! 637: } ! 638: ! 639: loc += 4; ! 640: #ifdef AR32WR ! 641: tempvax = (( cur4bytes >>16 ) & 0xffffL); ! 642: cur4bytes = (( cur4bytes <<16 ) | tempvax); ! 643: #endif ! 644: send = (cur4bytes >> 16) & 0xffffL; ! 645: convert(send, temp, NOLEAD); ! 646: sprintf(object,"%s%s ",object,temp); ! 647: cur2bytes = cur4bytes & 0xffffL; ! 648: send = cur4bytes & 0xffffL; ! 649: convert(send, temp, NOLEAD); ! 650: sprintf(object,"%s%s ",object,temp); ! 651: if (trace > 1) ! 652: printf("\nin get4bytes object<%s>\n",object); ! 653: } ! 654: /* ! 655: * label_free () ! 656: * ! 657: * Free all the space that has been allocated which would be the space ! 658: * for section names plus those label entries that are not already free. ! 659: */ ! 660: ! 661: label_free() ! 662: ! 663: { ! 664: struct SYMLINK *temp; ! 665: int i; ! 666: ! 667: cfree(section[0]); ! 668: cfree(section); ! 669: ! 670: for (i = 0; i < num_labels; i++) { ! 671: temp = head_ptr; ! 672: head_ptr = head_ptr->next; ! 673: free(temp->element); ! 674: free(temp); ! 675: } ! 676: ! 677: } ! 678: /* ! 679: * lib_free () ! 680: * ! 681: * After all the files have been processed, free the space that was ! 682: * allocated for libraries that were disassembled. ! 683: */ ! 684: ! 685: lib_free() ! 686: ! 687: { ! 688: /* the following array is from _extn.c */ ! 689: extern char *libs[]; ! 690: extern int lflag; /* from _extn.c */ ! 691: int i; ! 692: ! 693: for (i = lflag; i > 0; i--) ! 694: free(libs[i]); ! 695: ! 696: } ! 697: ! 698: /* ! 699: * line_nums () ! 700: * ! 701: * This function prints out the names of functions being disassembled ! 702: * and break-pointable line numbers. First it checks the address ! 703: * of the next function in the list of functions; if if matches ! 704: * the current location, it prints the name of that function. ! 705: * ! 706: * It then examines the line number entries. If the address of the ! 707: * current line number equals that of the current location, the ! 708: * line number is printed. ! 709: */ ! 710: line_nums() ! 711: { ! 712: /* the following items are from _extn.c */ ! 713: extern LDFILE *l_ptr, ! 714: *t_ptr, ! 715: *symb, ! 716: *symb_ptr; ! 717: ! 718: extern SCNHDR scnhdr; ! 719: extern FILHDR filhdr; ! 720: extern int trace; ! 721: extern int oflag; ! 722: #ifndef OLIST ! 723: extern int fflag; ! 724: #endif ! 725: extern long loc; ! 726: extern FUNCLIST *next_function; ! 727: extern FUNCLIST *currfunc; ! 728: #ifdef OLIST ! 729: extern int nosource; ! 730: extern int funcs_listed; ! 731: #endif ! 732: ! 733: SYMENT sym_ent; ! 734: SYMENT *sym_ptr = &sym_ent; ! 735: long sym_cnt; ! 736: char *flexname, /* pointer to flexname returned by ldgetname */ ! 737: *ldgetname(); ! 738: LINENO *lnno_ptr = &line_ent; ! 739: ! 740: #ifdef OLIST ! 741: linebuf[0] = '\0'; ! 742: #endif ! 743: ! 744: while (next_function != NULL) ! 745: { ! 746: /* not there yet */ ! 747: if (loc < next_function->faddr) ! 748: break; ! 749: ! 750: if (loc > next_function->faddr) ! 751: { ! 752: /* this is an error condition */ ! 753: fflush( stdout ); ! 754: fprintf( stderr, "\nWARNING: Possible strings in text or bad physical address before location "); ! 755: if (oflag) ! 756: fprintf( stderr, "0%lo\n", loc ); ! 757: else ! 758: fprintf( stderr, "0x%lx\n", loc ); ! 759: FSEEK( t_ptr, (next_function->faddr - scnhdr.s_paddr) + scnhdr.s_scnptr, 0); ! 760: loc = next_function->faddr; ! 761: } ! 762: ! 763: /* loc == next_function->addr, so print the function name */ ! 764: #if OLIST ! 765: funcs_listed++; ! 766: if (nosource == TRUE) ! 767: printf( "\t" ); ! 768: else if (curfile->f_nam[ strlen( curfile->f_nam ) -1] == 's') ! 769: printf( "\n\@FUNCTION: %s\n\n", next_function->funcnm ); ! 770: #endif ! 771: printf("%s()\n", next_function->funcnm ); ! 772: currfunc = next_function; ! 773: next_function = next_function->nextfunc; ! 774: } ! 775: ! 776: if (scnhdr.s_lnnoptr != NULL) ! 777: { ! 778: #if OLIST ! 779: /* read the first one for the section */ ! 780: if (loc == scnhdr.s_paddr || firsttime) ! 781: { ! 782: firsttime = 0; ! 783: FSEEK( l_ptr, scnhdr.s_lnnoptr, 0 ); ! 784: lnno_cnt = 0; ! 785: if (FREAD( (char *) lnno_ptr, LINESZ,1, l_ptr ) != 1) ! 786: fatal( "cannot read line numbers" ); ! 787: } ! 788: #else ! 789: if (loc == scnhdr.s_paddr) ! 790: { ! 791: if (fflag) { ! 792: if ((ldlinit(l_ptr, currfunc->fcnindex)) == FAILURE) ! 793: return; ! 794: } else ! 795: FSEEK( l_ptr, scnhdr.s_lnnoptr, 0 ); ! 796: lnno_cnt = 0; ! 797: if (FREAD( (char *) lnno_ptr, LINESZ,1, l_ptr ) != 1) ! 798: fatal( "cannot read line numbers" ); ! 799: } ! 800: #endif ! 801: ! 802: for ( ; lnno_cnt < scnhdr.s_nlnno; ) ! 803: { ! 804: if (lnno_ptr->l_lnno == FUNC_NM) ! 805: { ! 806: if (currfunc && lnno_ptr->l_addr.l_symndx == currfunc->fcnindex) ! 807: { ! 808: /* if the function matches the last one ! 809: * printed, skip the line number entry ! 810: */ ! 811: if (FREAD((char *) lnno_ptr, LINESZ,1, l_ptr ) !=1 ) ! 812: fatal( "cannot read line numbers" ); ! 813: lnno_cnt++; ! 814: } ! 815: else ! 816: { ! 817: /* should never get here. All of the ! 818: * functions should be in the function ! 819: * list, but the code is here just ! 820: * in case ! 821: */ ! 822: if (ldtbread( symb_ptr, lnno_ptr->l_addr.l_symndx, sym_ptr ) == FAILURE) ! 823: fatal( "cannot read symbol table"); ! 824: if (sym_ptr->n_value > loc) ! 825: break; ! 826: if (sym_ptr->n_value < loc) ! 827: #if OLIST ! 828: if (sym_ptr->n_value < curfile->tbegin) ! 829: { ! 830: lnno_cnt += 1; ! 831: if (FREAD ((char *) lnno_ptr, LINESZ, 1, l_ptr ) != 1) ! 832: fatal("cannot read line numbers"); ! 833: continue; ! 834: } ! 835: else ! 836: #endif ! 837: { ! 838: fflush( stdout ); ! 839: fprintf( stderr, "\nWARNING: Possible strings in text or bad physical address before location " ); ! 840: if (oflag) ! 841: fprintf( stderr, "0%lo\n", loc); ! 842: else ! 843: fprintf(stderr, "0x%lx\n", loc); ! 844: FSEEK(t_ptr, (sym_ptr->n_value - scnhdr.s_paddr) + scnhdr.s_scnptr, BEGINNING); ! 845: loc = sym_ptr->n_value; ! 846: } ! 847: ! 848: /* the address of the function matches so print its name */ ! 849: if(!(flexname = ldgetname(symb_ptr, sym_ptr))) ! 850: fprintf(stderr, "ldgetname returned 0\n"); ! 851: #ifdef OLIST ! 852: if (nosource == TRUE ) ! 853: printf("\t"); ! 854: else if (curfile->f_nam[strlen(curfile->f_nam)-1] =='s') ! 855: printf("\n\\@FUNCTION: %s\n\n", flexname); ! 856: #endif ! 857: printf("%s()\n",flexname); ! 858: lnno_cnt += 1; ! 859: if (FREAD( lnno_ptr, LINESZ, 1, l_ptr ) != 1) ! 860: fatal( "cannot read line numbers\n"); ! 861: } ! 862: } ! 863: else ! 864: { ! 865: /* this is just a line number entry */ ! 866: #ifdef OLIST ! 867: if ((loc == lnno_ptr->l_addr.l_paddr) && (nosource != TRUE)) ! 868: sprintf(linebuf, "%s[%-d%]", linebuf, lnno_ptr->l_lnno); ! 869: #else ! 870: if (loc == lnno_ptr->l_addr.l_paddr) ! 871: printf("[%d]",lnno_ptr->l_lnno); ! 872: #endif ! 873: else if (loc < lnno_ptr->l_addr.l_paddr) ! 874: break; ! 875: if (FREAD( lnno_ptr, LINESZ, 1, l_ptr ) != 1) ! 876: fatal( "cannot read line numbers\n" ); ! 877: lnno_cnt++; ! 878: } ! 879: } ! 880: } ! 881: ! 882: #ifndef OLIST ! 883: printf("\t"); ! 884: #endif ! 885: } ! 886: ! 887: /* ! 888: * looklabel (addr, sect_num) ! 889: * ! 890: * This function will look in the symbol table to see if ! 891: * a label exists which may be printed. ! 892: */ ! 893: ! 894: looklabel(addr, sect_num) ! 895: long addr; ! 896: unsigned short sect_num; ! 897: ! 898: { ! 899: struct SYMLINK *current, ! 900: *previous; ! 901: int i; ! 902: extern LDFILE *symb_ptr; ! 903: char *flexname, ! 904: *ldgetname(); ! 905: ! 906: current = head_ptr; ! 907: previous = current; ! 908: ! 909: for (i = 0; i < num_labels; i++) { ! 910: ! 911: /* both the address and section number must match */ ! 912: if (current->element->n_value == addr && ! 913: current->element->n_scnum == sect_num) { ! 914: ! 915: /* found the label so print it */ ! 916: if(!(flexname = ldgetname(symb_ptr, current->element))) { ! 917: fprintf(stderr, "ldgetname returned 0\n"); ! 918: } ! 919: printf("%s:\n",flexname); ! 920: ! 921: /* now free up the space occupied by the */ ! 922: /* found element */ ! 923: ! 924: if (current == head_ptr) ! 925: head_ptr = head_ptr->next; ! 926: ! 927: previous->next = current->next; ! 928: free (current->element); ! 929: free(current); ! 930: num_labels--; ! 931: return; ! 932: } ! 933: /* didn't find a label yet, so go to the next label */ ! 934: previous = current; ! 935: current = current->next; ! 936: } ! 937: } ! 938: ! 939: /* ! 940: * printline () ! 941: * ! 942: * Print the disassembled line, consisting of the object code ! 943: * and the mnemonics. The breakpointable line number, if any, ! 944: * has already been printed, and 'object' contains the offset ! 945: * within the section for the instruction. ! 946: */ ! 947: ! 948: printline() ! 949: ! 950: { ! 951: extern int oflag; /* in _extn.c */ ! 952: extern char object[]; ! 953: extern char mneu[]; ! 954: #ifdef OLIST ! 955: extern int nosource; ! 956: #endif ! 957: ! 958: #ifdef B16 ! 959: (oflag > 0) ? ! 960: printf("%-36s%s\n",object,mneu): /* to print octal */ ! 961: printf("%-30s%s\n",object,mneu); /* to print hex */ ! 962: #endif ! 963: #ifdef MC68 ! 964: (oflag > 0) ? ! 965: printf("%-36s%s\n",object,mneu): /* to print octal */ ! 966: printf("%-37s%s\n",object,mneu); /* to print hex */ ! 967: #endif ! 968: #ifdef N3B ! 969: #ifdef OLIST ! 970: if (nosource == TRUE) return; ! 971: printf("%-46s%-8s%s\n", object, linebuf, mneu); ! 972: #else ! 973: (oflag > 0) ? ! 974: printf("%-36s%s\n",object,mneu): /* to print octal */ ! 975: printf("%-37s%s\n",object,mneu); /* to print hex */ ! 976: #endif ! 977: #endif ! 978: #ifdef M32 ! 979: (oflag > 0) ? ! 980: printf("%-36s%s\n",object,mneu): /* to print octal */ ! 981: printf("%-37s%s\n",object,mneu); /* to print hex */ ! 982: #endif /* M32 */ ! 983: } ! 984: /* ! 985: * prt_offset () ! 986: * ! 987: * Print the offset, right justified, followed by a ':'. ! 988: */ ! 989: ! 990: ! 991: prt_offset() ! 992: ! 993: { ! 994: extern long loc; /* from _extn.c */ ! 995: extern int oflag; ! 996: extern char object[]; ! 997: ! 998: #ifdef OLIST ! 999: if (oflag) ! 1000: sprintf(object,"0%.7lo ", loc); ! 1001: else ! 1002: sprintf(object, "0x%.6lx ", loc); ! 1003: #else ! 1004: if (oflag) ! 1005: sprintf(object,"%6lo: ",loc); ! 1006: else ! 1007: sprintf(object,"%4lx: ",loc); ! 1008: #endif ! 1009: } ! 1010: /* ! 1011: * resync () ! 1012: * ! 1013: * If a bad op code is encountered, the disassembler will attempt ! 1014: * to resynchronize itself. The next line number entry and the ! 1015: * next function symbol table entry will be found. The restart ! 1016: * point will be the smaller of these two addresses and bytes ! 1017: * of object code will be dumped (not disassembled) until the ! 1018: * restart point is reached. ! 1019: */ ! 1020: ! 1021: ! 1022: resync() ! 1023: ! 1024: { ! 1025: /* the following 7 items are from _extn.c */ ! 1026: extern char *fname; ! 1027: extern char *sname; ! 1028: extern LDFILE *f_ptr; ! 1029: extern LDFILE *t_ptr; ! 1030: extern LDFILE *l_ptr; ! 1031: extern LDFILE *symb; ! 1032: extern FILHDR filhdr; ! 1033: extern SCNHDR scnhdr; ! 1034: extern long loc; ! 1035: extern FUNCLIST *next_function; ! 1036: extern FUNCLIST *currfunc; ! 1037: extern char mneu[]; ! 1038: extern int nosyms; ! 1039: #if OLIST ! 1040: extern int funcs_listed; ! 1041: extern int nosource; ! 1042: #endif ! 1043: ! 1044: #if AR16WR && !OLIST ! 1045: static long firstfn = -1L; ! 1046: #endif ! 1047: ! 1048: struct lineno *eptr = &line_ent; ! 1049: struct syment sentry, stbentry, *septr; ! 1050: long paddr, sindex, linaddr, symaddr, dumpaddr, s_end; ! 1051: ! 1052: linaddr = BADADDR; ! 1053: symaddr = BADADDR; ! 1054: s_end = scnhdr.s_paddr + scnhdr.s_size; ! 1055: /* Find the next line number entry if the file has not been ! 1056: * stripped of line number information. Each entry from the ! 1057: * beginning will be read until one having a greater address ! 1058: * than the present location is found. ! 1059: */ ! 1060: if (nosyms == TRUE) { ! 1061: printf ("\n\t** FILE IS STRIPPED **\t\n"); ! 1062: printf ("\t** SKIP TWO BYTES AND TRY AGAIN **\n"); ! 1063: return(SUCCESS); ! 1064: } ! 1065: if (stripped() != TRUE) ! 1066: { ! 1067: for( ; lnno_cnt < scnhdr.s_nlnno; lnno_cnt++ ) ! 1068: { ! 1069: if (eptr->l_lnno == 0) { ! 1070: if (symb == NULL) ! 1071: break; ! 1072: ldtbread(symb, eptr->l_addr.l_symndx, &sentry); ! 1073: linaddr = sentry.n_value; ! 1074: if (loc <= linaddr) ! 1075: goto symfind; ! 1076: } ! 1077: else if (eptr->l_addr.l_paddr >= loc) { ! 1078: linaddr = eptr->l_addr.l_paddr; ! 1079: goto symfind; ! 1080: } ! 1081: FREAD(eptr, LINESZ, 1, l_ptr); ! 1082: } ! 1083: /* Cannot restart based on line number information. ! 1084: * Try to use symbol table information to find restart ! 1085: * point. ! 1086: */ ! 1087: if (symb == NULL) ! 1088: linaddr = BADADDR; ! 1089: else ! 1090: /* If no further line numbers have been found, ! 1091: * the address of the section end will be a ! 1092: * candidate for a restart point. ! 1093: */ ! 1094: linaddr = s_end; ! 1095: } ! 1096: symfind: ! 1097: /* Find next function symbol table entry. */ ! 1098: for( ; next_function; currfunc = next_function, next_function = next_function->nextfunc ) ! 1099: if (next_function->faddr >= loc) ! 1100: { ! 1101: symaddr = next_function->faddr; ! 1102: break; ! 1103: } ! 1104: #if OLIST ! 1105: else ! 1106: funcs_listed += 1; ! 1107: ! 1108: if (next_function == NULL) ! 1109: symaddr = curfile->tend; ! 1110: #else ! 1111: #if AR32W || AR32WR ! 1112: if (next_function == NULL) ! 1113: symaddr = scnhdr.s_paddr + scnhdr.s_size; ! 1114: #else ! 1115: /* scan the symbol table */ ! 1116: if ((filhdr.f_nsyms != 0L) && (symb != NULL) && (ldtbseek(symb) != FAILURE)) { ! 1117: /* ! 1118: * set firstfn equal to the symbol table index ! 1119: * of the first function symbol table entry. ! 1120: * The search for the next function symbol ! 1121: * table entry will always begin at firstfn. ! 1122: */ ! 1123: septr = &stbentry; ! 1124: if (firstfn == BADADDR) { ! 1125: ldtbread (symb, 0, septr); ! 1126: for (sindex = 1+septr->n_numaux; (sindex<filhdr.f_nsyms) ! 1127: && ((septr->n_scnum<1) || (!ISFCN(septr->n_type) ! 1128: || (septr->n_value < scnhdr.s_paddr) ! 1129: || (septr->n_value > s_end))); sindex++) { ! 1130: ldtbread (symb, sindex, septr); ! 1131: sindex += septr->n_numaux; ! 1132: } ! 1133: firstfn = sindex -1 - septr->n_numaux; ! 1134: } ! 1135: ldtbread(symb, firstfn, septr); ! 1136: sindex = firstfn + 1 + septr->n_numaux; ! 1137: for (;(sindex < filhdr.f_nsyms) && ((septr->n_scnum < 1) ! 1138: || (septr->n_numaux == 0) || ( !ISFCN(septr->n_type)) ! 1139: || (septr->n_value < scnhdr.s_paddr) ! 1140: || (septr->n_value > s_end) ! 1141: || (septr->n_value <= loc)); sindex++) { ! 1142: ldtbread(symb, sindex, septr); ! 1143: sindex += septr->n_numaux; ! 1144: } ! 1145: /* ! 1146: * If the next fuction symbol table entry has been ! 1147: * found, it is a candidate for a restart point. ! 1148: * If the entire symbol table has been read, and a ! 1149: * possible restart point has not been found, the end ! 1150: * of the section is a candidate for a restart point. ! 1151: */ ! 1152: if ((sindex - septr->n_numaux) == filhdr.f_nsyms) ! 1153: symaddr = s_end; ! 1154: else ! 1155: symaddr = septr->n_value; ! 1156: } ! 1157: /* end of the section is end of the function */ ! 1158: #endif ! 1159: #endif ! 1160: ! 1161: if (symaddr == BADADDR) { ! 1162: /* Restart point was not found by searching the ! 1163: * symbol table. ! 1164: */ ! 1165: if (linaddr == BADADDR) { ! 1166: /* Restart point was not found by looking ! 1167: * at line number information. ! 1168: */ ! 1169: #ifdef OLIST ! 1170: if (nosource == FALSE) ! 1171: #endif ! 1172: { ! 1173: printf ("\n\t**\tCANNOT FIND NEXT LINE NUMBER\t\t\t**\n"); ! 1174: printf ("\t** CANNOT FIND NEXT FUNCTION SYMBOL TABLE ENTRY\t**\n"); ! 1175: printf ("\t** FOLLOWING DISASSEMBLY MAY BE OUT OF SYNC\t\t**\n"); ! 1176: } ! 1177: return (FAILURE); ! 1178: } ! 1179: else { ! 1180: /* The next line number entry will be the ! 1181: * restart point. ! 1182: */ ! 1183: paddr = linaddr; ! 1184: #ifdef OLIST ! 1185: if (nosource == FALSE) ! 1186: #endif ! 1187: { ! 1188: printf ("\n\t** OBJECT CODE WILL BE DUMPED UNTIL\t**\n"); ! 1189: printf ("\t** THE NEXT BREAKPOINTABLE LINE NUMBER\t**\n"); ! 1190: } ! 1191: } ! 1192: } ! 1193: else if (linaddr == BADADDR) { ! 1194: /* The next function symbol table entry or the end ! 1195: * of the section will be the restart point. ! 1196: */ ! 1197: paddr = symaddr; ! 1198: #ifdef OLIST ! 1199: if (nosource == FALSE) ! 1200: #endif ! 1201: { ! 1202: printf ("\n\t** OBJECT CODE WILL BE DUMPED UNTIL\t**\n"); ! 1203: printf ("\t** THE BEGINNING OF THE NEXT FUNCTION\t**\n"); ! 1204: printf ("\t** OR UNTIL THE END OF THE SECTION\t**\n"); ! 1205: } ! 1206: } ! 1207: else { ! 1208: /* The smaller address of the next line number ! 1209: * entry and the next function symbol table entry ! 1210: * will be the restart point. ! 1211: */ ! 1212: paddr = (linaddr < symaddr)? linaddr: symaddr; ! 1213: #ifdef OLIST ! 1214: if (nosource == FALSE) ! 1215: #endif ! 1216: { ! 1217: printf ("\n\t** OBJECT CODE WILL BE DUMPED UNTIL\t**\n"); ! 1218: printf ("\t** RESTART POINT IS REACHED\t\t**\n"); ! 1219: } ! 1220: } ! 1221: dumpaddr = (loc < paddr - scnhdr.s_paddr)? (paddr -scnhdr.s_paddr): ! 1222: paddr; ! 1223: for (; loc < dumpaddr; ) { ! 1224: /* Dump bytes until the restart point is reached. */ ! 1225: #ifdef OLIST ! 1226: if (nosource == FALSE) ! 1227: #endif ! 1228: printf("\t"); ! 1229: prt_offset(); ! 1230: #ifdef B16 ! 1231: getbyte( t_ptr ); ! 1232: if (loc < dumpaddr) ! 1233: getbyte( t_ptr ); ! 1234: #endif ! 1235: #ifdef MC68 ! 1236: get2bytes(t_ptr); ! 1237: #endif ! 1238: #ifdef N3B ! 1239: get2bytes(t_ptr); ! 1240: #endif ! 1241: #ifdef M32 ! 1242: get1byte(t_ptr); ! 1243: #endif /* M32 */ ! 1244: sprintf(mneu,""); ! 1245: printline(); ! 1246: } /* end of dump of unused object code */ ! 1247: ! 1248: #ifdef OLIST ! 1249: if ( nosource == FALSE ) ! 1250: #endif ! 1251: printf("\n\t** DISASSEMBLER RESYNCHRONIZED **\n"); ! 1252: return(SUCCESS); ! 1253: ! 1254: } ! 1255: /* ! 1256: * sect_name () ! 1257: * ! 1258: * If labels are to be looked up, the 'looklabel' routine needs to know ! 1259: * the number of the section being processed. Compare the section name ! 1260: * to the stored names, created in 'build_labels', and return the ! 1261: * appropriate section number. ! 1262: */ ! 1263: ! 1264: short ! 1265: sect_name() ! 1266: ! 1267: { ! 1268: /* the following 2 items are from _extn.c */ ! 1269: extern char *sname; ! 1270: extern FILHDR filhdr; ! 1271: ! 1272: unsigned short i; ! 1273: ! 1274: for (i = 1; i < filhdr.f_nscns +1; i++) ! 1275: if (strcmp(sname,section[i]) == STRNGEQ) ! 1276: return(i); ! 1277: ! 1278: return (FAILURE); ! 1279: } ! 1280: ! 1281: #if N3B | U3B | M32 | U3B5 ! 1282: /* ! 1283: * sfpconv(fprep, fpdoub) ! 1284: * ! 1285: * This routine will convert the long "fprep" single precision ! 1286: * floating point representation of a number into its decimal ! 1287: * equivalent. The result will be stored in *fpdoub. The routine ! 1288: * will return a value indicating what type of floating point ! 1289: * number was converted. ! 1290: */ ! 1291: sfpconv(fprep, fpdoub) ! 1292: long fprep; ! 1293: double *fpdoub; ! 1294: { ! 1295: unsigned short exponent; ! 1296: short leadbit, signbit; ! 1297: long mantissa; ! 1298: double dtemp, dec2exp; ! 1299: ! 1300: exponent = (unsigned short)((fprep>>23) & 0xffL); ! 1301: /* exponent is bits 1-8 of the long */ ! 1302: ! 1303: mantissa = fprep & 0x7fffffL; ! 1304: /* mantissa is bits 9-31 of the long */ ! 1305: ! 1306: signbit = (fprep>>31) & 0x1L; ! 1307: /* sign bit (1-negative, 0-positive) is bit 0 of long */ ! 1308: ! 1309: leadbit = 1; ! 1310: /* implied bit to the left of the decimal point */ ! 1311: ! 1312: if (exponent==255) ! 1313: if (mantissa) ! 1314: return(NOTANUM); ! 1315: else ! 1316: return((signbit)? NEGINF: INFINITY); ! 1317: ! 1318: if (exponent==0) ! 1319: if (mantissa) ! 1320: /* This is a denormalized number. The implied bit to ! 1321: * the left of the decimal point is 0. ! 1322: */ ! 1323: leadbit = 0; ! 1324: else ! 1325: return((signbit)? NEGZERO: ZERO); ! 1326: ! 1327: /* ! 1328: * Convert the 23 bit mantissa into "I.fraction" where ! 1329: * "I" is the implied bit. The 23 bits are divided by ! 1330: * 2 to the 23rd power to transform the mantissa into a ! 1331: * fraction. Then the implied bit is added on. ! 1332: */ ! 1333: dtemp = (double)(leadbit + (double)mantissa/TWO_23); ! 1334: ! 1335: /* Calculate 2 raised to the (exponent-BIAS) power and ! 1336: * store it in a double. ! 1337: */ ! 1338: if (exponent < BIAS) ! 1339: for(dec2exp=1; exponent < BIAS; ++exponent) ! 1340: dec2exp /= 2; ! 1341: else ! 1342: for(dec2exp=1; exponent > BIAS; --exponent) ! 1343: dec2exp *= 2; ! 1344: ! 1345: /* Multiply "I.fraction" by 2 raised to the (exponent-BIAS) ! 1346: * power to obtain the decimal floating point number. ! 1347: */ ! 1348: *fpdoub = dtemp *dec2exp; ! 1349: ! 1350: if (signbit) ! 1351: *fpdoub = -(*fpdoub); ! 1352: return(FPNUM); ! 1353: } ! 1354: #endif /* N3B | U3B | M32 | U3B5 */ ! 1355: ! 1356: /* ! 1357: * stripped () ! 1358: * ! 1359: * Is the file stripped (no line number entries)? ! 1360: * If so, return TRUE else FALSE. ! 1361: */ ! 1362: ! 1363: stripped() ! 1364: ! 1365: { ! 1366: extern SCNHDR scnhdr; /* from _extn.c */ ! 1367: ! 1368: return( (scnhdr.s_nlnno == 0) ? TRUE : FALSE); ! 1369: } ! 1370: ! 1371: /* ! 1372: * fatal() ! 1373: * ! 1374: * print an error message and quit ! 1375: */ ! 1376: ! 1377: fatal( message ) ! 1378: char *message; ! 1379: { ! 1380: extern char *fname; ! 1381: ! 1382: fprintf( stderr, "\n%s%s: %s: %s\n", SGS, TOOL, fname, message ); ! 1383: exit(1); ! 1384: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.