⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 order.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 3 页
字号:
bit_16                                 size;
bit_32                                 i ;
EndDeclarations
BeginCode

/*+-------------------------------------------------------------------------+
  |                                                                         |
  | Compute the address base for the executable image.  For .COM files this |
  | will be 100H, for .EXE and .SYS files, this will be 0.                  |
  |                                                                         |
  +-------------------------------------------------------------------------+*/

 next_available_address = 0L;
 If pefile.val IsTrue
  Then 
	 // This is buggy- we don't know the size of the header yet, so if they
   // make objectAlign too small we have problems...
   first_pe_section_address = address_base = imageBase.val + objectAlign.val ;
   next_available_address = address_base ; /* no gap */
   FLAT_address = address_base ;
  Else 
   If lxfile.val IsTrue OrIf lefile.val IsTrue
    Then
     first_pe_section_address = address_base = 0 ;
     next_available_address = address_base ; /* no gap */
     FLAT_address = address_base ;
    Else
     If comfile.val IsTrue
      Then
       address_base = 0x100L;
      Else
       address_base = 0L;
      EndIf ;
    EndIf
  EndIf;

/*+-------------------------------------------------------------------------+
  |                                                                         |
  |   The ordering expression for the segments must be known.  If the       |
  |   "/ORDER:(expression)" switch was specified, then it will be used      |
  |   regardless or whether or not "/DOSSEG" is set.  If the "/ORDER"       |
  |   switch was not specified and "/DOSSEG" was, then the appropriate      |
  |   expression is used.  Otherwise, the linker will just take the         |
  |   segments in the order they were encountered.                          |
  |                                                                         |
  | update: if use32 is specified we will use a custom ordering that works  |
  | with the ladsoft tools if no ordering is given                          |
  +-------------------------------------------------------------------------+*/

 If ordering.val IsNull
  Then
   If pefile.val IsTrue
    Then
			ordering.val = duplicate_string(
          string((byte *) ("((cl[*CODE]|cl[*code]|seg[*TEXT]|seg[*text]|cl[*CONST]|cl[*const]),"
                           " cl[*DATA]|cl[*data]|seg[*DATA]|seg[*data]|"
                           "   ((cl[DGROUP]|cl[dgroup)&!(cl[*BSS]|cl[*bss]));"
                           " (cl[DGROUP]|cl[dgroup)&(cl[*BSS]|cl[*bss]);cl[*STRING]|cl[*string];"
                           " cl[INITDATA];cl[EXITDATA];cl[CPPINIT];cl[CPPEXIT],"
                           " (cl[*BSS]|cl[*bss]|seg[*BSS]|seg[*bss]))")));
    Else
     If lxfile.val IsTrue OrIf lefile.val IsTrue
      Then
			ordering.val = duplicate_string(
          string((byte *) ("((cl[*CODE]|cl[*code]|seg[*TEXT]|seg[*text]|cl[*CONST]|cl[*const]|cl[*STRING]|cl[*string]),"
                           " cl[*DATA]|cl[*data]|seg[*DATA]|seg[*data]|"
                           "   ((cl[DGROUP]|cl[dgroup)&!(cl[*BSS]|cl[*bss]));"
                           " (cl[DGROUP]|cl[dgroup)&(cl[*BSS]|cl[*bss])|"
                           " cl[INITDATA];cl[EXITDATA];cl[CPPINIT];cl[CPPEXIT],"
                           " (cl[*BSS]|cl[*bss]|seg[*BSS]|seg[*bss]),"
                           " (cl[*STACK|cl[*stack]|seg[*STACK]|seg[*stack]))")));
      Else If use32.val IsTrue
       Then
         ordering.val = duplicate_string(
           string((byte *) ("(cl[TRAN], cl[STACK], (cl[*CODE]| cl[*code]| seg[*TEXT]| seg[*text]| "
                         " cl[*CONST]| cl[*const]| cl[*STRING]| cl[*string]| "
                         " cl[INITDATA]|cl[EXITDATA]|cl[CPPINIT]| cl[CPPEXIT])| "
                         " ((cl[DGROUP]|cl[dgroup)&!(cl[*BSS]|cl[*bss]))| "
                         " (cl[DGROUP]|cl[dgroup)&(cl[*BSS]|cl[*bss]))")));
       Else If DOSSEG.val IsTrue
        Then
         ordering.val = duplicate_string(
           string((byte *) ("(seg[*code]|seg[*CODE], "
                           "!(gr[dgroup]|gr[DGROUP]), "
                           "cl[begdata]|cl[BEGDATA], "
                           "cl[*data]|cl[*DATA], "
                           "!(cl[*bss]|cl[*BSS]|cl[*stack]|cl[*STACK]), "
                           "cl[*bss]|cl[*BSS], "
                           "cl[*stack]|cl[*STACK])")));
        Else
         ordering.val = duplicate_string(string((byte *) ("(true)")));
        EndIf ;
      EndIf;
     EndIf ;
    EndIf ;
  EndIf;

/*+-------------------------------------------------------------------------+
  |                                                                         |
  |  Check to insure a stack segment of appropriate size is present.  For   |
  |  .COM and .SYS files, no stack segment is required.  For .EXE files,    |
  |  one is required.  For .EXE files, we must insure that a stack of at    |
  |  least the size specified in the "/STACK" switch is available.          |
  |                                                                         |
  +-------------------------------------------------------------------------+*/

 If exefile IsFalse
  Then
   If stack_segment_found IsTrue
    Then
     linker_error(4, "Stack segment found for a non .EXE file.\n");
    EndIf;
  Else
   If (stack_segment_found IsFalse) AndIf
      (stack.set           IsFalse)
    Then
     If Not pefile.val AndIf Not lxfile.val AndIf Not lefile.val
      Then
        linker_error(4, "No stack segment for .EXE file.\n");
      EndIf ;
    Else
     If (stack.set IsTrue) AndIf 
        (Bit_16(Largest_stack_seg.length) LessThan stack.val)
      Then
       obj_generate_segment(generated_lname,
                            none_lname,
                            stack_combine,
                            2,              /* word aligned */
                            none_lname,
                            exe_file_list.first,
                            0L,             /* not absolute segment */
                            Bit_32(stack.val));
      EndIf;
    EndIf;
  EndIf;

/*+-------------------------------------------------------------------------+
  |                                                                         |
  |  Create a thunk table for imports.  We're in catch-22 here because      |
  |  fixups haven't been done so we don't know which symbols are used; but  |
  |  if we don't do this now we won't know how larget the code seg is.      |
  |  we are going to opt to waste space rather than rewrite the linker.     |
  +-------------------------------------------------------------------------+*/
 If pefile.val AndIf n_imports IsNotZero
  Then
		length = n_imports * 6 ;
   lseg = obj_generate_segment(generated_lname,
                               CODE_lname,
                               public_combine,
                               5,              /* DWORD aligned */
                               none_lname,
                               exe_file_list.first,
                               0L,             /* not absolute segment */
                               length);
   Lseg.highest_uninitialized_byte = length;
	 import_thunk_table = lseg ;
  EndIf
/*+-------------------------------------------------------------------------+
  |                                                                         |
  |  Handle near communals as follows:  If there is at least one near       |
  |  communal, create the segment "c_common" in group "DGROUP" with         |
  |  class "BSS".  Then, for each communal place it in "c_common" in        |
  |  ascending order while changing the dictionary entry from               |
  |  "near_communal" to "internal".                                         |
  |                                                                         |
  +-------------------------------------------------------------------------+*/

 If near_communals IsNotNull
  Then
   length = 0L;
   For pub=near_communals; pub IsNotNull; pub=Pub.Communal.next_communal
    BeginFor
     LoopIf(Pub.type_entry IsNot near_communal);
     length += Pub.Communal.element_size;
    EndFor;
   If length Exceeds 65536L
    Then
     linker_error(8, "Near communal size exceeds 64K by %lu bytes.\n",
                     length-65536L);
    EndIf;
   lseg = obj_generate_segment(c_common_lname,
                               BSS_lname,
                               blank_common_combine,
                               3,              /* paragraph aligned */
                               none_lname,
                               exe_file_list.first,
                               0L,             /* not absolute segment */
                               length);
   Lseg.highest_uninitialized_byte = length;
   group                        = lookup_group(DGROUP_lname);
   (*Lseg.segment).owning_group = group;
   offset = 0;
   For pub=near_communals; pub IsNotNull; pub=next_communal
    BeginFor
     next_communal        = Pub.Communal.next_communal;
     LoopIf(Pub.type_entry IsNot near_communal);
     size                 = Bit_16(Pub.Communal.element_size);
     Pub.type_entry       = internal;
     Pub.Internal.group   = group;
     Pub.Internal.lseg    = lseg;
     Pub.Internal.offset  = offset;
     Pub.Internal.frame   = 0;
     offset              += size;
    EndFor;
  EndIf;
 
/*+-------------------------------------------------------------------------+
  |                                                                         |
  |  Handle far communals as follows:  Packing as many far communals as     |
  |  will fit (64K), create private segments with the segment and class     |
  |  name of "FAR_BSS".  They do NOT go in DRGROUP.                         |
  |                                                                         |
  +-------------------------------------------------------------------------+*/

 lseg   = Null;
 offset = 0;
 For pub=far_communals; pub IsNotNull; pub=next_communal
  BeginFor
   next_communal = Pub.Communal.next_communal;
   LoopIf(Pub.type_entry IsNot far_communal); 
   length = Pub.Communal.element_size * Pub.Communal.element_count;
   If length Exceeds 65536L
    Then
     Pub.Communal.next_communal = huge_communals;
     huge_communals             = pub;
     ContinueLoop;
    EndIf;
   If (lseg IsNull) OrIf ((length + Bit_32(offset)) Exceeds 65536L)
    Then
     lseg = obj_generate_segment(FAR_BSS_lname,
                                 FAR_BSS_lname,
                                 blank_common_combine,
                                 3,              /* paragraph aligned */
                                 none_lname,
                                 exe_file_list.first,
                                 0L,             /* not absolute segment */
                                 0L);
     offset = 0;
    EndIf;
   Pub.type_entry                   = internal;
   Pub.Internal.group               = Null;
   Pub.Internal.lseg                = lseg;
   Pub.Internal.offset              = offset;
   Pub.Internal.frame               = 0;
   offset                          += Bit_16(length);
   Lseg.highest_uninitialized_byte += length;
   Lseg.length                     += length;
   (*Lseg.segment).length          += length;
  EndFor;

/*+-------------------------------------------------------------------------+
  |                                                                         |
  |  Handle huge communals as follows:  Taking as many segments as          |
  |  required, create private segments with the segment and class           |
  |  name of "HUGE_BSS".  They do NOT go in DRGROUP.                        |
  |                                                                         |
  +-------------------------------------------------------------------------+*/

 For pub=huge_communals; pub IsNotNull; pub=next_communal
  BeginFor
   next_communal = Pub.Communal.next_communal;
   length = Pub.Communal.element_size * Pub.Communal.element_count;
   lseg = obj_generate_segment(HUGE_BSS_lname,
                               HUGE_BSS_lname,
                               blank_common_combine,
                               3,              /* paragraph aligned */
                               none_lname,
                               exe_file_list.first,
                               0L,             /* not absolute segment */
                               0L);
   If Pub.Communal.element_size Exceeds 65536L
    Then
     linker_error(4, "Communal \"%s\" has element size exceeding 64K.\n",
                     Pub.symbol);
     offset = 0;
    Else
     offset = Bit_16(65536L Mod Pub.Communal.element_size);
    EndIf;
   length                          += Bit_32(offset);
   Pub.type_entry                   = internal;
   Pub.Internal.group               = Null;
   Pub.Internal.lseg                = lseg;
   Pub.Internal.offset              = offset;
   Pub.Internal.frame               = 0;
   Lseg.highest_uninitialized_byte += length;
   Lseg.length                     += length;
   (*Lseg.segment).length          += length;
  EndFor;

 return;
EndCode
#undef Pub
#undef Lseg
#undef Group

/*+-------------------------------------------------------------------------+
  |                                                                         |
  |                           order_token_get_char                          |
  |                                                                         |
  +-------------------------------------------------------------------------+*/
void order_token_get_char()
BeginDeclarations
EndDeclarations
BeginCode
 If token_break_char Is '\000'
  Then
   linker_error(8, "Expression syntax error:\n"
                   "\t\"%s\"\n",
                   String(ordering.val));
  EndIf;
 token_break_char = *order_expression_char_ptr++;
 return;
EndCode


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -