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