home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / pgmutl / val_link.arc / TMODULE.C < prev    next >
Text File  |  1989-02-18  |  82KB  |  2,167 lines

  1. /*                                 TMODULE.C                               */
  2.  
  3. /*
  4. Object modules are parsed via recursive descent as defined below:
  5.  
  6.      obj_t_module::      obj_THEADR obj_seg_grp {obj_component} obj_modtail
  7.  
  8.      obj_seg_grp::       {obj_LNAMES | obj_SEGDEF | obj_EXTDEF}
  9.                          {obj_TYPDEF | obj_EXTDEF | obj_GRPDEF}
  10.  
  11.      obj_component::     obj_data | obj_debug_record
  12.  
  13.      obj_data::          obj_content_def | obj_thread_def | obj_COMDEF |
  14.                          obj_TYPDEF | obj_PUBDEF | obj_EXTDEF |
  15.                          obj_FORREF | obj_MODPUB | obj_MODEXT
  16.  
  17.  
  18.      obj_debug_record::  obj_LINNUM
  19.  
  20.      obj_content_def::   obj_data_record {obj_FIXUPP}
  21.  
  22.      obj_thread_def::    obj_FIXUPP  (containing only thread fields)
  23.  
  24.      obj_data_record::   obj_LIDATA | obj_LEDATA
  25.  
  26.      obj_modtail::       obj_MODEND
  27. */
  28.  
  29. /*+-------------------------------------------------------------------------+
  30.   |                                                                         |
  31.   |                               obj_COMDEF                                |
  32.   |                                                                         |
  33.   +-------------------------------------------------------------------------+*/
  34. bit_16 obj_COMDEF()
  35. BeginDeclarations
  36. bit_32                                 element_count;
  37. bit_32                                 element_size;
  38. bit_8                                  element_type;
  39. bit_8                                  expected_type;
  40. bit_16                                 len;
  41. public_entry_ptr                       pub;
  42. #define Pub                            (*pub)
  43. EndDeclarations
  44. BeginCode
  45.  If Current_record_header.rec_typ IsNot COMDEF_record
  46.   Then
  47.    return(False);
  48.   EndIf;
  49.  While obj_ptr.b8 IsNot end_of_record.b8
  50.   BeginWhile
  51.    If n_externals NotLessThan max_externals.val
  52.     Then
  53.      linker_error(12, "Internal limit exceeded:\n"
  54.                       "\tModule:  \"%Fs\"\n"
  55.                       "\t  File:  \"%Fs\"\n"
  56.                       "\tOffset:  %lu\n"
  57.                       "\t Error:  Too many externals.  Max of %u exceeded.\n"
  58.                       "\t         Retry with larger \"/maxexternals:n\" "
  59.                                   "switch.\n",
  60.                       (*tmodule_name).symbol,
  61.                       (*infile.file_info).filename,
  62.                       current_record_offset,
  63.                       max_externals.val);
  64.     EndIf;
  65.    len         = obj_name_length();
  66.    If case_ignore.val
  67.     Then
  68.      far_to_lower(BytePtr(obj_ptr.b8), len);
  69.     EndIf;
  70.    pub         = lookup_public(len, obj_ptr.b8, 0);
  71.    obj_ptr.b8 += len;
  72.    obj_name_length();  /* Eat the type index. */
  73.    externals[++n_externals] = pub;
  74.    element_type  = *obj_ptr.b8++;
  75.    Using element_type
  76.     BeginCase
  77.      When 0x61:
  78.       expected_type = far_communal;
  79.       element_count = obj_leaf_descriptor();
  80.       element_size  = obj_leaf_descriptor();
  81.       break;
  82.      When 0x62:
  83.       expected_type = near_communal;
  84.       element_size  = obj_leaf_descriptor();
  85.       element_count = 1L;
  86.       break;
  87.      Otherwise:
  88.       linker_error(12, "Translator error:\n"
  89.                        "\tModule:  \"%Fs\"\n"
  90.                        "\t  File:  \"%Fs\"\n"
  91.                        "\tOffset:  %lu\n"
  92.                        "\t Error:  Communal type of \"%02X\" is illegal.\n",
  93.                        (*tmodule_name).symbol,
  94.                        (*infile.file_info).filename,
  95.                        current_record_offset,
  96.                        element_type);
  97.     EndCase;
  98.    If Pub.type_entry Is unused
  99.     Then
  100.      Insert pub AtEnd InList external_list EndInsert;
  101.      Pub.type_entry             = expected_type;
  102.      Pub.Communal.element_size  = element_size;
  103.      Pub.Communal.element_count = element_count;
  104.      Using element_type
  105.      BeginCase
  106.       When 0x61:
  107.        Pub.Communal.next_communal = far_communals;
  108.        far_communals              = pub;
  109.        break;
  110.       When 0x62:
  111.        Pub.Communal.next_communal = near_communals;
  112.        near_communals             = pub;
  113.        break;
  114.      EndCase;
  115.     Else
  116.      If Pub.type_entry Is expected_type
  117.       Then
  118.        If (element_size              * element_count)              Exceeds 
  119.           (Pub.Communal.element_size * Pub.Communal.element_count)
  120.         Then /* We need the largest common */
  121.          Pub.Communal.element_size  = element_size;
  122.          Pub.Communal.element_count = element_count;
  123.         EndIf;
  124.       Else
  125.        If (Pub.type_entry Is near_communal) OrIf
  126.           (Pub.type_entry Is far_communal)
  127.         Then
  128.          linker_error(4, "Translator error:\n"
  129.                          "\tModule:  \"%Fs\"\n"
  130.                          "\t  File:  \"%Fs\"\n"
  131.                          "\tOffset:  %lu\n"
  132.                          "\t Error:  Communal \"%Fs\" is declared both near "
  133.                                      "and far.\n",
  134.                          (*tmodule_name).symbol,
  135.                          (*infile.file_info).filename,
  136.                          current_record_offset,
  137.                          Pub.symbol);
  138.         EndIf;
  139.       EndIf;
  140.     EndIf;
  141.   EndWhile;
  142.  obj_next_record();
  143.  return(True);
  144. EndCode
  145. #undef Pub
  146.  
  147. /*+-------------------------------------------------------------------------+
  148.   |                                                                         |
  149.   |                               obj_COMENT                                |
  150.   |                                                                         |
  151.   +-------------------------------------------------------------------------+*/
  152. bit_16 obj_COMENT()
  153. BeginDeclarations
  154. bit_8                                  comment_class;
  155. EndDeclarations
  156. BeginCode
  157.  If Current_record_header.rec_typ IsNot COMENT_record
  158.   Then
  159.    return(False);
  160.   EndIf;
  161.  obj_ptr.b8++;
  162.  comment_class = *obj_ptr.b8++;
  163.  Using comment_class
  164.   BeginCase
  165.    When 158:
  166.     DOSSEG.val = True;
  167.     break;
  168.    When 161:
  169.     codeview_information_present = True;
  170.     break;
  171.    Otherwise:
  172.     break;
  173.   EndCase;
  174.  return(True);
  175. EndCode
  176.  
  177. /*+-------------------------------------------------------------------------+
  178.   |                                                                         |
  179.   |                             obj_component                               |
  180.   |                                                                         |
  181.   +-------------------------------------------------------------------------+*/
  182.  
  183. /* obj_component:: obj_data | obj_debug_record */
  184. bit_16 obj_component()
  185. BeginDeclarations
  186. EndDeclarations
  187. BeginCode
  188.  If obj_data() OrIf obj_debug_record()
  189.   Then
  190.    return(True);
  191.   EndIf;
  192.  return(False);
  193. EndCode
  194.  
  195. /*+-------------------------------------------------------------------------+
  196.   |                                                                         |
  197.   |                            obj_content_def                              |
  198.   |                                                                         |
  199.   +-------------------------------------------------------------------------+*/
  200.  
  201. /* obj_content_def:: obj_data_record {obj_FIXUPP} */
  202. bit_16 obj_content_def()
  203. BeginDeclarations
  204. EndDeclarations
  205. BeginCode
  206.  If Not obj_data_record()
  207.   Then
  208.    return(False);
  209.   EndIf;
  210.  While obj_FIXUPP()
  211.   BeginWhile
  212.   EndWhile;
  213.  return(True);
  214. EndCode
  215.  
  216. /*+-------------------------------------------------------------------------+
  217.   |                                                                         |
  218.   |                               obj_data                                  |
  219.   |                                                                         |
  220.   +-------------------------------------------------------------------------+*/
  221.  
  222. /* obj_data:: obj_content_def |
  223.               obj_thread_def  |
  224.               obj_TYPDEF      |
  225.               obj_PUBDEF      |
  226.               obj_EXTDEF */
  227.  
  228. bit_16 obj_data()
  229. BeginDeclarations
  230. EndDeclarations
  231. BeginCode
  232.  If obj_content_def() OrIf
  233.     obj_thread_def()  OrIf
  234.     obj_TYPDEF()      OrIf
  235.     obj_PUBDEF()      OrIf
  236.     obj_EXTDEF()      OrIf
  237.     obj_FORREF()      OrIf
  238.     obj_COMDEF()      OrIf
  239.     obj_MODEXT()      OrIf
  240.     obj_MODPUB()
  241.   Then
  242.    return(True);
  243.   EndIf;
  244.  return(False);
  245. EndCode
  246.  
  247. /*+-------------------------------------------------------------------------+
  248.   |                                                                         |
  249.   |                            obj_data_record                              |
  250.   |                                                                         |
  251.   +-------------------------------------------------------------------------+*/
  252.  
  253. /*  obj_data_record:: obj_LIDATA | obj_LEDATA */
  254.  
  255. bit_16 obj_data_record()
  256. BeginDeclarations
  257. EndDeclarations
  258. BeginCode
  259.  If obj_LIDATA() OrIf obj_LEDATA()
  260.   Then
  261.    return(True);
  262.   EndIf;
  263.  return(False);
  264. EndCode
  265.  
  266. /*+-------------------------------------------------------------------------+
  267.   |                                                                         |
  268.   |                           obj_debug_record                              |
  269.   |                                                                         |
  270.   +-------------------------------------------------------------------------+*/
  271.  
  272. /* obj_debug_record:: obj_LINNUM */
  273.  
  274. bit_16 obj_debug_record()
  275. BeginDeclarations
  276. EndDeclarations
  277. BeginCode
  278.  If obj_LINNUM()
  279.   Then
  280.    return(True);
  281.   EndIf;
  282.  return(False);
  283. EndCode
  284.  
  285. /*+-------------------------------------------------------------------------+
  286.   |                                                                         |
  287.   |                               obj_EXTDEF                                |
  288.   |                                                                         |
  289.   +-------------------------------------------------------------------------+*/
  290. bit_16 obj_EXTDEF()
  291. BeginDeclarations
  292. bit_16                                 len;
  293. public_entry_ptr                       pub;
  294. #define Pub                            (*pub)
  295. EndDeclarations
  296. BeginCode
  297.  If Current_record_header.rec_typ IsNot EXTDEF_record
  298.   Then
  299.    return(False);
  300.   EndIf;
  301.  While obj_ptr.b8 IsNot end_of_record.b8
  302.   BeginWhile
  303.    If n_externals NotLessThan max_externals.val
  304.     Then
  305.      linker_error(12, "Internal limit exceeded:\n"
  306.                       "\tModule:  \"%Fs\"\n"
  307.                       "\t  File:  \"%Fs\"\n"
  308.                       "\tOffset:  %lu\n"
  309.                       "\t Error:  Too many externals.  Max of %u exceeded.\n"
  310.                       "\t         Retry with larger \"/maxexternals:n\" "
  311.                                   "switch.\n",
  312.                       (*tmodule_name).symbol,
  313.                       (*infile.file_info).filename,
  314.                       current_record_offset,
  315.                       max_externals.val);
  316.     EndIf;
  317.    len         = obj_name_length();
  318.    If case_ignore.val
  319.     Then
  320.      far_to_lower(BytePtr(obj_ptr.b8), len);
  321.     EndIf;
  322.    pub         = lookup_public(len, obj_ptr.b8, 0);
  323.    obj_ptr.b8 += len;
  324.    obj_name_length();  /* Eat the type index. */
  325.    externals[++n_externals] = pub;
  326.    If Pub.type_entry Is unused
  327.     Then
  328.      Insert pub AtEnd InList external_list EndInsert;
  329.      Pub.type_entry = external;
  330.     Else
  331.      If (Pub.type_entry Is public_in_library) AndIf
  332.         (Not Pub.Library.requested)
  333.       Then
  334.        library_request_count++;
  335.        (*Pub.Library.lib_file).request_count++;
  336.        Pub.Library.requested = True;
  337.       EndIf;
  338.     EndIf;
  339.   EndWhile;
  340.  obj_next_record();
  341.  return(True);
  342. EndCode
  343. #undef Pub
  344.  
  345. /*+-------------------------------------------------------------------------+
  346.   |                                                                         |
  347.   |                               obj_FIXUPP                                |
  348.   |                                                                         |
  349.   +-------------------------------------------------------------------------+*/
  350. bit_16 obj_FIXUPP()
  351. BeginDeclarations
  352. EndDeclarations
  353. BeginCode
  354.  If Current_record_header.rec_typ IsNot FIXUPP_record
  355.   Then
  356.    return(False);
  357.   EndIf;
  358.  FIXUPP_contains_only_threads = True;
  359.  While obj_ptr.b8 IsNot end_of_record.b8
  360.   BeginWhile
  361.    If (*obj_ptr.TRD_DAT).type_fixupp_record IsZero
  362.     Then
  363.      obj_FIXUPP_thread();
  364.     Else
  365.      FIXUPP_contains_only_threads = False;
  366.      obj_FIXUPP_fixup();
  367.     EndIf;
  368.   EndWhile;
  369.  obj_next_record();
  370.  return(True);
  371. EndCode
  372.  
  373. /*+-------------------------------------------------------------------------+
  374.   |                                                                         |
  375.   |                           obj_FIXUPP_fixup                              |
  376.   |                                                                         |
  377.   +-------------------------------------------------------------------------+*/
  378. void obj_FIXUPP_fixup()
  379. BeginDeclarations
  380. FIX_DAT_type                           FIX_DAT;
  381. bit_16                                 frame_method;
  382. LOCAT_type                             LOCAT;
  383. bit_16                                 target_method;
  384. bit_8                                  temp;
  385. bit_16                                 thread_number;
  386. EndDeclarations
  387. BeginCode
  388. /*+-------------------------------------------------------------------------+
  389.   |                                                                         |
  390.   | The LOCAT field in a FIXUPP record has its low and high bytes swapped   |
  391.   | because the high order bit must be 0 for threads and 1 for fixups.      |
  392.   | Since that bit could not be placed in the offset, the bytes were        |
  393.   | swapped instead.                                                        |
  394.   |                                                                         |
  395.   +-------------------------------------------------------------------------+*/
  396.  
  397.  temp                  = obj_ptr.b8[0];
  398.  obj_ptr.b8[0]         = obj_ptr.b8[1];
  399.  obj_ptr.b8[1]         = temp;
  400.  
  401. /*+-------------------------------------------------------------------------+
  402.   |                                                                         |
  403.   |          Pick up the two required fields (LOCAT and FIX_DAT)            |
  404.   |                                                                         |
  405.   +-------------------------------------------------------------------------+*/
  406.  
  407.  LOCAT                 = *obj_ptr.LOCAT++;
  408.  FIX_DAT               = *obj_ptr.FIX_DAT++;
  409.  
  410. /*+-------------------------------------------------------------------------+
  411.   |                                                                         |
  412.   |          A fixup consists of a location, mode, frame and target.        |
  413.   |                         Process the location part.                      |
  414.   |                                                                         |
  415.   +-------------------------------------------------------------------------+*/
  416.  
  417.  fixup_index           = LOCAT.data_record_offset;
  418.  fixup.location_type   = LOCAT.loc;
  419.  
  420. /*+-------------------------------------------------------------------------+
  421.   |                                                                         |
  422.   |                         Process the mode part.                          |
  423.   |                                                                         |
  424.   +-------------------------------------------------------------------------+*/
  425.  
  426.  fixup.mode            = LOCAT.m;
  427.  
  428. /*+-------------------------------------------------------------------------+
  429.   |                                                                         |
  430.   |                         Process the frame part.                         |
  431.   |                                                                         |
  432.   +-------------------------------------------------------------------------+*/
  433.  
  434.  If FIX_DAT.f IsZero
  435.   Then  /* Frame is specified explicitly */
  436.    frame_method         = FIX_DAT.frame;
  437.    fixup.frame_method   = frame_method;
  438.    Using frame_method
  439.     BeginCase
  440.      When 0:
  441.       fixup.frame_referent = (void far *) snames[obj_index_segment()];
  442.       break;
  443.      When 1:
  444.       fixup.frame_referent = (void far *) gnames[obj_index_group()];
  445.       break;
  446.      When 2:
  447.       fixup.frame_referent = (void far *) externals[obj_index_external()];
  448.       break;
  449.      When 3:
  450.       fixup.frame_referent =
  451.        (void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
  452.      Otherwise:
  453.       fixup.frame_referent = Null;
  454.       break;
  455.     EndCase;
  456.   Else  /* Frame is specified by a thread */
  457.    thread_number        = FIX_DAT.frame;
  458.    If Not frame_thread[thread_number].thread_defined
  459.     Then
  460.      linker_error(12, "Translator error:\n"
  461.                       "\tModule:  \"%Fs\"\n"
  462.                       "\t  File:  \"%Fs\"\n"
  463.                       "\tOffset:  %lu\n"
  464.                       "\t Error:  Reference to frame thread %u which has "
  465.                                   "been defined.n",
  466.                       (*tmodule_name).symbol,
  467.                       (*infile.file_info).filename,
  468.                       current_record_offset,
  469.                       thread_number);
  470.     EndIf;
  471.    fixup.frame_referent = frame_thread[thread_number].referent;
  472.    fixup.frame_method   = frame_thread[thread_number].method;
  473.   EndIf;
  474.  
  475. /*+-------------------------------------------------------------------------+
  476.   |                                                                         |
  477.   |                         Process the target part.                        |
  478.   |                                                                         |
  479.   +-------------------------------------------------------------------------+*/
  480.  
  481.  If FIX_DAT.t IsZero
  482.   Then  /* Target is specified explicitly */
  483.    target_method       = FIX_DAT.targt;
  484.    fixup.target_method = target_method;
  485.    Using target_method
  486.     BeginCase
  487.      When 0:  /* Target is the segment referenced by the index */
  488.       fixup.target_referent = (void far *) snames[obj_index_segment()];
  489.       break;
  490.      When 1:  /* Target is the lowest seg in the group referenced 
  491.                  by the index */
  492.       fixup.target_referent = (void far *) gnames[obj_index_group()];
  493.       break;
  494.      When 2:
  495.       fixup.target_referent = (void far *) externals[obj_index_external()];
  496.       break;
  497.      When 3:
  498.       fixup.target_referent =
  499.        (void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
  500.       break;
  501.     EndCase;
  502.   Else  /* Target is specified by a thread */
  503.    thread_number         = FIX_DAT.targt;
  504.    If Not target_thread[thread_number].thread_defined
  505.     Then
  506.      linker_error(12, "Translator error:\n"
  507.                       "\tModule:  \"%Fs\"\n"
  508.                       "\t  File:  \"%Fs\"\n"
  509.                       "\tOffset:  %lu\n"
  510.                       "\t Error:  Reference to target thread %u which has "
  511.                                   "been defined.n",
  512.                       (*tmodule_name).symbol,
  513.                       (*infile.file_info).filename,
  514.                       current_record_offset,
  515.                       thread_number);
  516.     EndIf;
  517.    fixup.target_referent = target_thread[thread_number].referent;
  518.    fixup.target_method   = target_thread[thread_number].method;
  519.   EndIf;
  520.  
  521.  If FIX_DAT.p IsZero
  522.   Then  /* There is a target displacement */
  523.    fixup.target_offset = *obj_ptr.b16++;
  524.   Else  /* The target displacement is zero */
  525.    fixup.target_offset = 0;
  526.   EndIf;
  527.  
  528.  fixup.external_error_detected = False;
  529.  
  530.  If (fixup.mode IsZero) AndIf
  531.                              ((fixup.location_type Is base_location)    OrIf
  532.                               (fixup.location_type Is pointer_location) OrIf
  533.                               (fixup.location_type Is hibyte_location))
  534.   Then /* Undefined fixup action */
  535.    linker_error(4, "Possible translator error:\n"
  536.                    "\tModule:  \"%Fs\"\n"
  537.                    "\t  File:  \"%Fs\"\n"
  538.                    "\tOffset:  %lu\n"
  539.                    "\t Error:  Base, pointer or hibyte self-relative fixups\n"
  540.                    "\t         are undefined.\n",
  541.                    (*tmodule_name).symbol,
  542.                    (*infile.file_info).filename,
  543.                    current_record_offset);
  544.   EndIf;
  545.  
  546.  If last_LxDATA_record_type Is LEDATA_record
  547.   Then
  548.    If ((fixup.location_type Is base_location)     OrIf
  549.        (fixup.location_type Is pointer_location)) AndIf
  550.       (exefile IsTrue)
  551.     Then /* Base and pointer locations will require a relocation item
  552.             in the EXE header */
  553.      n_relocation_items++;
  554.     EndIf;
  555.    write_temp_file(Current_record_header.rec_typ,
  556.                    last_LxDATA_lseg,
  557.                    last_LxDATA_offset + fixup_index,
  558.                    BytePtr(Addr(fixup)),
  559.                    sizeof(fixup));
  560.   Else
  561.    If fixup.mode IsZero
  562.     Then
  563.      linker_error(4, "Translator warning:\n"
  564.                      "\tModule:  \"%Fs\"\n"
  565.                      "\t  File:  \"%Fs\"\n"
  566.                      "\tOffset:  %lu\n"
  567.                      "\t Error:  Self-relative fixup not permitted for "
  568.                                  "LIDATA.\n",
  569.                      (*tmodule_name).symbol,
  570.                      (*infile.file_info).filename,
  571.                      current_record_offset);
  572.     Else
  573.      obj_fixup_LIDATA();
  574.     EndIf;
  575.   EndIf;
  576.  
  577.  return;
  578. EndCode
  579.  
  580. /*+-------------------------------------------------------------------------+
  581.   |                                                                         |
  582.   |                            obj_fixup_LIDATA                             |
  583.   |                                                                         |
  584.   +-------------------------------------------------------------------------+*/
  585. void obj_fixup_LIDATA()
  586. BeginDeclarations
  587. obj_ptr_type                           old_obj_ptr;
  588. EndDeclarations
  589. BeginCode
  590.  LIDATA_index  = 0;
  591.  LIDATA_offset = last_LxDATA_offset;
  592.  old_obj_ptr   = obj_ptr;
  593.  obj_ptr.b8    = Last_LIDATA_record_header.variant_part;
  594.  end_of_last_LIDATA_record.b8 =
  595.   (byte *)
  596.    Addr(Last_LIDATA_record_header.variant_part
  597.     [Last_LIDATA_record_header.rec_len-1]);
  598.  obj_index_segment();
  599.  obj_ptr.b16++;
  600.  While obj_ptr.b8 IsNot end_of_last_LIDATA_record.b8
  601.   BeginWhile
  602.    obj_fixup_LIDATA_IDB();
  603.   EndWhile;
  604.  obj_ptr = old_obj_ptr;
  605.  return;
  606. EndCode
  607.  
  608. /*+-------------------------------------------------------------------------+
  609.   |                                                                         |
  610.   |                           obj_fixup_LIDATA_IDB                          |
  611.   |                                                                         |
  612.   +-------------------------------------------------------------------------+*/
  613. void obj_fixup_LIDATA_IDB()
  614. BeginDeclarations
  615. bit_16                                 block_count;
  616. bit_8                                 *content;
  617. bit_16                                 i;
  618. bit_16                                 j;
  619. bit_16                                 len;
  620. bit_16                                 old_index;
  621. bit_16                                 repeat_count;
  622. EndDeclarations
  623. BeginCode
  624.  repeat_count = *obj_ptr.b16++;  LIDATA_index += sizeof(bit_16);
  625.  block_count  = *obj_ptr.b16++;  LIDATA_index += sizeof(bit_16);
  626.  content      = obj_ptr.b8;
  627.  old_index    = LIDATA_index;
  628.  If block_count IsNotZero
  629.   Then  /* Handle recursive case:  Content is iterated data block */
  630.    For i=0; i<repeat_count; i++
  631.     BeginFor
  632.      obj_ptr.b8 = content;
  633.      LIDATA_index = old_index;
  634.      For j=0; j<block_count; j++
  635.       BeginFor
  636.        obj_fixup_LIDATA_IDB();
  637.       EndFor;
  638.     EndFor;
  639.   Else  /* Handle non-recursive case:  Content is data. */
  640.    For i=0; i<repeat_count; i++
  641.     BeginFor
  642.      obj_ptr.b8   = content;
  643.      LIDATA_index = old_index;
  644.      len          = Bit_16(*obj_ptr.b8++);  LIDATA_index += sizeof(bit_8);
  645.      If (fixup_index NotLessThan LIDATA_index)        AndIf
  646.         (fixup_index LessThan   (LIDATA_index + len))
  647.       Then
  648.        write_temp_file(Current_record_header.rec_typ,
  649.                        last_LxDATA_lseg,
  650.                        LIDATA_offset + fixup_index - LIDATA_index,
  651.                        BytePtr(Addr(fixup)),
  652.                        sizeof(fixup));
  653.        If ((fixup.location_type Is base_location)     OrIf
  654.            (fixup.location_type Is pointer_location)) AndIf
  655.           (exefile IsTrue)
  656.         Then /* Base and pointer locations will require a relocation item
  657.                 in the EXE header */
  658.          n_relocation_items++;
  659.         EndIf;
  660.       EndIf;
  661.      LIDATA_offset += len;
  662.     EndFor;
  663.    obj_ptr.b8    += len;
  664.    LIDATA_index  += len;
  665.   EndIf;
  666.  return;
  667. EndCode
  668.  
  669. /*+-------------------------------------------------------------------------+
  670.   |                                                                         |
  671.   |                           obj_FIXUPP_thread                             |
  672.   |                                                                         |
  673.   +-------------------------------------------------------------------------+*/
  674. void obj_FIXUPP_thread()
  675. BeginDeclarations
  676. bit_16                                 method;
  677. bit_16                                 thread;
  678. TRD_DAT_type                           TRD_DAT;
  679. EndDeclarations
  680. BeginCode
  681.  TRD_DAT = *obj_ptr.TRD_DAT++;
  682.  thread  = TRD_DAT.thred;
  683.  method  = TRD_DAT.method;
  684.  If TRD_DAT.d IsZero
  685.   Then  /* This is a target thread */
  686.    target_thread[thread].method = Bit_8(method);
  687.    target_thread[thread].thread_defined = True;
  688.    Using method
  689.     BeginCase
  690.      When 0:
  691.       target_thread[thread].referent =
  692.        (void far *) snames[obj_index_segment()];
  693.       break;
  694.      When 1:
  695.       target_thread[thread].referent =
  696.        (void far *) gnames[obj_index_group()];
  697.       break;
  698.      When 2:
  699.       target_thread[thread].referent =
  700.        (void far *) externals[obj_index_external()];
  701.       break;
  702.      When 3:
  703.       target_thread[thread].referent =
  704.        (void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
  705.      Otherwise:
  706.       target_thread[thread].referent = Null;
  707.       break;
  708.     EndCase;
  709.   Else  /* This is a frame thread */
  710.    frame_thread[thread].method = Bit_8(method);
  711.    frame_thread[thread].thread_defined = True;
  712.    Using method
  713.     BeginCase
  714.      When 0:
  715.       frame_thread[thread].referent =
  716.        (void far *) snames[obj_index_segment()];
  717.       break;
  718.      When 1:
  719.       frame_thread[thread].referent =
  720.        (void far *) gnames[obj_index_group()];
  721.       break;
  722.      When 2:
  723.       frame_thread[thread].referent =
  724.        (void far *) externals[obj_index_external()];
  725.       break;
  726.      When 3:
  727.       frame_thread[thread].referent =
  728.        (void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
  729.      Otherwise:
  730.       frame_thread[thread].referent = Null;
  731.       break;
  732.     EndCase;
  733.   EndIf;
  734.  return;
  735. EndCode
  736.  
  737. /*+-------------------------------------------------------------------------+
  738.   |                                                                         |
  739.   |                               obj_FORREF                                |
  740.   |                                                                         |
  741.   +-------------------------------------------------------------------------+*/
  742. bit_16 obj_FORREF()
  743. BeginDeclarations
  744. bit_16                                 len;
  745. bit_16                                 segment_index;
  746. EndDeclarations
  747. BeginCode
  748.  If Current_record_header.rec_typ IsNot FORREF_record
  749.   Then
  750.    return(False);
  751.   EndIf;
  752.  segment_index = obj_index_segment();
  753.  len           = Current_record_header.rec_len - 2;
  754.  If segment_index Exceeds 127
  755.   Then
  756.    len--;
  757.   EndIf;
  758.  write_temp_file(Current_record_header.rec_typ,
  759.                  snames[segment_index],
  760.                  0,
  761.                  BytePtr(obj_ptr.b8),
  762.                  len);
  763.  obj_next_record();
  764.  return(True);
  765. EndCode
  766.  
  767. /*+-------------------------------------------------------------------------+
  768.   |                                                                         |
  769.   |                           obj_generate_segment                          |
  770.   |                                                                         |
  771.   +-------------------------------------------------------------------------+*/
  772. lseg_ptr obj_generate_segment(lname_entry_ptr segment_lname,
  773.                               lname_entry_ptr class_lname,
  774.                               combine_type    combine,
  775.                               bit_8           align,
  776.                               lname_entry_ptr tmodule,
  777.                               file_info_ptr   file,
  778.                               bit_32          address,
  779.                               bit_32          length)
  780. BeginDeclarations
  781. lseg_ptr                               lseg;
  782. #define Lseg                           (*lseg)
  783. segment_entry_ptr                      seg;
  784. #define Seg                            (*seg)
  785. EndDeclarations
  786. BeginCode
  787.  If combine Is stack_combine
  788.   Then
  789.    length += AlignmentGap(length, 1L); /* Stacks should be an integral
  790.                                           number of words. */
  791.   EndIf;
  792.  seg             = lookup_segment(segment_lname, class_lname, combine);
  793.  If (combine IsNot common_combine) OrIf (Seg.lsegs.first IsNull)
  794.   Then
  795.    Seg.address   = address;
  796.    Seg.length   += length;
  797.    lseg          = (lseg_ptr) 
  798.                     allocate_memory(Addr(static_pool),
  799.                                     Bit_32(sizeof(lseg_type)));
  800.    Lseg.segment  = seg;
  801.    Lseg.tmodule  = tmodule;
  802.    Lseg.file     = file;
  803.    Lseg.address  = address;
  804.    Lseg.length   = length;
  805.    Lseg.align    = align;
  806.    If (combine IsNot common_combine)      AndIf
  807.       (combine IsNot blank_common_combine)
  808.     Then  /* Don't allocate common data yet.  (We will wait until we
  809.              know how long the common block will be.) */
  810.      Lseg.data   = allocate_memory(Addr(static_pool), length);
  811.     EndIf;
  812.  
  813.    Lseg.highest_uninitialized_byte = 0L;
  814.  
  815.    Insert lseg AtEnd InList Seg.lsegs EndInsert;
  816.   Else  /* Not the first occurrence of this common */
  817.    lseg = Seg.lsegs.first;
  818.    If length Exceeds Seg.length
  819.     Then  /* Expand common block to be big enough to hold this entry. */
  820.      Seg.length  =
  821.      Lseg.length = length;
  822.     EndIf;
  823.    If align Exceeds Lseg.align
  824.     Then  /* Align to largest boundary. */
  825.      Lseg.align = align;
  826.     EndIf;
  827.   EndIf;
  828.  If Seg.combine Is stack_combine
  829.   Then
  830.    If Not stack_segment_found
  831.     Then
  832.      largest_stack_seg        = seg;
  833.      largest_stack_seg_length = Seg.length;
  834.      stack_segment_found      = True;
  835.     Else
  836.      If Seg.length Exceeds largest_stack_seg_length
  837.       Then
  838.        largest_stack_seg        = seg;
  839.        largest_stack_seg_length = Seg.length;
  840.       EndIf;
  841.     EndIf;
  842.   EndIf;
  843.  return(lseg);
  844. EndCode
  845. #undef Lseg 
  846. #undef Seg
  847.  
  848. /*+-------------------------------------------------------------------------+
  849.   |                                                                         |
  850.   |                               obj_GRPDEF                                |
  851.   |                                                                         |
  852.   +-------------------------------------------------------------------------+*/
  853. bit_16 obj_GRPDEF()
  854. BeginDeclarations
  855. group_entry_ptr                        group;
  856. #define Group                          (*group)
  857. bit_16                                 group_index;
  858. lseg_ptr                               lseg;
  859. #define Lseg                           (*lseg)
  860. segment_entry_ptr                      seg;
  861. #define Seg                            (*seg)
  862. bit_16                                 segment_index;
  863. EndDeclarations
  864. BeginCode
  865.  If Current_record_header.rec_typ IsNot GRPDEF_record
  866.   Then
  867.    return(False);
  868.   EndIf;
  869.  group_index         = obj_index_LNAME();
  870.  group               = lookup_group(lnames[group_index]);
  871.  If n_groups NotLessThan max_groups.val
  872.   Then
  873.    linker_error(12, "Internal limit exceeded:\n"
  874.                     "\tModule:  \"%Fs\"\n"
  875.                     "\t  File:  \"%Fs\"\n"
  876.                     "\tOffset:  %lu\n"
  877.                     "\t Error:  Too many GRPDEFs.  Max of %u exceeded.\n"
  878.                     "\t         Retry with larger \"/maxgroups:n\" switch.\n",
  879.                     (*tmodule_name).symbol,
  880.                     (*infile.file_info).filename,
  881.                     current_record_offset,
  882.                     max_groups.val);
  883.   EndIf;
  884.  gnames[++n_groups]  = group;
  885.  While obj_ptr.b8 IsNot end_of_record.b8
  886.   BeginWhile
  887.    If *obj_ptr.b8++ IsNot 0xFF
  888.     Then
  889.      linker_error(12, "Translator error:\n"
  890.                       "\tModule:  \"%Fs\"\n"
  891.                       "\t  File:  \"%Fs\"\n"
  892.                       "\tOffset:  %lu\n"
  893.                       "\t Error:  GRPDEF record has a group component "
  894.                                   "descriptor which\n"
  895.                       "\t         does not start with 0xFF.\n",
  896.                       (*tmodule_name).symbol,
  897.                       (*infile.file_info).filename,
  898.                       current_record_offset);
  899.     EndIf;
  900.    segment_index = obj_index_segment();
  901.    lseg          = snames[segment_index];
  902.    seg           = Lseg.segment;
  903.    If Seg.owning_group IsNull
  904.     Then
  905.      Seg.owning_group = group;
  906.     Else
  907.      If Seg.owning_group IsNot group
  908.       Then
  909.        linker_error(4, "Attempt to place segment \"%Fs\" into group \"%Fs\"\n"
  910.                        "\twhen it is already in group \"%Fs\".\n"
  911.                        "\tRequest to place in group \"%Fs\" ignored.\n",
  912.                        (*Seg.segment_name).symbol, (*Group.group_name).symbol,
  913.                        (*(*Seg.owning_group).group_name).symbol,
  914.                        (*Group.group_name).symbol);
  915.      EndIf;
  916.     EndIf;
  917.   EndWhile;
  918.  obj_next_record();
  919.  return(True);
  920. EndCode
  921. #undef Seg
  922. #undef Group
  923. #undef Lseg
  924.  
  925. /*+-------------------------------------------------------------------------+
  926.   |                                                                         |
  927.   |                           obj_index_external                            |
  928.   |                                                                         |
  929.   +-------------------------------------------------------------------------+*/
  930. bit_16 obj_index_external()
  931. BeginDeclarations
  932. bit_16                                 index;
  933. EndDeclarations
  934. BeginCode
  935.  If *obj_ptr.b8 LessThan 128
  936.   Then
  937.    index = Bit_16(*obj_ptr.b8++);
  938.   Else
  939.    index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
  940.            Bit_16(*obj_ptr.b8++);
  941.   EndIf;
  942.    If index Exceeds n_externals
  943.     Then
  944.      linker_error(12, "Translator error:\n"
  945.                       "\tModule:  \"%Fs\"\n"
  946.                       "\t  File:  \"%Fs\"\n"
  947.                       "\tOffset:  %lu\n"
  948.                       "\t Error:  Invalid external index (%u) with only %u "
  949.                                   "externals defined.\n",
  950.                       (*tmodule_name).symbol,
  951.                       (*infile.file_info).filename,
  952.                       current_record_offset,
  953.                       index, n_externals);
  954.     EndIf;
  955.  return(index);
  956. EndCode
  957.  
  958. /*+-------------------------------------------------------------------------+
  959.   |                                                                         |
  960.   |                             obj_index_group                             |
  961.   |                                                                         |
  962.   +-------------------------------------------------------------------------+*/
  963. bit_16 obj_index_group()
  964. BeginDeclarations
  965. bit_16                                 index;
  966. EndDeclarations
  967. BeginCode
  968.  If *obj_ptr.b8 LessThan 128
  969.   Then
  970.    index = Bit_16(*obj_ptr.b8++);
  971.   Else
  972.    index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
  973.            Bit_16(*obj_ptr.b8++);
  974.   EndIf;
  975.    If index Exceeds n_groups
  976.     Then
  977.      linker_error(12, "Translator error:\n"
  978.                       "\tModule:  \"%Fs\"\n"
  979.                       "\t  File:  \"%Fs\"\n"
  980.                       "\tOffset:  %lu\n"
  981.                       "\t Error:  Invalid group index (%u) with only %u "
  982.                                   "groups defined.\n",
  983.                       (*tmodule_name).symbol,
  984.                       (*infile.file_info).filename,
  985.                       current_record_offset,
  986.                       index, n_groups);
  987.     EndIf;
  988.  return(index);
  989. EndCode
  990.  
  991. /*+-------------------------------------------------------------------------+
  992.   |                                                                         |
  993.   |                             obj_index_LNAME                             |
  994.   |                                                                         |
  995.   +-------------------------------------------------------------------------+*/
  996. bit_16 obj_index_LNAME()
  997. BeginDeclarations
  998. bit_16                                 index;
  999. EndDeclarations
  1000. BeginCode
  1001.  If *obj_ptr.b8 LessThan 128
  1002.   Then
  1003.    index = Bit_16(*obj_ptr.b8++);
  1004.   Else
  1005.    index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
  1006.            Bit_16(*obj_ptr.b8++);
  1007.   EndIf;
  1008.    If index Exceeds n_lnames
  1009.     Then
  1010.      linker_error(12, "Translator error:\n"
  1011.                       "\tModule:  \"%Fs\"\n"
  1012.                       "\t  File:  \"%Fs\"\n"
  1013.                       "\tOffset:  %lu\n"
  1014.                       "\t Error:  Invalid LNAME index (%u) with only %u "
  1015.                                   "LNAMEs defined.\n",
  1016.                       (*tmodule_name).symbol,
  1017.                       (*infile.file_info).filename,
  1018.                       current_record_offset,
  1019.                       index, n_lnames);
  1020.     EndIf;
  1021.  return(index);
  1022. EndCode
  1023.  
  1024. /*+-------------------------------------------------------------------------+
  1025.   |                                                                         |
  1026.   |                           obj_index_segment                             |
  1027.   |                                                                         |
  1028.   +-------------------------------------------------------------------------+*/
  1029. bit_16 obj_index_segment()
  1030. BeginDeclarations
  1031. bit_16                                 index;
  1032. EndDeclarations
  1033. BeginCode
  1034.  If *obj_ptr.b8 LessThan 128
  1035.   Then
  1036.    index = Bit_16(*obj_ptr.b8++);
  1037.   Else
  1038.    index = (Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
  1039.            Bit_16(*obj_ptr.b8++);
  1040.   EndIf;
  1041.    If index Exceeds n_segments
  1042.     Then
  1043.      linker_error(12, "Translator error:\n"
  1044.                       "\tModule:  \"%Fs\"\n"
  1045.                       "\t  File:  \"%Fs\"\n"
  1046.                       "\tOffset:  %lu\n"
  1047.                       "\t Error:  Invalid segment index (%u) with only %u "
  1048.                                   "segments defined.\n",
  1049.                       (*tmodule_name).symbol,
  1050.                       (*infile.file_info).filename,
  1051.                       current_record_offset,
  1052.                       index, n_segments);
  1053.     EndIf;
  1054.  return(index);
  1055. EndCode
  1056.  
  1057. /*+-------------------------------------------------------------------------+
  1058.   |                                                                         |
  1059.   |                         obj_iterated_data_block                         |
  1060.   |                                                                         |
  1061.   +-------------------------------------------------------------------------+*/
  1062. void obj_iterated_data_block()
  1063. BeginDeclarations
  1064. bit_16                                 block_count;
  1065. bit_8                                 *content;
  1066. bit_16                                 i;
  1067. bit_16                                 j;
  1068. bit_16                                 len;
  1069. bit_16                                 repeat_count;
  1070. EndDeclarations
  1071. BeginCode
  1072.  repeat_count = *obj_ptr.b16++;
  1073.  block_count  = *obj_ptr.b16++;
  1074.  If block_count IsNotZero
  1075.   Then  /* Handle recursive case:  Content is iterated data block */
  1076.    content = obj_ptr.b8;
  1077.    For i=0; i<repeat_count; i++
  1078.     BeginFor
  1079.      obj_ptr.b8 = content;
  1080.      For j=0; j<block_count; j++
  1081.       BeginFor
  1082.        obj_iterated_data_block();
  1083.       EndFor;
  1084.     EndFor;
  1085.   Else  /* Handle non-recursive case:  Content is data. */
  1086.    len = Bit_16(*obj_ptr.b8++);
  1087.    For i=0; i<repeat_count; i++
  1088.     BeginFor
  1089.      far_move(Addr(last_LxDATA_Lseg.data[LIDATA_offset]), 
  1090.               obj_ptr.b8, len);
  1091.      LIDATA_offset += len;
  1092.     EndFor;
  1093.    obj_ptr.b8 += len;
  1094.   EndIf;
  1095.  return;
  1096. EndCode
  1097.  
  1098. /*+-------------------------------------------------------------------------+
  1099.   |                                                                         |
  1100.   |                     obj_iterated_data_block_length                      |
  1101.   |                                                                         |
  1102.   +-------------------------------------------------------------------------+*/
  1103. bit_32 obj_iterated_data_block_length()
  1104. BeginDeclarations
  1105. bit_16                                 block_count;
  1106. bit_16                                 i;
  1107. bit_16                                 len;
  1108. bit_32                                 length;
  1109. bit_16                                 repeat_count;
  1110. EndDeclarations
  1111. BeginCode
  1112.  repeat_count = *obj_ptr.b16++;
  1113.  block_count  = *obj_ptr.b16++;
  1114.  If repeat_count IsZero
  1115.   Then /* This is a translator error. */
  1116.    linker_error(12, "Translator error:\n"
  1117.                     "\tModule:  \"%Fs\"\n"
  1118.                     "\t  File:  \"%Fs\"\n"
  1119.                     "\tOffset:  %lu\n"
  1120.                     "\t Error:  Repeat count in LIDATA iterated data block "
  1121.                                 "is zero.\n",
  1122.                     (*tmodule_name).symbol,
  1123.                     (*infile.file_info).filename,
  1124.                     current_record_offset);
  1125.   EndIf;
  1126.  length       = 0L;
  1127.  If block_count IsNotZero
  1128.   Then  /* Handle recursive case:  Content is iterated data block */
  1129.    For i=0; i<block_count; i++
  1130.     BeginFor
  1131.      length     += Bit_32(repeat_count) * obj_iterated_data_block_length();
  1132.     EndFor;
  1133.   Else  /* Handle non-recursive case:  Content is data. */
  1134.    len         = Bit_16(*obj_ptr.b8++);
  1135.    obj_ptr.b8 += len;
  1136.    length      = Bit_32(repeat_count) * Bit_32(len);
  1137.   EndIf;
  1138.  return(length);
  1139. EndCode
  1140.  
  1141. /*+-------------------------------------------------------------------------+
  1142.   |                                                                         |
  1143.   |                           obj_leaf_descriptor                           |
  1144.   |                                                                         |
  1145.   +-------------------------------------------------------------------------+*/
  1146. bit_32 obj_leaf_descriptor()
  1147. BeginDeclarations
  1148. bit_8                                  element_size;
  1149. EndDeclarations
  1150. BeginCode
  1151.  element_size = *obj_ptr.b8++;
  1152.  If element_size LessThan 129
  1153.   Then
  1154.    return(Bit_32(element_size));
  1155.   Else
  1156.    If element_size Is 129
  1157.     Then
  1158.      return(Bit_32(*obj_ptr.b16++));
  1159.     Else
  1160.      If element_size Is 132
  1161.       Then
  1162.        obj_ptr.b8--;
  1163.        return((*obj_ptr.b32++) And 0x00FFFFFFL);
  1164.       Else
  1165.        If element_size Is 136
  1166.         Then
  1167.          return(*obj_ptr.b32++);
  1168.         Else
  1169.          linker_error(12, "Translator error:\n"
  1170.                         "\tModule:  \"%Fs\"\n"
  1171.                         "\t  File:  \"%Fs\"\n"
  1172.                         "\tOffset:  %lu\n"
  1173.                         "\t Error:  Communal element size of %u is illegal.\n",
  1174.                         (*tmodule_name).symbol,
  1175.                         (*infile.file_info).filename,
  1176.                         current_record_offset,
  1177.                         element_size);
  1178.         EndIf;
  1179.       EndIf;
  1180.     EndIf;
  1181.   EndIf;
  1182.  return(0L);
  1183. EndCode
  1184.  
  1185. /*+-------------------------------------------------------------------------+
  1186.   |                                                                         |
  1187.   |                               obj_LEDATA                                |
  1188.   |                                                                         |
  1189.   +-------------------------------------------------------------------------+*/
  1190. bit_16 obj_LEDATA()
  1191. BeginDeclarations
  1192. bit_32                                 next_byte;
  1193. bit_16                                 len;
  1194. lseg_ptr                               lseg;
  1195. #define Lseg                           (*lseg)
  1196. bit_16                                 offset;
  1197. bit_16                                 segment_index;
  1198. EndDeclarations
  1199. BeginCode
  1200.  If Current_record_header.rec_typ IsNot LEDATA_record
  1201.   Then
  1202.    return(False);
  1203.   EndIf;
  1204.  last_LxDATA_record_type = Current_record_header.rec_typ;
  1205.  segment_index           = obj_index_segment();
  1206.  last_LxDATA_lseg        =
  1207.  lseg                    = snames[segment_index];
  1208.  len                     = Current_record_header.rec_len - 4;
  1209.  If segment_index Exceeds 127
  1210.   Then
  1211.    len--;
  1212.   EndIf;
  1213.  last_LxDATA_offset =
  1214.  offset             = *obj_ptr.b16++;
  1215.  next_byte          = Bit_32(offset) + Bit_32(len);
  1216.  If next_byte Exceeds Lseg.length
  1217.   Then
  1218.    linker_error(12, "Translator error:\n"
  1219.                     "\tModule:  \"%Fs\"\n"
  1220.                     "\t  File:  \"%Fs\"\n"
  1221.                     "\tOffset:  %lu\n"
  1222.                     "\t Error:  Attempt to initialize past end of LSEG.\n",
  1223.                     (*tmodule_name).symbol,
  1224.                     (*infile.file_info).filename,
  1225.                     current_record_offset);
  1226.   EndIf;
  1227.  If next_byte Exceeds Lseg.highest_uninitialized_byte
  1228.   Then
  1229.    Lseg.highest_uninitialized_byte = next_byte;
  1230.   EndIf;
  1231.  If (*last_LxDATA_Lseg.segment).combine IsNot common_combine
  1232.   Then
  1233.    far_move(Addr(Lseg.data[offset]), obj_ptr.b8, len);
  1234.   Else  /* We must save the initialization data out to the tmp file until
  1235.            later when we know the length. */
  1236.    write_temp_file(Current_record_header.rec_typ,
  1237.                    last_LxDATA_lseg,
  1238.                    last_LxDATA_offset,
  1239.                    BytePtr(obj_ptr.b8),
  1240.                    len);
  1241.   EndIf;
  1242.  obj_next_record();
  1243.  return(True);
  1244. EndCode
  1245.  
  1246. /*+-------------------------------------------------------------------------+
  1247.   |                                                                         |
  1248.   |                               obj_LIDATA                                |
  1249.   |                                                                         |
  1250.   +-------------------------------------------------------------------------+*/
  1251. bit_16 obj_LIDATA()
  1252. BeginDeclarations
  1253. bit_16                                 len;
  1254. bit_32                                 LIDATA_length;
  1255. bit_32                                 next_byte;
  1256. bit_16                                 segment_index;
  1257. EndDeclarations
  1258. BeginCode
  1259.  If Current_record_header.rec_typ IsNot LIDATA_record
  1260.   Then
  1261.    return(False);
  1262.   EndIf;
  1263.  far_move(BytePtr(last_LIDATA_record), 
  1264.           BytePtr(object_file_element),
  1265.           Current_record_header.rec_len + sizeof(obj_record_header_type) - 1);
  1266.  last_LxDATA_record_type = Current_record_header.rec_typ;
  1267.  segment_index           = obj_index_segment();
  1268.  last_LxDATA_lseg        = snames[segment_index];
  1269.  LIDATA_offset           =
  1270.  last_LxDATA_offset      = *obj_ptr.b16++;
  1271.  LIDATA_length           = obj_LIDATA_length();
  1272.  next_byte               = last_LxDATA_offset + LIDATA_length;
  1273.  If next_byte Exceeds last_LxDATA_Lseg.length
  1274.   Then
  1275.    linker_error(12, "Translator error:\n"
  1276.                     "\tModule:  \"%Fs\"\n"
  1277.                     "\t  File:  \"%Fs\"\n"
  1278.                     "\tOffset:  %lu\n"
  1279.                     "\t Error:  Attempt to initialize past end of LSEG.\n",
  1280.                     (*tmodule_name).symbol,
  1281.                     (*infile.file_info).filename,
  1282.                     current_record_offset);
  1283.   EndIf;
  1284.  If next_byte Exceeds last_LxDATA_Lseg.highest_uninitialized_byte
  1285.   Then
  1286.    last_LxDATA_Lseg.highest_uninitialized_byte = next_byte;
  1287.   EndIf;
  1288.  If (*last_LxDATA_Lseg.segment).combine IsNot common_combine
  1289.   Then
  1290.    While obj_ptr.b8 IsNot end_of_record.b8
  1291.    BeginWhile
  1292.    obj_iterated_data_block();
  1293.    EndWhile;
  1294.   Else  /* We must save the initialization data out to the tmp file until
  1295.            later when we know the length. */
  1296.    len                     = Current_record_header.rec_len - 4;
  1297.    If segment_index Exceeds 127
  1298.     Then
  1299.      len--;
  1300.     EndIf;
  1301.    write_temp_file(Current_record_header.rec_typ,
  1302.                    last_LxDATA_lseg,
  1303.                    last_LxDATA_offset,
  1304.                    BytePtr(obj_ptr.b8),
  1305.                    len);
  1306.   EndIf;
  1307.  obj_next_record();
  1308.  return(True);
  1309. EndCode
  1310.  
  1311. /*+-------------------------------------------------------------------------+
  1312.   |                                                                         |
  1313.   |                           obj_LIDATA_length                             |
  1314.   |                                                                         |
  1315.   +-------------------------------------------------------------------------+*/
  1316. bit_32 obj_LIDATA_length()
  1317. BeginDeclarations
  1318. bit_32                                 length;
  1319. bit_8                                  *start;
  1320. EndDeclarations
  1321. BeginCode
  1322.  start  = obj_ptr.b8;
  1323.  length = 0L;
  1324.  While obj_ptr.b8 IsNot end_of_record.b8
  1325.   BeginWhile
  1326.    length += obj_iterated_data_block_length();
  1327.   EndWhile;
  1328.  obj_ptr.b8 = start;
  1329.  return(length);
  1330. EndCode
  1331.  
  1332. /*+-------------------------------------------------------------------------+
  1333.   |                                                                         |
  1334.   |                               obj_LINNUM                                |
  1335.   |                                                                         |
  1336.   +-------------------------------------------------------------------------+*/
  1337. bit_16 obj_LINNUM()
  1338. BeginDeclarations
  1339. EndDeclarations
  1340. BeginCode
  1341.  If Current_record_header.rec_typ IsNot LINNUM_record
  1342.   Then
  1343.    return(False);
  1344.   EndIf;
  1345.  obj_next_record();
  1346.  return(True);
  1347. EndCode
  1348.  
  1349. /*+-------------------------------------------------------------------------+
  1350.   |                                                                         |
  1351.   |                               obj_LNAMES                                |
  1352.   |                                                                         |
  1353.   +-------------------------------------------------------------------------+*/
  1354. bit_16 obj_LNAMES()
  1355. BeginDeclarations
  1356. EndDeclarations
  1357. BeginCode
  1358.  If Current_record_header.rec_typ IsNot LNAMES_record
  1359.   Then
  1360.    return(False);
  1361.   EndIf;
  1362.  While obj_ptr.b8 IsNot end_of_record.b8
  1363.   BeginWhile
  1364.    If n_lnames NotLessThan max_lnames.val
  1365.     Then
  1366.      linker_error(12, "Internal limit exceeded:\n"
  1367.                       "\tModule:  \"%Fs\"\n"
  1368.                       "\t  File:  \"%Fs\"\n"
  1369.                       "\tOffset:  %lu\n"
  1370.                       "\t Error:  Too many LNAMES.  Max of %u exceeded.\n"
  1371.                       "\t         Retry with larger \"/maxlnames:n\" switch.\n",
  1372.                       (*tmodule_name).symbol,
  1373.                       (*infile.file_info).filename,
  1374.                       current_record_offset,
  1375.                       max_lnames.val);
  1376.     EndIf;
  1377.    lnames[++n_lnames] = obj_name();
  1378.   EndWhile;
  1379.  obj_next_record();
  1380.  return(True);
  1381. EndCode
  1382.  
  1383. /*+-------------------------------------------------------------------------+
  1384.   |                                                                         |
  1385.   |                               obj_MODEND                                |
  1386.   |                                                                         |
  1387.   +-------------------------------------------------------------------------+*/
  1388. bit_16 obj_MODEND()
  1389. BeginDeclarations
  1390. FIX_DAT_type                           END_DAT;
  1391. bit_16                                 frame_method;
  1392. MOD_TYP_type                           MOD_TYP;
  1393. bit_16                                 target_method;
  1394. bit_16                                 thread_number;
  1395. EndDeclarations
  1396. BeginCode
  1397.  If Current_record_header.rec_typ IsNot MODEND_record
  1398.   Then
  1399.    return(False);
  1400.   EndIf;
  1401.  MOD_TYP = *obj_ptr.MOD_TYP++;
  1402.  
  1403.  If MOD_TYP.zeros IsNotZero
  1404.   Then
  1405.    linker_error(4, "Translator error:\n"
  1406.                    "\tModule:  \"%Fs\"\n"
  1407.                    "\t  File:  \"%Fs\"\n"
  1408.                    "\tOffset:  %lu\n"
  1409.                    "\t Error:  Bits 1 thru 5 of MOD TYP must be zero.\n",
  1410.                    (*tmodule_name).symbol,
  1411.                    (*infile.file_info).filename,
  1412.                    current_record_offset);
  1413.   EndIf;
  1414.  
  1415.  If (MOD_TYP.mattr IsNot 1) AndIf (MOD_TYP.mattr IsNot 3)
  1416.   Then  /* We have no starting address */
  1417.    return(True);
  1418.   EndIf;
  1419.  
  1420.  If MOD_TYP.l IsNot 1
  1421.   Then
  1422.    linker_error(4, "Translator error:\n"
  1423.                    "\tModule:  \"%Fs\"\n"
  1424.                    "\t  File:  \"%Fs\"\n"
  1425.                    "\tOffset:  %lu\n"
  1426.                    "\t Error:  Bit 0 of MOD TYP must be one.\n",
  1427.                    (*tmodule_name).symbol,
  1428.                    (*infile.file_info).filename,
  1429.                    current_record_offset);
  1430.   EndIf;
  1431.  
  1432.  If start_address_found IsTrue
  1433.   Then
  1434.    linker_error(4, "Multiple start address encountered.  The start address\n"
  1435.                    "in module \"%Fs\" of file \"%Fs\" has been ignored.\n",
  1436.                    (*tmodule_name).symbol,
  1437.                    (*infile.file_info).filename);
  1438.   EndIf;
  1439.  
  1440.  start_address_found = True;
  1441.  
  1442. /*+-------------------------------------------------------------------------+
  1443.   |                                                                         |
  1444.   |                  Pick up the required field END_DAT.                    |
  1445.   |                                                                         |
  1446.   +-------------------------------------------------------------------------+*/
  1447.  
  1448.  END_DAT = *obj_ptr.FIX_DAT++;
  1449.  
  1450. /*+-------------------------------------------------------------------------+
  1451.   |                                                                         |
  1452.   |                         Process the frame part.                         |
  1453.   |                                                                         |
  1454.   +-------------------------------------------------------------------------+*/
  1455.  
  1456.  If END_DAT.f IsZero
  1457.   Then  /* Frame is specified explicitly */
  1458.    frame_method                 = END_DAT.frame;
  1459.    start_address.frame_method   = frame_method;
  1460.    Using frame_method
  1461.     BeginCase
  1462.      When 0:
  1463.       start_address.frame_referent =
  1464.        (void far *) snames[obj_index_segment()];
  1465.       break;
  1466.      When 1:
  1467.       start_address.frame_referent =
  1468.        (void far *) gnames[obj_index_group()];
  1469.       break;
  1470.      When 2:
  1471.       start_address.frame_referent =
  1472.        (void far *) externals[obj_index_external()];
  1473.       break;
  1474.      When 3:
  1475.       start_address.frame_referent =
  1476.        (void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
  1477.      Otherwise:
  1478.       start_address.frame_referent = Null;
  1479.       break;
  1480.     EndCase;
  1481.   Else  /* Frame is specified by a thread */
  1482.    thread_number                = END_DAT.frame;
  1483.    If Not frame_thread[thread_number].thread_defined
  1484.     Then
  1485.      linker_error(12, "Translator error:\n"
  1486.                       "\tModule:  \"%Fs\"\n"
  1487.                       "\t  File:  \"%Fs\"\n"
  1488.                       "\tOffset:  %lu\n"
  1489.                       "\t Error:  Reference to frame thread %u which has "
  1490.                                   "been defined.n",
  1491.                       (*tmodule_name).symbol,
  1492.                       (*infile.file_info).filename,
  1493.                       current_record_offset,
  1494.                       thread_number);
  1495.     EndIf;
  1496.    start_address.frame_referent = frame_thread[thread_number].referent;
  1497.    start_address.frame_method   = frame_thread[thread_number].method;
  1498.   EndIf;
  1499.  
  1500. /*+-------------------------------------------------------------------------+
  1501.   |                                                                         |
  1502.   |                         Process the target part.                        |
  1503.   |                                                                         |
  1504.   +-------------------------------------------------------------------------+*/
  1505.  
  1506.  If END_DAT.t IsZero
  1507.   Then  /* Target is specified explicitly */
  1508.    target_method               = END_DAT.targt;
  1509.    start_address.target_method = target_method;
  1510.    Using target_method
  1511.     BeginCase
  1512.      When 0:
  1513.       start_address.target_referent =
  1514.        (void far *) snames[obj_index_segment()];
  1515.       break;
  1516.      When 1:
  1517.       start_address.target_referent =
  1518.        (void far *) gnames[obj_index_group()];
  1519.       break;
  1520.      When 2:
  1521.       start_address.target_referent =
  1522.        (void far *) externals[obj_index_external()];
  1523.       break;
  1524.      When 3:
  1525.       start_address.target_referent =
  1526.        (void far *) (Bit_32(*obj_ptr.b16++) ShiftedLeft 4);
  1527.       break;
  1528.     EndCase;
  1529.   Else  /* Target is specified by a thread */
  1530.    thread_number                 = END_DAT.targt;
  1531.    If Not target_thread[thread_number].thread_defined
  1532.     Then
  1533.      linker_error(12, "Translator error:\n"
  1534.                       "\tModule:  \"%Fs\"\n"
  1535.                       "\t  File:  \"%Fs\"\n"
  1536.                       "\tOffset:  %lu\n"
  1537.                       "\t Error:  Reference to target thread %u which has "
  1538.                                   "been defined.n",
  1539.                       (*tmodule_name).symbol,
  1540.                       (*infile.file_info).filename,
  1541.                       current_record_offset,
  1542.                       thread_number);
  1543.     EndIf;
  1544.    start_address.target_referent = target_thread[thread_number].referent;
  1545.    start_address.target_method   = target_thread[thread_number].method;
  1546.   EndIf;
  1547.  
  1548.  If END_DAT.p IsZero
  1549.   Then  /* There is a target displacement */
  1550.    start_address.target_offset = *obj_ptr.b16++;
  1551.   Else  /* The target displacement is zero */
  1552.    linker_error(12, "Translator error:\n"
  1553.                     "\tModule:  \"%Fs\"\n"
  1554.                     "\t  File:  \"%Fs\"\n"
  1555.                     "\tOffset:  %lu\n"
  1556.                     "\t Error:  Only primary fixups allowed in MODEND.\n",
  1557.                     (*tmodule_name).symbol,
  1558.                     (*infile.file_info).filename,
  1559.                     current_record_offset);
  1560.    start_address.target_offset = 0;
  1561.   EndIf;
  1562.  return(True);
  1563. EndCode
  1564.  
  1565. /*+-------------------------------------------------------------------------+
  1566.   |                                                                         |
  1567.   |                               obj_MODEXT                                |
  1568.   |                                                                         |
  1569.   +-------------------------------------------------------------------------+*/
  1570. bit_16 obj_MODEXT()
  1571. BeginDeclarations
  1572. bit_16                                 len;
  1573. public_entry_ptr                       pub;
  1574. #define Pub                            (*pub)
  1575. EndDeclarations
  1576. BeginCode
  1577.  If Current_record_header.rec_typ IsNot MODEXT_record
  1578.   Then
  1579.    return(False);
  1580.   EndIf;
  1581.  While obj_ptr.b8 IsNot end_of_record.b8
  1582.   BeginWhile
  1583.    If n_externals NotLessThan max_externals.val
  1584.     Then
  1585.      linker_error(12, "Internal limit exceeded:\n"
  1586.                       "\tModule:  \"%Fs\"\n"
  1587.                       "\t  File:  \"%Fs\"\n"
  1588.                       "\tOffset:  %lu\n"
  1589.                       "\t Error:  Too many externals.  Max of %u exceeded.\n"
  1590.                       "\t         Retry with larger \"/maxexternals:n\" "
  1591.                                   "switch.\n",
  1592.                       (*tmodule_name).symbol,
  1593.                       (*infile.file_info).filename,
  1594.                       current_record_offset,
  1595.                       max_externals.val);
  1596.     EndIf;
  1597.    len         = obj_name_length();
  1598.    If case_ignore.val
  1599.     Then
  1600.      far_to_lower(BytePtr(obj_ptr.b8), len);
  1601.     EndIf;
  1602.    pub         = lookup_public(len, obj_ptr.b8, tmodule_number);
  1603.    obj_ptr.b8 += len;
  1604.    obj_name_length();  /* Eat the type index. */
  1605.    externals[++n_externals] = pub;
  1606.    If Pub.type_entry Is unused
  1607.     Then
  1608.      Insert pub AtEnd InList external_list EndInsert;
  1609.      Pub.type_entry = external;
  1610.     EndIf;
  1611.   EndWhile;
  1612.  obj_next_record();
  1613.  return(True);
  1614. EndCode
  1615. #undef Pub
  1616.  
  1617. /*+-------------------------------------------------------------------------+
  1618.   |                                                                         |
  1619.   |                               obj_MODPUB                                |
  1620.   |                                                                         |
  1621.   +-------------------------------------------------------------------------+*/
  1622. bit_16 obj_MODPUB()
  1623. BeginDeclarations
  1624. bit_16                                 group_index;
  1625. bit_16                                 frame;
  1626. bit_16                                 len;
  1627. public_entry_ptr                       pub;
  1628. #define Pub                            (*pub)
  1629. bit_16                                 segment_index;
  1630. EndDeclarations
  1631. BeginCode
  1632.  If Current_record_header.rec_typ IsNot MODPUB_record
  1633.   Then
  1634.    return(False);
  1635.   EndIf;
  1636.  group_index = obj_index_group();
  1637.  segment_index = obj_index_segment();
  1638.  If (segment_index IsZero) AndIf (group_index IsZero)
  1639.   Then
  1640.    frame = *obj_ptr.b16++;
  1641.   EndIf;
  1642.  While obj_ptr.b8 IsNot end_of_record.b8
  1643.   BeginWhile
  1644.    len = obj_name_length();
  1645.    If case_ignore.val
  1646.     Then
  1647.      far_to_lower(BytePtr(obj_ptr.b8), len);
  1648.     EndIf;
  1649.    pub = lookup_public(len, obj_ptr.b8, tmodule_number);
  1650.    obj_ptr.b8 += len;
  1651.    If Pub.type_entry Is internal
  1652.     Then
  1653.      linker_error(4, "Duplicate definition of public \"%Fs\".\n"
  1654.                      "\tDefinition in module \"%Fs\" of file \"%Fs\" "
  1655.                      "ignored.\n",
  1656.                      Pub.symbol,
  1657.                      (*tmodule_name).symbol,(*infile.file_info).filename);
  1658.      obj_ptr.b16++;      /* Eat offset. */
  1659.      obj_name_length();  /* Eat type index. */
  1660.     Else
  1661.      If Pub.type_entry Is unused
  1662.       Then
  1663.        Insert pub AtEnd InList external_list EndInsert;
  1664.       EndIf;
  1665.      Pub.type_entry       = internal;
  1666.      Pub.Internal.group   = gnames[group_index];
  1667.      Pub.Internal.lseg    = snames[segment_index];
  1668.      Pub.Internal.frame   = frame;
  1669.      Pub.Internal.offset  = *obj_ptr.b16++;
  1670.      obj_name_length();  /* Eat type index. */
  1671.     EndIf;
  1672.   EndWhile;
  1673.  obj_next_record();
  1674.  return(True);
  1675. EndCode
  1676. #undef Pub
  1677.  
  1678. /*+-------------------------------------------------------------------------+
  1679.   |                                                                         |
  1680.   |                              obj_modtail                                |
  1681.   |                                                                         |
  1682.   +-------------------------------------------------------------------------+*/
  1683.  
  1684. /* obj_modtail:: obj_MODEND */
  1685.  
  1686. bit_16 obj_modtail()
  1687. BeginDeclarations
  1688. EndDeclarations
  1689. BeginCode
  1690.  If obj_MODEND()
  1691.   Then
  1692.    return(True);
  1693.   EndIf;
  1694.  return(False);
  1695. EndCode
  1696.  
  1697. /*+-------------------------------------------------------------------------+
  1698.   |                                                                         |
  1699.   |                               obj_name                                  |
  1700.   |                                                                         |
  1701.   +-------------------------------------------------------------------------+*/
  1702. lname_entry_ptr obj_name()
  1703. BeginDeclarations
  1704. lname_entry_ptr                        name;
  1705. bit_16                                 len;
  1706. EndDeclarations
  1707. BeginCode
  1708.  len = obj_name_length();
  1709.  If len IsZero
  1710.   Then
  1711.    name = none_lname;
  1712.   Else
  1713.    If case_ignore.val
  1714.     Then
  1715.      far_to_lower(BytePtr(obj_ptr.b8), len);
  1716.     EndIf;
  1717.    name        = lookup_lname(len, obj_ptr.b8);
  1718.    obj_ptr.b8 += len;
  1719.   EndIf;
  1720.  return(name);
  1721. EndCode
  1722.  
  1723. /*+-------------------------------------------------------------------------+
  1724.   |                                                                         |
  1725.   |                            obj_name_length                              |
  1726.   |                                                                         |
  1727.   +-------------------------------------------------------------------------+*/
  1728. bit_16 obj_name_length()
  1729. BeginDeclarations
  1730. EndDeclarations
  1731. BeginCode
  1732.  If *obj_ptr.b8 LessThan 128
  1733.   Then
  1734.    return(Bit_16(*obj_ptr.b8++));
  1735.   Else
  1736.    return((Bit_16(*obj_ptr.b8++ - 128) ShiftedLeft 8) +
  1737.           (Bit_16(*obj_ptr.b8++)));
  1738.   EndIf;
  1739. EndCode
  1740.  
  1741. /*+-------------------------------------------------------------------------+
  1742.   |                                                                         |
  1743.   |                             obj_next_record                             |
  1744.   |                                                                         |
  1745.   +-------------------------------------------------------------------------+*/
  1746. void obj_next_record()
  1747. BeginDeclarations
  1748. EndDeclarations
  1749. BeginCode
  1750.  Repeat
  1751.   BeginRepeat
  1752.    file_read(object_file_element,  sizeof(obj_record_header_type) - 1);
  1753.    While (Current_record_header.rec_typ Is LINNUM_record) OrIf
  1754.          ((Current_record_header.rec_typ Is COMENT_record) AndIf
  1755.           (Current_record_header.rec_len Exceeds MAX_OBJECT_FILE_READ_SIZE))
  1756.     BeginWhile
  1757.      file_position(Bit_32(infile.byte_position) +
  1758.                    infile.start_of_buffer_position +
  1759.                    Bit_32(Current_record_header.rec_len));
  1760.      file_read(object_file_element,  sizeof(obj_record_header_type) - 1);
  1761.     EndWhile;
  1762.    current_record_offset = Bit_32(infile.byte_position) +
  1763.                            infile.start_of_buffer_position -
  1764.                            Bit_32(sizeof(obj_record_header_type)-1);
  1765.    If Current_record_header.rec_len Exceeds MAX_OBJECT_FILE_READ_SIZE
  1766.     Then
  1767.      linker_error(12, "Probable invalid OBJ format "
  1768.                       "or possible translator error:\n"
  1769.                       "\tModule:  \"%Fs\"\n"
  1770.                       "\t  File:  \"%Fs\"\n"
  1771.                       "\tOffset:  %lu\n"
  1772.                       "\t Error:  Record too long.\n"
  1773.                       "\t         Max record length supported by this "
  1774.                                  "linker is %u bytes.\n",
  1775.                       (*tmodule_name).symbol,
  1776.                       (*infile.file_info).filename,
  1777.                       current_record_offset,
  1778.                       MAX_OBJECT_FILE_READ_SIZE);
  1779.     EndIf;
  1780.    file_read(Current_record_header.variant_part, 
  1781.              Current_record_header.rec_len);
  1782.    If (objchecksum.val IsTrue) AndIf
  1783.       (Bit_8(checksum(Current_record_header.rec_len +
  1784.                       sizeof(obj_record_header_type)-1,
  1785.                      (byte *) current_record_header)) IsNotZero)
  1786.     Then
  1787.      linker_error(12, "Translator error:\n"
  1788.                       "\tModule:  \"%Fs\"\n"
  1789.                       "\t  File:  \"%Fs\"\n"
  1790.                       "\tOffset:  %lu\n"
  1791.                       "\t Error:  Checksum error.\n",
  1792.                       (*tmodule_name).symbol,
  1793.                       (*infile.file_info).filename,
  1794.                       current_record_offset);
  1795.     EndIf;
  1796.    obj_ptr.b8 = Current_record_header.variant_part;
  1797.    end_of_record.b8 =
  1798.     (byte *)
  1799.      Addr(Current_record_header.variant_part[Current_record_header.rec_len-1]);
  1800.    RepeatIf obj_COMENT()
  1801.   EndRepeat;
  1802.  return;
  1803. EndCode
  1804.  
  1805. /*+-------------------------------------------------------------------------+
  1806.   |                                                                         |
  1807.   |                               obj_PUBDEF                                |
  1808.   |                                                                         |
  1809.   +-------------------------------------------------------------------------+*/
  1810. bit_16 obj_PUBDEF()
  1811. BeginDeclarations
  1812. bit_16                                 group_index;
  1813. bit_16                                 frame;
  1814. bit_16                                 len;
  1815. public_entry_ptr                       pub;
  1816. #define Pub                            (*pub)
  1817. bit_16                                 segment_index;
  1818. EndDeclarations
  1819. BeginCode
  1820.  If Current_record_header.rec_typ IsNot PUBDEF_record
  1821.   Then
  1822.    return(False);
  1823.   EndIf;
  1824.  group_index = obj_index_group();
  1825.  segment_index = obj_index_segment();
  1826.  If (segment_index IsZero) AndIf (group_index IsZero)
  1827.   Then
  1828.    frame = *obj_ptr.b16++;
  1829.   EndIf;
  1830.  While obj_ptr.b8 IsNot end_of_record.b8
  1831.   BeginWhile
  1832.    len = obj_name_length();
  1833.    If case_ignore.val
  1834.     Then
  1835.      far_to_lower(BytePtr(obj_ptr.b8), len);
  1836.     EndIf;
  1837.    pub = lookup_public(len, obj_ptr.b8, 0);
  1838.    obj_ptr.b8 += len;
  1839.    If Pub.type_entry Is internal
  1840.     Then
  1841.      linker_error(4, "Duplicate definition of public \"%Fs\".\n"
  1842.                      "\tDefinition in module \"%Fs\" of file \"%Fs\" "
  1843.                      "ignored.\n",
  1844.                      Pub.symbol,
  1845.                      (*tmodule_name).symbol,(*infile.file_info).filename);
  1846.      obj_ptr.b16++;      /* Eat offset. */
  1847.      obj_name_length();  /* Eat type index. */
  1848.     Else
  1849.      If Pub.type_entry Is unused
  1850.       Then
  1851.        Insert pub AtEnd InList external_list EndInsert;
  1852.       EndIf;
  1853.      If (Pub.type_entry Is public_in_library) AndIf
  1854.         (Pub.Library.requested)
  1855.       Then
  1856.        library_request_count--;
  1857.        (*Pub.Library.lib_file).request_count--;
  1858.       EndIf;
  1859.      Pub.type_entry       = internal;
  1860.      Pub.Internal.group   = gnames[group_index];
  1861.      Pub.Internal.lseg    = snames[segment_index];
  1862.      Pub.Internal.frame   = frame;
  1863.      Pub.Internal.offset  = *obj_ptr.b16++;
  1864.      obj_name_length();  /* Eat type index. */
  1865.     EndIf;
  1866.   EndWhile;
  1867.  obj_next_record();
  1868.  return(True);
  1869. EndCode
  1870. #undef Pub
  1871.  
  1872. /*+-------------------------------------------------------------------------+
  1873.   |                                                                         |
  1874.   |                               obj_SEGDEF                                |
  1875.   |                                                                         |
  1876.   +-------------------------------------------------------------------------+*/
  1877. bit_16 obj_SEGDEF()
  1878. BeginDeclarations
  1879. acbp_type                              acbp;
  1880. bit_32                                 address;
  1881. bit_8                                  align;
  1882. lname_entry_ptr                        class_lname;
  1883. bit_8                                  combine;
  1884. bit_32                                 length;
  1885. lseg_ptr                               lseg;
  1886. #define Lseg                           (*lseg)
  1887. bit_16                                 segment_index;
  1888. lname_entry_ptr                        segment_lname;
  1889. EndDeclarations
  1890. BeginCode
  1891.  If Current_record_header.rec_typ IsNot SEGDEF_record
  1892.   Then
  1893.    return(False);
  1894.   EndIf;
  1895.  acbp    = *obj_ptr.acbp++;
  1896.  align   = Bit_8(acbp.a);
  1897.  If align Is absolute_segment
  1898.   Then
  1899.    address  = (Bit_32(*obj_ptr.b16++) ShiftedLeft 4L);  /* Frame */
  1900.    address += Bit_32(*obj_ptr.b8++);                    /* Offset */
  1901.   Else
  1902.    address = 0L;
  1903.   EndIf;
  1904.  If align Exceeds dword_aligned
  1905.   Then
  1906.    linker_error(12, "Translator error:\n"
  1907.                     "\tModule:  \"%Fs\"\n"
  1908.                     "\t  File:  \"%Fs\"\n"
  1909.                     "\tOffset:  %lu\n"
  1910.                     "\t Error:  Align type of %u is undefined.\n",
  1911.                     (*tmodule_name).symbol,
  1912.                     (*infile.file_info).filename,
  1913.                     current_record_offset,
  1914.                     align);
  1915.   EndIf;
  1916.  combine = Bit_8(acbp.c);
  1917.  If (combine Is 4) OrIf (combine Is 7)
  1918.   Then /* Treat combine types 4 and 7 the same as 2. */
  1919.    combine = public_combine;
  1920.   EndIf;
  1921.  If (combine Is 1) OrIf (combine Is 3)
  1922.   Then /* This is a translator error. */
  1923.    linker_error(12, "Translator error:\n"
  1924.                     "\tModule:  \"%Fs\"\n"
  1925.                     "\t  File:  \"%Fs\"\n"
  1926.                     "\tOffset:  %lu\n"
  1927.                     "\t Error:  Combine type of %u is undefined.\n",
  1928.                     (*tmodule_name).symbol,
  1929.                     (*infile.file_info).filename,
  1930.                     current_record_offset,
  1931.                     combine);
  1932.   EndIf;
  1933.  length = Bit_32(*obj_ptr.b16++);
  1934.  If acbp.b IsNotZero
  1935.   Then
  1936.    If length IsNotZero
  1937.     Then
  1938.      linker_error(12, "Translator error:\n"
  1939.                       "\tModule:  \"%Fs\"\n"
  1940.                       "\t  File:  \"%Fs\"\n"
  1941.                       "\tOffset:  %lu\n"
  1942.                       "\t Error:  SEGDEF has acbp.b of 1 and length not "
  1943.                                   "zero.\n",
  1944.                       (*tmodule_name).symbol,
  1945.                       (*infile.file_info).filename,
  1946.                       current_record_offset);
  1947.     EndIf;
  1948.    length = 65536L;
  1949.   EndIf;
  1950.  segment_index         = obj_index_LNAME();
  1951.  segment_lname         = lnames[segment_index];
  1952.  class_lname           = lnames[obj_index_LNAME()];
  1953.  lseg = obj_generate_segment(segment_lname,
  1954.                              class_lname,
  1955.                              combine,
  1956.                              align,
  1957.                              tmodule_name,
  1958.                              infile.file_info,
  1959.                              address,
  1960.                              length);
  1961.  If n_segments NotLessThan max_segments.val
  1962.   Then
  1963.    linker_error(12, "Internal limit exceeded:\n"
  1964.                     "\tModule:  \"%Fs\"\n"
  1965.                     "\t  File:  \"%Fs\"\n"
  1966.                     "\tOffset:  %lu\n"
  1967.                     "\t Error:  Too many SEGDEFs.  Max of %u exceeded.\n"
  1968.                     "\t         Retry with larger \"/maxsegments:n\" "
  1969.                                 "switch.\n",
  1970.                     (*tmodule_name).symbol,
  1971.                     (*infile.file_info).filename,
  1972.                     current_record_offset,
  1973.                     max_segments.val);
  1974.   EndIf;
  1975.  snames[++n_segments]  = lseg;
  1976.  
  1977.  obj_next_record();
  1978.  return(True);
  1979. EndCode
  1980. #undef Lseg
  1981.  
  1982. /*+-------------------------------------------------------------------------+
  1983.   |                                                                         |
  1984.   |                              obj_seg_grp                                |
  1985.   |                                                                         |
  1986.   +-------------------------------------------------------------------------+*/
  1987.  
  1988. /* obj_seg_grp:: {obj_LNAMES | obj_SEGDEF | obj_EXTDEF}
  1989.                  {obj_TYPDEF | obj_EXTDEF | obj_GRPDEF} */
  1990. bit_16 obj_seg_grp()
  1991. BeginDeclarations
  1992. EndDeclarations
  1993. BeginCode
  1994.  While obj_LNAMES() OrIf obj_SEGDEF() OrIf obj_EXTDEF()
  1995.   BeginWhile
  1996.   EndWhile;
  1997.  While obj_TYPDEF() OrIf obj_EXTDEF() OrIf obj_GRPDEF()
  1998.   BeginWhile
  1999.   EndWhile;
  2000.  return(True);
  2001. EndCode
  2002.  
  2003. /*+-------------------------------------------------------------------------+
  2004.   |                                                                         |
  2005.   |                               obj_THEADR                                |
  2006.   |                                                                         |
  2007.   +-------------------------------------------------------------------------+*/
  2008. bit_16 obj_THEADR()
  2009. BeginDeclarations
  2010. EndDeclarations
  2011. BeginCode
  2012.  If Current_record_header.rec_typ IsNot THEADR_record
  2013.   Then
  2014.    return(False);
  2015.   EndIf;
  2016.  tmodule_name = obj_name();
  2017.  obj_next_record();
  2018.  return(True);
  2019. EndCode
  2020.  
  2021. /*+-------------------------------------------------------------------------+
  2022.   |                                                                         |
  2023.   |                             obj_thread_def                              |
  2024.   |                                                                         |
  2025.   +-------------------------------------------------------------------------+*/
  2026.  
  2027. /* obj_thread_def:: obj_FIXUPP  (containing only thread fields) */
  2028.  
  2029. bit_16 obj_thread_def()
  2030. BeginDeclarations
  2031. EndDeclarations
  2032. BeginCode
  2033.  If obj_FIXUPP()
  2034.   Then
  2035.    If FIXUPP_contains_only_threads
  2036.     Then
  2037.      return(True);
  2038.     Else
  2039.      linker_error(12, "Translator error:\n"
  2040.                       "\tModule:  \"%Fs\"\n"
  2041.                       "\t  File:  \"%Fs\"\n"
  2042.                       "\tOffset:  %lu\n"
  2043.                       "\t Error:  \"THREAD DEF\" FIXUPP encountered which "
  2044.                                   "did not contain\n"
  2045.                       "\t          only thread defs.\n",
  2046.                       (*tmodule_name).symbol,
  2047.                       (*infile.file_info).filename,
  2048.                       current_record_offset);
  2049.     EndIf;
  2050.   EndIf;
  2051.  return(False);
  2052. EndCode
  2053.  
  2054. /*+-------------------------------------------------------------------------+
  2055.   |                                                                         |
  2056.   |                              obj_tmodule                                |
  2057.   |                                                                         |
  2058.   +-------------------------------------------------------------------------+*/
  2059.  
  2060. /* obj_t_module:: obj_THEADR obj_seg_grp {obj_component} obj_modtail */
  2061.  
  2062. bit_16 obj_tmodule()
  2063. BeginDeclarations
  2064. EndDeclarations
  2065. BeginCode
  2066.  far_set(BytePtr(externals), 0,
  2067.          sizeof(public_entry_ptr)*(max_externals.val+1));
  2068.  far_set(BytePtr(gnames),    0,
  2069.          sizeof(group_entry_ptr)*(max_groups.val+1));
  2070.  far_set(BytePtr(lnames),    0,
  2071.          sizeof(lname_entry_ptr)*(max_lnames.val+1));
  2072.  far_set(BytePtr(snames),    0,
  2073.          sizeof(lseg_ptr)*(max_segments.val+1));
  2074.  far_set(BytePtr(target_thread), 0, sizeof(thread_type)*4);
  2075.  far_set(BytePtr(frame_thread),  0, sizeof(thread_type)*4);
  2076.  
  2077.  n_externals =
  2078.  n_groups    =
  2079.  n_lnames    =
  2080.  n_segments  = 0;
  2081.  tmodule_number++;
  2082.  tmodule_name = lookup_lname(31, (byte *) "(THEADR record not encountered)");
  2083.  obj_next_record();
  2084.  If Not obj_THEADR()
  2085.   Then
  2086.    linker_error(12, "Translator error:\n"
  2087.                     "\tModule:  \"%Fs\"\n"
  2088.                     "\t  File:  \"%Fs\"\n"
  2089.                     "\tOffset:  %lu\n"
  2090.                     "\t Error:  T-MODULE record missing.\n",
  2091.                     (*tmodule_name).symbol,
  2092.                     (*infile.file_info).filename,
  2093.                     current_record_offset);
  2094.   EndIf;
  2095.  If Not obj_seg_grp()
  2096.   Then
  2097.    linker_error(12, "Translator error:\n"
  2098.                     "\tModule:  \"%Fs\"\n"
  2099.                     "\t  File:  \"%Fs\"\n"
  2100.                     "\tOffset:  %lu\n"
  2101.                     "\t Error:  Segment/Group definition record(s) missing.\n",
  2102.                     (*tmodule_name).symbol,
  2103.                     (*infile.file_info).filename,
  2104.                     current_record_offset);
  2105.   EndIf;
  2106.  While obj_component()
  2107.   BeginWhile
  2108.   EndWhile;
  2109.  If Not obj_modtail()
  2110.   Then
  2111.    linker_error(12, "Translator error:\n"
  2112.                     "\tModule:  \"%Fs\"\n"
  2113.                     "\t  File:  \"%Fs\"\n"
  2114.                     "\tOffset:  %lu\n"
  2115.                     "\t Error:  MODEND record missing.\n",
  2116.                     (*tmodule_name).symbol,
  2117.                     (*infile.file_info).filename,
  2118.                     current_record_offset);
  2119.   EndIf;
  2120.  return(True);
  2121. EndCode
  2122.  
  2123. /*+-------------------------------------------------------------------------+
  2124.   |                                                                         |
  2125.   |                               obj_TYPDEF                                |
  2126.   |                                                                         |
  2127.   +-------------------------------------------------------------------------+*/
  2128. bit_16 obj_TYPDEF()
  2129. BeginDeclarations
  2130. EndDeclarations
  2131. BeginCode
  2132.  If Current_record_header.rec_typ IsNot TYPDEF_record
  2133.   Then
  2134.    return(False);
  2135.   EndIf;
  2136.  obj_next_record();
  2137.  return(True);
  2138. EndCode
  2139.  
  2140. /*+-------------------------------------------------------------------------+
  2141.   |                                                                         |
  2142.   |                              write_temp_file                            |
  2143.   |                                                                         |
  2144.   +-------------------------------------------------------------------------+*/
  2145. void write_temp_file(bit_8           rec_typ,
  2146.                      lseg_ptr        lseg,
  2147.                      bit_16          offset,
  2148.                      byte_ptr        data,
  2149.                      bit_16          len)
  2150. BeginDeclarations
  2151. EndDeclarations
  2152. BeginCode
  2153.  temp_file_header.rec_typ       = rec_typ;
  2154.  temp_file_header.rec_len       = len;
  2155.  temp_file_header.lseg          = lseg;
  2156.  temp_file_header.offset        = offset;
  2157.  file_write(BytePtr(Addr(temp_file_header)), 
  2158.             Bit_32(sizeof(temp_file_header)));
  2159.  If len Exceeds 0
  2160.   Then
  2161.    file_write(data, Bit_32(len));
  2162.   EndIf;
  2163.  return;
  2164. EndCode
  2165.  
  2166.  
  2167.