home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SOURCE / STARTUP / DOS / CRT0DAT.AS_ / CRT0DAT.AS
Encoding:
Text File  |  1993-02-08  |  21.8 KB  |  1,114 lines

  1.     page    ,132
  2.     title    crt0dat - DOS and Windows shared startup and termination
  3. ;***
  4. ;crt0dat.asm - DOS and Windows shared startup and termination
  5. ;
  6. ;    Copyright (c) 1985-1992, Microsoft Corporation.  All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;    Shared startup and termination.
  10. ;
  11. ;    NOTE:  This source is included in crt0.asm for assembly purposes
  12. ;    when building .COM startup.  This is so the .COM startup resides
  13. ;    in a single special object that can be supplied to the user.
  14. ;
  15. ;*******************************************************************************
  16.  
  17. _NFILE_ =    20        ; Maximum number of file handles
  18.  
  19. ifdef _QWIN
  20. _WFILE_ =    20        ; Maximum number of QWIN file handles
  21. endif
  22.  
  23. ?DF    =    1        ;; tell cmacros.inc we want to define our own segments
  24.  
  25. .xlist
  26. include version.inc
  27. include cmacros.inc
  28. include msdos.inc
  29. include defsegs.inc
  30. include stdlib.inc
  31. .list
  32.  
  33. ifndef _WINDOWS
  34.     _DEBUGSCREEN equ 1        ; debug screen swapping
  35. endif
  36.  
  37. ifdef FARSTACK
  38. ife sizeD
  39. error <You cannot have a far stack in Small or Medium memory models.>
  40. endif
  41. endif
  42.  
  43. ifdef    _COM_
  44.     if sizeC or sizeD
  45.     error <Must use Small memory model for .COM files.>
  46.     endif
  47. endif    ;_COM_
  48.  
  49.  
  50. CrtDefSegs  <code,cdata,data>
  51.  
  52. ifdef _DEBUGSCREEN
  53.     CrtDefSegs    <dbdata>
  54. endif    ; _DEBUGSCREEN
  55.  
  56. ifndef _WINDOWS
  57.     CrtDefSegs    <xiqcseg>
  58. endif
  59.  
  60.     CrtDefSegs    <xifseg,xiseg,xoseg,xofseg,xpseg,xcseg,xcfseg>
  61.  
  62.     CrtDefSegs    <xifcseg>
  63.  
  64.  
  65. ifdef  _COM_
  66.     CrtDefSegs <emdata, emcode>
  67. endif    ;_COM_
  68.  
  69. defGrp    DGROUP            ; define DGROUP
  70.  
  71. codeOFFSET equ    offset _TEXT:
  72. dataOFFSET equ    offset DGROUP:
  73.  
  74. page
  75.  
  76.  
  77. sBegin    xifbseg
  78. xifbegin label    byte        ; Far initializers begin/end
  79. sEnd    xifbseg
  80.  
  81. sBegin    xifeseg
  82. xifend    label    byte
  83. sEnd    xifeseg
  84.  
  85.  
  86. sBegin    xibseg
  87. xibegin label    byte        ; Initializers begin/end
  88. sEnd    xibseg
  89.  
  90. sBegin    xieseg
  91. xiend    label    byte
  92. sEnd    xieseg
  93.  
  94.  
  95.     sBegin  xifcbseg
  96.     xifcbegin label   byte    ; far C++ constructors begin/end
  97.     sEnd    xifcbseg
  98.  
  99.     sBegin  xifceseg
  100.     xifcend   label   byte
  101.     sEnd    xifceseg
  102.  
  103.  
  104. sBegin    xobseg
  105. xontab    label    byte        ; atexit/onexit begin/end
  106. sEnd    xobseg
  107.  
  108. sBegin    xoeseg
  109. xonend    label    byte
  110. sEnd    xoeseg
  111.  
  112.  
  113. ife sizeC
  114.     ; in large model _fatexit = atexit so table not needed
  115.     sBegin  xofbseg
  116.     xfontab  label   byte    ; far atexit/onexit begin/end
  117.     sEnd    xofbseg
  118.  
  119.     sBegin  xofeseg
  120.     xfonend  label   byte
  121.     sEnd    xofeseg
  122. endif
  123.  
  124.  
  125. sBegin    xpbseg
  126. xpbegin label    byte        ; Pre-terminators begin/end
  127. sEnd    xpbseg
  128.  
  129. sBegin    xpeseg
  130. xpend    label    byte
  131. sEnd    xpeseg
  132.  
  133.  
  134. sBegin    xcbseg
  135. xcbegin label    byte        ; C terminators begin/end
  136. sEnd    xcbseg
  137.  
  138. sBegin    xceseg
  139. xcend    label    byte
  140. sEnd    xceseg
  141.  
  142.  
  143. sBegin    xcfbseg
  144. xcfbegin label    byte        ; C far terminators begin/end
  145. sEnd    xifbseg
  146.  
  147. sBegin    xcfeseg
  148. xcfend    label    byte
  149. sEnd    xcfeseg
  150.  
  151.  
  152. sBegin    cdata            ; floating point setup segment
  153. assumes ds,data
  154.  
  155.     dw    0        ; force segment to be at least 0's
  156. labelD    <PUBLIC,_fpinit>    ; public for signal
  157. fpmath    dd    1 dup (?)    ; linking trick for fp
  158. fpdata    dd    1 dup (?)
  159. fpsignal dd    1 dup (?)    ; fp signal message
  160.  
  161. sEnd
  162.  
  163. ifdef   _BAT16
  164.     extrn LibvapExit:NEAR    
  165. endif   ;_BAT16
  166.  
  167. ifdef _DEBUGSCREEN
  168. sBegin    dbdata                ;
  169.     assumes ds,data         ; Used to do the running under
  170. externW     __aDBswpflg        ; a debugger screen swapping
  171. externW     __aDBexit        ;
  172. sEnd    dbdata                ;
  173.     extrn    __aDBdoswp:ABS        ;
  174. endif    ; _DEBUGSCREEN
  175.  
  176. ifndef _WINDOWS
  177. sBegin    xiqcseg
  178. labelW <PUBLIC,__qczrinit>        ;* QC -Zr initializer call address
  179.     dw 1 dup(?)
  180. sEnd    xiqcseg
  181. endif
  182.  
  183.  
  184. ifdef  _COM_
  185.     sBegin  EmData
  186.     labelB  _EmDataLabel
  187.     sEnd    EmData
  188.  
  189.     sBegin  EmCode
  190.     globalW _EmDataSeg,0
  191.     sEnd    EmCode
  192.  
  193. else    ;not _COM
  194.   ifndef  _WINDOWS
  195.     EMULATOR_DATA  segment para public 'FAR_DATA'
  196.     EMULATOR_DATA  ends
  197.  
  198.     EMULATOR_TEXT  segment para public 'CODE'
  199.  
  200.     public __EmDataSeg
  201.     __EmDataSeg dw  EMULATOR_DATA
  202.  
  203.     EMULATOR_TEXT  ends
  204.   endif   ;not _WINDOWS
  205. endif    ;not _COM_
  206.  
  207. sBegin    data
  208. assumes ds,data
  209.  
  210. ifndef _WINDLL
  211. ;    special C environment string
  212.     labelB    <PUBLIC,_acfinfo>
  213.     cfile    db    '_C_FILE_INFO='
  214.     cfilex    db    0
  215.     cfileln =    cfilex-cfile
  216. endif    ;!_WINDLL
  217.  
  218. globalD _aintdiv,0        ; divide error interrupt vector save
  219.  
  220. globalT _fac,0            ; floating accumulator
  221. globalW errno,0         ; initial error code
  222. globalW _umaskval,0        ; initial umask value
  223.  
  224. ifndef _WINDLL
  225. ;=============== following must be in this order
  226.  
  227. globalW _pspadr,0        ; psp:0 (far * to PSP segment)
  228. globalW _psp,0            ; psp:0 (paragraph #)
  229.  
  230. ;=============== above must be in this order
  231. endif
  232.  
  233. ;=============== following must be in this order
  234. ifdef _WINDOWS
  235.  
  236. labelW    <PUBLIC,_winver>    ; WIN version
  237. globalB _winminor,0
  238. globalB _winmajor,0
  239.  
  240. endif    ;_WINDOWS
  241.  
  242. labelW    <PUBLIC,_osver>        ; OS version
  243. globalB _osminor,0
  244. globalB _osmajor,0
  245.  
  246. globalW _osversion,0
  247.  
  248. ;=============== above must be in this order
  249.  
  250.  
  251. ifdef _WINDOWS
  252. globalB _osmode,_WIN_MODE    ; Windows
  253. globalB _cpumode,_PROT_MODE    ; protected mode (default)
  254. else
  255. globalB _osmode,_DOS_MODE    ; DOS
  256. globalB _cpumode,_REAL_MODE    ; real mode
  257. endif
  258.  
  259. labelW    <PUBLIC,_oserr>
  260. globalW _doserrno,0        ; initial DOS error code
  261.  
  262. ;
  263. ; --- I/O Data ---
  264. ;
  265.  
  266. globalW _nfile,_NFILE_            ; maximum number of file handles
  267.  
  268. ifdef _QWIN
  269. globalW _wfile,_WFILE_            ; maximum number of QWIN file handles
  270. globalW _wnfile,(_NFILE_+_WFILE_)    ; maximum number of total file handles
  271. endif
  272.  
  273. ifdef _WINDOWS
  274. ifdef _BAT16
  275. labelB  <PUBLIC,_osfile>
  276.     db    3 dup (FOPEN+FTEXT+FDEV); stdin/out/err
  277.     db    _NFILE_-3 dup (0)    ; the other handles
  278. else    ;_BAT16
  279. labelB    <PUBLIC,_osfile>
  280.     db    _NFILE_ dup (0)     ; (no std files in windows)
  281. endif    ;_BAT16
  282. else
  283. labelB    <PUBLIC,_osfile>
  284.     db    3 dup (FOPEN+FTEXT)    ; stdin, stdout, stderr
  285.     db    2 dup (FOPEN)        ; stdaux, stdprn
  286.     db    _NFILE_-5 dup (0)    ; the other 15 handles
  287. endif    ;_WINDOWS
  288.  
  289. ifdef    _QWIN
  290. labelB    <PUBLIC,_wsfile>
  291.     db    (FOPEN+FTEXT+FDEV)    ; stdin/out/err
  292.     db    _WFILE_-1 dup (0)    ; the other QWIN handles
  293.  
  294. ; Make sure _osfile and _wsfile are contiguous
  295. .ERRE    offset _osfile+_NFILE_ EQ offset _wsfile
  296. endif    ;_QWIN
  297.  
  298. ifdef _QWIN
  299. ;Force in QWIN system
  300. extrn    __qwinused:word         ; QWIN used/notused flag
  301. endif
  302.  
  303. ; --- End I/O Data ---
  304.  
  305. globalW __argc,0
  306. globalDP __argv,0
  307. globalDP _environ,0        ; environment pointer
  308.  
  309. labelD    <PUBLIC,_pgmptr>    ; pointer to program name
  310.     dw    dataOFFSET dos2nam
  311. ifdef _COM_
  312.     dw    0        ; No relocations in tiny model
  313. elseifdef _QC2
  314.     dw    0        ; No DGROUP references allowed
  315. elseifdef _WINDOWS
  316.     dw    0        ; No DGROUP references allowed
  317. else    ;DEFAULT
  318.     dw    DGROUP
  319. endif
  320.  
  321. dos2nam db    0        ; dummy argv[0] for DOS 2.X
  322.  
  323.  
  324. ; signal related common data
  325.  
  326. globalW _child,0        ; flag used to handle signals from child process
  327.  
  328. ifndef _WINDOWS
  329. ;Overlay related data
  330. globalB _ovlflag,0    ;Overlay flag (0 = no overlays)
  331. globalB _intno,0    ;Overlay interrupt value (e.g., 3F)
  332. globalD _ovlvec,0    ;Address of original overlay handler
  333. endif    ;!_WINDOWS
  334.  
  335.  
  336. globalB _exitflag,0    ; callable exit
  337.  
  338. sEnd    data
  339.  
  340. page
  341.  
  342. externNP _fptrap
  343.  
  344. ifndef    _WINDLL
  345.     externP _cintDIV
  346. endif
  347.  
  348. ifndef    _WINDOWS
  349.     externP _nullcheck
  350. endif
  351.  
  352. ifdef  FARSTACK
  353.     ifdef  _WINDOWS
  354.     externP _GetDGROUP
  355.     endif
  356. endif
  357.  
  358. ifdef _QWIN
  359.     externNP  _wcexit            ; exit the QWIN system
  360. endif
  361.  
  362. ifdef _WINDLL
  363.     extern    __nearstub:near         ; weak extern substitute
  364.     extern    __freefarheap(__nearstub):near    ; free up all far heap mem
  365.     extern    __freebasedheap(__nearstub):near; free up all based heap mem
  366. endif
  367.  
  368. if (_NFILE_ NE 20)
  369.     ifdef _WINDOWS
  370.     extern    SETHANDLECOUNT:far        ; set file count
  371.     endif
  372. endif
  373.  
  374. sBegin    code
  375. assumes cs,code
  376.  
  377. if    sizeC
  378. global    proc    far
  379. endif
  380.  
  381. page
  382. ;***
  383. ;_cinit - C initialization
  384. ;
  385. ;Purpose:
  386. ;    This routine performs the shared DOS and Windows initialization.
  387. ;    The following order of initialization must be preserved -
  388. ;
  389. ;    1.    Integer divide interrupt vector setup
  390. ;    2.    Floating point initialization
  391. ;    3.    Copy ;C_FILE_INFO into _osfile
  392. ;    4.    Check for devices for file handles 0 - 4
  393. ;    5.    General C initializer routines
  394. ;
  395. ;Entry:
  396. ;
  397. ;Exit:
  398. ;
  399. ;Uses:
  400. ;
  401. ;Exceptions:
  402. ;
  403. ;*******************************************************************************
  404.  
  405. cProc    _cinit,<PUBLIC>,<>
  406.  
  407. ifdef    _WINDOWS        ; add windows prolog/epilog code to far frames
  408. if    sizeC
  409. cBegin
  410. else
  411. cBegin    <nogen>
  412. endif    ;sizeC
  413. else
  414. cBegin    <nogen>         ; no local frame to set up in standard libs
  415. endif    ; _WINDOWS
  416.  
  417. assumes ds,data
  418. ifndef FARSTACK
  419. assumes ss,data
  420. endif
  421.  
  422. ifdef _COM_
  423. ;
  424. ;    Initialize the DGROUP portion of _pgmptr.  We must do this at
  425. ;    runtime since there are no load-time fixups in .COM files.
  426. ;
  427.     mov    word ptr [_pgmptr+2],ds ; init seg portion of _pgmptr
  428. endif    ;_COM_
  429.  
  430.  
  431. if (_NFILE_ NE 20)
  432. ;
  433. ;    *** Increase File Handle Count ***
  434. ;
  435. ifdef _WINDOWS
  436.     mov    bx,_NFILE_    ; number of file handle to allow
  437.     push    bx
  438.     call    SETHANDLECOUNT    ; issue the system call
  439.     ;check for error here, if desired (AX equals number of files supported)
  440. else
  441. ;    This code only works on DOS Version 3.3 and later.
  442.     mov    ah,67h        ; system call number
  443.     mov    bx,_NFILE_    ; number of file handles to allow
  444.     callos            ; issue the system call
  445.     ;check for error here, if desired (if carry set, AX equals error code)
  446. endif
  447. ;
  448. ;    *** End Increase File Handle Count ***
  449. ;
  450. endif    ; (_NFILE_ NE 20)
  451.  
  452. ifndef  _BAT16
  453. ifndef    _WINDLL
  454.  
  455. ;    1.    Integer divide interrupt vector setup
  456.  
  457.     mov    ax,DOS_getvector shl 8 + 0
  458.     callos            ; save divide error interrupt
  459.     mov    word ptr [_aintdiv],bx
  460.     mov    word ptr [_aintdiv+2],es
  461.  
  462.     push    cs
  463.     pop    ds
  464.     assumes ds,nothing
  465.     mov    ax,DOS_setvector shl 8 + 0
  466.     mov    dx,codeOFFSET _cintDIV
  467.     callos            ; set divide error interrupt
  468.  
  469. ifdef FARSTACK
  470.     ifdef  _WINDOWS
  471.     callcrt _GetDGROUP
  472.     mov    ds, ax
  473.     else
  474.     mov    ax, DGROUP
  475.     mov    ds, ax
  476.     endif
  477. else
  478.     push    ss
  479.     pop    ds        ; restore DS=DGROUP
  480. endif
  481.     assumes ds,data
  482.  
  483. endif    ;!_WINDLL
  484. endif   ;!_BAT16
  485.  
  486.  
  487. ;    2.    Floating point initialization
  488.  
  489.  
  490. if  memS
  491.  
  492.   ifdef  _WINDOWS
  493.     mov    cx,word ptr [fpmath+2]
  494.     jcxz    nofloat_i
  495.  
  496.   else      ;not _WINDOWS
  497.     cmp    word ptr [fpmath], 0        ; Note: make sure offset __fpmath != 0
  498.     je    nofloat_i
  499.  
  500.     mov    word ptr [fpmath+2], cs     ; fix up these far addresses
  501.     mov    word ptr [fpsignal+2], cs   ; in the small model math libs
  502.  
  503.     ifdef  _COM_
  504.     mov    [_EmDataSeg], cs
  505.     mov    ax, offset DGROUP:_EmDataLabel
  506.     sub    ax, offset EMULATOR_DATA:_EmDataLabel
  507.     mov    cl, 4
  508.     shr    ax, cl
  509.     add    [_EmDataSeg], ax
  510.     endif   ;_COM_
  511.  
  512.   endif   ;not _WINDOWS
  513.  
  514. else    ;not memS
  515.  
  516.     mov    cx,word ptr [fpmath+2]
  517.     jcxz    nofloat_i
  518.  
  519. endif    ;not memS
  520.  
  521. ifdef    _WINDLL
  522.     xor    si,si        ; no environment in Win DLL
  523. else    ;!_WINDLL
  524.     mov    es,[_psp]    ; psp segment
  525.     mov    si,es:[DOS_ENVP] ; environment segment
  526. endif    ;_WINDLL
  527.  
  528.     mov    ax, word ptr [fpdata]
  529.     mov    dx, word ptr [fpdata+2]
  530.     xor    bx,bx        ; (si) = environment segment
  531.     call    [fpmath]    ; fpmath(0) - init
  532.     jnc    fpok
  533.     jmp    _fptrap     ; issue "Floating point not loaded"
  534.                 ; error and abort
  535. fpok:
  536.  
  537. ifndef _WINDLL
  538.  
  539.     mov    ax, word ptr [fpsignal]
  540.     mov    dx, word ptr [fpsignal+2]
  541.     mov    bx,3
  542.     call    [fpmath]    ; fpmath(3) - set signal address
  543.  
  544. endif    ;!_WINDLL
  545.  
  546. nofloat_i:
  547.  
  548.  
  549.  
  550. ifndef _WINDLL
  551.  
  552. ;    3.    Copy _C_FILE_INFO= into _osfile
  553.  
  554. ;    fix up files inherited from parent using _C_FILE_INFO=
  555.  
  556.     mov    es,[_psp]    ; es = PSP
  557.     mov    cx,word ptr es:[DOS_envp] ; es = user's environment
  558.     jcxz    nocfi        ;   no environment !!!
  559.     mov    es,cx
  560.     xor    di,di        ; start at 0
  561.  
  562. cfilp:
  563.     cmp    byte ptr es:[di],0 ; check for end of environment
  564.     je    nocfi        ;   yes - not found
  565.     mov    cx,cfileln
  566.     mov    si,dataOFFSET cfile
  567.     repe    cmpsb        ; compare for '_C_FILE_INFO='
  568.     je    gotcfi        ;   yes - now do something with it
  569.     mov    cx,07FFFh    ; environment max = 32K
  570.     xor    ax,ax
  571.     repne    scasb        ; search for end of current string
  572.     jne    nocfi        ;   no 00 !!! - assume end of env.
  573.     jmp    cfilp        ; keep searching
  574.  
  575. ;    found _C_FILE_INFO= and transfer info into _osfile
  576.  
  577. gotcfi:
  578.     push    es
  579.     push    ds
  580.     pop    es        ; es = DGROUP
  581.     pop    ds        ; ds = env. segment
  582.     assumes ds,nothing
  583.     assumes es,data
  584.     mov    si,di        ; si = startup of _osfile info
  585.     mov    di,dataOFFSET _osfile ; di = _osfile block
  586.  
  587.     mov    cl, 4
  588.  
  589. osfile_lp:
  590.     lodsb
  591.     sub    al, 'A'
  592.     jb    donecfi
  593.     shl    al, cl
  594.     xchg    dx, ax
  595.  
  596.     lodsb
  597.     sub    al, 'A'
  598.     jb    donecfi
  599.     or    al, dl
  600.     stosb
  601.     jmp    short osfile_lp
  602.  
  603. donecfi:
  604. ifdef FARSTACK
  605.     push    es
  606. else
  607.     push    ss
  608. endif
  609.     pop    ds        ; ds = DGROUP
  610.     assumes ds,data
  611.  
  612. nocfi:
  613.  
  614. endif    ;!_WINDLL
  615.  
  616.  
  617. ifndef _WINDOWS
  618.  
  619. ;    4.    Check for devices for file handles 0 - 4
  620. ;
  621. ;        Clear the FDEV bit (which might be inherited from C_FILE_INFO)
  622. ;        and then call DOS to see if it really is a device or not
  623. ;
  624.     mov    bx,4
  625.  
  626. devloop:
  627.     and    _osfile[bx],not FDEV ; clear FDEV bit on principal
  628.  
  629.     mov    ax,DOS_ioctl shl 8 + 0 ; issue ioctl(0) to get dev info
  630.     callos
  631.     jc    notdev
  632.  
  633.     test    dl,80h        ; is it a device ?
  634.     jz    notdev        ;   no
  635.     or    _osfile[bx],FDEV ;   yes - set FDEV bit
  636.  
  637. notdev:
  638.     dec    bx
  639.     jns    devloop
  640.  
  641. endif    ;!_WINDOWS
  642.  
  643.  
  644. ;    5.    General C initializer routines
  645.  
  646.     mov    si,dataOFFSET xifbegin
  647.     mov    di,dataOFFSET xifend
  648.     call    farinitterm    ; call the far initializers
  649.  
  650.     mov    si,dataOFFSET xibegin
  651.     mov    di,dataOFFSET xiend
  652.     call    initterm    ; call the initializers
  653.  
  654.     mov    si,dataOFFSET xifcbegin
  655.     mov    di,dataOFFSET xifcend
  656.     call    farinitterm    ; call far C++ constructors.
  657.  
  658. ifdef    _WINDOWS    ; add epilog code to windows far frame
  659. if    sizeC
  660. cEnd
  661. else
  662.     ret
  663. cEnd    <nogen>
  664. endif    ;sizeC
  665. else
  666.     ret
  667. cEnd    <nogen>     ; standard C libs
  668. endif    ; _WINDOWS
  669.  
  670.  
  671. page
  672. ;***
  673. ;exit(status), _exit(status), _cexit(void), _c_exit(void) - C termination
  674. ;
  675. ;Purpose:
  676. ;
  677. ;    Entry points:
  678. ;
  679. ;        exit(code):  Performs all the C termination functions
  680. ;            and terminates the process with the return code
  681. ;            supplied by the user.
  682. ;
  683. ;        _exit(code):  Performs a quick exit routine that does not
  684. ;            do certain 'high-level' exit processing.  The _exit
  685. ;            routine terminates the process with the return code
  686. ;            supplied by the user.
  687. ;
  688. ;        _cexit():  Performs the same C lib termination processing
  689. ;            as exit(code) but returns control to the caller
  690. ;            when done (i.e., does NOT terminate the process).
  691. ;
  692. ;        _c_exit():  Performs the same C lib termination processing
  693. ;            as _exit(code) but returns control to the caller
  694. ;            when done (i.e., does NOT terminate the process).
  695. ;
  696. ;    Termination actions:
  697. ;
  698. ;        exit(), _cexit ():
  699. ;
  700. ;        1.    call user's terminator routines
  701. ;        2.    call C runtime preterminators
  702. ;
  703. ;        _exit(), _c_exit():
  704. ;
  705. ;        3.    call C runtime terminators
  706. ;        4.    perform _nullcheck() for null pointer assignment
  707. ;        5.    terminate floating point
  708. ;        6.    reset divide by zero interrupt vector
  709. ;        7.    return to DOS or caller
  710. ;
  711. ;    Notes:
  712. ;
  713. ;    The termination sequence is complicated due to the multiple entry
  714. ;    points sharing the common code body while having different entry/exit
  715. ;    sequences.
  716. ;
  717. ;Entry:
  718. ;    exit(), _exit()
  719. ;        int status - exit status (0-255)
  720. ;
  721. ;    _cexit(), _c_exit()
  722. ;        <no input>
  723. ;
  724. ;Exit:
  725. ;    exit(), _exit()
  726. ;        <EXIT to DOS>
  727. ;
  728. ;    _cexit(), _c_exit()
  729. ;        Return to caller
  730. ;
  731. ;Uses:
  732. ;
  733. ;Exceptions:
  734. ;
  735. ;*******************************************************************************
  736.  
  737. ifndef _WINDLL
  738.  
  739. ;
  740. ;--- exit(): Full exit and term process ---
  741. ;
  742.  
  743.  
  744. public    _exit
  745. _exit:
  746. cProc    dummy1,<>,<>
  747.  
  748.     parmw    status        ; termination code
  749.  
  750. cBegin
  751.  
  752.     xor    cx,cx        ; exit(): cl = 0, ch = 0
  753.     jmp    short common1    ; join common code
  754.  
  755. cEnd    <nogen>
  756.  
  757. ;
  758. ;--- _exit(): Quickie exit and term process ---
  759. ;
  760.  
  761.  
  762. public    __exit
  763. __exit:
  764. cProc    dummy2,<>,<>
  765.  
  766.     parmw    status        ; termination code
  767.  
  768. cBegin
  769.  
  770.     mov    cx,1        ; _exit(): cl = 1, ch = 0
  771.     jmp    short common1    ; join common code
  772.  
  773. cEnd    <nogen>
  774.  
  775. endif    ;!_WINDLL
  776.  
  777. if    sizeC
  778. global    endp
  779. endif
  780.  
  781. ;
  782. ;--- _cexit(): Full exit and return to caller ---
  783. ;
  784.  
  785. cProc    _cexit,<PUBLIC>,<SI,DI>
  786.  
  787. cBegin
  788.  
  789.     mov    cx,(1 SHL 8)    ; _cexit(): ch = 1, cl = 0
  790.     jmp    short common1    ; join common code
  791.  
  792. cEnd    <nogen>
  793.  
  794. ;
  795. ;--- _c_exit(): Quickie exit and return to caller ---
  796. ;
  797.  
  798. cProc    _c_exit,<PUBLIC>,<SI,DI>
  799.  
  800. cBegin
  801.  
  802.     mov    cx,(1 SHL 8)+1    ; _c_exit(): ch = 1, cl = 1
  803.     ;fall through
  804.  
  805. ;
  806. ;--- Common entry point ---
  807. ; cx = entry value:
  808. ;    cl = full vs quick exit path
  809. ;         0 = exit() code
  810. ;         1 = _exit() code
  811. ;    ch = term process vs return to caller
  812. ;         0 = term process
  813. ;         1 = return to caller
  814. ;
  815.  
  816. common1:            ; all code paths join here
  817.  
  818. assumes ds,data
  819. ifndef FARSTACK
  820. assumes ss,data
  821. endif
  822.  
  823. ;
  824. ; save exit flag (used by terminators)
  825. ;
  826.     mov    [_exitflag],ch
  827.  
  828. ;
  829. ; If _exit()/_c_exit(), jump over the initial termination processing
  830. ; cx = entry code
  831. ;
  832.  
  833.     push    cx        ; save entry code on top of stack
  834.     or    cl,cl        ; cl != 0 means _exit()/_c_exit()
  835.     jnz    short common2    ; if _exit()/_c_exit(), jump down
  836.     ;fall thru        ; continue (exit, _cexit)
  837.  
  838.  
  839. ;    1.    call user terminators
  840. ;        (atexit/onexit processing)
  841.  
  842.     mov    si,dataOFFSET xontab
  843.     mov    di,dataOFFSET xonend
  844.     call    initterm    ; atexit/onexit table
  845.  
  846. ife sizeC
  847.     ; in large code, _fatexit = atexit so no need to walk far table
  848.     mov    si,dataOFFSET xfontab
  849.     mov    di,dataOFFSET xfonend
  850.     call    farinitterm    ; far atexit/onexit table
  851. endif
  852.  
  853. ;    2.    call C runtime preterminators
  854. ;        - flushall
  855. ;        - rmtmp
  856.  
  857.     mov    si,dataOFFSET xpbegin ; beginning of pre-terminators
  858.     mov    di,dataOFFSET xpend ; end of pre-terminators
  859.     call    initterm
  860.  
  861. ifdef _QWIN
  862. ;
  863. ; Exit the QWIN system.  We can't do this in the pre-terminators because
  864. ; we want to make sure flushall() gets called before _QWINExit.
  865. ;
  866.     mov    si,[status]
  867.     push    si
  868.     call    _wcexit
  869.     add    sp,2
  870.  
  871. endif    ;_QWIN
  872.  
  873. ifdef _DEBUGSCREEN
  874. ;
  875. ; Tell the debugger we are going to exit
  876. ;
  877.     cmp    __aDBswpflg,__aDBdoswp    ; Are we under a debugger?
  878.     jne    @F            ; No -- skip forward
  879.     cCall    __aDBexit        ; Yes -- tell it we are exiting
  880. @@:
  881. endif    ; _DEBUGSCREEN
  882.  
  883. ;
  884. ;--- Common entry point ---
  885. ;
  886.  
  887. common2:            ; __exit() enters here
  888.  
  889.  
  890. ;    3.    perform C terminators
  891.  
  892.     mov    si,dataOFFSET xcbegin
  893.     mov    di,dataOFFSET xcend
  894.     call    initterm    ; call the terminators
  895.  
  896.     mov    si,dataOFFSET xcfbegin
  897.     mov    di,dataOFFSET xcfend
  898.     call    farinitterm    ; call the far terminators
  899.  
  900. ;    4.    perform _nullcheck() for null pointer assignment
  901.  
  902. ifndef    _COM_        ; DS:0 is the PSP in .COM files!
  903. ifndef    _WINDOWS    ; Don't validate the copyright message in windows
  904.  
  905.     call    _nullcheck    ; check data in NULL data segment at DS:0
  906.                 ; this must be far call in large code models
  907.                 ; since user can stub it out
  908.     or    ax,ax        ; zero if no null ptr assignment detected
  909.     jz    afternullchk
  910.  
  911.     pop    ax        ; get entry code
  912.     or    ah,ah        ; ah != 0 means _cexit()/_c_exit()
  913.     push    ax        ; put it back for later
  914.     jnz     short afternullchk ; jump if no status value (_cexit/_c_exit)
  915.  
  916.     cmp    status,0    ; zero if no other error has occurred
  917.     jnz    short afternullchk
  918.     mov    status,255    ; nonzero status to indicate an
  919.                 ; null-pointer-assignment error
  920. afternullchk:
  921.  
  922. endif    ;_WINDOWS
  923. endif    ;_COM_
  924.  
  925. ;    5.    terminate floating point
  926. ;    6.    reset divide by zero interrupt vector
  927.  
  928.     call    _ctermsub    ; fast cleanup
  929.  
  930. ifdef _WINDLL
  931. ;    6a.    free up all global memory to the OS
  932. ;        [NOTE 1: This is necessary because WINDLL memory is
  933. ;        shared and windows won't reclaim it.]
  934. ;        [NOTE 2: This routine must be called last because a
  935. ;        terminator may reference the heap.]
  936.  
  937.     call    __freefarheap     ; free up far memory
  938.     call    __freebasedheap  ; free up based memory
  939. endif
  940.  
  941. ;    7.    return to the DOS or caller
  942.  
  943. ifdef  _WINDLL
  944.     ; Always return to caller (exit/_exit is illegal)
  945.     pop    ax        ; clean off stack
  946. else
  947.     pop    ax        ; get entry code off top of stack
  948.     or    ah,ah        ; ah = 0 means term process
  949.     jnz     returning    ; skip down if not term'ing
  950.  
  951. ;    7a.     return to the DOS
  952.  
  953. exiting:
  954.     mov    ax,status    ; get return value
  955.  
  956. ifdef   _BAT16
  957.     jmp    LibvapExit    ;* BAT16 uses different exit code
  958. else    ; _BAT16
  959.     callos    terminate    ; exit with al = return code
  960. endif   ; _BAT16
  961.  
  962.     ;*** PROCESS IS TERMINATED ***
  963.  
  964. endif    ;_WINDLL
  965.  
  966. ;    7b.    Return to caller.
  967.  
  968. returning:
  969.  
  970. cEnd    <nolocals>
  971.  
  972.  
  973. page
  974. ;***
  975. ;_ctermsub - more C termination code
  976. ;
  977. ;Purpose:
  978. ;    This routine
  979. ;        (1) performs floating-point termination
  980. ;        (2) resets the divide by zero interrupt vector
  981. ;        (3) restore int 3F handler
  982. ;
  983. ;Entry:
  984. ;
  985. ;Exit:
  986. ;
  987. ;Uses:
  988. ;    AX,BX,CX,DX.
  989. ;
  990. ;Exceptions:
  991. ;
  992. ;*******************************************************************************
  993.  
  994. labelNP <PUBLIC,_ctermsub>
  995.  
  996. ;    4.    terminate floating point
  997.  
  998.  
  999.     mov    cx,word ptr [fpmath+2] ; test for floating point
  1000.     jcxz    nofloat_t    ;   no
  1001.  
  1002.     mov    bx,2        ;   yes - cleanup
  1003.     call    [fpmath]
  1004.  
  1005. nofloat_t:
  1006.  
  1007.  
  1008. ifndef    _BAT16
  1009. ifndef    _WINDLL
  1010.  
  1011. ;    5.    reset divide by zero interrupt vector
  1012.  
  1013.     push    ds
  1014.     lds    dx,[_aintdiv]    ; ds:dx = restore vector
  1015.     mov    ax,DOS_setvector shl 8 + 0
  1016.     callos            ; set divide error interrupt
  1017.     pop    ds
  1018.  
  1019. endif    ;!_WINDLL
  1020. endif    ;!_BAT16
  1021.  
  1022.  
  1023.     ret
  1024.  
  1025.  
  1026. page
  1027. ;***
  1028. ;initterm - do a set of initializers or terminators
  1029. ;
  1030. ;Purpose:
  1031. ;    The initializors and terminators may be written in C
  1032. ;    so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  1033. ;    We go through them in reverse order for onexit.
  1034. ;
  1035. ;Entry:
  1036. ;    SI    = start of procedure list
  1037. ;    DI    = end of procedure list
  1038. ;
  1039. ;Exit:
  1040. ;
  1041. ;Uses:
  1042. ;
  1043. ;Exceptions:
  1044. ;
  1045. ;*******************************************************************************
  1046.  
  1047. if sizeC
  1048. farinitterm:            ; large code farinitterm = initterm
  1049. endif
  1050.  
  1051. initterm:
  1052.     cmp    si,di        ; are we done?
  1053.     jae    itdone        ;   yes - no more
  1054.  
  1055. if    sizeC
  1056.     sub    di,4
  1057.     mov    ax,[di]
  1058.     or    ax,[di+2]
  1059.     jz    initterm    ; skip null procedures
  1060.     call    dword ptr [di]
  1061. else
  1062.     dec    di
  1063.     dec    di
  1064.     mov    cx,[di]
  1065.     jcxz    initterm    ; skip null procedures
  1066.     call    cx
  1067. endif
  1068.     jmp    initterm    ; keep looping
  1069.  
  1070. itdone:
  1071.     ret
  1072.  
  1073. page
  1074.  
  1075. ife    sizeC            ; S/C models only
  1076. ;***
  1077. ;farinitterm - do a set of far initializers or terminators
  1078. ;
  1079. ;Purpose:
  1080. ;    The initializors and terminators may be written in C
  1081. ;    so we are assuming C conventions (DS=SS, CLD, SI and DI preserved)
  1082. ;    We go through them in reverse order for onexit.
  1083. ;
  1084. ;Entry:
  1085. ;    SI    = start of procedure list
  1086. ;    DI    = end of procedure list
  1087. ;
  1088. ;Exit:
  1089. ;
  1090. ;Uses:
  1091. ;
  1092. ;Exceptions:
  1093. ;
  1094. ;*******************************************************************************
  1095.  
  1096. farinitterm:
  1097.     cmp    si,di        ; are we done?
  1098.     jae    faritdone    ;   yes - no more
  1099.  
  1100.     sub    di,4
  1101.     mov    ax,[di]
  1102.     or    ax,[di+2]
  1103.     jz    farinitterm    ; skip null procedures
  1104.     call    dword ptr [di]
  1105.     jmp    farinitterm    ; keep looping
  1106.  
  1107. faritdone:
  1108.     ret
  1109. endif    ;sizeC
  1110.  
  1111. sEnd
  1112.  
  1113.     end
  1114.