home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK7 / SOURCE / STARTUP / DOS / STDENVP.AS$ / STDENVP
Encoding:
Text File  |  1991-11-06  |  8.0 KB  |  360 lines

  1.     page    ,132
  2.     title    stdenvp - standard _setenvp routine
  3. ;***
  4. ;stdenvp.asm - standard _setenvp routine
  5. ;
  6. ;    Copyright (c) 1985-1992, Microsoft Corporation.  All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;    This module is called by the C start-up routine to set up "environ".
  10. ;    It copies the environment strings and a null-terminated table of
  11. ;    pointers to those strings into the heap.
  12. ;    The global symbol "_environ" is set to point to this array.
  13. ;
  14. ;*******************************************************************************
  15.  
  16.  
  17. include version.inc
  18. .xlist
  19. include cmacros.inc
  20. include msdos.inc
  21. include rterr.inc
  22. .list
  23.  
  24. ifdef FARSTACK
  25. ife sizeD
  26.     error <You cannot have a far stack in Small or Medium memory models.>
  27. endif
  28. endif
  29.  
  30. externNP _myalloc        ; allocation routine for arguments
  31.  
  32. sBegin    data
  33. assumes ds,data
  34.  
  35. externDP _environ        ; environment pointer
  36.  
  37. ifdef _WINDOWS
  38.     extrn        GETDOSENVIRONMENT:far
  39. else
  40.     externW _psp        ; PSP segment #
  41. endif
  42.  
  43. ifndef _WINDLL
  44.     externB _acfinfo    ; _C_FILE_INFO string
  45. endif
  46.  
  47.  
  48. sEnd    data
  49.  
  50. sBegin    code
  51. assumes ds,data
  52. assumes cs,code
  53. ifndef FARSTACK
  54. assumes ss,data
  55. endif
  56.  
  57. page
  58. ;***
  59. ;_stdenvp - set up "envp" for C programs
  60. ;
  61. ;Purpose:
  62. ;    Reads the environment and build the envp array for C programs.
  63. ;
  64. ;Entry:
  65. ;    The environment strings occur at the beginning of the segment.
  66. ;    The list of environment strings is terminated by an extra null
  67. ;    byte.  Thus two null bytes in a row indicate the end of the
  68. ;    last environment string and the end of the environment, resp.
  69. ;
  70. ;Exit:
  71. ;    "environ" points to a null-terminated list of pointers to ASCIZ
  72. ;    strings, each of which is of the form "VAR=VALUE".  The strings
  73. ;    are copied from the environment segment into space allocated on
  74. ;    the heap.  The list of pointers is also located on there.
  75. ;
  76. ;Uses:
  77. ;    Locks the environment segment before use, and unlocks afterward
  78. ;    Allocates space on the heapfor the environment strings
  79. ;    and a list of pointers to them.
  80. ;
  81. ;    All registers except DS, SS, and BP are modified
  82. ;    Note especially that SI and DI are NOT preserved!
  83. ;
  84. ;Exceptions:
  85. ;
  86. ;*******************************************************************************
  87.  
  88. cProc    _setenvp,<PUBLIC>,<ds>
  89.  
  90. if sizeD
  91.     localW    envseg        ; segment OS environment segment
  92.     localW    envtab        ; segment environment pointer table
  93. ifdef FARSTACK
  94.     localW    datagroup    ; segment of the DGROUP
  95. endif ;FARSTACK
  96. endif ;sizeD
  97.  
  98. cBegin
  99.  
  100. ifdef _WINDOWS
  101.     call    GETDOSENVIRONMENT    ; dx:ax = environment
  102.     or    ax,ax            ; offset==0 ? (it's supposed to be)
  103.     jz    @F            ; jump if so
  104.     mov    dx,ax            ; use NULL environment
  105. @@:
  106.     mov    bx,dx            ; bx = DOS env seg
  107.     assumes es,nothing
  108.     mov    es,dx            ; es = bx = DOS env seg
  109. else    ;!_WINDOWS
  110.     mov    es,[_psp]    ; es = PSP seg
  111.     assumes es,nothing
  112.     mov    bx,word ptr es:[DOS_ENVP]
  113.     mov    es,bx        ; es = OS environment segment
  114. endif    ;_WINDOWS
  115.  
  116. if sizeD
  117.     mov    [envseg],es    ; save OS seg on stack for later
  118. endif
  119.  
  120. ifdef FARSTACK
  121.     mov    [datagroup],ds    ; save DGROUP for later
  122. endif
  123.  
  124. ;
  125. ; --- Scan the list of environment strings calculating the following
  126. ; values:
  127. ;    (1) si will count the number of environment strings
  128. ;    (2) di will count the number of bytes the strings occupy
  129. ; Stop on a null string
  130. ;
  131. ; bx = es = OS environment segment
  132. ; ds = DGROUP
  133. ;
  134.  
  135.     xor    ax,ax        ; ax = 0 (search byte)
  136.     xor    si,si        ; si = 0 (env pointer count)
  137.     xor    di,di        ; di = 0 (initial offset)
  138.     mov    cx,-1        ; cx = ffff (infinite count)
  139.  
  140.     or    bx,bx        ; OS env seg == NULL ??
  141.     jz    noenv        ; yes, no environment
  142.     cmp    byte ptr es:[0],0 ; OS env seg start with null byte ??
  143.     je    noenv        ; yes, no environment
  144.  
  145. scanenv:
  146.     repnz    scasb
  147.     inc    si        ; si = envp count
  148.     scasb
  149.     jnz    scanenv
  150.  
  151. noenv:
  152.     mov    ax,di        ; ax = length of env strings
  153.     inc    ax
  154.     and    al,not 1    ; round up to even
  155.  
  156.     inc    si        ; si = env pointer count + 1 (for null)
  157.     mov    di,si        ; di = env pointer count (save)
  158.     shl    si,1        ; si = env pointer count * 2
  159. if    sizeD
  160.     shl    si,1        ; si = env pointer count * 4
  161. endif
  162.  
  163. ;
  164. ; --- Allocate space for environment strings
  165. ; ax = # bytes for env strings
  166. ; si = # bytes for env pointers
  167. ; di = # of pointers
  168. ; es = OS environment segment
  169. ; ds = ss = DGROUP  (ss = stack for FARSTACK)
  170. ;
  171.     ; allocate space for strings
  172.                 ; ax = size needed for strings
  173.     mov    cx,_RT_SPACEENV ; error message in case of death.
  174.     call    _myalloc    ; takes ax = total # of bytes needed
  175. if    sizeD
  176.     push    dx        ; push segment to string area
  177. endif
  178.     push    ax        ; push offset to string area
  179.  
  180.     ; allocate space for the pointer table
  181.  
  182.     mov    ax,si        ; ax = space for pointers
  183.     call    _myalloc    ; takes ax = total # of bytes needed
  184.     mov    word ptr [_environ],ax    ; init environ
  185. if    sizeD
  186.     mov    word ptr [_environ+2],dx; segment address for large model
  187.     mov    word ptr [envtab],dx    ; save segment here too
  188. endif
  189.  
  190. ;
  191. ; --- Successfully allocated space for env table and strings
  192. ; Init registers for env copy loop
  193. ;
  194. ; ax = offset to env table area
  195. ; di = # of pointers
  196. ; es = OS environment segment
  197. ; ds = DGROUP
  198. ; tos = offset to string area
  199. if sizeD
  200. ; tos-2 = segment to string area
  201. endif
  202. ;
  203.  
  204. env_ok:
  205.  
  206. if sizeD
  207.     push    es
  208.     pop    ds        ; ds = OS env segment
  209.     assumes es,nothing
  210.     assumes ds,nothing
  211. else
  212.     push    es
  213.     push    ds
  214.     pop    es        ; es = DGROUP
  215.     pop    ds        ; ds = OS env segment
  216.     assumes es,data
  217.     assumes ds,nothing
  218. endif
  219.  
  220.     mov    cx,di        ; cx = envcnt
  221.     mov    bx,ax        ; bx = offset env pointers area
  222.     xor    si,si        ; si = OS env string area
  223.     pop    di        ; di = offset env string area
  224. if sizeD
  225.     pop    es        ; es:di = pointer env string area
  226. endif
  227.  
  228.  
  229. ;
  230. ; --- Check for no environment
  231. ;
  232.  
  233.     dec    cx        ; adjust for the last entry of 0000
  234.     jcxz    envdone     ;   done - no environment
  235.  
  236. ;
  237. ; --- Loop through the environment
  238. ; (1) Setup the environment table of pointers (environ)
  239. ; (2) Copy the environment strings into our address space
  240. ; (3) Do NOT copy the _C_FILE_INFO string
  241. ;
  242. if sizeD
  243. ; cx = # of env strings left to copy
  244. ; bx = offset of env pointer table
  245. ; ds:si = pointer to OS environment area
  246. ; es:di = pointer to next envstrg destination
  247. else
  248. ; cx = # of env strings left to copy
  249. ; ds:si = offset  to OS environment area
  250. ; es:bx = offset of env pointer table
  251. ; es:di = pointer to next envstrg destination
  252. ; es = DGROUP
  253. endif
  254.  
  255. envloop:
  256.  
  257. ifndef _WINDLL
  258.     ; --- Check for _C_FILE_INFO
  259.  
  260.     mov    ax,ds:[si]    ; get first two bytes of string
  261. ifdef FARSTACK
  262.     push    ds
  263.     mov    ds,[datagroup]
  264.     assumes ds,data
  265.     cmp    ax,word ptr [_acfinfo]    ; compare to "_C"
  266.     pop    ds
  267.     assumes ds,nothing
  268. else
  269.     cmp    ax,word ptr ss:[_acfinfo]    ; is it "_C" ?
  270. endif ;FARSTACK
  271.     jne    not_cfi     ; nope, continue
  272.  
  273.     push    cx        ; save context
  274.     push    si
  275.     push    di
  276. if sizeD
  277.     push    es
  278. ifdef FARSTACK
  279.     mov    es,[datagroup]    ; es = DGROUP
  280. else
  281.     push    ss
  282.     pop    es        ; es = DGROUP
  283. endif ;FARSTACK
  284. endif
  285.  
  286.     mov    di,dataOFFSET _acfinfo    ; es:di = pointer to _C_FILE_INFO
  287.     mov    cx,_C_FILE_INFO_LEN SHR 1    ; length of string in words
  288.     repe    cmpsw        ; compare the strings
  289.  
  290. if sizeD
  291.     pop    es        ; restore context
  292. endif
  293.     pop    di
  294.     pop    si
  295.     pop    cx
  296.                 ; is it _C_FILE_INFO ??
  297.     je    envcopy     ; yes, don't store this one
  298.     ;fall thru        ; nope, store it
  299.  
  300. endif    ;!_WINDLL
  301.  
  302.     ; --- store env string pointer in table
  303.  
  304. not_cfi:
  305.  
  306. if sizeD
  307.     mov    ds,[envtab]    ; ds:bx = next table entry
  308. endif
  309.                 ; es:di = next env string area
  310. if sizeD
  311.     mov    ds:[bx],di    ; save env string pointer in table
  312.     mov    ds:[bx+2],es
  313.     add    bx,4        ; bump table pointer
  314. else
  315.     mov    es:[bx],di    ; save env string pointer in table
  316.     inc    bx        ; bump table pointer
  317.     inc    bx
  318. endif
  319.  
  320.     ; --- copy string from OS segment into our memory
  321.  
  322. envcopy:
  323.  
  324. if sizeD
  325.     mov    ds,[envseg]    ; ds:si = string in OS seg
  326. endif
  327.  
  328. envcpy:
  329.     lodsb            ; get a char from OS segment
  330.     stosb            ; copy into library space
  331.     or    al,al        ; end of string ??
  332.     jnz    envcpy        ; nope, continue copying string
  333.  
  334.     loop    envloop     ; do the next environment variable
  335.  
  336. ;
  337. ; --- Done copying strings
  338. ; put a null at the end of the envtab table
  339. ;
  340.  
  341. envdone:
  342.  
  343. if sizeD
  344.     mov    ds,[envtab]        ; ds:bx = env table pointer
  345.     mov    ds:[bx],cx        ; store a null
  346.     mov    ds:[bx+2],cx
  347. else
  348.     mov    es:[bx],cx        ; store a null
  349. endif
  350.  
  351. if sizeD
  352. cEnd
  353. else
  354. cEnd    <nolocals>
  355. endif
  356.  
  357. sEnd    code
  358.  
  359.     end
  360.