home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 1.ddi / MWHC.001 / M < prev    next >
Encoding:
Text File  |  1992-12-09  |  58.2 KB  |  1,747 lines

  1. small_m = 1
  2. mach386 = 1
  3. GOC = 1
  4. comment %
  5. **************************************************************************
  6. ***  (c) Copyright 1983 - 1992            MetaWare Incorporated.       ***
  7. **************************************************************************
  8. ***  You have the same rights to the object form of this program as    ***
  9. ***  you do to the object code of the library.  You may not distribute ***
  10. ***  this source, even if modified by you.                             ***
  11. **************************************************************************
  12. ***  The source to this module is provided for the convenience of      ***
  13. ***  MetaWare Pascal and High C users that need to tailor their        ***
  14. ***  execution environments.  The casual user should NOT play with the ***
  15. ***  code. This code is subject to change without notice in future     ***
  16. ***  releases of the compilers.                                        ***
  17. **************************************************************************
  18. ***  You must preserve the library copyright notice defined in this    ***
  19. ***  module if your program uses any portion at all of the run-time    ***
  20. ***  library (including this initializer or any other supplied run-    ***
  21. ***  time source).  The copyright notice is in the definition of       ***
  22. ***  the initial stack segment.  We recommend it be left right there.  ***
  23. ***  But you can move it to anywhere you want as long it appears in    ***
  24. ***  any linked program (.exe or ROM-burned program) using the library.***
  25. **************************************************************************
  26.  
  27.  
  28.       MetaWare Pascal or High C Runtime Initialization Module
  29.                    for small model, protected mode 386.
  30.  
  31.  
  32.  --------------------------------------------------------------------------
  33.   This initializer supports:
  34.  --------------------------------------------------------------------------
  35.   a. Pharlap's 386 DOS|Extender, run386.
  36.   b. A.I. Architect's (Eclipse) OS/386 DOS extender.
  37.  
  38.  --------------------------------------------------------------------------
  39.   Assembly instructions:
  40.  --------------------------------------------------------------------------
  41.   By default, the code assumes the use of 386asm.  If your would like to
  42.   use MASM, you must define USING_MASM later in the defines section.
  43.  
  44.  --------------------------------------------------------------------------
  45.   Differences between Pascal and C run-time initialization:
  46.  --------------------------------------------------------------------------
  47.   In C, the argv array must be allocated and computed.  In Pascal argument
  48.   processing is handled through a separate argument pacakge.
  49.  
  50.  --------------------------------------------------------------------------
  51.   Defines that you can set:
  52.  --------------------------------------------------------------------------
  53.   1. USING_MASM.  Set this if you are using MASM to assemble this file.
  54.   2. HC.  Set if this is for the High C library; not set otherwise.
  55.   3. STACK_SIZE.  Set this to the size of the stack you want.
  56.   4. no87.  Set this if you know you have no 8087 or 287.  It will eliminate
  57.        the initialization code for the chip.
  58.        Also, it will remove the printing of the "no87" environment variable
  59.        if you have an 8087/287 and the no87 variable is set to non-blank string.
  60.        (Don't confuse the "no87" define in this assembly from the no87
  61.        MS-DOS environment variable.  Read the programmer's Guide for more info
  62.        on the latter.)
  63.        Another reason to set this variable is that you know you're never
  64.        going to use an 8087/287, even if you have one.  It's especially
  65.        useful to remove the printing of the no87 environment variable on
  66.        programs for which the 8087/287 processor is irrelevant.
  67.   5. DOS.   Set this if this initializer is for MS-DOS (default).  Unset it
  68.        for embedded applications where DOS doesn't exist.  If you unset it,
  69.        you won't get argc/argv for C, nor the arg package for Pascal.
  70.        It doesn't remove all of the DOS-dependent code -- some of it you must
  71.        still rewrite for embedded applications (like how to find the top of
  72.        memory).  (By "unset" we mean just comment out the line setting it!)
  73.        Note that unsetting DOS doesn't remove all DOS-dependent code in
  74.        the library.  For example, the interrupt handler initialization
  75.        uses INT 21h, and so does all I/O.  Read the Embedded Applications
  76.        section of the Programmer's Guide for more information about how
  77.        to change those modules (source is generally provided).
  78.   6. SG_exists  -- Set when IGC environment is possible.
  79.        Unsetting it comments out code dependent on that environment only.
  80.   7. PL_exists  -- Set when PharLap DOS|Extender environment is possible.
  81.        Unsetting it comments out code dependent on that environment only.
  82.   8. NOWTK      -- Set if either the Weitek 1167 will never be present or
  83.        if you never care about it.
  84.   9. PHAR_LAP_CAN_GROW_HEAP. Phar Lap's DOS|Extender 1.1t or later can grow
  85.        the heap dynamically. For enabling Phar Lap DOS|Extender to grow the
  86.        heap dynamically, ; uncomment the next line.
  87.  10. AIA_CAN_GROW_HEAP. For Lahey-linked programs, we assume expansion can
  88.        occur, since such linked programs do not give you all of memory.
  89.  
  90.  --------------------------------------------------------------------------
  91.   Initializer Source Files 
  92.  --------------------------------------------------------------------------
  93.  
  94.  Set the appropriate defines in the init.inc module, and then assemble
  95.  init.asm, init_67.asm, and init_87.asm.
  96.  
  97.  init.inc - This file includes definitions used across assembly files
  98.  init.asm - general stuff    
  99.  init_67.asm - Weitek coprocessor initialization
  100.  init_87.asm - x87, Cyrix coprocessor initialization
  101.  
  102.  init.h    - Include file to access intializer globals, functions from C 
  103.  cinit.c - Main initialization routine. Makes calls into init.asm code. 
  104.  
  105.  mini-Makefile:
  106.  
  107.      INITOBJS = init.obj init_67.obj init_87.obj cinit.obj 
  108.     
  109.      .asm.obj:
  110.         386asm $@
  111.     
  112.      .c.obj:
  113.         hc386 -c $@
  114.     
  115.      init.obj:    init.inc init.asm 
  116.     
  117.      init_67.obj:    init.inc init_67.asm 
  118.     
  119.      init_87.obj:    init.inc init_87.asm 
  120.  
  121.       cinit.obj:    init.h cinit.c
  122.  
  123.  --------------------------------------------------------------------------
  124.   Memory Layout:
  125.  --------------------------------------------------------------------------
  126.  
  127.  High memory   +---------------+
  128.                | END OF MEMORY |
  129.                |---------------|
  130.   _heaphi ->   | top-of-heap   |
  131.   _heaptop ->  |   ...         |
  132.                | bottom-of-heap|
  133.   _TOP  ->     |---------------|  <- Of size STACK_SIZE, unless there isn't
  134.                |   stack       |  <- room, in which case the first heap
  135.                |   ...         |  <- allocation will fail.
  136.                | end-of-stack  |
  137.   _BASE ->     +---------------+
  138.                DATA   segments   (static variables and named common)
  139.  Low memory    CODE   segments
  140.  See the programmer's guide for more information and pictures of
  141.  run-time organization with the different memory models.
  142.  Stack margin1 is 512 bytes above the true end-of-stack.
  143.  Stack margin2 is 256 bytes above the true end-of-stack.
  144.  In non-large models, the stack margins go in a reserved area in the data
  145.  segment, not in the stack segment.  In the large model, since there is
  146.  no single data segment, the stack margins go at the tail end of the stack
  147.  (at ss:-2 and ss:-4).
  148.  
  149.  If stack overflow checking is enabled, here is the code that is generated:
  150.        For procedures using 256 or less bytes in the stack:
  151.                cmp     esp,Stack_margin_1
  152.                jnb     around
  153.                int     0
  154.        around: ...
  155.  
  156.        Since Stack_margin_2 is 512 above true e-o-s, such procedures will always
  157.        leave at least 256 bytes (512-256) left in the stack.
  158.  
  159.        For procedures that use more than 256 bytes:
  160.                mov     eax,esp
  161.                sub     eax,Stack_margin_2
  162.                cmp     eax,Amount_to_allocate
  163.                jae     around
  164.                int     0
  165.        around: ...
  166.  
  167.        Since Stack_margin1 is 256 from true end,
  168.        such procedures will leave at least 256 bytes in the stack.
  169.  
  170.     Therefore, stack overflow occurs when less than 256 bytes would be
  171.     left AFTER stack allocation.
  172.     This permits the run-time environment to do some processing
  173.     such as producing a trace or cleaning up.
  174. %
  175. comment @
  176.  --------------------------------------------------------------------------
  177.   AutoDesk Compatibility
  178.  --------------------------------------------------------------------------
  179.         Modified for AutoLISP and protected mode ADI
  180.  
  181.         Expects to be called at starting address as a subroutine, rather
  182.         than as an executable program from the operating system.  Stack
  183.         and segment registers must be correctly set up; and some
  184.         additional information is expected in these registers:
  185.  
  186.         ECX     Compatibility-check value.  Must be equal to (our
  187.                 locally defined symbol) chkval.  If it isn't, we assume
  188.                 we are erroneously being executed as an independent
  189.                 separate program.  This won't work, so we exit
  190.                 immediately to the system.
  191.  
  192.         DX:ESI  Pointer to structure containing initialization information.
  193.                 A minimum structure size of 8 bytes is mandatory (12 bytes
  194.                 if PADI is set).  The first 4 bytes of the structure must
  195.                 contain the number of bytes making up the structure.  The
  196.                 second 4 bytes must contain the initial heapsize of the
  197.                 child process, obtained from the loader in AutoCAD.  If
  198.                 PADI is set, the third 4 bytes must contain the physical
  199.                 address of the packet buffer in AutoCAD to be used for
  200.                 communication with protected mode ADI drivers.  All subsequent
  201.                 bytes are the business between AutoCAD and the loaded child
  202.                 process and may vary.
  203.  
  204.         The value we return is the argument to exit() which terminates us.
  205.         We preserve no registers, not even SS and SP.
  206.  
  207.         Some protected mode ADI, ADS, and AutoLISP modifications are
  208.         conditioned on the tag ACAD.
  209.  
  210.         Some code for ADS only is included only if the tag ADS is
  211.         predefined (e.g., in the assembler command line).
  212.  
  213.         Code required for AutoCAD protected mode ADI drivers only is included
  214.         by setting PADI in the assembler command line.
  215.         @
  216.  
  217. minmem equ 4    ; Offset within the structure containing initialization
  218.                 ; information to the initial heap size of the child process.
  219.  
  220. ifdef   PADI
  221. physadr equ 8   ; Offset within the structure containing initialization
  222.                 ; information to the physical address of a buffer shared
  223.                 ; between AutoCAD and a protected mode ADI driver.
  224. endif   ; PADI
  225.  
  226. ;---------------------------------------------------------------------------
  227. ; Start of program code.
  228. ;---------------------------------------------------------------------------
  229.     .386p        ; Need p to execute "lsl" to determine limit
  230.             ; of data segment.
  231.     .287
  232.     name    init
  233.     include    init.inc    ; defaults moved into init.inc
  234.                 ; several assemblies use them.
  235.                 ; init.asm, init_67.asm init_87.asm
  236.  
  237.     ; The following include file is provided by IGC.
  238.     ; GDA.STR is general data area structure for VM/RUN (X-AM).
  239.     ; Upon entry to target program from VMRUN, EDX --> GDA.
  240.     ; GDA is not useful when solely in the Phar-Lap environment.
  241.     ; Use "gda.h" in the inc/ directory to access the GDA from C:
  242.     ;
  243.     ;     #include "gda.h"
  244.     ;    GDA *gdaptr;
  245.     include gda.str
  246.  
  247. ;--------------------------------------------------------------------------
  248. ;  Fix segment ordering.
  249. ;--------------------------------------------------------------------------
  250.     ; The following dummy segment instructs linker to put "code" lowest
  251.     ; Must be made public since the main module also has public code,
  252.     ; and some primitive linkers can't handle segments of the same name
  253.     ; with different privacy attributes.  (This does not include Phar Lap's
  254.     ; linker.)
  255.  
  256. ;-- stack segment ----------------------------------------------------------
  257. if      eWINDOWS
  258.  
  259. ; stack comes before code in windows
  260.  
  261. ; Use dword alignment for stack segment in the future.
  262.  
  263. STACK? segment dword stack 'STACK'   ; of at least 80 bytes.
  264. ; Copyright message got moved out of here so that the stack wouldn't
  265. ; take up space in the .exe file.
  266.  
  267. start_of_stack equ this byte
  268.         db      STACK_SIZE dup (?)      ; The default stack of 64K.
  269. STACK? ends                     ; MS-DOS loader puts info at the
  270.                                         ; tail end of the stack during loading.
  271. endif
  272.  
  273. ;-- code segment ----------------------------------------------------------
  274. _TEXT   segment dword public 'CODE'
  275. _TEXT   ends
  276.  
  277. ;-- data segment ----------------------------------------------------------
  278. _DATA   segment dword public 'DATA'
  279.         pubname stack_limit
  280. The_stack_margin equ this word
  281. def     stack_limit,dd,0            ; Stack margins.
  282.         dd      0
  283. _DATA    ends
  284.  
  285. ;-- const segment ----------------------------------------------------------
  286. CONST    segment    public 'CONST'
  287. CONST    ends
  288.  
  289. ;-- bss segment ----------------------------------------------------------
  290. _BSS    segment    public 'BSS'
  291. _BSS    ends
  292.  
  293.  
  294. ;-- end bss segment ----------------------------------------------------------
  295. _EBSS_    segment public 'BSS'
  296. _ebss    equ this byte
  297. _EBSS_    ends
  298.  
  299.  
  300. ;-- stack segment ----------------------------------------------------------
  301. if not eWINDOWS
  302.  
  303. ;    stack comes after BSS if not windows
  304.  
  305. if    not eUSING_MASM
  306.  
  307. ; Use dword alignment for stack segment in the future.
  308. STACKNAME equ ?STACK
  309.  
  310. STACKNAME segment dword stack 'STACK'   ; of at least 80 bytes.
  311. ; Copyright message got moved out of here so that the stack wouldn't
  312. ; take up space in the .exe file.
  313.  
  314. start_of_stack equ this byte
  315.         db      STACK_SIZE dup (?)    ; The default stack of 8K.
  316. STACKNAME ends                ; MS-DOS loader puts info at the
  317.                     ; tail end of the stack during loading.
  318.  
  319. else  ; eUSING_MASM
  320.  
  321. ; Use dword alignment for stack segment in the future.
  322.  
  323. ?STACK segment dword stack 'STACK'   ; of at least 80 bytes.
  324. ; Copyright message got moved out of here so that the stack wouldn't
  325. ; take up space in the .exe file.
  326.  
  327. start_of_stack equ this byte
  328.         db      STACK_SIZE dup (?)    ; The default stack of 8K.
  329. ?STACK ends                ; MS-DOS loader puts info at the
  330.                     ; tail end of the stack during loading.
  331. endif ; not eUSING_MASM
  332. endif ; not eWINDOWS
  333.  
  334. ;---------------------------------------------------------------------------
  335. ;  Line terminator convention.
  336. ;---------------------------------------------------------------------------
  337.     ; This must be a MetaWare Pascal string:  2 bytes for the length,
  338.     ; then the actual string characters follow.
  339.     ; Even if the string is of length one, leave the length of this
  340.     ; segment at 8 bytes. (leave lt2 present even if not used.)
  341.     ; Line termination convention for input:
  342.  
  343. _MWLTCONV       segment common dword 'DATA'
  344. ltconv_in       dw      0       ; length is 2 for line terminator.
  345.                 ; zero says allow either char for line term.
  346. lt1i            db      13      ; CR
  347. lt2i            db      10      ; LF
  348. ; Line termination convention for output; must be length of one or two chars.
  349. ltconv_out      dw      2       ; length is 2 for line terminator.
  350. lt1o            db      13      ; CR
  351. lt2o            db      10      ; LF
  352. _MWLTCONV       ends
  353.  
  354. ;---------------------------------------------------------------------------
  355. ;  Call on entry segments
  356. ;---------------------------------------------------------------------------
  357.     ; This segment is used to 'register' functions which must be called
  358.     ; by the start-up routine.  Each of the functions to be called
  359.     ; contain the following three segments, of which the first and last
  360.     ; are empty. The central segment contains zero or more pointers to
  361.     ; routines that the initializer must call during startup.
  362. PUBLIC __mwdfc, __mwdlc
  363. if eHC
  364. _MWIFC    segment    public word 'DATA'
  365.     if eUSING_MASM_51
  366.     assume  cs:_MWIFC    ; hushes up MASM 5.1 errors
  367.     endif
  368. __mwifc label near
  369. _MWIFC    ends
  370. _MWIMC    segment    public word 'DATA'
  371. _MWIMC    ends
  372. _MWILC    segment    public word 'DATA'
  373.     if eUSING_MASM_51
  374.     assume  cs:_MWILC    ; hushes up MASM 5.1 errors
  375.     endif
  376. __mwilc label near
  377. _MWILC    ends
  378. _MWDFC    segment    public word 'DATA'
  379.     if eUSING_MASM_51
  380.     assume  cs:_MWDFC    ; hushes up MASM 5.1 errors
  381.     endif
  382. __mwdfc    label near
  383. _MWDFC    ends
  384. _MWDMC    segment    public word 'DATA'
  385. _MWDMC    ends
  386. _MWDLC    segment    public word 'DATA'
  387.     if eUSING_MASM_51
  388.     assume  cs:_MWDLC    ; hushes up MASM 5.1 errors
  389.     endif
  390. __mwdlc    label near
  391. _MWDLC    ends
  392. ; the following for use in windows's adk destructor, previously conflict
  393. ; with C++ destructor.
  394. if      eWINDOWS
  395. PUBLIC __mwdfw, __mwdlw
  396. _MWDFW    segment    public word 'DATA'
  397.     if eUSING_MASM_51
  398.     assume  cs:_MWDFW    ; hushes up MASM 5.1 errors
  399.     endif
  400. __mwdfw    label near
  401. _MWDFW    ends
  402. _MWDMW    segment    public word 'DATA'
  403. _MWDMW    ends
  404. _MWDLW    segment    public word 'DATA'
  405.     if eUSING_MASM_51
  406.     assume  cs:_MWDLW    ; hushes up MASM 5.1 errors
  407.     endif
  408. __mwdlw    label near
  409. _MWDLW    ends
  410. endif
  411. endif
  412.  
  413. ;--------------------------------------------------------------------------
  414. ;  Start of data segment.
  415. ;--------------------------------------------------------------------------
  416. DSEG    segment dword 'DATA'
  417.  
  418.     ;----------------------------------------------------------------------
  419.     ;  Public symbol declarations.
  420.     ;----------------------------------------------------------------------
  421.         ; The symbols declared with the defequ or pubnames macros are
  422.         ; prefixed with "_mw".  Input and output are for Pascal but must be
  423.     ; provided in C if we link in the C initializer with Pascal routines.
  424.  
  425.         pubnames <input,output>
  426.         pubnames <es,is_286,envp,8087,387,1167>
  427.         pubnames <argp,arglen,prognamep>
  428.         pubnames <CPU,OS,env,wind,printnochipmsg,init_ver>
  429.     pubnames <emc87,heap_expansion_enabled>
  430.         extrn   _osmajor:byte,_osminor:byte
  431.     if eHC
  432.         pubname argvp
  433.     endif
  434.  
  435.     ; Define input and output descriptors
  436.     ; Pascal file variables Input and Output.
  437.     ; They are initialized in Pascal's Finit.p.
  438.  
  439. defequ  input,dw,0
  440. defequ  output,dw,1
  441.  
  442.     ;----------------------------------------------------------------------
  443.     ;  Initialize the "host" package.
  444.     ;----------------------------------------------------------------------
  445.         ; Initialize the "host" package that identifies the system we're
  446.         ; running on.  See the interface file Host.pf distributed with
  447.         ; Professional Pascal or High C for the enumerated type declaration
  448.         ; for the values of CPU and OS.
  449.  
  450. defequ  CPU,db,8        ; Indicates 386.
  451. defequ  OS,db,0         ; Indicates MSDOS.
  452.  
  453.     ;----------------------------------------------------------------------
  454.     ;  Initialize the graphics selector.
  455.     ;----------------------------------------------------------------------
  456.         ; The startup code detects the host environment and sets the graphics
  457.     ; selector accordingly.  This info is used by GFX.
  458.  
  459. defequ    gsel,dw,0    ; graphics selector
  460. public    _mwgsel     ; Pharlap (PL_env) uses 1C
  461.             ; Eclipse (AI_env) uses B8 and B0
  462.  
  463.     ;----------------------------------------------------------------------
  464.     ;  Data definitions.
  465.     ;----------------------------------------------------------------------
  466.  
  467. STDERR  equ     2              ; standard error file handle
  468. _psp    equ     this byte
  469. def     es,df,0
  470.     ; The contents of es prior to invoking program
  471.         ; df is Microsoft's way of saying 48-bit pointer;
  472.         ; Phar Lap uses dp or df.
  473. escontents equ _psp             ; Program segment prefix pointer.
  474. envptr  equ 2CH               ; Offset in DOS ctrl block where env address
  475.                 ; is located
  476.  
  477. ifdef    STACK_SIZE
  478.         public  _top,_base,_psp
  479. _top          dd    0        ; Top of stack (relative to SS).
  480. _base          dd    0        ; Base of stack (relative to DS).
  481. _heaphi       dd    0           ; offset to top of system heap
  482. _heaptop      dd    0           ; offset to top of previous heap request
  483.                                 ; (heaptop+1)..(heaphi) is available
  484.  
  485. osver          dd    ?    ; all 32 bits of os version
  486. virtbase      dd    ?       ; ptr to allocated memory
  487. totsize       dd        ?       ; total size of request
  488. lasthand      dw 2 dup (?)    ; last handle allocated
  489.  
  490. ifdef   SG_exists
  491.         public  _gda
  492. _gda    dd      0               ; Address of gda (softguard only)
  493. endif    ; SG_exists
  494. endif    ; STACK_SIZE
  495.  
  496. defequ  argp,df,?           ; Pointer to command arguments
  497. if    eHC
  498. defequ  argvp,df,?           ; Address of argv array for C.
  499. endif   ; eHC
  500.  
  501.     even
  502. if    eWINDOWS
  503.     pubname is_p
  504. if    not eHC
  505.     defequ is_p,db,1        ; Is the RTE Pascal or C?
  506. else
  507.     defequ is_p,db,0        ; low-level interface clears errno
  508. endif
  509. endif
  510.  
  511. defequ  arglen,DD,?         ; Length of command argument string
  512. defequ  envp,df,0           ; Pointer to environment string
  513. defequ  is_286,db,0         ; True if this is a 286.
  514.  
  515. _8087   equ     this word       ; Need word to store control word into.
  516. def     8087,dw,0           ; Set to true if 8087 is present
  517.     db    0dh,0ah,'80x87$'
  518. temp    dw      0
  519.  
  520. _387    equ     this word       ; Need word to store control word into.
  521. def     387,dw,0            ; Set to true if 80387 is present.
  522.     db    0dh,0ah,'80387$'
  523.  
  524. _1167   equ     this word
  525. def     1167,dw,0           ; True if 1167 is present.
  526.  
  527. _emc87    equ    this word
  528. def    emc87,dw,0        ; Set to true if emc87 is present.
  529.     db    0dh,0ah,'Cyrix EMC87$'
  530.  
  531.     public    _mwno87
  532. _mwno87    dd    0        ; pointer to no87 environment string.
  533. _mwno87es dw    0,0        ; MUST immediately follow mwno87!!!!!!
  534.  
  535. savefs    dw    0
  536. Null_pname db   0           ; Null prog name for < DOS 3.0.
  537.  
  538. ; Prognamep is initialized to a 32-bit pointer to a 0-byte in case
  539. ; we can't obtain the program name.
  540. defequ  prognamep,dd,Null_pname    ; Pointer to program name
  541.         prognamep_seg dw 0
  542.  
  543. return_address equ this byte    ; Used to save the return address before the
  544. return_off    dd    0    ; stack is set up.  We can then use a jump
  545. return_seg    dw    0    ; instruction to return.
  546.  
  547. SG_ENV = 1
  548. PL_ENV = 2
  549. AI_ENV = 3
  550. SSI_ENV = 4
  551. D4G_ENV = 5
  552.  
  553. defequ  env,db,0            ; Which environment are we in?  SG/PL/AI?
  554. public _mwenv
  555. defequ  wind,db,0            ; Are we running under windows?
  556. defequ  printnochipmsg,db,0
  557. defequ  init_ver,db,2        ; Which init is this? (1==LOC,2==GOC)
  558. Lahey_format_load_file db 0     ; .plx (Phar-Lap linked) by default.
  559.  
  560. ; is heap expandable?
  561. CANT_EXPAND = 0
  562. CAN_EXPAND = 1
  563. if eWINDOWS
  564.     defequ    heap_expansion_enabled,db,CANT_EXPAND
  565. else
  566.     defequ    heap_expansion_enabled,db,CAN_EXPAND
  567. endif
  568.  
  569. ifdef   ACAD
  570. chkval  equ     1234                    ; magic interface-compatibility code
  571. ifdef  ADS                              ; Avoid excess globals for ADS
  572. info_off    equ    ads_info_off
  573. info_sel    equ    ads_info_sel
  574. else
  575.         public  brkflg,stkflg
  576. endif   ; ADS
  577.         public  info_off,info_sel
  578. ifdef   PADI
  579.     align    4
  580.         public  cbufadr
  581. cbufadr  dd     0                       ; ptr to common pg between ACAD & PADI
  582. phys_adr dd     0                       ; physical address of common page
  583. endif   ; PADI
  584. brkflg  dd      0                       ; set nonzero for Control C
  585. stkflg  dd      0                       ; set nonzero for stack overflow
  586. interr  db      "Incompatible program interface",0Dh,0Ah,"$"
  587. rtnaddr df      0                       ; Caller's return address.
  588. info_off dd     0                       ; Offset of initialization info struct
  589. info_sel dw     0                       ; Selector of initialization info struct
  590. min_mem dd      0                       ; initial driver heap size
  591. endif   ; ACAD
  592.  
  593. PSPseg  dw      24h     ; Pointer to DOS's Program segment prefix: Phar Lap.
  594. ENVseg    dw    2ch     ; Pointer to DOS's environment string: Phar Lap.
  595. DSEG    ends
  596.  
  597. if eDOS
  598.     if eWINDOWS
  599.     DGROUP group _BSS,_DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV, _MWDFW, _MWDMW, _MWDLW
  600.     else
  601.     if eUSING_MASM
  602.         DGROUP  group _BSS,_DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,_EBSS_
  603.     else
  604.         DGROUP  group _BSS,_DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,STACKNAME,_EBSS_
  605.     endif
  606.     endif
  607. else
  608.     DGROUP  group _DATA,DSEG,_MWIFC,_MWIMC,_MWILC,_MWDFC,_MWDMC,_MWDLC,_MWLTCONV,STACKNAME,_EBSS_
  609. endif
  610.  
  611. assume_dgroup macro
  612. if    eUSING_FLAT
  613.     assume    ds:FLAT
  614. else    
  615.     assume  ds:DGROUP
  616. endif    
  617.     endm
  618.  
  619. ;--------------------------------------------------------------------------
  620. ;  Start of code segment.
  621. ;--------------------------------------------------------------------------
  622. ?INIT   segment dword 'CODE'
  623. if    not eUSING_FLAT
  624. CGROUP  group   ?INIT,_TEXT
  625.         assume cs:CGROUP
  626. else
  627. FLAT      group    ?INIT,_TEXT
  628.     assume cs:FLAT
  629. endif
  630.  
  631.     ;---------------------------------------------------------------------------
  632.     ;  Declare external procedures
  633.     ;---------------------------------------------------------------------------
  634.     ; Extern procs must be defined within current code segment for
  635.     ; correct relocation bits to be generated.
  636.     ; Phar lap assembler won't take next line; it plays according to the rules
  637.     ; (as opposed to Microsoft's assembler):
  638.  
  639.     extrn   exit:near
  640. if  eHC
  641.     extrn   main:near       ; Main program entry point
  642.     extequ  set_up_args,near; Routine to compute argv pointers.
  643. else
  644.     extequ  main,near       ; Main program entry point
  645. endif
  646.  
  647. ifdef   ACAD
  648. ifdef   ADS
  649. getinitinfo     equ    adsi_getinitinfo
  650. map_phys_mem    equ    ads_map_phys_mem
  651. endif   ; ADS
  652. ifndef  PADI
  653. extrn   getinitinfo:near        ; initialize child process loaded by AutoCAD
  654. endif   ; !PADI
  655. extrn   map_phys_mem:near       ; allows 3rd party to install a routine to map
  656.                                 ; physical memory between the stack and heap
  657. endif   ; ACAD
  658.  
  659. if not eUSING_FLAT
  660. Stack_margin_big_place        equ    dword ptr DGROUP:The_stack_margin
  661. Stack_margin_small_place    equ    dword ptr DGROUP:The_stack_margin+Word_size
  662. else
  663. Stack_margin_big_place        equ    dword ptr The_stack_margin
  664. Stack_margin_small_place    equ    dword ptr The_stack_margin+Word_size
  665. endif
  666.  
  667.     ;-------------------------------------------------------------------------
  668.     ;  Here begins the execution of a Professional Pascal or High C program.
  669.     ;-------------------------------------------------------------------------
  670.  
  671. init    proc
  672.         publab  INIT    ; Compiler generates this in upper case.
  673.  
  674.     ; INIT: Initialization code
  675.     ; - set initial stackpointer, framepointer
  676.     ; - jump to _CINIT function to continue initialization.
  677.         assume_dgroup
  678.  
  679.     if    eHC
  680.         Small_data_HC = 1
  681.     endif
  682.     SETBLOCK equ 4Ah
  683.  
  684.     jmp    Start_init
  685.     public    __main
  686. __main:
  687.     jmp    main
  688.  
  689. ifdef   ACAD
  690. comment @
  691.         For applications which are called as a subroutine from AutoCAD
  692.         (namely AutoLISP), here is the ultimate exit point which returns
  693.         back to AutoCAD.
  694.         @
  695. ifndef  ADS                     ; Take care with public names in ADS
  696.         public  exit_to_acad
  697. endif
  698. exit_to_acad:
  699.         jmp     rtnaddr         ; Return to AutoCAD
  700. endif   ; ACAD
  701.  
  702. Start_init:
  703.  
  704. ifdef   ACAD
  705.         cmp     ecx,chkval              ; Proper chkval argument?
  706.         je      m00
  707.         mov     edx,offset interr       ; "Incompatible program interface"
  708.         mov     ah,9
  709.         int     21h                     ; Print the message.
  710.         mov     ax,4C01h
  711.         int     21h                     ; Exit to DOS.
  712. m00:
  713.         mov     info_off,esi            ; offset of initialization info struct
  714.         mov     info_sel,dx             ; selector of info struct
  715.         mov     es,dx
  716.         mov     eax,es:[esi].minmem
  717.         mov     min_mem,eax             ; initial heap size of driver
  718. ifdef   PADI
  719.         mov     eax,es:[esi].physadr
  720.         mov     phys_adr,eax            ; phys addr of pg w/ PADI packet buffer
  721. endif   ; PADI
  722.         mov     ax,ds
  723.         mov     es,ax
  724.         pop     dword ptr rtnaddr       ; Save return address, offset
  725.         pop     ax
  726.         mov     word ptr rtnaddr+4,ax   ;    and segment.
  727. endif   ; ACAD
  728.  
  729. ;       default assumptions
  730. if eWINDOWS
  731.     mov    env,SSI_ENV
  732. else
  733. ;    determine OS version
  734.     call    init_const
  735.  
  736. if ePL_exists
  737.     mov     env,PL_ENV
  738. endif
  739.  
  740.     ; DOS|Extender environment discovery code obtained from Phar Lap:
  741. if eSG_exists
  742.     ; IGC: eax = abcdabcd.  Also, code segment is privilege level 3
  743.     ; (= 43 hex).
  744.     cmp     al,0cdh         ; eax = abcdabcd for IGC.
  745.     jne     short not_sg
  746.     cmp     ah,0abh
  747.     jne     short not_sg
  748.     ; Flaw: If we are in non-protected mode and get this far,
  749.     ; the cmp eax will have 16 bits too much constant, and will
  750.     ; cause the initializer to bomb.  It is unlikely that ax=abcd
  751.     ; yet eax <> abcdabcd.  --fixed with shift sequence.
  752. ;;;    cmp     eax,0abcdabcdh  ; Now try 386 instruction.
  753.     shr    eax,8
  754.     cmp    ah,0cdh
  755.     jne     short not_sg
  756.     shr    eax,8
  757.     cmp    ah,0abh
  758.     jne     short not_sg
  759.     mov     env,SG_ENV
  760.     mov     _gda,edx
  761.     jmp     short Initialize_everything
  762. not_sg: 
  763. endif ; SG_exists
  764.  
  765. if eD4G_exists
  766.     ; Magic code to figure out if this is Rational's 32-bit DOS extender.
  767.  
  768.     ; jmp    force_rational        
  769.     mov    dx,78h
  770.     mov    ax,0ff00h
  771.     call    _mwint21
  772.     cmp    eax, 4734ffffh    ; 4G
  773.     jne    short not_d4g
  774.  
  775. force_rational:
  776.         mov    env,D4G_ENV
  777.     mov    ax, es
  778.     mov    PSPseg, ax
  779.     mov    bx,2Ch
  780.     mov    ax,es:[bx]
  781.     mov    ENVseg, ax
  782. not_d4g:
  783. endif ; D4G_exists
  784.  
  785. if eAI_exists
  786.     cmp     env,D4G_ENV
  787.     je      short not_ai
  788.     cmp    env,SSI_ENV
  789.     je    short not_ai
  790.     mov    eax,osver
  791.         shr     eax,16
  792.         cmp     ax,'DX'
  793.         je      short not_ai
  794.         mov     env,AI_ENV
  795. not_ai:
  796. endif ; AI_exists
  797. endif ; eWINDOWS
  798.  
  799. Initialize_everything:
  800.  
  801.     sub     ebp,ebp             ; Initialize stack frame pointer
  802.  
  803.     ; Make sure stack is mod 4 in case it's not.
  804.     and     esp,0fffffffch      ; Drop extra bytes.  Oh well.
  805.     assume_dgroup
  806.  
  807. if      eWINDOWS
  808.         ; Incoming registers:
  809.         ; esi: initial amount of heap provided by loader, at tail end of DGROUP.
  810.         ; ebx: pointer to argument strings.
  811.         ; edi: pointer to program name.
  812.         ; environ:
  813.         ; ax:0:
  814.         ;      (db 'var=value',0)*
  815.         ;      (db 0)+          ; possibly some 0 padding for expansion later
  816.         ; ax:edi:
  817.         ;       db 'progname',0 ; fully-expanded (drive & path)
  818.         ; ax:ebx:
  819.         ;       db 'invoke name',0   ; the invocation prog name.
  820.         ;       db 'arguments',0     ; 1 or more arguments.
  821.         ;       db 0
  822.         ; handle-table:
  823.         ;       dd count
  824.         ;       (db type, dd handle)*
  825.         ;               type = 0 unused; 1 session; 2 file.
  826.  
  827.     cmp    env,SSI_ENV
  828.     jne    next0
  829.         mov     word ptr envp+Word_size,ax      ; Offset is already 0.
  830.         ; mov   envp,0                          ; This is already 0.
  831.         
  832.         mov     word ptr argp+Word_size,ax      ; Offset of arguments.
  833.         mov     dword ptr argp,ebx              ; Will be adjusted to skip prog 
  834.                                                 ; name later.
  835.         
  836.         mov     word ptr prognamep+Word_size,ax
  837.         mov     dword ptr prognamep,edi         ; Save prog name offset.
  838.  
  839.     ; initialize heap
  840.     mov    _base,0
  841.         mov     ax,ds
  842.         lsl     eax,eax                 ; Find total space.
  843.         mov     _heaphi,eax             ; End of heap.
  844.  
  845.         mov     _top,esi        ; heap starts here
  846.     mov    eax,esi            
  847.     inc    eax                    ; increase size to page boundary
  848.     add    eax,4095
  849.     and    eax,0fffff000h
  850.     dec     eax
  851.     mov    _heaptop,eax            ; and this is where heap really starts
  852. next0:
  853. endif ; eWINDOWS
  854.  
  855.     ; For the 386 we own all of memory.  Size up memory 
  856.     ; and inform the heap manager.
  857.     mov     Stack_margin_big_place,Stack_margin_big
  858.     mov     Stack_margin_small_place,Stack_margin_small
  859.     add     Stack_margin_big_place,offset start_of_stack
  860.     add     Stack_margin_small_place,offset start_of_stack
  861.  
  862. if eSG_exists
  863.     ; Initialize stack, IGC environemnt.
  864.     ; This code will work for h (highest) and a (append after load)
  865.     ; stk options. esp already setup by vmrun loader.
  866.     cmp     env,SG_ENV
  867.     jne     short next1
  868.  
  869.     mov     eax,esp             ; get stack pointer
  870.     mov     ecx,[edx].GDA_STKSZ     ; get stack size, kbytes
  871.     shl     ecx,10              ; convert from k to # of bytes
  872.     sub     eax,ecx             ; calculate base of stack addr
  873.     mov     _base,eax           ; stack base
  874.     mov     eax,[edx].GDA_HLOD      ; get highest load address
  875.     mov     _top,eax            ; bottom of heap
  876.  
  877.     inc    eax                    ; increase size to page boundary
  878.     add    eax,4095
  879.     and    eax,0fffff000h
  880.     dec     eax
  881.     mov    _heaptop,eax            ; end of previous heap
  882.  
  883.     mov     eax,[edx].GDA_HLOD      ; get highest load address
  884.     mov     ecx,[edx].GDA_HMEM      ; get available high memory
  885.     shl     ecx,10              ; convert from k to # of bytes
  886.     add     eax,ecx             ; calculate heap top addr
  887.     mov     _heaphi,eax         ; top of heap
  888.  
  889.     ; Free memory below 640K for subsequent use by EXEC.
  890.     mov     ebx,[edx].GDA_TLOW      ; Subtract highest used low address.
  891.     sub     ebx,[edx].GDA_PSPA      ; Subtract lowest used low address.
  892.     shr     ebx,4                   ; Convert to paragraphs.
  893.     inc     ebx                     ; Safety?
  894.     mov     ah,SETBLOCK             ; SETBLOCK to bx paragraphs from
  895.     ; psp start.
  896.     call    _mwint21
  897.     test    byte ptr [edx].GDA_ENV,GDA_WEITEK
  898.     setne   byte ptr _1167
  899. next1:
  900. endif   ; SG_exists
  901.  
  902. if ePL_exists
  903.     cmp     env,PL_ENV
  904.     jne     short next2
  905.  
  906.     mov     eax,esp
  907.     mov     _base,0         ; Start of stack.
  908.     mov     _top,eax
  909.  
  910.     inc    eax            ; increase size to page boundary
  911.     add    eax,4095
  912.     and    eax,0fffff000h
  913.     dec     eax
  914.     mov    _heaptop,eax    ; end of previous heap
  915.  
  916.     mov    ax,fs
  917.     mov    savefs,ax
  918.     and     ax,ax       ; If fs = 0 (Lahey linker), can't have Weitek.
  919.     sete    Lahey_format_load_file
  920.  
  921.     mov     ax,ds
  922.     lsl     eax,eax         ; load segment limit of data segment.
  923.     mov     _heaphi,eax     ; Top of heap (linear address).
  924. next2:
  925. endif  ; PL_exists
  926.  
  927. if eD4G_exists
  928.         cmp     env,D4G_ENV            ; One doesn't shrink the heap in DOS4G.
  929.         jne    short next2a
  930.  
  931.     mov     _base,0
  932.     mov     _top,esp
  933.         mov    _heaphi,esp             ; previous top of heap
  934.     mov     _heaptop,esp            ; top of heap (empty)
  935. next2a:
  936. endif
  937.  
  938. ifdef   ACAD
  939. ifndef  PADI
  940. Comment @
  941.         Take information from a structure in AutoCAD, pointed to by
  942.         info_sel:info_off, and store it for use by routines in the
  943.         program loaded by AutoCAD to which this module is linked.
  944.         @
  945.         movzx   eax,word ptr info_sel
  946.         push    eax
  947.         push    info_off
  948.         call    getinitinfo
  949.         add     esp,8
  950. endif
  951. endif
  952.     extrn    _cinit:near
  953. if    eWINDOWS
  954.     mov    wind,1
  955.     call    _cinit
  956.     db    0cbh            ; retf
  957. else
  958.     jmp    _cinit
  959. endif   ; eWINDOWS
  960. init    endp
  961.  
  962. if    eHC
  963.     db  'High C'
  964. else
  965.     db  'Professional Pascal'
  966. endif
  967.     db  ' Run-time Library Copyright (C) 1983-1992 MetaWare Incorporated.'
  968.  
  969. ;-------------------------------------------------------------------------------
  970. ; init_const
  971. ;-------------------------------------------------------------------------------
  972. init_const proc
  973.     publab init_const
  974.     prolog
  975.     assume_dgroup
  976. ;    initialize constants ... may be called from init,
  977. ;       or from WINDOWS environment initializer
  978.  
  979. ;    determine DOS version number
  980.     push    eax
  981.     push    ebx
  982.         xor     eax,eax
  983.         mov     ah,30h        ; Get DOS version number
  984.     call    _mwint21
  985.         mov     word ptr _osmajor,ax    ; Moves minor (AH) and major (AL).
  986.     mov    osver,eax    ; also save full version locally
  987.     pop    ebx
  988.     pop    eax
  989.  
  990.     epilog
  991. init_const endp
  992.  
  993. if    eDOS and not eWINDOWS
  994. ;-------------------------------------------------------------------------------
  995. ; init_env_area()
  996. ;-------------------------------------------------------------------------------
  997.     ; Process environment area and parameter strings.
  998.  
  999. init_env_area proc
  1000.     publab init_env_area
  1001.     ;assume    cs:CGROUP
  1002.     assume_dgroup
  1003.  
  1004.     Parm_string_offset = 80h           ; Offset in PSP containing parm
  1005.                     ; string (len+bytes).
  1006.                     ; Pop return address off of stack
  1007.     pop    dword ptr return_off
  1008.     ifdef    Small_data
  1009.     push    cs            ; 32 bits?
  1010.     endif
  1011.     pop    eax            ; Pop dword to maintain 
  1012.     mov    word ptr return_seg,ax    ; stack alignment!
  1013.  
  1014.     cld                            ; All moves are forward
  1015.  
  1016. if eSG_exists
  1017.     cmp     env,SG_ENV
  1018.     jne      short next3
  1019.  
  1020.     ; GDA has pointer to PSP.  PSP has env seg, which, shifted left by 4,
  1021.     ; yields the 32 bit address of the env.
  1022.         mov     edi,[edx].GDA_PSPA      ; Get flat PSP address.
  1023.         mov     word ptr argp+Word_size,ds
  1024.         mov     dword ptr _psp,edi
  1025.         mov     word ptr _psp+Word_size,ds
  1026.         lea     eax,Parm_string_offset[edi] ; eax = pso+edi.
  1027.         xor     ebx,ebx
  1028.         mov     bl,[eax]               ; Get length of parm string.
  1029.         mov     arglen,ebx
  1030.         inc     eax
  1031.         mov     dword ptr argp,eax      ; Addr of parm string.
  1032.         mov     bx,envptr[edi]      ; Get segment address of
  1033.                     ; environment pointer.
  1034.         shl     ebx,4               ; Convert to 32-bit flat address.
  1035.         mov     dword ptr envp,ebx
  1036.         mov     word ptr envp+Word_size,ds ; Fill out 48-bit address
  1037.         jmp     more_init2
  1038. next3:
  1039. endif  ; SG_exists
  1040.  
  1041. if ePL_exists or eD4G_exists
  1042.     cmp     env,PL_ENV
  1043.     je      short next4a
  1044.     cmp     env,D4G_ENV
  1045.     jne     next4
  1046. next4a:
  1047.         cmp     Lahey_format_load_file,1
  1048.         je      short ES_points_to_PSP_already
  1049.         mov     ax,PSPseg
  1050.         mov     bx,cs
  1051.         arpl    ax,bx
  1052.         mov     es,ax                   ; Load es with psp address.
  1053.  
  1054.         ; Load environment segment into cx.
  1055.         mov     cx,ENVseg
  1056.         arpl    cx,bx
  1057.         jmp     short more
  1058.  
  1059. ES_points_to_PSP_already:
  1060.         ; Load environment segment into cx.
  1061.         mov     cx,es:02ch
  1062.         mov     ax,es
  1063. more:
  1064.         mov     word ptr _psp+Word_size,ax      ; Construct 48-bit psp address.
  1065.         mov     word ptr escontents+Word_size,ax; No displacement
  1066.         mov     word ptr envp+Word_size,cx    ; Environment segment.
  1067.         xor     eax,eax
  1068.     push    eax
  1069.         mov     al,es:Parm_string_offset     ; Length of parm string
  1070.     mov    arglen,eax
  1071.  
  1072. ; In C, the parameter string must be moved to a DS-accessible area
  1073. ; if small-data model.
  1074. if    eHC
  1075. ;       Move the parm string into the stack so that it can be accessed by
  1076. ;       small-data programs with only 16-bit pointers.
  1077.         mov     ecx,eax     ; parameter length
  1078.     inc    ecx
  1079.         add     al,3
  1080.         and     al,0fch     ; Make sure eax is multiple of 4.
  1081.         sub     esp,eax      ; Length of parm string.
  1082.         mov     edi,esp      ; Move the parameter string here.
  1083.         mov     dword ptr argp,edi ; Save address of args.
  1084.         ;push    edx         ; Allow byte for parm string overwrite
  1085.                 ; by C arg processor.  But make stack
  1086.                 ; word-aligned for efficiency.
  1087.         push    ds          ; Save it.
  1088.         push    es          ; source is es:81h
  1089.         pop     ds
  1090.         push    es          ; Save es.
  1091.         push    ss
  1092.         pop     es          ; Dest is ss:di.
  1093.         mov     esi, offset Parm_string_offset+1
  1094.         rep     movsb       ; es:di := parm string.
  1095.         pop     es
  1096.         pop     ds
  1097.  
  1098. else   ; not eHC
  1099.     ; Large-data or Pascal model    
  1100.     ; just store the address of the parms.
  1101.         mov     ax,word ptr escontents+Word_size
  1102.         mov     word ptr argp+Word_size,ax
  1103.         mov     dword ptr argp,Parm_string_offset+1     ; Addr of parm string.
  1104. endif  ; eHC
  1105.  
  1106. next4:
  1107. endif  ; PL_exists or D4G_exists
  1108.  
  1109. more_init2:
  1110.  
  1111. if eD4G_exists
  1112.         cmp     env,D4G_ENV
  1113.         je    no_change
  1114. endif
  1115.  
  1116. if eSG_exists
  1117.         cmp     env,SG_ENV
  1118.         je      no_change
  1119. endif
  1120.  
  1121. if eAI_exists
  1122.         cmp     env,AI_ENV
  1123.     jne     short not_ai2
  1124.  
  1125.         mov     ebx,_top                ; Top of stack in bytes
  1126.  
  1127. ifndef  AIA_CAN_GROW_HEAP
  1128. ;       If Lahey format, we must be able to grow.
  1129.         cmp     Lahey_format_load_file,1
  1130.         jne     short no_change
  1131. endif
  1132.  
  1133.         jmp     short Free_up
  1134. not_ai2:
  1135. endif   ; AI_exists
  1136.  
  1137. if      ePL_exists
  1138. ifndef  PHAR_LAP_CAN_GROW_HEAP
  1139.         jmp     short no_change
  1140. else
  1141.         ; Now free all of the heap, so that we
  1142.     ; allocate more only when necessary.
  1143. ifdef   ACAD
  1144.  
  1145. ifdef   PADI
  1146.         mov     ebx,_top                ; Get top of stack
  1147.         add     ebx,4095                ; Round it up a page
  1148.         shr     ebx,12                  ; Get number of pages
  1149.         push    ebx                     ; Store for later use
  1150.         push    ds
  1151.         pop     es
  1152.         mov     ah,SETBLOCK             ; Set PADI memory size to smallest #
  1153.         int     21h                     ;   of pages ecompassing top of stack
  1154.  
  1155.         mov     ebx,phys_adr            ; Get phys addr of pg w/ packet buffer
  1156.         mov     eax,250Ah
  1157.         mov     ecx,1
  1158.         int     21h                     ; Map pg w/ pkt buf to end of new PADI
  1159.                                         ;   memory block, above top of stack
  1160.         mov     cbufadr,eax             ; Store mapped offset as ptr to buf
  1161.  
  1162.         call    map_phys_mem            ; allow 3rd party a chance to map in
  1163.                                         ;   phys mem (returns # of pgs mapped)
  1164.         pop     ebx                     ; Get # of pgs to top of stack
  1165.         inc     ebx                     ; Add 1 for page mapped to end of seg
  1166.         add     ebx,eax                 ; Add add'l pgs mapped by 3rd party
  1167.         shl     ebx,12                  ; Get bottom of heap, in bytes
  1168.     dec    ebx
  1169.         mov     _heaptop,ebx
  1170.     and    ebx, 0fffffffch
  1171.         mov     _top,ebx                ; Assumption made _top is heap bottom
  1172. else    ; PADI
  1173.         mov     ebx,_top                ; Get top of stack
  1174.         add     ebx,4095                ; Round it up a page
  1175.         shr     ebx,12                  ; Get number of pages
  1176.         push    ebx                     ; Store for later use
  1177.         push    ds
  1178.         pop     es
  1179.         mov     ah,SETBLOCK             ; Set memory size to smallest #
  1180.         int     21h                     ;   of pages ecompassing top of stack
  1181.  
  1182.         call    map_phys_mem            ; Allow 3rd party a chance to map in
  1183.                                         ;   phys mem (returns # of pgs mapped)
  1184.         pop     ebx                     ; Get # of pgs to top of stack
  1185.         or      eax,eax                 ; Any pages mapped?
  1186.         jz      no_map
  1187.         add     ebx,eax                 ; If so, add it in
  1188.         shl     ebx,12                  ; Get bottom of heap, in bytes
  1189.     dec    ebx
  1190.         mov     _heaptop,ebx
  1191.     and     ebx, 0fffffffch
  1192.         mov     _top,ebx                ; Assumption made _top is heap bottom
  1193. no_map:
  1194. endif   ; PADI
  1195.  
  1196.         mov     ebx,min_mem             ; Initial size of heap
  1197. else    ; ACAD
  1198.         mov     ax,4
  1199.         mov     es,ax
  1200.         mov     ebx,es:[5ch]   ; Initial size of heap: load image size in bytes.
  1201.                                ; See Phar Lap TN #21.
  1202. endif   ; ACAD
  1203.         jmp     short Free_up
  1204. endif   ; PHAR_LAP_CAN_GROW_HEAP
  1205. endif   ; PL_exists
  1206.  
  1207. if ePL_exists or eAI_exists
  1208. Free_up:
  1209.         add     ebx,4095                ; Round up to pages.
  1210.         shr     ebx,12                  ; Convert to 4K pages.
  1211.  
  1212. ifdef   ACAD
  1213. ifdef   PADI
  1214.         ; Initial heap size, set up in min_mem above with a minimum
  1215.         ; heap value that comes from the loader in AutoCAD, does not
  1216.         ; account for the extra page added on as a result of the page
  1217.         ; mapping done above to obtain access to a buffer common with
  1218.         ; AutoCAD.  Therefore, the number of pages for the initial
  1219.         ; heap size is increased by one.
  1220.  
  1221.         inc     ebx
  1222.  
  1223. endif   ; PADI
  1224.  
  1225.         ; Any additional pages mapped onto the segment as a result of
  1226.         ; calling map_phys_mem() above is added here.
  1227.  
  1228.         add     ebx,eax                 ; Add add'l pgs mapped by 3rd party
  1229. endif   ; ACAD
  1230.  
  1231.         inc     ebx                     ; Add 1 page for initial heap.
  1232.  
  1233.         mov     edx, ebx
  1234.         shl     edx,12                  ; Future value for heaphi.
  1235.     dec     edx
  1236.  
  1237.         cmp     env,PL_ENV
  1238.         je      short No_para
  1239.         shl     ebx, 8                  ; Convert to paragraphs for AIA.
  1240. No_para:
  1241.         push    ds
  1242.         pop     es                      ; Segment to free up.
  1243.         mov     ah,SETBLOCK             ; SETBLOCK to bx paras from psp start.
  1244.     call    _mwint21
  1245.         jc      short no_change         ; If couldn't get the extra page, oops!
  1246.         mov     _heaphi,edx
  1247. endif   ; PL_exists or AI_exists
  1248.  
  1249.  
  1250. no_change:
  1251.  
  1252. ; find program name...
  1253. ;     -- Format of DOS environment:              VVV 3.x only VVV
  1254. ;     -- t1 nul t2 nul t3 nul ... tn nul nul x x program-name nul
  1255. ; Go to end of environment string to get program name for DOS 3.0.
  1256. ; While we're doing so, see if he said "NO87=" something, in which case,
  1257. ; mimicking Microsoft's emulator, we print the string (unless it's
  1258. ; nothing but blanks), and disable use
  1259. ; of the 80287 if the combination emulation/80287 library is linked in.
  1260.  
  1261.         les     edi,envp        ; Pointer to environment area.
  1262.         xor     eax,eax         ; search for 0 byte.
  1263. Scan_again:
  1264.         cmp     dword ptr es:[edi],'78ON'   ; NO87
  1265.         jne     short not1
  1266.         cmp     byte ptr es:4[edi],'='   ; =
  1267.         jne     short not1
  1268.  
  1269. ; All this fuss just to print the NO87 string!
  1270. ifndef  no87
  1271.     add    edi,5
  1272.     mov    _mwno87,edi
  1273.     mov    _mwno87es,es    ;save pointer and print it later.
  1274. endif   ; no87
  1275.  
  1276. not1:    
  1277.     sub     ecx,ecx
  1278.     dec     ecx             ; ecx := -1
  1279.         repnz   scasb           ; Search for 0.
  1280. ; We MUST have found the 0 byte; we're positioned at the byte after.
  1281.         cmp     byte ptr es:[edi],0     ; Two 0 bytes in a row?
  1282.         jne     Scan_again      ; Nope, keep going.
  1283.  
  1284. ;     Now we've found the environment area end.  
  1285. ;    +3 bytes later is the prog name.
  1286.         add     edi,3           ; Move to program name.
  1287.         cmp     _osmajor,3      ; Program name supplied by OS?
  1288.         jb      short NO_PNAME_AVAIL
  1289.         cmp     env,SG_ENV
  1290.         jne     short get_pname
  1291. ;       cmp     env,AI_ENV        ** commented out 18-Jun92 (MJMauro)
  1292. ;       je      short get_pname         **
  1293.         ; IGC: pname is addressable.
  1294.         mov     dword ptr prognamep,edi
  1295.         mov     word ptr prognamep+Word_size,ds
  1296.         jmp     short _prog_name
  1297.  
  1298. NO_PNAME_AVAIL:
  1299. ; No program name.  Supply the null string.
  1300. if eHC
  1301. ;       Allocate the null byte on the stack right after the parms.
  1302.         xor     edx,edx
  1303.         push    edx             ; Null byte(s).
  1304.         mov     dword ptr prognamep,esp  ; Pointer to the program name.
  1305. endif ; eHC
  1306.         jmp     short _prog_name
  1307. get_pname:
  1308.  
  1309. if ePL_exists or eD4G_exists or eAI_exists
  1310.     cmp     env,PL_ENV
  1311.     je      short next5a
  1312.     cmp     env,AI_ENV
  1313.     je      short next5a
  1314.     cmp     env,D4G_ENV
  1315.     jne     next5
  1316. next5a:
  1317.  
  1318. ; In small-data C, the program name must be moved into the DS group.
  1319. ifdef   Small_data_HC           ; Move the program name to the stack.
  1320.         mov     ax,es
  1321.         lsl     eax,eax         ; load segment limit of env string.
  1322.         xor     eax,eax
  1323.         ; Find length of program name.
  1324.         sub     ecx,ecx
  1325.         dec     ecx
  1326.         mov     ebx,edi         ; Save starting address of name.
  1327.         repnz   scasb
  1328.         sub     edi,ebx         ; Length of name (including 0 trailer).
  1329.         lea     eax,3[edi]      ; Add some space on stack...
  1330.     and    al,0fch        ; only al involved, so use shorter instructions.
  1331.         sub     esp,eax         ; Allocate space for name.
  1332.         mov     dword ptr prognamep,esp  ; Where the name will be put.
  1333.         mov     ecx,edi         ; Length of name
  1334.         mov     esi,ebx         ; Name is stored here.
  1335.         mov     edi,esp         ; Copy to here.
  1336.         push    ds
  1337.         mov     ds,word ptr envp+Word_size
  1338.         push    ss
  1339.         pop     es
  1340.         rep     movsb
  1341.         pop     ds
  1342. else
  1343.         ; Non-small data case:  just record the address.
  1344.         mov     dword ptr prognamep,edi
  1345.         mov     word ptr prognamep+Word_size,es
  1346. endif   ; Small_data_HC
  1347.  
  1348. next5:
  1349. endif   ; PL_exists or D4G_exists or AI_exists
  1350.  
  1351. _prog_name:
  1352. if eHC
  1353.     ; Now allocate the space for the argv pointers.  One for the program 
  1354.     ; name and one for each argument.  Although we don't know how many 
  1355.     ; arguments there are, there can be at most 1 for every two characters 
  1356.     ; of the environment string.
  1357.     mov     eax,arglen
  1358.     inc     eax
  1359.     shr     eax,1   ; Max arg ptrs for parameters
  1360.     inc     eax     ; Count the program name.
  1361.     inc     eax     ; ANSI requires argv[argc] = null pointer.
  1362.     shl     eax,2   ; Multiply by pointer size
  1363.     sub     esp,eax ; Now allocate it.
  1364.     mov     dword ptr argvp,esp      ; sp is here.
  1365. endif   ; HC
  1366.  
  1367.     jmp    fword ptr return_address
  1368. init_env_area endp
  1369. endif   ; eDOS and not eWINDOWS
  1370.  
  1371.  
  1372.  
  1373. ;-------------------------------------------------------------------------------
  1374. ; clear_bss()
  1375. ;-------------------------------------------------------------------------------
  1376. clear_bss proc
  1377.     publab    clear_bss
  1378.     prolog eax,ecx,edi
  1379.  
  1380.     assume_dgroup
  1381.  
  1382.     extrn    _edata:near
  1383.     extrn    _end:near
  1384.  
  1385.     xor    eax,eax
  1386.       mov    edi,offset ds:_edata
  1387.       ;mov    ecx,offset ds:_end
  1388.       mov    ecx,offset ds:_ebss
  1389.     sub    ecx,edi
  1390.     
  1391.     shr ecx,1
  1392.     rep stosw
  1393.     adc ecx,ecx
  1394.     rep stosb ; Could be smarter -- use stosd, but compilcates code
  1395.     epilog
  1396. clear_bss endp
  1397.  
  1398. ;-------------------------------------------------------------------------------
  1399. ; call_onentry_fcns()
  1400. ;-------------------------------------------------------------------------------
  1401. call_onentry_fcns proc
  1402.     publab    call_onentry_fcns
  1403.     prolog
  1404.  
  1405.         assume_dgroup
  1406.         push    ds
  1407.         pop     es
  1408.     mov    ax,fs
  1409.     mov    savefs,ax
  1410.         ; ss is already = ds.
  1411.  
  1412.     ; Clear BSS segment
  1413. if    eD4G_exists
  1414.   if    not eWINDOWS
  1415.     call    clear_bss
  1416.   endif
  1417. endif
  1418.  
  1419. ; Here begins new code...C++ initialization is done in C, so we just set up
  1420. ; and call a C routine to do the work.
  1421.  
  1422. ; typedef struct {
  1423. ;    ulong    init_level;
  1424. ;    void (*ct)();
  1425. ;    ulong    reserved;
  1426. ;    } ct_elem, *ct_array;
  1427. ; void _mwdo_ctors(ct_array ctors, int ctor_size, ct_array dtors, int dtor_size)
  1428.  
  1429.  
  1430.     mov    ebx,offset _MWDFC
  1431.     mov    ecx,offset _MWDLC
  1432.     sub    ecx,ebx
  1433.     push    ecx            ; Size of destructor array
  1434.     push    ebx            ; Beginning of destructor array
  1435.     mov    ebx,offset ds:__mwifc
  1436.     mov    ecx,offset ds:__mwilc
  1437.     sub    ecx,ebx
  1438.     push    ecx            ; Size of constructor array.
  1439.     push    ebx            ; Beginning of constructor array
  1440.     extrnf    _mwdo_ctors
  1441.     call    _mwdo_ctors
  1442.     add    esp,10h            ; pop 4 
  1443.  
  1444.     ; Set graphics selector _mwgsel according to the environment
  1445.     ; and equipment configuration. 
  1446.     ;
  1447. if ePL_exists
  1448.     cmp    env,PL_ENV        ;Is this Pharlap's environment?
  1449.     jne    short next10
  1450.     mov    gsel,1ch        ;Pharlap uses 0x1c
  1451. next10:
  1452. endif
  1453.  
  1454. if eD4G_exists
  1455.     cmp    env,D4G_ENV
  1456.     jne    short next10a
  1457.     mov    ax, ds
  1458.     mov    gsel, ds        ; use flat
  1459. next10a:
  1460. endif
  1461.  
  1462. if eAI_exists
  1463.     cmp    env,AI_ENV        ;OS386?
  1464.     jne    short next11
  1465. AI_sel:
  1466.     mov    ah,12h            ;OS386 has different selectors
  1467.     mov    bl,10h            ;for color and bw.
  1468.     int    10h            ;ask the BIOS which it is
  1469.     and    bh,bh
  1470.     jz    color
  1471. b_and_w:
  1472.     mov    gsel,0b0h        ;OS386 bw selector is 0xb0
  1473.     jmp    short selector_is_set
  1474. color:
  1475.     mov    gsel,0b8h        ;OS386 color selector is 0xb8
  1476.     jmp    short selector_is_set
  1477. next11:
  1478. endif
  1479.  
  1480. selector_is_set:
  1481.  
  1482.     epilog
  1483. call_onentry_fcns endp
  1484.  
  1485. ;--------------------------------------------------------------------------
  1486. ;       procedure Expand_Heap();
  1487. ;--------------------------------------------------------------------------
  1488. ; The heap manager calls this routine to expand the heap when it
  1489. ; detects a heap overflow.  The expansion expands allocates more memory
  1490. ; starting at _heaptop+1,  recording the new top-of-heap in _heaptop.
  1491. ; If expansion is required, heaphi is adjusted.
  1492. ; Currently this is implemented only for Phar Lap's DOS|Extender.
  1493.  
  1494. expand_heap proc far
  1495.  
  1496.     publab    expand_heap
  1497.     prolog
  1498.  
  1499.     parm386 <<request,dword>>
  1500.     parm86  <<request,dword>>
  1501.  
  1502.     mov    eax, request
  1503.     mov     virtbase,0
  1504.         mov     ebx,_heaphi            ; our upper-bounds
  1505.     sub     ebx,_heaptop           ; space left in heap
  1506.     cmp     eax,ebx                ; is it big enough?
  1507.     ja      short get_more
  1508.  
  1509.     mov     eax,_heaptop           ; compute start of new user heap
  1510.     inc     eax  
  1511.     mov     virtbase,eax
  1512.     dec     eax 
  1513.  
  1514.     add     eax,request            ; compute new heaptop
  1515.     mov     _heaptop,eax 
  1516.     jmp     return_from_expand
  1517.  
  1518. get_more:
  1519.         cmp     env,D4G_ENV
  1520.       jne    not_dos4g
  1521.  
  1522. ;       ***********************
  1523. ;       *                     *
  1524. ;       *       DOS4G         *
  1525. ;       *                     *
  1526. ;       ***********************
  1527.     mov     ebx,request             ; user request is multiple of 4k
  1528.         shrd    ecx,ebx,16    
  1529.         shr    ecx,16
  1530.     shr    ebx,16
  1531.         mov    ax,0501h
  1532.         int    31h
  1533.     jc    return_from_expand
  1534.  
  1535.     ; Answer comes back in bx:cx.
  1536.     shl    ebx,16
  1537.     mov    bx,cx                ; Form 32-bit address in ebx.
  1538.  
  1539.     ; Handle comes back in si:di
  1540.     mov    lasthand,si
  1541.     mov    lasthand+2,di
  1542.  
  1543.     mov    virtbase,ebx
  1544.     mov    ecx,request             ; amount requested
  1545.     add    ecx,ebx                ; add virtual base
  1546.     mov    _heaptop,ecx            ; user top of heap
  1547.     mov    _heaphi,ecx            ; same as system top of heap
  1548.  
  1549.      jmp    return_from_expand
  1550.  
  1551. not_dos4g:
  1552. ;       ***********************
  1553. ;       *                     *
  1554. ;       *     NOT DOS4G       *
  1555. ;       *                     *
  1556. ;       ***********************
  1557.  
  1558.         ; Has the user shut off heap expansion?  
  1559.         cmp    heap_expansion_enabled,CANT_EXPAND
  1560.         je    return_from_expand
  1561.         cmp     env,PL_ENV
  1562.  
  1563. ifndef  PHAR_LAP_CAN_GROW_HEAP
  1564.     je      return_from_expand ; Must have release >= 1.1t.
  1565. else
  1566.     je    short Can_grow    
  1567. endif   
  1568.  
  1569. ifndef    AIA_CAN_GROW_HEAP
  1570. ;       If Lahey format, we must be able to grow.
  1571.     cmp    Lahey_format_load_file,1
  1572.     jne     short return_from_expand
  1573. else    
  1574.     cmp     env,AI_ENV
  1575.     jne    return_from_expand
  1576. endif   
  1577.  
  1578. Can_grow:
  1579. if not    eWINDOWS
  1580.         mov    ax,ds                   ; find top of heap
  1581.         lsl    eax,eax
  1582.     cmp     eax,_heaphi             ; if different, reset heap
  1583.     je      grow
  1584.  
  1585.         mov     _heaptop,eax            ; reset heap, as non-malloc request
  1586.     mov     _heaphi,eax             ; is blocking our request
  1587.     jmp     short grow
  1588.  
  1589. grow:
  1590.     mov     eax,_heaptop            ; next page starts on next byte
  1591.         inc     eax                     ; size = offset + 1
  1592.     add     eax,request             ; add in request
  1593.     mov     totsize,eax             ; save total size for later
  1594.  
  1595.     shr    eax,12                  ; convert to pages
  1596.     cmp     env,AI_ENV
  1597.     jne    short pages
  1598.     shl    eax,8                ; convert pages to paragraphs for AI.
  1599.  
  1600. pages:    
  1601.     mov     ebx,eax                 ; prepare for INT 21h
  1602.     mov    ah,SETBLOCK
  1603.     call    _mwint21
  1604.     jc    short return_from_expand
  1605.  
  1606.     mov     eax,_heaptop            ; next page starts on next byte
  1607.     inc     eax                     ; new user heap will start here
  1608.     mov     virtbase,eax
  1609.  
  1610.     mov     eax,totsize             ; retrieve total size of request
  1611.     dec     eax                     ; convert to offset
  1612.     mov     _heaphi,eax             ; update pointers
  1613.     mov     _heaptop,eax
  1614. endif ; eWINDOWS
  1615.  
  1616. return_from_expand:
  1617.     mov     eax,virtbase
  1618.     epilog
  1619. expand_heap endp    
  1620.  
  1621.  
  1622. ;-------------------------------------------------------------------------
  1623. ;       procedure set_stack_limits(small,large:Cardinal);
  1624. ;-------------------------------------------------------------------------
  1625. ;       Set the two limits.
  1626. ;       This is called by the heap manager when the heap begins to creep
  1627. ;       into the stack, or when the heap has left the stack area.
  1628. ;       Basically, when the heap has used the lower portion of the stack,
  1629. ;       the stack margin variables are set to reflect a higher bottom-of-stack
  1630. ;       location, so that stack overflow will occur when the stack is within
  1631. ;       256 bytes of the heap.
  1632. ;       If the stack precedes the heap, the heap never creeps into the
  1633. ;       stack and this procedure will never be called.
  1634.  
  1635. Set_stack_limits        proc    far
  1636.         publab  set_stack_limits
  1637.         return  8
  1638. Set_stack_limits        endp
  1639.  
  1640. ;-------------------------------------------------------------------------
  1641. ;       function ss: Cardinal; {Returns paragraph address of stack segment
  1642. ;-------------------------------------------------------------------------
  1643. ssx     proc    far
  1644.         publab  ss
  1645.         mov     ax,ss
  1646.         return
  1647. ssx     endp
  1648.  
  1649. ;-------------------------------------------------------------------------
  1650. ;       function Getds: Cardinal;       -- Returns ds register.
  1651. ;-------------------------------------------------------------------------
  1652. ;       This function may actually no longer be needed.
  1653. ifdef   Small_data
  1654. getds   proc    far
  1655.         publab  getds   ; return ds register.
  1656.     xor    eax,eax
  1657.         mov    ax,ds
  1658.         return
  1659. getds   endp
  1660.  
  1661. getcs   proc    far
  1662.         publab  getcs   ; return cs register.
  1663.     xor    eax,eax
  1664.         mov    ax,cs
  1665.         return
  1666. getcs   endp
  1667. endif
  1668.  
  1669. _exit   proc    near            ;force an immediate exit to dos.
  1670.         public  _exit
  1671.         mov     eax, esp
  1672.         mov     al, [eax+4]
  1673.         mov     ah, 4ch
  1674.     call    _mwint21
  1675. _exit   endp
  1676.  
  1677. ; void contract_heap (void *allocated)
  1678. ;     memory, starting at *allocated, is returned to the system
  1679. contract_heap proc near
  1680.     publab contract_heap
  1681.     prolog
  1682.  
  1683.     parm386    <<loc,dword>>
  1684.     parm86    <<loc,dword>>
  1685.  
  1686.         cmp     env,D4G_ENV
  1687.       jne    not_dos4g2
  1688.  
  1689. ;       ***********************
  1690. ;       *                     *
  1691. ;       *       DOS4G         *
  1692. ;       *                     *
  1693. ;       ***********************
  1694.  
  1695. ;    return memory to system
  1696.     mov    si,lasthand
  1697.     mov    di,lasthand+2
  1698.         mov    ax,0502h
  1699.         int    31h
  1700.     jc    return_fail
  1701.     jmp    return_okay
  1702.  
  1703. not_dos4g2:
  1704. ;       ***********************
  1705. ;       *                     *
  1706. ;       *     NOT DOS4G       *
  1707. ;       *                     *
  1708. ;       ***********************
  1709.  
  1710. ;    return memory to system
  1711.     mov    eax,loc
  1712.     shr    eax,12                  ; convert to pages
  1713.     cmp     env,AI_ENV
  1714.     jne    short pages2
  1715.     shl    eax,8                ; convert pages to paragraphs for AI.
  1716.  
  1717. pages2:    
  1718.     mov     ebx,eax
  1719.     mov    ah,SETBLOCK
  1720.     int    21h
  1721.     jc    short return_fail
  1722.  
  1723. return_okay:
  1724. ;       adjust _heaphi
  1725.     mov    eax,loc
  1726.     dec    eax
  1727.     mov    _heaphi,eax        ; _heaphi := totsize - 1
  1728.  
  1729. ;       if _heaptop > _heaphi, then adjust _heaptop
  1730.     cmp    eax,_heaptop
  1731.     jge    return_from_contract
  1732.     mov    _heaptop,eax        ; _heaptop := _heaphi
  1733.     jmp    return_from_contract
  1734.  
  1735. return_fail:
  1736. ;    adjust _heaptop, as we now have room
  1737.     mov    eax,loc
  1738.     dec    eax
  1739.     mov    _heaptop,eax
  1740.  
  1741. return_from_contract:
  1742.     epilog
  1743. contract_heap    endp
  1744.  
  1745. ?INIT   ends
  1746.         end     init
  1747.