typmgr.asm
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:27k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. TITLE TYPMGR - Type Table Management Code for QBI
  2. ;***
  3. ;TypMgr.asm - Type Table Management Code for QBI
  4. ;
  5. ; Copyright <C> 1986, Microsoft Corporation
  6. ;
  7. ;Purpose:
  8. ; Create and search for User defined types and elements of types
  9. ;Assumptions:
  10. ; The "module type table" was at one point an actual table. With QB5/EB,
  11. ; it was moved into the module variable table - - - both VAR and
  12. ; TYP/ELEM structures have no particular order requirements, being
  13. ; chained together, and both are created and discarded at the same
  14. ; time. We can therefore have VAR, TYP, and ELEM structs interleaved 
  15. ; in the one physical table, but continue to think of them as unique 
  16. ; logical tables.
  17. ;
  18. ; Each module type table consists of a single chain of TYP structures
  19. ; the offset to the first TYP in this chain is at offset oOFIRST_TYP 
  20. ; in the table.
  21. ;
  22. ; The first TYP struct in each module type table must start at an offset
  23. ; greater than ET_MAX so an oTyp for a user-defined record is always 
  24. ; greater than any predefined type constant. Besides the offset to the 
  25. ; first TYP, the number of currently defined types is found in the table
  26. ; following the offset to the first TYP at offset oCTYPES.
  27. ;
  28. ; Each user-defined type has an associated chain of elements. The offset
  29. ; to the first element in a type is contained in the TYP structure. The
  30. ; elements are always chained in the same order as they are found in
  31. ; the text; this is ensured by the fact that the entire type table
  32. ; is discarded (and the module put in SS_RUDE) whenever a type is
  33. ; removed or an element is inserted out of order (i.e., not sequentially
  34. ; after the last element inserted in the type).
  35. ;
  36. ; Note that TYP and ELEM structures are intermingled in the table
  37. ; The physical order doesn't matter, only the chain order (we can
  38. ; never walk each physical entry in the table, only walk the TYP
  39. ; chain and each ELEM chain).
  40. ;
  41. ; The TYP and ELEM structures are similar; we take advantage of the
  42. ; fact that the oNam field is in the same location for both.
  43. ;
  44. ;*******************************************************************************
  45. .xlist
  46. include version.inc
  47. TYPMGR_ASM = ON ;don't include EXTRNs defined in this file
  48. includeOnce architec
  49. includeOnce context
  50. includeOnce heap
  51. includeOnce names
  52. includeOnce qbimsgs
  53. includeOnce rtps
  54. includeOnce scanner
  55. includeOnce txtmgr
  56. includeOnce variable
  57. .list
  58. ; .sall
  59. assumes DS,DATA
  60. assumes ES,DATA
  61. assumes SS,DATA
  62. assumes CS,CP
  63. sBegin DATA
  64. staticW oElemLast,0 ;used to allow DefineElem to leverage off of
  65. ;some code in RefElem
  66. externB b$ErrInfo
  67. sEnd DATA
  68. sBegin CP
  69. assumes cs,CP
  70. ;***
  71. ;DefineTyp(oNam) - create a new entry in the type table
  72. ;Purpose:
  73. ;  Called when the parser encounters a TYPE statement, to create a new
  74. ;  entry in the module type table for the type. 
  75. ;
  76. ;  Note that the scanner uses bits 13, 14, & 15 of an oTyp, so type tables
  77. ;  can be no larger than 8k.
  78. ;
  79. ;  Note: EB has a special use for this where the 'oNam' is really something
  80. ;  else. The high bit set on input indicates that this is not really
  81. ;  an oNam - - - the high bit is maintained in the oNam field of the typ.
  82. ;
  83. ;Entry:
  84. ;  oNam - module name table offset for the name of the type.
  85. ;
  86. ;Exit:
  87. ;  returns an offset into mrsCur.bdVar for the new type entry, or an
  88. ;  error code, depending on bit 15 of the return value. If bit 15 is
  89. ;  clear, an offset is returned, if set, the return value with bit 15
  90. ;  masked off is a standard basic error code.
  91. ;
  92. ;Exceptions:
  93. ;  none.
  94. ;  
  95. ;
  96. ;******************************************************************************
  97. cProc DefineTyp,<FAR,PUBLIC,NODATA>,<SI,DI>
  98. parmW oNam
  99. localW oTypLast
  100. cBegin DefineTyp
  101. ; register si = pTypBase
  102. ; register di = pTyp
  103. ; dx = cbOld
  104. DbChk MrsCur
  105. mov si,[mrsCur.MRS_bdVar.BD_pb]
  106. mov di,[si+oOFIRST_TYP]
  107. mov dx,[mrsCur.MRS_bdVar.BD_cbLogical] ; dx = cbOld
  108. jmp SHORT DefineTyp_Loop_Check
  109. DefineTyp_Loop:
  110. add di,si ;pTyp = pTyp + pTypBase
  111. mov ax,PTRVAR[di.TYP_oNam]
  112. cmp [oNam],ax
  113. jnz DefineTyp_No_Error
  114. mov ax,08000H OR ER_DD
  115. jmp short DefineTyp_Exit
  116. DefineTyp_No_Error:
  117. mov ax,PTRVAR[di.TYP_oTypNext]
  118. and ah,07FH  ; mask off flag bit
  119. sub di,si
  120. mov [oTypLast],di ;oTypLast = pTyp - pTypBase
  121. xchg ax,di ;di = new oTyp
  122. DefineTyp_Loop_Check:
  123. or di,di ;end of TYP chain?
  124. jnz DefineTyp_Loop ;  brif not
  125. cmp WORD PTR PTRVAR[si+oCTYPES],CTYPESMAX ;[3]
  126. je DefineTyp_OM_ER1 ;brif this would cause table to have more than 
  127. ;the legal max. number of types
  128. push dx ;save cbOld across call
  129. PUSHI ax,<dataOFFSET mrsCur.MRS_bdVar>
  130. PUSHI ax,<SIZE TYP>
  131. call BdGrowVar ; grow type table enough for new type
  132. ; we can't just blindly call BdGrowVar at a point where the user CAN
  133. ;  continue - - - but txtmgr guarantees that any edit of a TYPE 
  134. ;  statement or of an element in a TYPE block causes module rude edit
  135. DbAssertRel  grs.GRS_otxCONT,z,UNDEFINED,CP,<DefineTyp: CAN Continue>
  136. pop dx ;restore cbOld
  137. or ax,ax
  138. jne DefineTyp_Cont ; brif attempt to grow table succeeded
  139. DefineTyp_OM_ER1:
  140. jmp short DefineTyp_OM_ER
  141. DefineTyp_Cont:
  142. mov si,[mrsCur.MRS_bdVar.BD_pb]
  143. ;update pTypBase in case of heap movement
  144. inc PTRVAR[si+oCTYPES]
  145. ; increment count of types in table
  146. mov di,dx ;cbOld
  147. add di,si ;di = pTyp
  148. mov ax,[oNam]
  149. mov PTRVAR[di.TYP_oNam],ax
  150. sub ax,ax
  151. mov PTRVAR[di.TYP_cbData],ax
  152. mov PTRVAR[di.TYP_oElementFirst],ax
  153. mov PTRVAR[di.TYP_oTypNext],ax
  154. mov bx,[oTypLast]
  155. cmp PTRVAR[si+oOFIRST_TYP],ax
  156. ;special case of start of type table?
  157. jne ChainTyp ;  brif not
  158. mov bx,oOFIRST_TYP - TYP_oTypNext
  159. ; this will make the following instruction
  160. ; put this oTyp in the table, to start the 
  161. ; TYP chain
  162. ChainTyp:
  163. or PTRVAR[bx.TYP_oTypNext][si],dx
  164. xchg ax,dx ;cbOld = oTypNew = retval
  165. DefineTyp_Exit:
  166. cEnd DefineTyp
  167. DefineTyp_OM_ER:
  168. mov ax,ER_OM OR 08000H
  169. jmp SHORT DefineTyp_Exit
  170. ;***
  171. ;RefTyp(oNam, oTxRef) - Return oTyp for a type described by oNam
  172. ;
  173. ;Purpose:
  174. ;  Given an oNam and the text offset at which it was found, return the 
  175. ;  offset into the type table for the type of this name.
  176. ;  If the text offset at which the type was defined is larger than oTxRef
  177. ;  (i.e., if this amounts to a forward reference), return an error code,
  178. ;  MSG_UndType.
  179. ;
  180. ;Entry:
  181. ;  oNam - offset into the module name table.
  182. ;  oTxRef - offset into active text table where type reference was found
  183. ;
  184. ;Exit:
  185. ;  If bit 15 is clear, return value is an offset into the module type table 
  186. ;  for the desired type entry; if bit 15 is set, the return value is an 
  187. ;  error code; this error code with bit 15 masked off is a standard basic 
  188. ;  error code.
  189. ;  Only one error code is defined: the case where no type entry is found
  190. ;  with the input oNam.
  191. ;  If this error occurs, the parser will emit an opReParse - - - it is NOT
  192. ;  safe to create an empty type entry in this case, because the reference
  193. ;  might create a static variable entry, which would end up with a size
  194. ;  of zero for the value field ... a type reference prior to definition
  195. ;  must trigger an error.
  196. ;
  197. ;Exceptions:
  198. ;  none.
  199. ;Preserves:
  200. ;  ES
  201. ;******************************************************************************
  202. cProc RefTyp,<PUBLIC,FAR,NODATA>,<ES>   
  203. parmW oNam
  204. parmW oTxRef
  205. cBegin RefTyp
  206. DbChk MrsCur
  207. ;Check to see that this is not a forward reference
  208. cCall OtxTypDefined,<oNam>
  209. RefTyp_Cont:
  210. mov bx,[mrsCur.MRS_bdVar.BD_pb] 
  211. mov dx,PTRVAR[bx+oOFIRST_TYP]; dx = offset to first typ in chain
  212. xchg bx,dx
  213. cmp ax,[oTxRef] ;returned from OtxTypDefined
  214. jb RefLoop_Start
  215. RefTyp_Err_Exit:
  216. mov ax,MSG_UndType OR 08000H
  217. jmp SHORT RefTyp_Exit
  218. RefTyp_Loop:
  219. mov bx,PTRVAR[bx.TYP_oTypNext] ; offset to next type (oTypCur)
  220. and bh,07FH  ; mask off flag bit
  221. RefLoop_Start:
  222. or bx,bx
  223. je RefTyp_Err_Exit ;brif no more entries - not found
  224. add bx,dx ;bx = pTypCur
  225. mov ax,PTRVAR[bx.TYP_oNam]
  226. cmp [oNam],ax
  227. jne RefTyp_Loop ;brif names don't match
  228. or BPTRVAR[bx.TYP_fReferenced],080H
  229. ;set fReferenced bit
  230. xchg ax,bx
  231. sub ax,dx ;subtract off table base for retval
  232. RefTyp_Exit:
  233. cEnd RefTyp
  234. ;***
  235. ;DefineElem(oNam, oTyp, oTypElem) - Add an element to a type
  236. ;DefineElemFixed(cbFixed, oNam, oTyp, oTypElem) - alternate entry point.
  237. ;
  238. ;Purpose:
  239. ;  Given an oNam for a new element, the oTyp for the type entry the element
  240. ;  is to be a part of, and the oTyp for the type of the new element,
  241. ;  add the element to the chain of elements for that type.
  242. ;  DefineElemExp converted to DefineElemFixed as part of revision [7].
  243. ;Entry:
  244. ;  oNam - offset into mrsCur.bdlNam for the element being defined
  245. ;  oTyp - offset into mrsCur.bdVar for the type entry it will belong to
  246. ;  oTypElem - oTyp for the element that's being defined, i.e., the type
  247. ;             of the new element (can be some user defined type).
  248. ;  For DefineElemExp, oTypElem will be ET_FS or ET_FT, and this word
  249. ;       parameter will also have its high bit set (per pcode) if
  250. ;       the cbFixed parameter is really an oNam of a constant which
  251. ;       contains the length of the fixed-length string/text.
  252. ;Exit:
  253. ;  A new element entry is allocated, completely filled in, and linked in to
  254. ;     the end of the element chain for the given type.
  255. ;  Return value is a standard BASIC error code, OR'd with 0x8000 for 
  256. ;     consistency with other TypeMgr functions. Possible error codes are:
  257. ;
  258. ;     ER_DD - already exists an element of this type of that oNam
  259. ;     ER_OM - Out of Memory
  260. ;     MSG_UndType - recursive definition, i.e., element not allowed to
  261. ;                       be of the same oTyp as its parent type.
  262. ;     MSG_InvConst - DefineElemExp called with the oNam for a CONSTant, and
  263. ; some error occured in finding a matching CONSTant.
  264. ;     If all bits are clear (i.e., 0 is returned), no error.
  265. ;
  266. ;  NOTE: As a side effect of this routine, mkVar.MKVAR_oTyp can be modified.
  267. ;        This is wierd, but it saves some code in RefElem and callers.
  268. ;
  269. ;Exceptions:
  270. ;  none.
  271. ;
  272. ;******************************************************************************
  273. cProc DefineElemFixed,<PUBLIC,NEAR,NODATA>
  274. parmW cbFixed
  275. parmW oNam
  276. parmW oTyp
  277. parmW oTypElem
  278. cBegin
  279. mov cx,[cbFixed]
  280. cCall DefineElemCommon,<oNam,oTyp,oTypElem>
  281. cEnd
  282. cProc DefineElem,<PUBLIC,NEAR,NODATA>
  283. cBegin <nogen>
  284. xor cx,cx
  285. cEnd <nogen>
  286. cProc DefineElemCommon,<NEAR,NODATA>,<SI,DI>
  287. parmW oNam
  288. parmW oTyp
  289. parmW oTypElem
  290. localW cbOld
  291. localW pTyp
  292. localW cbFixed 
  293. cBegin
  294. mov [cbFixed],cx ; remember if fixed-length string/text
  295. ;   element or not
  296. jcxz DefineElem_Shared ;brif DefineElem was called
  297. mov ax,[oTypElem]
  298. or ah,ah
  299. jns DefineElem_Shared ; brif cbFixed actually is a byte count
  300. and ah,07FH  ; mask off high bit
  301. mov [oTypElem],ax ; restore as an actual ET_ type
  302. xchg ax,cx
  303. ;ax = oNam of a CONSTant
  304. mov [mkVar.MKVAR_oNam],ax
  305. mov [mkVar.MKVAR_oTyp],ET_I2
  306. mov [mkVar.MKVAR_flags],0 ;only want to find ET_I2 match
  307. or [mkVar.MKVAR_flags2],MV_fDontCreate
  308. call MakeVariable
  309. xchg ax,bx ;put retval in bx
  310. mov ax,MSG_InvConst OR 08000H ;in case of error return
  311. or bx,bx
  312. js DefineElem_Exit2 ;brif some error finding the CONSTant
  313. add bx,[mrsCur.MRS_bdVar.BD_pb]
  314. mov ax,PTRVAR[bx.VAR_value] ;get the I2 CONSTant value
  315. mov [cbFixed],ax
  316. DefineElem_Shared: ;code common to both entry points from
  317. ;  here on
  318. DbChk oNam,oNam
  319. DbChk oTyp,oTyp
  320. DbChk oTyp,oTypElem
  321. mov ax,[mrsCur.MRS_bdVar.BD_cbLogical] 
  322. mov [cbOld],ax
  323. mov ax,[oTypElem]
  324. cmp [oTyp],ax
  325. mov ax,MSG_UndType OR 08000H ;give this error for self recursion.
  326.  ;note that that parser won't allow
  327.  ;indirect recursion case to occur
  328. jz DefineElem_Exit2 ;brif self recursion - error
  329. mov [oElemLast],0
  330. push [oNam] ; parm to RefElem
  331. PUSHI ax,ET_IMP ; error if match regardless of type
  332. mov ax,[oTyp]
  333. mov [mkVar.MKVAR_oTyp],ax
  334. call far ptr RefElem  ; ax = retval - better be an error
  335. ;  NOTE: Updates oElemLast
  336. cmp ax,MSG_UndElem OR 08000H ; RefElem shouldn't have found elem
  337. mov ax,ER_DD OR 08000H ;ER_DD if it did
  338. jz DefineElem_Cont0
  339. DefineElem_Exit2:
  340. jmp DefineElem_Exit1
  341. DefineElem_Cont0:
  342. mov cx,[cbFixed]
  343. jcxz Grow_tElem ; brif not fixed-length string/text elem
  344. mov cx,2 ; size of ELEM_cbFixed field
  345. Grow_tElem:
  346. add cx,SIZE ELEM
  347. PUSHI ax,<dataOFFSET mrsCur.MRS_bdVar>
  348. push cx
  349. call BdGrowVar ; grow type table enough for new type
  350. or ax,ax
  351. je DefineElem_OM_Error_1
  352. mov di,[mrsCur.MRS_bdVar.BD_pb] ;di points to base of type table
  353. mov ax,[oTyp]
  354. add ax,di
  355. mov [pTyp],ax
  356. mov si,[cbOld]
  357. add si,di ;si points to element being defined
  358. mov ax,[oNam]
  359. mov PTRVAR[si.ELEM_oNam],ax
  360. mov PTRVAR[si.ELEM_oElementNext],0 ;[3]
  361. mov ax,[oTypElem]
  362. mov PTRVAR[si.ELEM_oTyp],ax
  363. cCall CbTyp,<ax>
  364. jnz Got_cbTyp ; brif type wasn't ET_FS or ET_FT
  365. mov ax,[cbFixed]
  366. mov PTRVAR[si.ELEM_cbFixed],ax 
  367. Got_cbTyp:
  368. mov bx,[pTyp]
  369. mov cx,PTRVAR[bx.TYP_cbData]
  370. mov PTRVAR[si.ELEM_oVar],cx
  371. add PTRVAR[bx.TYP_cbData],ax
  372. jc DefineElem_OM_Error ; brif wrap beyond 64k
  373. mov ax,[oTypElem]
  374. cmp ax,ET_MAX
  375. jbe @F ; brif new elem not of user-def. type
  376. or BPTRVAR[bx.TYP_fReferenced],080H    
  377. ;set fReferenced bit
  378. @@:
  379. cmp ax,ET_SD ; dynamic string?
  380. jnz @F ; brif not
  381. or BPTRVAR[bx.TYP_flags],F_NOBLKCPYTYP 
  382. ; remember that in order to assign a
  383. ; var of this type to another such
  384. ; var, we can't simply block copy
  385. @@:
  386. mov bx,[oElemLast]
  387. mov ax,[cbOld]
  388. or bx,bx
  389. jne Not_1st_Elem ;brif this is not 1st elem in typ
  390. mov bx,[pTyp] ;special start of elem chain code
  391. mov PTRVAR[bx.TYP_oElementFirst],ax
  392. jmp SHORT DefineElem_Cont2
  393. DefineElem_OM_Error_1:
  394. DefineElem_OM_Error:
  395. mov ax,ER_OM OR 08000H
  396. DefineElem_Exit1:
  397. jmp short DefineElem_Exit
  398. Not_1st_Elem: ;link new element in @ end of chain
  399. mov PTRVAR[bx.ELEM_oElementNext][di],ax
  400. DefineElem_Cont2:
  401. sub ax,ax
  402. DefineElem_Exit:
  403. cEnd DefineElem
  404. ;***
  405. ;RefElem - return offset to specified element in tTyp
  406. ;
  407. ;Purpose:
  408. ;  Given the oNam for an element in type mkVar.MKVAR_oTyp, return the offset 
  409. ;  into mrsCur.bdVar for the element, and place the type of the element into
  410. ;  mkVar.MKVAR_oTyp.
  411. ;
  412. ;Entry:
  413. ;  oNam - name of the element to be found
  414. ;  oTypElem - oTyp of element; ET_IMP if caller doesn't know type.
  415. ; This is used so we can give ER_TM if user puts an (incorrect)
  416. ; explicit type char on an element reference.
  417. ;  The oTyp of the parent type is in mkVar.MKVAR_oTyp.
  418. ;Exit:
  419. ;  return value is an offset into mrsCur.bdVar for the element if bit
  420. ;     15 is clear, or is a standard BASIC error code OR'd with bit 15 if set.
  421. ;  If successful, mkVar.MKVAR_oTyp is changed to the oTyp of the found element.
  422. ;  If the found element is a fixed-length string/text, mkVar.MKVAR_fsLength
  423. ; is changed to the length of the string.
  424. ;  Static oElemLast:
  425. ; if the element contains no types of the found element is the first
  426. ; in the chain, oElemLast will be unchanged.
  427. ; else if the element is found, oElemLast will be an offset to the
  428. ; previous element in the chain.
  429. ; else (element not found in non-empty element chain), oElemLast is
  430. ; an offset to the last element in the chain.
  431. ;
  432. ;Exceptions:
  433. ;  none.
  434. ;
  435. ;******************************************************************************
  436. cProc RefElem,<PUBLIC,FAR>,<si,di>
  437. parmW oNamElem
  438. parmW oTypElem
  439. cBegin
  440. mov si,[mrsCur.MRS_bdVar.BD_pb] 
  441. mov bx,[mkVar.MKVAR_oTyp]
  442. DbChk UserTyp,bx ;Ensure the oTyp we're looking in is 
  443. ;  valid, and a user defined oTyp
  444. mov ax,PTRVAR[bx.TYP_oElementFirst][si]
  445. and ah,07FH ;mask off fReferenced bit
  446. xchg di,ax ;di = table offset to first elem in typ
  447. mov dx,[oNamElem]
  448. DbChk oNam,dx 
  449. jmp short RefElem_LoopStart 
  450. RefElem_MSG_Undefined:
  451. mov ax,MSG_UndElem OR 08000H
  452. jmp SHORT RefElem_Exit
  453. RefElem_Loop:
  454. mov di,PTRVAR[di.ELEM_oElementNext]
  455. RefElem_LoopStart:
  456. or di,di
  457. jz RefElem_MSG_Undefined ;brif end of elem chain - elem not found
  458. mov [oElemLast],di ;always keep oElem of last elem here
  459. add di,si ;di = pElem
  460. cmp PTRVAR[di.ELEM_oNam],dx
  461. jnz RefElem_Loop ;brif no match
  462. mov ax,PTRVAR[di.ELEM_oTyp]
  463. mov [mkVar.MKVAR_oTyp],ax ;set oTyp of found element in location
  464. ;  provided by caller
  465. mov bx,ax
  466. cmp ax,ET_FS
  467. jnz RefElem_Exit1
  468. mov bx,ET_SD ; explicit type char for ET_SD ($)
  469. ; legally matches element of ET_FS
  470. mov ax,PTRVAR[di.ELEM_cbFixed] 
  471. mov [mkVar.MKVAR_fsLength],ax  
  472. RefElem_Exit1:
  473. xchg ax,di ;ax = pElemFound
  474. sub ax,si ;ax = retval = oElemFound
  475. .errnz ET_IMP - 0
  476. mov cx,[oTypElem]
  477. jcxz RefElem_Exit ; brif caller doesn't want to
  478. ; check type of element
  479. cmp cx,bx ; does element match given oTyp?
  480. jz RefElem_Exit ; brif so
  481. mov ax,ER_TM OR 08000H ; type mismatch error
  482. RefElem_Exit:
  483. cEnd
  484. ;***
  485. ;CompareTypsRecurse - compare 2 types to see if they're the same
  486. ;
  487. ;Purpose:
  488. ; Given two oTyps, compare them (recursively element-by-element)
  489. ; to see if they're the same. The given oTyp's do not have to be
  490. ; for user-defined types - - - any valid oTyp's are okay.
  491. ;
  492. ;Entry:
  493. ;  ax = oTyp1 - first type
  494. ;  bx = oTyp2 - first type
  495. ;  if SizeD,
  496. ; ds is set to seg of type table for oTyp1,
  497. ; es is set to seg of type table for oTyp2.
  498. ;  else
  499. ; si points to base of type table for oTyp1
  500. ; di points to base of type table for oTyp2
  501. ;Exit:
  502. ;  PSW.Z set if the two types match, reset if not.
  503. ; if PSW.Z set, CX = 0 indicates no further comparison need be made.
  504. ; if CX != 0, however, the oTyp's are either ET_FS or ET_FT, and
  505. ; the lengths must be compared by the caller (who presumeably has
  506. ; access to these lengths).
  507. ;  If PSW.Z reset, CX = 0 if routine succeeded, ER_OM if insufficient
  508. ; stack space for required recursion.
  509. ;Exceptions:
  510. ;  none.
  511. ;
  512. ;******************************************************************************
  513. cProc CompareTypsRecurse,<NEAR,NODATA>
  514. cBegin CompareTypsRecurse
  515. cmp bx,ET_MAX ;is oTyp2 user-defined?
  516. jbe Compare_Cmp_Exit ; brif not
  517. cmp ax,ET_MAX ;is oTyp1 user-defined?
  518. jbe Compare_Cmp_Exit ; brif not
  519. add ax,si ;ax = pTyp1
  520. add bx,di ;bx = pTyp2
  521. mov bx,PTRVAR[bx.TYP_oElementFirst]
  522. and bh,07FH ;mask off fReferenced bit
  523. xchg ax,bx
  524. mov bx,[bx.TYP_oElementFirst]
  525. and bh,07FH ;mask off fReferenced bit
  526. Elem_Compare_Loop:
  527. ;bx = oElem1, ax = oElem2
  528. or bx,bx
  529. jz Compare_Cmp_Exit ;end of chain 1 - set exit code based on
  530. ; whether both chains end
  531. or ax,ax ;end of chain 2?
  532. jz Compare_Cmp_Exit ;brif end of chain 2  - reset PSW.Z,exit
  533. ;not end of either chain - - continue
  534. add bx,si ;bx = pElem1
  535. push bx ;save across recursive call
  536. mov bx,[bx.ELEM_oTyp]
  537. xchg ax,bx ;ax = oTyp of element 1, bx = oElem2
  538. add bx,di ;bx = pElem2
  539. push bx ;save across recursive call
  540. mov bx,PTRVAR[bx.ELEM_oTyp] ; bx = oTyp of element2
  541. mov cx,sp
  542. sub cx,6 ;CompareTypsRecurse requires 6 bytes
  543. ; of stack space per invocation
  544. cmp cx,[b$pend]
  545. ja Compare_Cont ;brif sufficient stack space to recurse
  546. mov cx,ER_OM ;abnormal termination - not enough stack
  547. mov [b$ErrInfo],OMErr_STK;note this is really Out of Stack space
  548. pop ax ; clean stack
  549. pop ax ; clean stack
  550. or sp,sp ;reset PSW.Z to indicate failure
  551. jmp short CompareTypsRec_Exit1
  552. Compare_Cont:
  553. call CompareTypsRecurse ;compare these types
  554. pop bx ;pElem2Old
  555. pop ax ;pElem1Old
  556. jnz CompareTypsRec_Exit ;if any element match fails, whole
  557. ; process terminates
  558. jcxz Compare_Cont_1
  559. ;ET_FS or ET_FT - - - oTyp's compare, but must also check string
  560. ;lengths - - -
  561. xchg ax,bx
  562. mov cx,[bx.ELEM_cbFixed] ; cx = size of element1
  563. xchg ax,bx
  564. cmp cx,PTRVAR[bx.ELEM_cbFixed] 
  565. jnz CompareTypsRec_Exit ; if lengths are different, no match
  566. Compare_Cont_1:
  567. mov bx,PTRVAR[bx.ELEM_oElementNext] ; fetch new oElem2
  568. xchg ax,bx ;ax = oElem2, bx = pElem1Old
  569. mov bx,[bx.ELEM_oElementNext]
  570. jmp short Elem_Compare_Loop ;continue until end of both chains
  571. ; found, or an element pair is found
  572. ; that doesn't match
  573. Compare_Cmp_Exit:
  574. cmp ax,ET_FS ; special comparison required?
  575. jnz CompareTypsRec_Cmp ; brif no special compare step
  576. ;ax is either ET_FS or ET_FT
  577. cmp ax,bx ; set condition codes for retval
  578. mov cx,sp ; caller must check string lengths
  579. jmp short CompareTypsRec_Exit1 
  580. CompareTypsRec_Cmp:
  581. cmp ax,bx ;sets condition codes for retval
  582. CompareTypsRec_Exit:
  583. mov cx,0 ;routine terminated normally
  584. CompareTypsRec_Exit1:
  585. cEnd CompareTypsRecurse
  586. ;***
  587. ;CompareTyps - compare 2 types to see if they're the same
  588. ;
  589. ;Purpose:
  590. ; Given two oTyps, compare them (recursively element-by-element)
  591. ; to see if they're the same. The given oTyp's do not have to be
  592. ; for user-defined types - - - any valid oTyp's are okay.
  593. ;
  594. ; This routine does the start-up work, and uses
  595. ; CompareTypsRecurse to do the actual comparison.
  596. ;
  597. ; Interface modified as revision [15].
  598. ;
  599. ;Entry:
  600. ;  ax = oRs1  - oRs of first type
  601. ;  bx = oRs2  - oRs of first type
  602. ;  cx = oTyp1 - first type
  603. ;  dx = oTyp2 - first type
  604. ;
  605. ;  parm1 = oRs1 = oRs of 1st type
  606. ;  parm2 = oRs2 = oRs of 2nd type
  607. ;  parm3 = oTyp1 = oTyp of 1st type
  608. ;  parm4 = oTyp2 = oTyp of 2nd type
  609. ;Exit:
  610. ;  PSW.Z set if the two types match, reset if not.
  611. ;  If PSW.Z reset, CX = 0 if routine succeeded, ER_OM if insufficient
  612. ; stack space for required recursion.
  613. ;
  614. ;  AX = 0 if two types match
  615. ;  If AX != 0, DX = 0 if routine succeeded, ER_OM if insufficient
  616. ; stack space for required recursion.
  617. ;Preserves:
  618. ;  ES - scanner depends on this (in non-windows versions)
  619. ;Exceptions:
  620. ;  none.
  621. ;
  622. ;******************************************************************************
  623. cProc CompareTyps,<PUBLIC,FAR,NODATA>,<SI,DI,ES>
  624. parmW oRs1
  625. parmW oRs2
  626. parmW oTyp1
  627. parmW oTyp2
  628. cBegin CompareTyps
  629. assumes ds,DATA 
  630. mov ax,[oRs1] ; parm to OMrsORs
  631. call OMrsORs  ;get oMrs of type1
  632. mov si,[oRs2]
  633. xchg si,ax ;si = oMrs1, ax = oRs2
  634. call OMrsORs ;get oMrs of type2
  635. xchg ax,di ;di = oMrs2, ax = garbage
  636. mov cx,[oTyp1]
  637. mov dx,[oTyp2]
  638. cmp si,di ;oTyp's in different modules?
  639. jnz Diff_Module ; brif so
  640. cmp cx,dx ;return PSW.Z set appropriately
  641. mov cx,0 ;CompareTyps terminated normally
  642. jmp short CompareTyps_Exit
  643. Diff_Module:
  644. push [grs.GRS_oRsCur]
  645. push cx ;preserve oTyp's across call
  646. push dx
  647. call MrsDeActivate ;so both mrs's are in mrs table
  648. RS_BASE add,si ; si = pMrs1
  649. RS_BASE add,di ; di = pMrs2
  650. GETRS_SEG es,bx,<SIZE,LOAD> ;[5] es == Rs table seg, trashes bx
  651. mov si,PTRRS[si.MRS_bdVar.BD_pb] ;[2] si = base pointer to type table 1
  652. mov di,PTRRS[di.MRS_bdVar.BD_pb] ;[2] di = base pointer to type table 2
  653. pop bx ;bx = oTyp2
  654. pop ax ;ax = oTyp1
  655. call CompareTypsRecurse
  656. pop ax ;oRsCur on entry
  657. pushf ;save retval flags
  658. cCall RsActivateCP,<ax> ;restore oRsCur to entry value
  659. popf
  660. CompareTyps_Exit:
  661. mov dx,cx ; per new interface
  662. mov ax,sp ; non-zero
  663. jnz CompareTyps_Exit_1 ; brif types don't match
  664. sub ax,ax
  665. CompareTyps_Exit_1:
  666. cEnd CompareTyps
  667. ;***
  668. ;ONamOElem, ONamOTyp - Return the oNam for the name of a given element or type
  669. ;Purpose: 
  670. ;  Used for descanning. Given an offset into mrsCur.bdVar to an element or type
  671. ;  entry, returns the oNam for the name of the element.
  672. ;
  673. ;Entry:
  674. ;  oElem or oTyp - offset into mrsCur.bdVar for the desired element or type
  675. ;
  676. ;Exit:
  677. ;  return value is an offset into the module name table for the name of the
  678. ; element or type.
  679. ;
  680. ;Exceptions:
  681. ;  none.
  682. ;
  683. ;Preserves:
  684. ;  All but AX and BX (for callers in CP. Callers from outside CP cannot
  685. ;  assume this).
  686. ;
  687. ;******************************************************************************
  688. PUBLIC ONamOTyp
  689. ONamOTyp PROC FAR
  690. .errnz TYP_oNam - ELEM_oNam
  691. ;fall into ONamOElem, taking advantage of the fact that the oNam
  692. ;  field is in the same position in the ELEM and TYP structures.
  693. ONamOTyp ENDP
  694. cProc ONamOElem,<PUBLIC,FAR,NODATA>
  695. parmW oStruc
  696. cBegin ONamOElem
  697. mov bx,[oStruc]
  698. add bx,[mrsCur.MRS_bdVar.BD_pb]
  699. mov ax,[bx.ELEM_oNam]
  700. cEnd ONamOElem
  701. ;===============================================================================
  702. ;***
  703. ;ForEachPrimElem - recursively walk each primitive element in a TYPE
  704. ;
  705. ;Purpose:
  706. ;  Recursively visit each primitive element in a TYPE. By "primitive element"
  707. ;  we mean an element that is not itself of some user-defined type.
  708. ;  For each primitive element, call the near routine pointed to by SI.
  709. ;  In the special case where SI == 0, just increment CX instead, i.e., this
  710. ;  routine then simply counts all primitive elements.
  711. ;
  712. ;Entry:
  713. ;  an oTyp in ax.
  714. ;  SI == 0 to count, or is a near pointer to a helper routine.
  715. ;
  716. ;Exit:
  717. ;  if SI == 0, cx = count of primitive elements on exit,
  718. ;  otherwise cx is not touched, and can be used as a return value by the
  719. ; helper routine.
  720. ;  Does not use dx - - - caller & helper routine can also use dx as desired.
  721. ;
  722. ;Exceptions:
  723. ;  In non-RELEASE case, DebHalt may be called if input not a valid 
  724. ;     user-defined oTyp.
  725. ;
  726. ;******************************************************************************
  727. DbPub ForEachPrimElem 
  728. cProc ForEachPrimElem,<NEAR,NODATA>,<DI>
  729. cBegin
  730. DbChk oTyp,ax
  731. mov bx,[mrsCur.MRS_bdVar.BD_pb] 
  732. mov di,ax
  733. mov di,PTRVAR[di.TYP_oElementFirst][bx]
  734. and di,07FFFH ;mask off fReferenced bit
  735. add di,bx ;di = pElem
  736. add ax,bx
  737. cmp ax,di
  738. jz ForEachPrimElem_Exit
  739. ForEachPrimElem_Loop_Start:
  740. lea ax,[bx+0]
  741. cmp ax,di
  742. jz ForEachPrimElem_Exit ;brif end of chain
  743. mov ax,PTRVAR[di.ELEM_oTyp] 
  744. cmp ax,ET_MAX
  745. ja @F ; brif user-defined type
  746. or si,si ; special case?
  747. jnz CallHelper ; brif not - - call helper
  748. inc cx ; increment count of prim elements
  749. jmp short ForEachPrimElem_Continue 
  750. CallHelper:
  751. ;ax == oTyp of primitive element
  752. ;if SizeD, es == segment of type table
  753. ;di == pElem for primitive element
  754. call si ; call helper for this prim element
  755. jmp short ForEachPrimElem_Continue 
  756. @@:
  757. call ForEachPrimElem  ; recurse to handle elements in
  758. ; this user-defined type
  759. ForEachPrimElem_Continue:
  760. mov di,PTRVAR[di.ELEM_oElementNext]
  761. add di,bx ;add table base to get next element
  762. jmp short ForEachPrimElem_Loop_Start
  763. ForEachPrimElem_Exit:
  764. cEnd
  765. ;***
  766. ;CPrimElemFar(oTyp) - return the number of primitive elements in a type
  767. ;
  768. ;Purpose:
  769. ;  Recursively count the total number of primitive elements owned by a 
  770. ;  given user-defined type. 
  771. ;
  772. ;Entry:
  773. ;  an oTyp.
  774. ;
  775. ;Exit:
  776. ;  a count of the number of actual elements (i.e., of type ET_I2, ET_I4,
  777. ;     ET_R4, ET_R8, fixed-length string, etc) in the type.
  778. ;
  779. ;Exceptions:
  780. ;  In non-RELEASE case, DebHalt may be called if input not a valid 
  781. ;     user-defined oTyp.
  782. ;
  783. ;******************************************************************************
  784. cProc CPrimElemFar,<PUBLIC,FAR,NODATA>,<SI>
  785. parmW oTyp
  786. cBegin CPrimElemFar
  787. mov ax,[oTyp]
  788. sub si,si ; just inc cx for each prim element
  789. sub cx,cx ; initialize count
  790. call ForEachPrimElem  ; cx == count of primitive elemtns
  791. xchg ax,cx ; ax == retval
  792. cEnd CPrimElemFar
  793. ;===============================================================================
  794. sEnd CP
  795. ;===============================================================================
  796. end