home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OBJASM.ZIP / OPROCESS.C < prev    next >
C/C++ Source or Header  |  1990-12-19  |  36KB  |  1,171 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "o.h"
  4.  
  5. extern unsigned long data_offset;
  6. extern char *buff_end;
  7. extern char *buff_cur;
  8. extern char *buff_beg;
  9. extern char buff[];
  10.  
  11. /*
  12. ** Local Variables
  13. */
  14. static char     hex_comment[COMSIZE] = {0};
  15. static char     idb_buff[256];
  16. static char     dup_buff[256];
  17. static char     struc_buff[256];
  18. static char     structure_form[128];
  19. static NODE_T   *sex_node;
  20. static NODE_T   *data_node;
  21. static DAT_T    *data_rec;
  22. static int      record_overused = 0;
  23.  
  24. /*
  25. ** Local Prototypes
  26. */
  27. void pub_advance( void );
  28. void fix_advance( void );
  29. void lone_public( void );
  30. void data_byte( int );
  31. void pre_dups( long, int );
  32. int proc_idb( int, unsigned long, int *, int, unsigned int *, unsigned long *);
  33. int proc_label( void );
  34. int proc_fixup( void );
  35. int proc_normal( int );
  36. void iterated( DAT_T *, DAT_T * );
  37. void enumerated( DAT_T *, DAT_T *, int );
  38. void proc_drec( DAT_T *, DAT_T *, int );
  39. NODE_T *list_sex( NODE_T *, int );
  40.  
  41. void pub_advance()
  42. {
  43.     /*
  44.     ** Advance to next Publics record
  45.     */
  46.     pub_node = traverse( pub_node, RIGHT );
  47.     pub_rec = (PUB_T *)pub_node->data;
  48. }
  49.  
  50. void fix_advance()
  51. {
  52.     /*
  53.     ** Advance to next Fixup record
  54.     */
  55.     fix_node = traverse( fix_node, RIGHT );
  56.     fix_rec = (FIX_T *)fix_node->data;
  57. }
  58.  
  59. void hint_advance()
  60. {
  61.     /*
  62.     ** Advance to next Hint record
  63.     */
  64.     hint_node = traverse( hint_node, RIGHT );
  65.     hint_rec = (HINT_T *)hint_node->data;
  66. }
  67.  
  68. void lone_public()
  69. {
  70.     char    operand[80];
  71.     long    relative;
  72.  
  73.     if ( pass == 3 ) {
  74.         out_label( pub_rec->name );
  75.         out_directive( "=" );
  76.         if ( segment == 0 ) {
  77.             sprintf( operand, "0%04Xh", pub_rec->offset );
  78.         } else {
  79.             relative = (long)pub_rec->offset - inst_offset;
  80.             if ( relative < 0L ) {
  81.                 sprintf( operand, "$ - 0%04lXh", -relative );
  82.             } else {
  83.                 sprintf( operand, "$ + 0%04lXh", relative );
  84.             }
  85.         }
  86.         out_operand( operand );
  87.         out_endline();
  88.     }
  89. }
  90.  
  91. int data_check( offset )
  92.     unsigned int    offset;
  93. {
  94.     int             direct;
  95.  
  96.     /*
  97.     ** Are we at a public symbol?
  98.     */
  99.     pub_search.seg_idx = segment;
  100.     pub_search.offset  = inst_offset + offset;
  101.     direct = RIGHT;
  102.     while ( pub_node != public_tree
  103.             && (direct = pub_compare( &pub_search, pub_rec )) == LEFT ) {
  104.         lone_public();
  105.         pub_advance();
  106.     }
  107.     if ( direct == EQUAL ) {
  108.         return( LABEL );
  109.     }
  110.  
  111.     /*
  112.     ** Are we at a fix-up position?
  113.     */
  114.     fix_search.seg_idx    = segment;
  115.     fix_search.dat_offset = data_offset;
  116.     fix_search.offset     = (int)(inst_offset - data_offset) + offset;
  117.     direct = RIGHT;
  118.     while ( fix_node != fix_tree 
  119.             && (direct = fix_compare( &fix_search, fix_rec )) == LEFT ) {
  120.         fix_advance();
  121.     }
  122.     /* Are we on a fixup that is in the right position?  We can't just test
  123.     ** whether the "direct==EQUAL" because we could have fixups from the
  124.     ** next data record showing up.
  125.     */
  126.     if ( fix_rec->seg_idx == segment
  127.       && fix_rec->dat_offset + fix_rec->offset == inst_offset + offset ) {
  128.         return( FIXUP );
  129.     }
  130.     /*
  131.     ** Are we close to a public symbol? (prevents 2 byte operands)
  132.     */
  133.     if ( pub_node != public_tree 
  134.             && pub_rec->seg_idx == pub_search.seg_idx 
  135.             && pub_rec->offset  == pub_search.offset + 1 ) {
  136.         return( BAD );
  137.     }
  138.     /*
  139.     ** Are we close to a fix-up? (prevents 2 byte operands)
  140.     */
  141.     if ( fix_node != fix_tree
  142.       && fix_rec->seg_idx == segment
  143.       && fix_rec->dat_offset + fix_rec->offset == inst_offset + offset + 1 ) {
  144.         return( BAD );
  145.     }
  146.     return( 0 );
  147. }
  148.  
  149. void data_byte( size )
  150.     int     size;
  151. {
  152.     char    *opcode;
  153.     int     out_count;
  154.     int     times;
  155.     char    operand[50];
  156.     char    rev_buff[10];
  157.     char    temp[4];
  158.  
  159.     if ( last_pub_rec && pass == 3 ) {
  160.         if ( last_pub_rec->type == FAR ) {
  161.             out_directive("=");
  162.             out_operand("$");
  163.         }
  164.         if ( last_pub_rec->type == NEAR ) {
  165.             out_endline();
  166.         }
  167.     }
  168.  
  169.     opcode = size_to_opcode( size, × );
  170.  
  171.     while ( times ) {
  172.         out_count = 0;
  173.         strcpy( operand, "0" );
  174.         while ( out_count < size ) {
  175.             rev_buff[ out_count ] = (unsigned char)buff_regetc();
  176.             out_count++;
  177.         }
  178.         out_count = size;
  179.         while ( out_count ) {
  180.             --out_count;
  181.             sprintf( temp, "%02X", (unsigned char)rev_buff[out_count] );
  182.             strcat( operand, temp );
  183.         }
  184.         strcat( operand, "h" );
  185.         if ( pass == 3 ) {
  186.             out_directive( opcode );
  187.             out_operand( operand );
  188.             out_endline();
  189.         }
  190.         --times;
  191.     }
  192.     last_pub_rec = NULL;
  193. }
  194.  
  195. void pre_dups( count, orgable )
  196.     long    count;
  197.     int     orgable;
  198. {
  199.     char    *opcode;
  200.     char    *operand;
  201.     char    temp[80];
  202.     int     times;
  203.  
  204.     if ( last_pub_rec && pass == 3 ) {
  205.         if ( last_pub_rec->type == FAR ) {
  206.             out_directive("=");
  207.             out_operand("$");
  208.         }
  209.         if ( last_pub_rec->type == NEAR ) {
  210.             out_endline();
  211.         }
  212.     }
  213.  
  214.     if ( count != 0L ) {
  215.         if ( (orgable && inst_offset == 0 && count > 0L) || count < 0L ) {
  216.             opcode = "ORG";
  217.             sprintf( temp, "0%04Xh", inst_offset + count );
  218.             operand = temp;
  219.         } else {
  220.             if ( compatibility == 2 ) {
  221.                 operand = "1";                  /* Default operand */
  222.                 switch( (int)count ) {
  223.                     case 1:    opcode = "rb";  break;
  224.                     case 2:    opcode = "rw";  break;
  225.                     case 4:    opcode = "rd";  break;
  226.                     default:    opcode = "rs";
  227.                                 sprintf( temp, "0%04Xh", count );
  228.                                 operand = temp;
  229.                                 break;
  230.                 }
  231.             } else {
  232.                 operand = "1 dup (?)";          /* Default operand */
  233.  
  234.                 opcode = size_to_opcode( (int)count, × );
  235.  
  236.                 sprintf( temp, "%d dup(?)", times );
  237.                 operand = temp;
  238.             }
  239.         }
  240.         if ( pass == 3 && count != 0L ) {
  241.             out_directive( opcode );
  242.             out_operand( operand );
  243.             out_endline();
  244.         }
  245.         inst_offset += count;
  246.         last_pub_rec = NULL;
  247.     }
  248. }
  249.  
  250. int proc_idb( depth, mult, dup_only, extended, length_used, repeat_cnt )
  251.     int             depth;
  252.     unsigned long   mult;
  253.     int             *dup_only;
  254.     int             extended;
  255.     unsigned int    *length_used;
  256.     unsigned long   *repeat_cnt;
  257. {
  258.     unsigned long   repeat;
  259.     unsigned int    num_blocks;
  260.     unsigned int    blocks;
  261.     unsigned int    length;
  262.     int             data;
  263.     unsigned int    data_size;
  264.     unsigned int    result;
  265.     int             fix_size;
  266.     char            operand[80];
  267.     unsigned char   rev_buff[10];
  268.     unsigned int    out_count;
  269.     int             dcheck;
  270.     int             dummy;
  271.  
  272.     result = 512;
  273.  
  274.     repeat = (unsigned long)buff_regetc();
  275.     repeat += (unsigned long)buff_regetc() << 8;
  276.     *length_used += 2;
  277.  
  278.     if ( extended ) {
  279.         repeat += (unsigned long)buff_regetc() << 16;
  280.         repeat += (unsigned long)buff_regetc() << 24;
  281.         *length_used += 2;
  282.     }
  283.     num_blocks = buff_regetc();
  284.     num_blocks += buff_regetc() << 8;
  285.     *length_used += 2;
  286.  
  287.     if ( repeat_cnt ) {             /* Return repeat count if needed */
  288.         *repeat_cnt = repeat;
  289.     }
  290.  
  291.     if ( repeat != 1 || num_blocks != 0 ) {
  292.         sprintf( idb_buff, "%ld dup(", repeat );
  293.         strcat( dup_buff, idb_buff );
  294.     }
  295.  
  296.     mult *= repeat;
  297.  
  298.     if ( num_blocks ) {
  299.         blocks = num_blocks;
  300.         while ( blocks ) {
  301.             if ( depth == 2 ) {
  302.                 *dup_only = TRUE;
  303.             }
  304.             data_size = proc_idb( depth+1, mult, dup_only, extended,
  305.                                                        length_used, NULL );
  306.             if ( data_size < result ) {
  307.                 result = data_size;
  308.             }
  309.             --blocks;
  310.             if ( blocks != 0 ) {
  311.                 strcat( dup_buff, "," );
  312.                 strcat( struc_buff, "," );
  313.             }
  314.         }
  315.     } else {
  316.         length = buff_regetc();
  317.         result = length;
  318.         *length_used += length + 1;         /* one extra for the length byte */
  319.         data_size = 0;
  320.         while ( length ) {
  321.             do {
  322.                 data = buff_getc();
  323.                 if ( data == EOF ) {
  324.                     break;
  325.                 }
  326.                 if ( data < ' ' || data > '~' ) {
  327.                     break;
  328.                 }
  329.                 data_size++;
  330.                 inst_offset += mult;
  331.                 dcheck = data_check( 0 );
  332.             } while ( *dup_only && (dcheck == NORMAL || dcheck == BAD) );
  333.             if ( *dup_only && data_size >= data_string ) {
  334.                 buff_reseek();
  335.                 length -= data_size;
  336.                 idb_buff[0] = '\'';
  337.                 out_count = 1;
  338.                 while ( data_size ) {
  339.                     data = buff_regetc();
  340.                     idb_buff[out_count++] = (char)data;
  341.                     --data_size;
  342.                 }
  343.                 idb_buff[out_count++] = '\'';
  344.                 idb_buff[out_count] = '\0';
  345.                 if ( depth != 1 ) {
  346.                     *dup_only = TRUE;
  347.                 }
  348.                 strcat( dup_buff, idb_buff );
  349.                 strcat( struc_buff, idb_buff );
  350.             } else {
  351.                 /*
  352.                 ** Was it a fixup?
  353.                 */
  354.                 inst_offset -= data_size * mult;
  355.                 buff_reseek();      /* Back to start, string look */
  356.                                     /* may have moved ptr         */
  357.                 if ( data_check( 0 ) == FIXUP ) {
  358.                     if ( depth != 1 ) {
  359.                         *dup_only = TRUE;
  360.                     }
  361.                     if ( fix_rec->form == POINTER ) {
  362.                         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  363.                                                     FAR, FALSE, &dummy, DS );
  364.                     } else {
  365.                         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  366.                                                     NEAR, FALSE, &dummy, DS );
  367.                     }
  368.                     inst_offset += fix_size * mult;
  369.                     length -= fix_size;
  370.                     if ( pass == 3 ) {
  371.                         strcat( dup_buff, operand );
  372.                         strcat( struc_buff, operand );
  373.                     }
  374.                     buff_empty();
  375.                 } else {
  376.                     /*
  377.                     ** Nope, not a string.  Leave one or multiple bytes
  378.                     */
  379.                     data_size = length;
  380.                     if ( data_size != 2 && data_size != 4 && data_size != 6
  381.                                         && data_size != 8 && data_size != 10 ) {
  382.                         data_size = 1;
  383.                     }
  384.                     strcat( dup_buff, "0" );
  385.                     if ( depth == 1 ) {
  386.                         strcat( struc_buff, "0" );
  387.                     }
  388.                     out_count = 0;
  389.                     while ( out_count < data_size ) {
  390.                         rev_buff[ out_count ] = (unsigned char)buff_regetc();
  391.                         out_count++;
  392.                     }
  393.                     out_count = data_size;
  394.                     while ( out_count ) {
  395.                         --out_count;
  396.                         if ( depth != 1 ) {
  397.                             if ( rev_buff[out_count] != 0 ) {
  398.                                 *dup_only = TRUE;
  399.                             }
  400.                         }
  401.                         sprintf( idb_buff, "%02X", rev_buff[out_count] );
  402.                         strcat( dup_buff, idb_buff );
  403.                         if ( depth == 1 ) {
  404.                             strcat( struc_buff, idb_buff );
  405.                         }
  406.                     }
  407.                     strcat( dup_buff, "h" );
  408.                     if ( depth == 1 ) {
  409.                         strcat( struc_buff, "h" );
  410.                     }
  411.  
  412.                     length -= data_size;
  413.                     inst_offset += mult * data_size;
  414.                 }
  415.             }
  416.             if ( length ) {
  417.                 strcat( dup_buff, "," );
  418.             }
  419.         }
  420.     }
  421.  
  422.     if ( repeat != 1 || num_blocks != 0 ) {
  423.         strcat( dup_buff, ")" );
  424.     }
  425.  
  426.     return( result );
  427. }
  428.  
  429.  
  430. int proc_label()
  431. {
  432.     char            text[50];
  433.     unsigned long   past_seg;
  434.     char            *size_text;
  435.  
  436.     if ( pub_rec->type == FAR ) { 
  437.         size_text = "THIS FAR";
  438.     } else {
  439.         size_text = "THIS NEAR";
  440.     }
  441.  
  442.     if ( pass == 3 ) {
  443.         if ( pub_rec->offset >= seg_rec->length ) {
  444.             past_seg = pub_rec->offset - seg_rec->length;
  445.             if ( past_seg == 0 ) {
  446.                 strcpy( text, "$" );
  447.             } else {
  448.                 sprintf( text, "$ + 0%04Xh", size_text, past_seg );
  449.             }
  450.             out_line( pub_rec->name, "=", text, "" );
  451.         } else {
  452.             if ( pub_rec->type == FAR ) {
  453.                 out_line( pub_rec->name, "equ", "THIS FAR", "" );
  454.             } else {
  455.                 if ( pub_rec->type == NEAR ) {
  456.                     /* Put a colon ':' on labels within code segments */
  457.                     sprintf( text, "%s:", pub_rec->name );
  458.                     out_label( text );
  459.                 } else {
  460.                     out_label( pub_rec->name );
  461.                 }
  462.             }
  463.         }
  464.     }
  465.     last_pub_rec = pub_rec;
  466.     pub_advance();
  467.     if ( pub_rec->seg_idx == last_pub_rec->seg_idx 
  468.             && pub_rec->offset == last_pub_rec->offset ) {
  469.         if ( pass == 3 ) {
  470.             if ( last_pub_rec->type != NEAR ) {
  471.                 out_directive( "equ" );
  472.                 sprintf( text, "%s", size_text );
  473.                 out_operand( text );
  474.             }
  475.             out_endline();
  476.         }
  477.         proc_label();
  478.     }
  479.     return( 0 );
  480. }
  481.  
  482. int proc_fixup()
  483. {
  484.     int     fix_size;
  485.     int     fix_form;
  486.     int     fix_extended;
  487.     char    operand[100];
  488.     int     dummy;
  489.  
  490.     fix_form     = fix_rec->form;
  491.     fix_extended = fix_rec->extended;
  492.  
  493.     if ( fix_form == POINTER ) {
  494.         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  495.                                                     FAR, FALSE, &dummy, DS );
  496.     } else {
  497.         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  498.                                                     NEAR, FALSE, &dummy, DS );
  499.     }
  500.  
  501.     if ( pass == 3 ) {
  502.         if ( fix_form == OFFSET && fix_extended ) {
  503.             out_directive( "dd" );
  504.         } else {
  505.             if ( fix_form == POINTER && fix_extended ) {
  506.                 out_directive( "df" );
  507.             } else {
  508.                 out_directive( fix_type[fix_form].form );
  509.             }
  510.         }
  511.     }
  512.     inst_offset += fix_size;
  513.  
  514.     if ( pass == 3 ) {
  515.         out_operand( operand );
  516.         out_endline();
  517.     }
  518.     buff_empty();
  519.     if ( last_pub_rec ) {
  520.         last_pub_rec->type = size_to_type(fix_size);
  521.         last_pub_rec = NULL;
  522.     }
  523.     return( fix_size );
  524. }
  525.  
  526. int proc_normal( inst_proc )
  527.     int     inst_proc;
  528. {
  529.     int     data_size;
  530.     int     data;
  531.     int     inst_length;
  532.     int     zeros;
  533.     int     string_limit;
  534.     int     dcheck;
  535.     char    temp[3];
  536.     int     this_size;
  537.     int     data_type;
  538.     int     direct;
  539.  
  540.     data_type = UNKNOWN;
  541.     /*
  542.     ** Step 0, determine if there is a hint record at this position
  543.     */
  544.     hint_search.seg_idx    = segment;
  545.     hint_search.offset     = inst_offset;
  546.     direct = RIGHT;
  547.     while ( hint_node != hint_tree
  548.             && (direct = hint_compare( &hint_search, hint_rec )) == LEFT ) {
  549.         hint_advance();
  550.         direct = RIGHT;
  551.     }
  552.     if ( direct == EQUAL ) {
  553.         data_type = hint_rec->hint_type;
  554.     }
  555.  
  556.     if ( data_type == UNKNOWN ) {       /* Default, search for string */
  557.         /*
  558.         ** Step 1, Is it a string?
  559.         */
  560.         data_size = 0;
  561.         zeros = TRUE;
  562.         do {
  563.             data = buff_getc();
  564.             if ( data == EOF ) {
  565.                 break;
  566.             }
  567.             if ( data != 0 && data != 0x0A && data != 0x0D && data != 0x1B
  568.                   && (data < ' ' || data > '~') ) {
  569.                 break;
  570.             }
  571.             if ( data != 0 ) {
  572.                 zeros = FALSE;
  573.             }
  574.             data_size++;
  575.             inst_offset++;
  576.             dcheck = data_check( 0 );
  577.         } while ( dcheck == NORMAL || dcheck == BAD );
  578.  
  579.         if ( inst_proc ) {
  580.             string_limit = code_string;
  581.         } else {
  582.             string_limit = data_string;
  583.         }
  584.         if ( data_size >= string_limit || (zeros && data_size > 1) ) {
  585.             if ( last_pub_rec && last_pub_rec->type > FAR ) {
  586.                 this_size = type_to_size(last_pub_rec->type);
  587.                 if ( data_size < this_size ) {
  588.                     last_pub_rec->type = BYTE_PTR;
  589.                 }
  590.                 data_byte( this_size );
  591.                 buff_reseek();
  592.                 inst_offset -= data_size;
  593.                 inst_offset += this_size;
  594.                 last_pub_rec = NULL;
  595.                 return( this_size );
  596.             } else {
  597.                 /*
  598.                 ** Either near, far, or unknown
  599.                 */
  600.                 if ( last_pub_rec && pass == 3 ) {
  601.                     if ( last_pub_rec->type == FAR ) {
  602.                         out_directive("=");
  603.                         out_operand("$");
  604.                     }
  605.                     if ( last_pub_rec->type == NEAR ) {
  606.                         out_endline();
  607.                     }
  608.                 }
  609.                 empty_string( data_size );
  610.                 buff_reseek();
  611.                 last_pub_rec = NULL;
  612.                 return( data_size );
  613.             }
  614.         }
  615.         buff_reseek();
  616.         inst_offset -= data_size;
  617.     }
  618.  
  619.     if ( data_type == NEAR || (inst_proc && data_type == UNKNOWN) ) {
  620.         data = (unsigned char)buff_getc();
  621. #ifdef DEBUG
  622.         printf("DIS-ASSEMBLY Instruction lookup [%02X]\n", data );
  623. #endif
  624.         hex_finish = TRUE;
  625.  
  626.         inst_length = (*instr[data].rtn)
  627.                         ((unsigned char)data,
  628.                         instr[data].text,
  629.                         instr[data].special );
  630.         if ( inst_length == 0 ) {       /* Wrong, it wasn't an instruction */
  631.             data_type = UNKNOWN;
  632.         }
  633.     } else {
  634.         inst_length = 0;
  635.     }
  636.  
  637.     if ( inst_length ) {
  638.         /*
  639.         ** Check for instruction routine returning the proper number
  640.         ** of bytes eaten from buffer.
  641.         */
  642.         if ( buff_cur - buff_beg != inst_length ) {
  643. #ifdef DEBUG
  644.             printf("PN: Buffer remaining: %04d Length remaining: %04d\n",
  645.                                         buff_cur - buff_beg, inst_length );
  646. #endif
  647.             fmt_error("Dis-assembly Internal Instruction Processing" );
  648.         }
  649.  
  650.         /*
  651.         ** Yes, instruction, throw away buffer
  652.         */
  653.         if ( strlen(hex_comment) == 0 ) {
  654.             sprintf( hex_comment, "%04X: ", inst_offset );
  655.         }
  656.         this_size = inst_length;
  657.         while ( this_size ) {
  658.             sprintf( temp, "%02X", (unsigned char)buff_regetc() );
  659.             strcat( hex_comment, temp );
  660.             --this_size;
  661.         }
  662.         if ( hex_finish ) {
  663.             if ( pass == 3 ) {
  664.                 if ( hex_output ) {
  665.                     out_comment( hex_comment );
  666.                 }
  667.                 out_endline();
  668.             }
  669.             hex_comment[0] = '\0';
  670.         }
  671.         inst_offset += inst_length;
  672.         if ( last_pub_rec ) {
  673.             if ( last_pub_rec->type != FAR ) {
  674.                 last_pub_rec->type = NEAR;
  675.             }
  676.             last_pub_rec = NULL;
  677.         }
  678.         return( inst_length );
  679.     }
  680.  
  681.     /*
  682.     ** Ingore any assumes that might have been pending
  683.     */
  684.     abort_assumes();
  685.  
  686.     /*
  687.     ** Nope, not instruction.  Leave byte
  688.     */
  689.     buff_reseek();      /* Back to start, instruction */
  690.                         /* look may have moved ptr    */
  691.     if ( last_pub_rec && last_pub_rec->type > FAR ) {
  692.         if ( last_pub_rec->type == UNKNOWN ) {
  693.             last_pub_rec->type = BYTE_PTR;      /* Default if not known */
  694.         }
  695.         if ( data_type == UNKNOWN ) {           /* Default if no hint */
  696.             data_type = last_pub_rec->type;
  697.         }
  698.         last_pub_rec->type = data_type;         /* Assign actual type */
  699.     } else {
  700.         if ( data_type == UNKNOWN ) {
  701.             data_type = BYTE_PTR;
  702.         }
  703.     }
  704.     data_size = type_to_size( data_type );
  705.     data_byte( data_size );
  706.     last_pub_rec = NULL;
  707.     inst_offset += data_size;
  708.     return( data_size );
  709. }
  710.  
  711. void iterated( data_rec, next_rec )
  712.     DAT_T   *data_rec;
  713.     DAT_T   *next_rec;
  714. {
  715.     char            temp[20];
  716.     unsigned int    length;
  717.     unsigned int    length_used;
  718.     PUB_T           *save_pub_rec;
  719.     int             dup_only;
  720.     int             dummy;
  721.     unsigned long   repeat;
  722.     STRUC_T         *this_struc;
  723.  
  724.     length = data_rec->length;
  725.     fseek( o_file, data_rec->file_pos, L_SET );
  726.     length = buff_init( length );
  727.  
  728.     if ( data_check( 0 ) == LABEL ) {
  729.         proc_label();
  730.     }
  731.  
  732.     save_pub_rec = last_pub_rec;
  733.     if ( last_pub_rec ) {
  734.         if ( pass == 3 ) {
  735.             if ( last_pub_rec->type == FAR ) {
  736.                 out_directive("=");
  737.                 out_operand("$");
  738.             }
  739.             if ( last_pub_rec->type == NEAR ) {
  740.                 out_endline();
  741.             }
  742.         }
  743.     }
  744.  
  745.     /*
  746.     ** Process iterated data with this record
  747.     */
  748.     strcpy( structure_form, "" );
  749.     if ( data_rec->structure ) {
  750.         /* Processing for structures */
  751.         dup_only = FALSE;
  752.     } else {
  753.         if ( pass == 1 ) {
  754.             dup_only = FALSE;       /* Give 1 chance (pass 1) at structuring */
  755.         } else {
  756.             dup_only = TRUE;
  757.         }
  758.     }
  759.  
  760.     dup_buff[0]   = '\0';
  761.     strcpy( struc_buff, "<" );
  762.  
  763.     while ( length > 0 ) {
  764.         length_used = 0;
  765.         data_rec->size = proc_idb( 1, 1L, &dup_only, data_rec->extended,
  766.                                            &length_used, &repeat );
  767.         sprintf( temp, "(%ld,%1d)", repeat, size_to_type(data_rec->size) );
  768.         strcat( structure_form, temp );
  769.         length -= length_used;
  770.         if ( length ) {
  771.             strcat( dup_buff, "," );
  772.             strcat( struc_buff, "," );
  773.         }
  774.     }
  775.  
  776.     if ( dup_only ) {
  777.         if ( save_pub_rec ) {
  778.             save_pub_rec->type = size_to_type( data_rec->size );
  779.         }
  780.         if ( pass == 3 ) {
  781.             out_directive( size_to_opcode(data_rec->size, &dummy) );
  782.             out_operand( dup_buff );
  783.             out_endline();
  784.         }
  785.     } else {
  786.         /*
  787.         ** Its a structure!
  788.         */
  789.         strcat( struc_buff, ">" );
  790.  
  791.         if ( pass == 1 ) {
  792.             data_rec->structure = struc_insert( structure_form );
  793.         }
  794.  
  795.         this_struc = data_rec->structure;
  796.  
  797.         if ( save_pub_rec ) {
  798.             save_pub_rec->structure = this_struc;
  799.         }
  800.  
  801.         if ( pass == 3 ) {
  802.             sprintf( temp, "struct_%d", this_struc->index );
  803.             out_directive( temp );
  804.             out_operand( struc_buff );
  805.             out_endline();
  806.         }
  807.     }
  808.  
  809.     next_rec;                   /* Prevent unused variable warnings */
  810. }
  811.  
  812.  
  813. void enumerated( data_rec, next_rec, inst_proc )
  814.     DAT_T           *data_rec;
  815.     DAT_T           *next_rec;
  816.     int             inst_proc;
  817. {
  818.     int             length;
  819.     int             result;
  820.     unsigned long   prev_offset;
  821.     int             addition;
  822.     int             dcheck;
  823.  
  824.     /*
  825.     ** Process enumerated data within this record
  826.     */
  827.     length = data_rec->length;
  828.     fseek( o_file, data_rec->file_pos+record_overused, L_SET );
  829.     length = buff_init( length-record_overused );
  830.     addition = 0;
  831.     if ( next_rec ) {
  832.         fseek( o_file, next_rec->file_pos, L_SET );
  833.         addition = 0x10;      /* Longest instruction can be 0x10 bytes long */
  834.         if ( addition > next_rec->length ) {
  835.             addition = next_rec->length;
  836.         }
  837.         length += buff_add( addition );
  838.     }
  839.     while ( length > addition ) {
  840. #ifdef DEBUG
  841.         printf( "DIS-ASSEMBLY processing enumerated %08lX %04X %04X %04X %04X\n", 
  842.                     data_rec, data_rec->offset, data_rec->length, length, 
  843.                     inst_offset );
  844. #endif
  845.         if ( length < 0 ) {
  846.             fmt_error( "Dis-assembly Record Over-run" );
  847.         }
  848.  
  849.         prev_offset = inst_offset;
  850.  
  851.         dcheck = data_check( 0 );
  852.  
  853.         switch ( dcheck ) {
  854.             case BAD:       result = proc_normal( inst_proc );      break;
  855.             case LABEL:     result = proc_label();                  break;
  856.             case FIXUP:     result = proc_fixup();                  break;
  857.             case NORMAL:    result = proc_normal( inst_proc );      break;
  858.         }
  859.  
  860.         length -= result;
  861.  
  862.         if ( (unsigned long)result != inst_offset - prev_offset ) {
  863. #ifdef DEBUG
  864.             printf("Instruction Length was %ld, delta IP = %ld\n",
  865.                                    (long)result, inst_offset - prev_offset );
  866. #endif
  867.             fmt_error("Dis-assembly Instruction Size Error");
  868.         }
  869.  
  870.         if ( data_rec->offset + data_rec->length - length + addition 
  871.                                                         != inst_offset ) {
  872.             fmt_error("Dis-assembly Instruction Mis-alignment");
  873.         }
  874.  
  875.         if ( buff_end - buff_cur != length ) {
  876. #ifdef DEBUG
  877.             printf("Buffer remaining: %04d Length remaining: %04d\n", 
  878.                                             buff_end - buff_cur, length );
  879. #endif
  880.             fmt_error("Dis-assembly Internal Instruction Processing" );
  881.         }
  882.     }
  883.     record_overused = addition - length;
  884. }
  885.  
  886. void proc_drec( data_rec, next_rec, inst_proc )
  887.     DAT_T   *data_rec;
  888.     DAT_T   *next_rec;
  889.     int     inst_proc;
  890. {
  891.     int     orgable;
  892.  
  893. #ifdef DEBUG
  894.     printf("DIS-ASSEMBLY offset %04X\n", data_rec->offset );
  895. #endif
  896.     if ( pass == 3 ) {
  897.         out_newline();
  898.     }
  899.     /*
  900.     ** Do we need an ORG statement or dup(?)'s ?
  901.     */
  902.     if ( inst_offset != data_rec->offset+record_overused ) {
  903.         pub_search.seg_idx = segment;
  904.         pub_search.offset = data_rec->offset+record_overused;
  905.         orgable = TRUE;
  906.         while ( pub_node != public_tree 
  907.                 && pub_compare(&pub_search,pub_rec) == LEFT ) {
  908.             pre_dups( pub_rec->offset - inst_offset, orgable );
  909.             proc_label();
  910.             orgable = FALSE;
  911.         }
  912.         pre_dups( data_rec->offset+record_overused - inst_offset, orgable );
  913.     }
  914.     data_offset = data_rec->offset;
  915.  
  916.     switch( data_rec->type ) {
  917.         case ENUMERATED:
  918.             enumerated( data_rec, next_rec, inst_proc );
  919.             break;
  920.         case ITERATED:
  921.             iterated( data_rec, next_rec );
  922.             break;
  923.     }
  924. }
  925.  
  926.  
  927. NODE_T *list_sex( node, seg_num )
  928.     NODE_T  *node;
  929.     int     seg_num;
  930. {
  931.     SEX_T   *sex_rec;
  932.     EXT_T   *ext_rec;
  933.  
  934.     sex_rec = (SEX_T *)node->data;
  935.     while ( node != sex_tree && sex_rec->seg_index < seg_num ) {
  936.         node = traverse( node, RIGHT );
  937.         sex_rec = (SEX_T *)node->data;
  938.     }
  939.     out_newline();
  940.     while ( node != sex_tree && sex_rec->seg_index == seg_num ) {
  941.         ext_rec = sex_rec->ext_rec;
  942.         if ( ext_rec->used == seg_num ) {       /* Still in this segment? */
  943.             print_ext( sex_rec->ext_rec );
  944.         }
  945.         node = traverse( node, RIGHT );
  946.         sex_rec = (SEX_T *)node->data;
  947.     }
  948.     return( node );
  949. }
  950.  
  951. void process_segment()
  952. {
  953.     NAME_T          *name_rec;
  954.     DAT_T           *next_rec;
  955.     int             inst_proc;
  956.     int             seg_reg;
  957.  
  958.     segment = seg_rec->index;
  959.  
  960.     /*
  961.     ** Skip segments which have no data, no external definitions,
  962.     ** and no public symbols
  963.     */
  964.     if ( seg_rec->length == 0
  965.   && (sex_node == sex_tree || ((SEX_T *)sex_node->data)->seg_index > segment)
  966.   && (pub_node == public_tree || ((PUB_T *)pub_node->data)->seg_idx > segment)
  967.         ) {
  968.         return;
  969.     }
  970.  
  971.     for ( seg_reg = 0; seg_reg < MAX_SEG_REGS; seg_reg++ ) {
  972.         seg_rec->new_mode [seg_reg] = 0;
  973.         seg_rec->new_index[seg_reg] = 0;
  974.         seg_rec->prv_mode [seg_reg] = 0;
  975.         seg_rec->prv_index[seg_reg] = 0;
  976.     }
  977.  
  978.     /* Move to the hint records for this segment */
  979.     while ( hint_node != hint_tree && hint_rec->seg_idx < segment ) {
  980.         hint_node = traverse( hint_node, RIGHT );
  981.     }
  982.  
  983.     name_search.index = seg_rec->name;      /* Look up segment name */
  984.     name_rec = (NAME_T *)find( (char *)&name_search, 
  985.                                             name_tree, name_compare, NULL );
  986.     if ( name_rec == NULL ) fmt_error( "Lost Code Segment Name (Oops!)" );
  987.     cseg_name = name_rec->name;
  988.  
  989. #ifdef DEBUG
  990.     printf("DIS-ASSEMBLY pass %d: segment %s\n", pass, cseg_name);
  991. #endif
  992.  
  993.     if ( seg_rec->bit32 ) {
  994.         segment_mode = 386;
  995.     } else {
  996.         segment_mode = 286;
  997.     }
  998.  
  999.     if ( segment_mode == 386 ) {
  1000.         segment_bytes = 4;
  1001.     } else {
  1002.         segment_bytes = 2;
  1003.     }
  1004.  
  1005.     if ( pass == 3 ) {
  1006.         out_newline();
  1007.         if ( seg_rec->code ) {
  1008.             if ( compatibility == 2 ) {
  1009.                 out_line( cseg_name, "CSEG", "", "" );
  1010.             } else {
  1011.                 out_line( cseg_name, "SEGMENT", "", "" );
  1012.                 seg_rec->new_mode[1] = SEGMENT;     /* Default assume for CS: */
  1013.                 seg_rec->new_index[1] = segment;
  1014.                 adjust_assumes();
  1015.             }
  1016.         } else {
  1017.             if ( compatibility == 2 ) {
  1018.                 if ( stricmp(seg_rec->class->name,"CODE") == 0 ) {
  1019.                     out_line( cseg_name, "CSEG", "", "" );
  1020.                 } else
  1021.                 if ( stricmp(seg_rec->class->name,"DATA") == 0 ) {
  1022.                     out_line( cseg_name, "DSEG", "", "" );
  1023.                 } else
  1024.                 if ( stricmp(seg_rec->class->name,"STACK") == 0 ) {
  1025.                     out_line( cseg_name, "SSEG", "", "" );
  1026.                 } else
  1027.                 if ( stricmp(seg_rec->class->name,"EXTRA") == 0 ) {
  1028.                     out_line( cseg_name, "ESEG", "", "" );
  1029.                 } else {
  1030.                     out_line( cseg_name, seg_rec->class->name, "", "" );
  1031.                 }
  1032.             } else {
  1033.                 out_line( cseg_name, "SEGMENT", "", "" );
  1034.             }
  1035.         }
  1036.         sex_node = list_sex( sex_node, segment );   /* List local extrns */
  1037.     }
  1038.  
  1039. #ifdef DEBUG
  1040.     sprintf( operand, "; Segment mode is %d\n", segment_mode );
  1041.     if ( pass == 3 ) {
  1042.         out_line( "", operand, "", "" );
  1043.     }
  1044. #endif
  1045.  
  1046.     inst_proc = seg_rec->code;
  1047.  
  1048.     last_pub_rec = NULL;
  1049.     inst_offset = 0;                        /* Start at beginning of seg */
  1050.  
  1051.     inst_init();
  1052.  
  1053.     /*
  1054.     ** Loop through all data records for this segment
  1055.     */
  1056.     if ( data_node != data_tree ) {
  1057.         while ( data_rec->seg_idx == segment ) {
  1058.             /*
  1059.             ** Advance to next data record
  1060.             */
  1061.             data_node = traverse( data_node, RIGHT );
  1062.             /*
  1063.             ** Check if we can process this record with extra bytes from
  1064.             ** the next record.  This is to catch any instructions which
  1065.             ** span the record edges. (Only for ENUMERATED records)
  1066.             */
  1067.             next_rec = (DAT_T *)data_node->data;
  1068.             if ( data_node != data_tree && data_rec->type == ENUMERATED &&
  1069.                     next_rec->type == ENUMERATED &&
  1070.                     next_rec->seg_idx == segment && 
  1071.                     data_rec->offset + data_rec->length == next_rec->offset ) {
  1072.                 proc_drec( data_rec, next_rec, inst_proc );
  1073.             } else {
  1074.                 proc_drec( data_rec, NULL, inst_proc );
  1075.             }
  1076.             data_rec = next_rec;
  1077.         }
  1078.     }
  1079.  
  1080.     if ( pass == 3 && pub_rec->seg_idx == segment ) {
  1081.         out_newline();                  /* Blank line before trailings */
  1082.     }
  1083.     while ( pub_rec->seg_idx == segment ) {
  1084.         pre_dups( pub_rec->offset - inst_offset, FALSE );
  1085.         proc_label();
  1086.     }
  1087.  
  1088.     pre_dups( seg_rec->length - inst_offset, FALSE );
  1089.         
  1090.     if ( pass == 3 ) {
  1091.         out_newline();
  1092.         if ( compatibility == 2 ) {
  1093.         } else {
  1094.             out_line( cseg_name, "ENDS", "", "" );
  1095.         }
  1096.     }
  1097. }
  1098.  
  1099.  
  1100. void process()
  1101. {
  1102.     NODE_T          *seg_node;
  1103.     char            text[80];
  1104.     int             dummy;
  1105.  
  1106.     pub_node  = start( public_tree, RIGHT );    /* Start at beginning of */
  1107.     pub_rec   = (PUB_T *)pub_node->data;        /* Public symbols list   */
  1108.  
  1109.     fix_node  = start( fix_tree, RIGHT );       /* Start at beginning of */
  1110.     fix_rec   = (FIX_T *)fix_node->data;        /* Fixup records list    */
  1111.  
  1112.     data_node = start( data_tree, RIGHT );      /* Start at beginning of */
  1113.     data_rec = (DAT_T *)data_node->data;        /* Data record list      */
  1114.  
  1115.     hint_node  = start( hint_tree, RIGHT );     /* Start at beginning of */
  1116.     hint_rec   = (HINT_T *)hint_node->data;     /* Hints list            */
  1117.  
  1118.     sex_node = start( sex_tree, RIGHT );        /* Start at beginning of */
  1119.  
  1120.     if ( pass == 3 && !processor_type_comment_occurred ) {
  1121.         out_line( "", ".286p", "", "" );
  1122.         out_line( "", ".287", "", "" );
  1123.         processor_mode = 286;
  1124.     }
  1125.  
  1126.     /*
  1127.     ** Display all defined public values ( segment == 0 )
  1128.     */
  1129.     segment = 0;
  1130.     if ( pass == 3 && pub_rec->seg_idx == segment ) {
  1131.         out_newline();                  /* Blank line before trailings */
  1132.     }
  1133.     while ( pub_rec->seg_idx == segment ) {
  1134.         lone_public();                  /* Finish off any trailing */
  1135.         pub_advance();                  /* lone public labels      */
  1136.     }
  1137.  
  1138.     /*
  1139.     ** Loop through all segments
  1140.     */
  1141.     segment_mode = processor_mode;
  1142.     seg_node = start( segment_tree, RIGHT );
  1143.     while ( seg_node != segment_tree ) {
  1144.         seg_rec = (SEG_T *)seg_node->data;
  1145.         process_segment();
  1146.         seg_node = traverse( seg_node, RIGHT );
  1147.     }
  1148.  
  1149.     /*
  1150.     ** Finish off this module
  1151.     */
  1152.     fix_search.seg_idx    = 0;
  1153.     fix_search.dat_offset = 0;
  1154.     fix_search.offset     = 1;          /* Look for MODEND record */
  1155.  
  1156.     fix_rec = (FIX_T *)find( (char *)&fix_search, fix_tree, fix_compare, NULL );
  1157.     if ( fix_rec == NULL ) {
  1158.         if ( pass == 3 ) {
  1159.             out_newline();
  1160.             out_opcode("END");
  1161.             out_newline();
  1162.         }
  1163.     } else {
  1164.         get_target( text, fix_rec, 0, 0L, FALSE, 0, FALSE, &dummy, CS );
  1165.         if ( pass == 3 ) {
  1166.             out_newline();
  1167.             out_line( "", "END", text, "Module starting address" );
  1168.         }
  1169.     }
  1170. }
  1171.