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

操作系统开发

开发平台:

Visual C++

  1. TITLE txtsave.asm - ASCII Save Functions
  2. ;==========================================================================
  3. ;
  4. ;Module:  txtsave.asm - ASCII Save Functions
  5. ;System:  Quick BASIC Interpreter
  6. ;
  7. ;=========================================================================*/
  8. include version.inc
  9. TXTSAVE_ASM = ON
  10. includeOnce architec
  11. includeOnce context
  12. includeOnce heap
  13. includeOnce lister
  14. includeOnce names
  15. includeOnce opcontrl
  16. includeOnce opid
  17. includeOnce opmin
  18. includeOnce opstmt
  19. includeOnce parser
  20. includeOnce pcode
  21. includeOnce qbimsgs
  22. includeOnce rtinterp
  23. includeOnce rtps
  24. includeOnce rttemp
  25. includeOnce scanner
  26. includeOnce txtmgr
  27. includeOnce txtint
  28. includeOnce util
  29. includeOnce ui
  30. includeOnce variable
  31. includeOnce edit
  32. assumes DS,DATA
  33. assumes SS,DATA
  34. assumes ES,NOTHING
  35. ASC_CRLF EQU 0A0Dh ;ASCII Carriage return/Line Feed
  36. ASC_TAB  EQU 9 ;ASCII Tab
  37. sBegin DATA
  38. EXTRN tabStops:WORD ;defined in edit manager
  39. EXTRN b$PTRFIL:WORD ;defined by runtime - current channel ptr
  40. CrLf DW ASC_CRLF ;for file line termination
  41. oMrsSaveDecl DW 0 ;used by SaveDeclares
  42. sEnd DATA
  43. sBegin CODE
  44. ;Table of opcodes used to search for DECLARE or CALL statements
  45. ;
  46. tOpDecl LABEL WORD
  47. opTabStart DECL
  48. opTabEntry DECL,opStDeclare
  49. opTabEntry DECL,opStCall
  50. opTabEntry DECL,opStCalls
  51. opTabEntry DECL,opStCallLess
  52. opTabEntry DECL,opEot
  53. sEnd CODE
  54. EXTRN B$BUFO:FAR
  55. EXTRN B$KILL:FAR
  56. sBegin CP
  57. assumes cs,CP
  58. ;*************************************************************
  59. ; ushort SaveTxdCur(ax:otxStart)
  60. ; Purpose:
  61. ; ASCII save the contents of the current text table
  62. ; Entry:
  63. ; ax = text offset to start saving text
  64. ; Exit:
  65. ; ax = size of last line output (=2 if trailing blank line)
  66. ; ps.bdpSrc is used
  67. ; Exceptions:
  68. ; Can cause runtime error (Out of memory, I/O errors)
  69. ;
  70. ;*************************************************************
  71. SaveTxdCur PROC NEAR
  72. DbChk Otx,ax
  73. push si
  74. push di
  75. sub di,di ;Init cbLastLine = 0
  76. mov [otxListNext],ax ;ListLine() updates [otxListNext]
  77. test [mrsCur.MRS_flags2],FM2_NoPcode ; document file?
  78. je GetOtxEndProg ; file is measured in Otxs, not lines
  79. DbAssertRel [otxListNext],e,0,CP,<SaveTxdCur:Not starting at the begining of file>
  80. push [mrsCur.MRS_pDocumentBuf] 
  81. call S_LinesInBuf ; get # lines in document buffer
  82. jmp short SetMaximumSave
  83. GetOtxEndProg:
  84. call OtxEndProg ;ax = otx to Watch pcode
  85. SetMaximumSave:
  86. xchg si,ax ;si = otx to Watch pcode
  87. StLoop:
  88. mov ax,[otxListNext] ;ax=offset for next line to list
  89. cmp ax,si
  90. DJMP jae SlDone ;brif done with this text table
  91. test [mrsCur.MRS_flags2],FM2_NoPcode ; document file?
  92. je ListPcodeLine ; brif not, let lister get line
  93. push [mrsCur.MRS_pDocumentBuf] ; document table to list from
  94. push ax ; line to list
  95. push ps.PS_bdpSrc.BDP_cbLogical ; length of buffer
  96. push ps.PS_bdpSrc.BDP_pb ;pass ptr to dest buf
  97. call S_cbGetLineBuf ; AX = cBytes in line
  98. inc [otxListNext] ; bump pointer to next line
  99. mov [cLeadingSpaces],0 ; start with no leading spaces
  100. mov bx,[ps.PS_bdpSrc.BDP_pb]; BX = ptr to 0 terminated string
  101. CheckNextChar:
  102. cmp byte ptr [bx],' ' ; Is it a space
  103. jne GotLine  ; brif not, say that we got line
  104. inc [cLeadingSpaces] ; indicate another space
  105. inc bx ; point to next character
  106. jmp CheckNextChar ; check it for a space
  107. ListPCodeLine:
  108. push ax ;pass offset to ListLine
  109. PUSHI ax,<DATAOFFSET ps.PS_bdpSrc> ;pass dst buf ptr to listline
  110. call ListLine ;ax=char count
  111. inc ax ;test for UNDEFINED
  112. jne NotOmErr ;brif out-of-memory
  113. jmp OmErrCP
  114. NotOmErr:
  115. dec ax ;restore ax = byte count
  116. GotLine:
  117. cmp [fLsIncluded],0
  118. jne StLoop ;brif line was part of $INCLUDE file
  119. test mrsCur.MRS_flags2,FM2_EntabSource ;do we need to entab leading
  120. ;blanks?
  121. jz NoEntab  ;brif not
  122. mov cl,[cLeadingSpaces] ;cl = count of leading spaces
  123. or cl,cl ;any leading spaces?
  124. jnz EntabLeadingSpaces ;brif so, replace with tabs
  125. NoEntab:
  126. mov bx,[ps.PS_bdpSrc.BDP_pb]
  127. EntabCont:
  128. ; There is currently no need to call UpdChanCur here, because
  129. ; there is no chance of having nested open files during ascii save.
  130. DbAssertRel b$PTRFIL,ne,0,CP,<SaveTxdCur:Invalid channel>
  131. ; Call OutLine as we can not guarentee that the buffer
  132. ; pointed to by BX contains at least two more bytes.
  133. ; This is slower, but will not trash the heaps.
  134. mov di,ax ; DI = new "cbLastLine"
  135. inc di ; account for CRLF
  136. inc di
  137. call OutLine  ; Print line and CRLF
  138. DJMP jmp SHORT StLoop
  139. SlDone:
  140. xchg ax,di ;ax = cb last line emitted
  141. pop di
  142. pop si
  143. ret
  144. SaveTxdCur ENDP
  145. ; We have a line with leading spaces which needs to be entabbed.
  146. ; We will convert spaces to tabs in the buffer, and return the
  147. ; new buffer char count, and a ptr to the start of the buffer.
  148. ;
  149. ; Entry:
  150. ; ax = count of chars in line buffer
  151. ; cl = count of leading spaces
  152. ; Exit:
  153. ; ax = adjusted count of chars in line buffer
  154. ; bx = ptr to first char in buffer
  155. ; Uses:
  156. ; bx,cx,dx
  157. EntabLeadingSpaces:
  158. push ax ;preserve buffer char count
  159. xchg ax,cx
  160. sub ah,ah ;ax = cLeadingSpaces
  161. mov dx,ax ;remember cLeadingSpaces
  162. mov cx,[tabStops] ;get user defined tabstop settings
  163. ; User interface guarantees tabStops will not be set to 0
  164. DbAssertRel cx,nz,0,CP,<tabStops=0 detected in Ascii save>
  165. div cl ;al=tab count, ah=space count
  166. mov bx,[ps.PS_bdpSrc.BDP_pb] ;bx=ptr to line buffer
  167. add bx,dx ;bx=ptr to first non-leading space
  168. sub dl,al
  169. sub dl,ah ;dx=excess space in buffer
  170. sub bl,ah ;backup over remaining spaces
  171. sbb bh,0
  172. xchg ax,cx
  173. sub ch,ch ;cx=tab count
  174. jcxz NoTabs ;brif none to replace
  175. mov al,ASC_TAB
  176. TabLoop:
  177. dec bx ;back up a char
  178. mov [bx],al  ;replace space with tab
  179. loop TabLoop
  180. NoTabs:
  181. pop ax ;recover buffer char count
  182. sub ax,dx ;adust for removed spaces
  183. jmp EntabCont
  184. ;*************************************************************
  185. ; OutLine, OutCrLf
  186. ; Purpose:
  187. ; OutLine - Output line and CR-LF to current file
  188. ; OutCrLf - Output CR-LF to current file
  189. ; Entry:
  190. ; bx points to 1st byte to output
  191. ; ax = byte count
  192. ;
  193. ;*************************************************************
  194. OutLine PROC NEAR
  195. ; There is currently no need to call UpdChanCur here, because
  196. ; there is no chance of having nested open files during ascii save.
  197. DbAssertRel b$PTRFIL,ne,0,CP,<OutLine:Invalid channel>
  198. push ds ;pass segment of buffer
  199. push bx ;pass offset of buffer
  200. push ax ;pass length of buffer
  201. call B$BUFO ;output line via runtime
  202. ;fall into OutCrLf
  203. OutLine ENDP
  204. OutCrLf PROC
  205. ; There is currently no need to call UpdChanCur here, because
  206. ; there is no chance of having nested open files during ascii save.
  207. DbAssertRel b$PTRFIL,ne,0,CP,<OutCrLf:Invalid channel>
  208. push ds
  209. PUSHI ax,<dataOFFSET CrLf>
  210. PUSHI ax,2
  211. call B$BUFO ;output CR/LF via runtime
  212. ret
  213. OutCrLf ENDP
  214. ;*************************************************************
  215. ; RelShBuf
  216. ; Purpose:
  217. ; Release temporary text table used by SaveProcHdr.
  218. ; Called when we're done saving, or when an error occurs.
  219. ;
  220. ;*************************************************************
  221. RelShBuf PROC NEAR
  222. mov [txdCur.TXD_bdlText_cbLogical],0
  223. ;so TxtDiscard won't examine deleted txt
  224. call TxtDiscard ;discard temporary text table
  225. call TxtActivate ;make module's text table cur again
  226. mov [ps.PS_bdpDst.BDP_cbLogical],0 ;release space held by temp bd
  227. ret
  228. RelShBuf ENDP
  229. ;*************************************************************
  230. ; ushort SaveProcHdr(ax:otxProcDef)
  231. ; Purpose:
  232. ; ASCII save the current procedure's header.
  233. ;
  234. ; Entry:
  235. ; ax = otxProcDef = offset into procedure's text table to opBol for line
  236. ;    containing SUB/FUNCTION statement.  0 if this table has no
  237. ;    SUB/FUNCTION statement yet.
  238. ;
  239. ; Exit:
  240. ; ps.bdpSrc is used
  241. ; grs.fDirect = FALSE
  242. ; ax = 0 if no error, else Standard BASIC error code (i.e. ER_xxx)
  243. ;
  244. ; Exceptions:
  245. ; Can cause runtime error (Out of memory, I/O errors)
  246. ;
  247. ;*************************************************************
  248. SaveProcHdr PROC NEAR
  249. push si ;save caller's si,di
  250. push di
  251. mov di,ax ;di = otxProcDef
  252. push [grs.GRS_oPrsCur] ;pass current oPrs to PrsActivate below
  253. ;fill tEtTemp[] with DEFTYP's from start of proc table to SUB line
  254. mov ax,di ;ax = otxProcDef
  255. mov bx,dataOFFSET tEtTemp ;bx -> type table
  256. call OtxDefType
  257. ;move everything up to proc def from procedure's to temp text table
  258. PUSHI ax,<dataOFFSET ps.PS_bdpDst>
  259. push di ;pass otxProcDef
  260. call BdRealloc
  261. or ax,ax
  262. je JE1_ShOmErr ;brif out-of-memory error
  263. PUSHI ax,<dataOFFSET txdCur.TXD_bdlText>
  264. SetStartOtx ax
  265. push ax
  266. push [ps.PS_bdpDst.BDP_pb]
  267. push di ;pass otxProcDef
  268. call BdlCopyFrom
  269. ;Now we create a temporary text table for saving the synthetically
  270. ;generated procedure header.  We must go through the following steps
  271. ; to do this:
  272. ;  PrsDeactivate()  ---  causes module's text table to be made active
  273. ;  TxtDeactivate()  ---  causes no text table to be made active
  274. ;  TxtCurInit()     ---  make temp text table active
  275. ;  put synthetically generated pcode into txdCur
  276. ;  ASCII save this pcode buffer to the file
  277. ;  TxtDiscard()     ---  discard temporary text table
  278. ;  TxtActivate()    ---  make module's text table current again
  279. ;  PrsActivate(oPrsSave)
  280. ;[flagsTM.FTM_SaveProcHdr] is non-zero while in critical state
  281. ; within function SaveProcHdr. Tells SaveFile's error cleanup
  282. ; to take special action.
  283. or [flagsTM],FTM_SaveProcHdr ;if err, remember to clean up
  284. call PrsDeactivate ;make module's text table active
  285. call TxtDeactivate ;causes no text table to be made active
  286. call TxtCurInit ;make temp text table active
  287. je ShOmErr ;brif out-of-memory error
  288. ;emit synthetic DEFxxx statements as transition from end of last
  289. ;text table to procedure definition line
  290. PUSHI ax,<dataOFFSET ps.PS_tEtCur>
  291. PUSHI ax,<dataOFFSET tEtTemp>
  292. SetStartOtx ax ;insert at start of text
  293. call InsertEtDiff
  294. JE1_ShOmErr:
  295. je ShOmErr ;brif out-of-memory error
  296. call OtxEndProg ;ax = otx to Watch pcode
  297. xchg si,ax ; = offset beyond synthetic DEFxxx stmts
  298. ;Append everything up to SUB line to temp table
  299. push si ;pass otx to Watch pcode
  300. push di ;pass otxProcDef
  301. call TxtMoveUp
  302. je ShOmErr ;brif out-of-memory error
  303. PUSHI ax,<dataOFFSET txdCur.TXD_bdlText>
  304. push si ;pass otx to Watch pcode
  305. push [ps.PS_bdpDst.BDP_pb]
  306. push di ;pass otxProcDef
  307. call BdlCopyTo
  308. call SqueezeDefs ;takes parm in si
  309. ;if setting of $STATIC/$DYNAMIC differs between procedure's header
  310. ;and where procedure will be listed in source file,
  311. ;insert pcode to change the state for the procedure,
  312. ;Note: fLsDynArrays's value will be changed by ListLine() when it
  313. ;      lists the line emitted by InsertDynDiff (if any)
  314. SetStartOtx ax ;insert at start of text
  315. mov dh,[fLsDynArrays] ;dh = old $STATIC/$DYNAMIC state
  316. mov dl,[fProcDyn] ;dl = new $STATIC/$DYNAMIC state
  317. call InsertDynDiff
  318. je ShOmErr ;brif out of memory error
  319. SetStartOtx ax ;start saving at start of text
  320. call SaveTxdCur ;save procedure's header to file
  321. call RelShBuf ;release temp text tbl
  322. and [flagsTM],NOT FTM_SaveProcHdr ;reset critical section flag
  323. ;oPrs parm was pushed on entry to this function
  324. call PrsActivateCP
  325. sub ax,ax ;return no-error result
  326. ;al = error code
  327. ShExit:
  328. mov [ps.PS_bdpDst.BDP_cbLogical],0 ;release space held by temp bd
  329. or al,al ;set condition codes for caller
  330. pop di ;restore caller's si,di
  331. pop si
  332. ret
  333. ShOmErr:
  334. pop ax ;discard oPrs
  335. mov al,ER_OM ;return al = out-of-memory error
  336. jmp SHORT ShExit
  337. SaveProcHdr ENDP
  338. ;Cause runtime error "Out of memory"
  339. OmErrCP:
  340. mov al,ER_OM
  341. call RtError
  342. ;*************************************************************
  343. ; ONamOtherOMrs
  344. ; Purpose:
  345. ; Given an oNam in current mrs, convert it to an oNam
  346. ; in another mrs (which has a different name table).
  347. ; Entry:
  348. ; grs.oMrsCur = source oMrs
  349. ; ax = source oNam
  350. ; dx = target oMrs
  351. ; Exit:
  352. ; ax = target oNam (0 if out of memory error)
  353. ; flags set based upon return value.
  354. ;
  355. ;*************************************************************
  356. cProc ONamOtherOMrs,<NEAR>
  357. localV bufNam,CB_MAX_NAMENTRY
  358. cBegin
  359. cmp [grs.GRS_oMrsCur],dx
  360. je OnOExit ;brif source mrs = target mrs
  361. xchg ax,bx ;bx = oNam (save until CopyONamPb)
  362. push di
  363. push [grs.GRS_oRsCur] ;save caller's oRs -for RsActivate below
  364. mov di,dx ;di = target oMrs
  365. lea ax,bufNam
  366. push ax ;save ptr to string
  367. ; string ptr in ax
  368. ; oNam to CopyONamPb in bx
  369. cCall CopyONamPb,<ax,bx> ; ax = byte count
  370. push ax ;save byte count
  371. cCall MrsActivateCP,<di> ;activate target mrs
  372. pop cx ;cx = byte count
  373. pop ax ;ax = ptr to bufNam
  374. call ONamOfPbCb ;ax = target oNam (ax=Pb, cx=Cb)
  375. xchg di,ax ;di = target oNam
  376. call RsActivateCP ;re-activate caller's oRs
  377. ; parm was pushed on entry
  378. xchg ax,di ;ax = target oNam
  379. pop di ;restore caller's es,di
  380. OnOExit:
  381. or ax,ax ;set condition codes
  382. cEnd
  383. ;*************************************************************
  384. ; SaveDeclares
  385. ; Purpose:
  386. ; Generate synthetic DECLARE stmts for forward referenced
  387. ; SUBs and FUNCTIONs in this module as follows:
  388. ; Pass1:
  389. ;  For every prs in system,
  390. ;    reset FTX_TmpDecl
  391. ;    if prs type is FUNCTION and prs is in mrs being saved,
  392. ;       set FTX_TmpRef bit, else reset it
  393. ; Pass2:
  394. ;  For every text table in this module
  395. ;    Search text table for a reference to a SUB or FUNCTION
  396. ;     if opStDeclare ref found
  397. ;        set FTX_TmpDecl bit
  398. ;     else if CALL, CALLS, implied CALL
  399. ;        set FTX_TmpRef bit
  400. ; Pass3:
  401. ;  For every prs in system,
  402. ;    if FP_DEFINED and FTX_TmpRef bit are set, and FTX_TmpDecl bit is not,
  403. ;    copy pcode for definition to module, changing opcode to opStDeclare,
  404. ;    and changing the oNam for each formal parm and explicitly
  405. ;    listing the TYPE.
  406. ;
  407. ; Exit:
  408. ; grs.fDirect = FALSE
  409. ; ax = 0 for out of memory error.
  410. ; flags set on value in ax
  411. ;*************************************************************
  412. ;----------------------------------------------------------------
  413. ;  For every prs with a text table in system,
  414. ;    reset FTX_TmpDecl
  415. ;    if prs type is FUNCTION and prs is in mrs being saved,
  416. ;       set FTX_TmpRef bit, else reset it
  417. ;----------------------------------------------------------------
  418. cProc SdPass1,<NEAR>
  419. cBegin
  420. and [txdCur.TXD_flags],NOT (FTX_TmpDecl OR FTX_TmpRef)
  421. ;start out by turning both bits off
  422. cmp [prsCur.PRS_procType],PT_FUNCTION
  423. jne Sd1ResetBits ;exit if SUB
  424. mov ax,[oMrsSaveDecl]
  425. cmp ax,[prsCur.PRS_oMrs]
  426. jne Sd1ResetBits ;exit if Func defined in another module
  427. ;for func in module, assume it is referenced.  For external func
  428. ;refs, even qbi requires user have a DECLARE stmt for it.
  429. or [txdCur.TXD_flags],FTX_TmpRef ;turn on FTX_TmpRef bit
  430. Sd1ResetBits:
  431. mov ax,sp ;return TRUE for ForEachCP
  432. cEnd
  433. ;-----------------------------------------------------------------
  434. ;  For every text table in module being saved:
  435. ;    Search text table for a reference to a SUB or FUNCTION
  436. ;     if opStDeclare ref found
  437. ;        set FTX_TmpDecl bit
  438. ;     else if CALL, CALLS, implied CALL
  439. ;        set FTX_TmpRef bit
  440. ;-----------------------------------------------------------------
  441. cProc SdPass2,<NEAR>,<si>
  442. cBegin
  443. SetStartOtx si ;otxCur = start of text
  444. Sd2Loop:
  445. push si
  446. PUSHI ax,<CODEOFFSET tOpDecl>
  447. call TxtFindNextOp ;ax = otx to next opStDeclare opcode
  448. cmp dl,DECL_opEot
  449. je Sd2Exit
  450. xchg si,ax ;si = new otxCur
  451. GetSegTxtTblCur ;es = seg addr of text table
  452. mov ax,es:4[si] ;ax = oPrs field
  453. call PPrsOPrs ; es:bx points to prs structure
  454. ;all other regs preserved
  455. test BPTRRS[bx.PRS_flags],FP_DEFINED 
  456. je Sd2Loop ;don't count references to native-code
  457. ; procedures, only those defined with
  458. ; a SUB/FUNCTION stmt
  459. mov al,FTX_TmpRef
  460. .errnz DECL_opStDeclare
  461. or dl,dl ;dl = 0 for DECLARE, non-zero for CALL
  462. jne Sd2SetBit ;brif CALL
  463. mov al,FTX_TmpDecl
  464. Sd2SetBit:
  465. or BPTRRS[bx.PRS_txd.TXD_flags],al 
  466. jmp SHORT Sd2Loop
  467. Sd2Exit:
  468. mov ax,sp ;return TRUE for ForEachCP
  469. cEnd
  470. ;***
  471. ;GetWord
  472. ;Purpose:
  473. ; This header block added as part of revision [5]
  474. ;Preserves:
  475. ; All but ES, BX, and SI
  476. ;******************************************************************************
  477. GetWord PROC NEAR
  478. GetSegTxtTblCur ;es = seg addr of text table
  479. lods WORD PTR es:[si] ;ax = cntEos
  480. ret
  481. GetWord ENDP
  482. MoveWord PROC NEAR
  483. call GetWord
  484. jmp Emit16_AX ;emit cntEos operand
  485. ; and return to caller
  486. MoveWord ENDP
  487. ;------------------------------------------------------------------------------
  488. ;  For every prs with a text table in system,
  489. ;    if FP_DEFINED and FTX_TmpRef bit are set, and FTX_TmpDecl bit is not,
  490. ;    copy pcode for definition to module, changing opcode to opStDeclare,
  491. ;    and changing the oNam for each formal parm and explicitly
  492. ;    listing the TYPE.
  493. ;
  494. ;------------------------------------------------------------------------------
  495. cProc SdPass3,<NEAR>,<si,di>
  496. localW oNamParm
  497. cBegin
  498. test [prsCur.PRS_flags],FP_DEFINED
  499. je J1_Sd3Exit ; don't count references to
  500. ; undefined procedures
  501. test [txdCur.TXD_flags],FTX_TmpRef
  502. je J1_Sd3Exit ;don't generate DECLARE for text tbl
  503. ; with no references in this module
  504. test [txdCur.TXD_flags],FTX_TmpDecl
  505. je EmitDecl ;don't generate DECLARE for prs which
  506. J1_Sd3Exit:
  507. jmp Sd3Exit ; already has a declare in this prs
  508. EmitDecl:
  509. mov ax,[prsCur.PRS_otxDef] ; ax = otx to opStSub/Function
  510. mov si,ax ;ax = si = text offset
  511. call OtxDefTypeCur ;fill ps.tEtCur with default types
  512. ; at definition of procedure
  513. mov ax,opBol
  514. call Emit16_AX
  515. mov ax,opStDeclare
  516. call Emit16_AX
  517. lodsw ;si=si+2 (points to cntEos parm)
  518. .errnz DCL_cntEos
  519. call MoveWord ;move cntEos from es:[si] to ps.bdpDst
  520. .errnz DCL_oPrs - 2
  521. call MoveWord ;move oPrs from es:[si] to ps.bdpDst
  522. .errnz DCL_atr - 4
  523. call GetWord ;ax = procAtr from es:[si]
  524. push ax ;save proc atr
  525. .errnz DCLA_procType - 0300h
  526. and ah,DCLA_procType / 100h ;ah = procType
  527. cmp ah,PT_FUNCTION
  528. jne NoProcType ;brif this is not a FUNCTION
  529.    .errnz DCLA_Explicit - 0080h
  530. or al,al
  531. js NoProcType ;brif it was explicitly typed
  532. push [prsCur.PRS_ogNam]
  533. call ONamOfOgNam ; ax = oNam of this prs
  534. DbAssertRel  ax,nz,0,CP,<txtsave.asm: ONamOfOgNam returned ax = 0>
  535. cCall OTypOfONamDefault,<ax> ; ax = default oTyp (ax)
  536.    or al,DCLA_Explicit ;remember this was Explicitly typed
  537. pop dx
  538. mov ah,dh ;ax = new procAtr
  539. push ax
  540. ;top of stack = procAtr
  541. NoProcType:
  542. call Emit16 ;emit proc atr operand
  543. .errnz DCL_cParms - 6
  544. call GetWord ;ax = cParms operand from es:[si]
  545. mov di,ax ;di = cParms
  546. call Emit16_AX ;emit cParms operand
  547. inc di
  548. Sd3ParmLoop:
  549. dec di ;decrement parm count
  550. jz Sd3Exit ;brif done with parms
  551. .errnz DCLP_id - 0
  552. call GetWord ;ax = parm's oNam or oVar
  553. cCall oNamoVarRudeOrParse,<ax>;if we text not in rude map oVar
  554. ; to oNam
  555. mov [oNamParm],ax
  556. mov dx,[oMrsSaveDecl]
  557. call ONamOtherOMrs ;ax = equivalent oNam in module dx
  558. ; (es is preserved)
  559. je Sd3OmExit ;brif OM error (AX=0) to stop ForEach
  560. call Emit16_AX ; oVar in SS_PARSE or SS_EXECUTE
  561.   .errnz DCLP_atr - 2 ;Formal parm attributes (PATR_xxx)
  562. call GetWord ;ax = formal parm atr
  563. push ax ;save parmAtr
  564. .errnz PATR_asClause AND 0FFh
  565. test ah,PATR_asClause / 100h
  566. jne Sd3AsClause ;brif 'id AS xxx'
  567. .errnz PATR_explicit AND 0FFh
  568. or ah,PATR_explicit / 100h ;in DECLARE, force it to be explicit
  569. Sd3AsClause:
  570. call Emit16_AX
  571. ; if not SS_RUDE, it is oTyp of user type.
  572. .errnz DCLP_oTyp - 4 ;Type of the formal parm
  573. call GetWord ;ax = oNam for <user type> if > ET_MAX
  574. pop bx ;bx = parmAtr
  575. .errnz PATR_asClause AND 0FFh
  576. .errnz PATR_explicit AND 0FFh
  577. test bh,(PATR_explicit OR PATR_asClause) / 100h
  578. jne NotImpl ;brif not implicitly typed
  579. push [oNamParm]
  580. call OTypOfONamDefault ;ax = default oTyp for parm (ax)
  581. NotImpl:
  582. cmp ax,ET_MAX
  583. jbe NotUserTyp ;brif it is a primitive type
  584. ;Since declares are inserted before any type declarations, we cannot
  585. ;insert any references to a type name in the declare.  SOOO, we
  586. ;just always use as ANY for synthetic declares with user defined
  587. ;types.
  588. sub ax,ax ;ax = AS ANY
  589. NotUserTyp:
  590. call Emit16_AX
  591. jmp SHORT Sd3ParmLoop
  592. Sd3Exit:
  593. mov ax,sp ;return TRUE for ForEachCP
  594. Sd3OmExit:
  595. cEnd
  596. ;-------------------------------------------------------------
  597. ; SaveDeclares - main code
  598. ;-------------------------------------------------------------
  599. PUBLIC SaveDeclares ;for debugging only
  600. cProc SaveDeclares,<NEAR>,<si>
  601. cBegin
  602. DbAssertRelB [txdCur.TXD_scanState],e,SS_RUDE,CP,<SaveDeclares:TxdCur not in SS_RUDE>
  603. call PrsDeactivate ;make module's txt tbl active
  604. mov ax,[grs.GRS_oMrsCur]
  605. mov [oMrsSaveDecl],ax
  606. test [mrsCur.MRS_flags2],FM2_Include ;is this an include mrs?
  607. jne SdGoodExit ;don't insert decls into include
  608. ;mrs's.  Re-Including could break
  609. ;a previously running program.
  610. ;For each prs in system which has a text table:
  611. mov al,FE_PcodeMrs+FE_PcodePrs+FE_SaveRs
  612. mov bx,CPOFFSET SdPass1 ;bx = adr of function to call
  613. call ForEachCP
  614. ;For each text table in module being saved:
  615. mov al,FE_CallMrs+FE_PcodePrs+FE_SaveRs
  616. mov bx,CPOFFSET SdPass2 ;bx = adr of function to call
  617. call ForEachCP
  618. sub ax,ax
  619. mov [ps.PS_bdpDst.BDP_cbLogical],ax
  620. call SetDstPbCur
  621. ;For each prs in system which has a text table:
  622. mov al,FE_PcodeMrs+FE_PcodePrs+FE_SaveRs
  623. mov bx,CPOFFSET SdPass3 ;bx = adr of function to call
  624. call ForEachCP
  625. je SdExit ;brif out-of-memory
  626. SetStartOtx si ;insert DECLAREs at start of module
  627. call TxtInsert
  628. je SdExit ;brif out-of-memory
  629. SetStartOtx si ;otxInsert = start of text
  630. mov bx,[ps.PS_bdpDst.BDP_cbLogical] ;pass cbInserted in bx
  631. or bx,bx ;was any pcode inserted?
  632. je NoDeclaresInserted ;brif not
  633. or [mrsCur.MRS_flags2],FM2_Modified ;set modified bit so compiler
  634. ;will compile same source as QBI for
  635. ;MakeExe.
  636. push bx ;save cbInsert
  637. call DrawDebugScrFar ;update list windows for inserted text
  638. pop bx ;restore bx=cbInsert
  639. NoDeclaresInserted:
  640. call TxtInsUpdate
  641. SdGoodExit:
  642. mov ax,sp ;return non-zero (not out-of-memory)
  643. SdExit:
  644. or ax,ax ;set condition codes
  645. cEnd
  646. ;*************************************************************
  647. ; SaveAllDeclares
  648. ; Purpose:
  649. ; Generate synthetic DECLARE stmts for forward referenced
  650. ; SUBs and FUNCTIONs for every module in the system.
  651. ; Called by UI before MakeExe to ensure that Compiler
  652. ; will compile same source as interpreter.  This solves
  653. ; the situation for a QB2/3 program is loaded and works
  654. ; correctly for QBI, but will not compile in BC. If we
  655. ; have inserted synthetic declares, or altered the pcode
  656. ; in some way, we need to make sure that the dirty bit
  657. ; gets set for the module.
  658. ; Entry:
  659. ; none.
  660. ; Exit:
  661. ; grs.fDirect = FALSE
  662. ; ax = 0 for no error, else QBI standard error code.
  663. ;*************************************************************
  664. cProc SaveAllDeclares,<PUBLIC,FAR>
  665. cBegin
  666. ;For each mrs in system which has a pcode text table:
  667. mov al,FE_PcodeMrs+FE_CallMrs+FE_SaveRs
  668. mov bx,CPOFFSET SaveDeclares ;bx = adr of function to call
  669. call ForEachCP
  670. mov ax,ER_OM ;default Out of memory error
  671. je SaveAllDeclaresExit ;brif out-of-memory
  672. sub ax,ax
  673. SaveAllDeclaresExit:
  674. cEnd
  675. ;*************************************************************
  676. ; ushort AsciiSave()
  677. ; Purpose:
  678. ; ASCII save the current module (with all its procedures)
  679. ;
  680. ; Exit:
  681. ; grs.fDirect = FALSE
  682. ; ps.bdpSrc is used
  683. ; ax = 0 if no error, else Standard BASIC error code (i.e. ER_xxx)
  684. ;
  685. ; Exceptions:
  686. ; Can cause runtime error (Out of memory, I/O errors)
  687. ;
  688. ;*************************************************************
  689. cProc AsciiSave,<NEAR>,<si>
  690. cBegin
  691. call AlphaBuildORs ; build sorted list of all oRs's
  692. or ax,ax ;set flags based on returned value
  693. mov ax,ER_OM ;prepare to return Out-of-memory error
  694. je AsDone ;brif error
  695. call PrsDeactivate ;make module's txt table active
  696. sub ax,ax
  697. mov [fLsDynArrays],al ;default state is $STATIC
  698. DbAssertRel ax,e,0,CP,<AsciiSave: ax!=0> ;SaveTxdCur needs ax=0
  699. ;ax = otx of 1st line in current text table to be written to file
  700. AsLoop:
  701. call SaveTxdCur ;save module/procedure text table
  702. test [mrsCur.MRS_flags2],FM2_NoPcode ; document file?
  703. jne NotModuleText ; brif so, never add blank line
  704. cmp ax,2 ;was last line a blank one?
  705. jbe NotModuleText ;brif so
  706. call OutCrLf  ;output a blank line so comment blocks
  707. ;are associated with correct text tbls
  708. NotModuleText:
  709. call OtxDefTypeEot ;fill ps.tEtCur with default types
  710. ; at end of module/procedure
  711. call NextAlphaPrs ;activate next procedure in module
  712. or ax,ax ;set flags
  713. je AsDone ;brif no more procedures in module
  714. SetStartOtx ax
  715. test [prsCur.PRS_flags],FP_DEFINED
  716. je ProcNotDefined ;brif no SUB/FUNCTION stmt
  717. push [prsCur.PRS_otxDef] ;push offset to opStSub/opStFunction
  718. call OtxBolOfOtx ;ax = text offset for 1st line of SUB
  719. ProcNotDefined:
  720. mov si,ax ;si = ax = otxProcDef
  721. call SaveProcHdr ;save proc hdr(ax) (may contain some
  722. ; synthetically generated statements
  723. jne AsDone ;brif error
  724. xchg ax,si ;ax = otxProcDef
  725. jmp SHORT AsLoop
  726. ;al = 0 if no error, else standard QBI error code
  727. AsDone:
  728. cEnd ;AsciiSave
  729. ;****************************************************************************
  730. ;SaveModName - save the name of the current module to the file
  731. ;
  732. ;Purpose:
  733. ; Used by Save to save the name of each module in a .MAK file.
  734. ;Entry:
  735. ; The .MAK file is open to current channel
  736. ; si points to static buffer holding name of the MAK file's directory.
  737. ; di points to static buffer which can be used to hold module's name
  738. ;Exceptions:
  739. ; Assumes caller called RtSetTrap to trap runtime errors.
  740. ;
  741. ;****************************************************************************
  742. SaveModName PROC NEAR
  743. mov ax,di ; pDest (parm to CopyOgNamPbNear)
  744. mov bx,[mrsCur.MRS_ogNam] ; ogNam (parm to CopyOgNamPbNear)
  745. call CopyOgNamPbNear ; copies name to buffer, returns 
  746. ;   ax = cbName
  747. mov bx,di
  748. add bx,ax ; add cbName
  749. mov BYTE PTR [bx],0 ; zero terminate
  750. ;MakeRelativeFileSpec(szFilename, szMakDirectory)
  751. cCall MakeRelativeFileSpec,<di,si> ;convert szFilename to relative
  752. ; path from szMakDirectory if possible
  753. cCall CbSz,<di> ;ax = length of result path
  754. ;ax = size of line to output
  755. mov bx,di ;bx points to start of line to output
  756. call OutLine ;output the line
  757. ret
  758. SaveModName ENDP
  759. ;****************************************************************************
  760. ; FNotMainModule
  761. ; Purpose:
  762. ; Called via ForEachCP to see if there is any pcode module
  763. ; that is not the main module (i.e. to see if this is a
  764. ; multiple-module program.
  765. ; Exit:
  766. ; Return 0 in ax if current module is not main-module
  767. ; else return non-zero in ax
  768. ;
  769. ;****************************************************************************
  770. FNotMainModule PROC NEAR
  771. mov ax,[grs.GRS_oMrsCur]
  772. cmp ax,[grs.GRS_oMrsMain]
  773. mov ax,sp ;prepare to return non-zero
  774. je FNotMainExit
  775. sub ax,ax ;return 0 (not main module)
  776. FNotMainExit:
  777. ret
  778. FNotMainModule ENDP
  779. ;*************************************************************
  780. ; SaveMakFile
  781. ; Purpose:
  782. ; Called by SaveFile to see if we're saving the main module
  783. ; of a multi-module program.  If so, this creates <filename>.MAK
  784. ; file and writes the names of all modules in the program.
  785. ; Entry:
  786. ; mrsCur.ogNam is current module's filename
  787. ; Exit:
  788. ; ax = error code (0 if none), condition codes set
  789. ; Exceptions:
  790. ; assumes caller has called SetRtTrap to trap runtime errors
  791. ;
  792. ;*************************************************************
  793. cProc SaveMakFile,<NEAR>,<si,di>
  794. localV szDir,FILNAML
  795. localV filenameNew,FILNAML ; size expected by runtime routines
  796. ; used for filename normalization
  797. localV sdFilenameNew,<SIZE SD>
  798. cBegin
  799. mov ax,[grs.GRS_oMrsMain]
  800. cmp ax,[grs.GRS_oMrsCur]
  801. jne SmfGood ;brif this isn't main module
  802. mov bx,si ;bx = psdFilename
  803. lea si,[sdFilenameNew] ;si = &sdFilenameNew
  804. lea di,[filenameNew]
  805. mov [si.SD_pb],di ; set up string descr.
  806. call MakFilename ;fill di with <moduleName>.MAK
  807. jne SmfExit  ;brif Bad File Name
  808. mov al,FE_PcodeMrs+FE_CallMrs+FE_SaveRs
  809. mov bx,CPOFFSET FNotMainModule ;bx = adr of function to call
  810. call ForEachCP ;ax=0 if multi-module program
  811. je MultiModules ;brif multi-module program is loaded
  812. push di ;pass ptr to szFilenameNew
  813. call DelFile ;delete filename.MAK
  814. jmp SHORT SmfGood ;exit if not multi-module program
  815. ;Open filename in sdFilename (si) (.MAK file) and write all module names to it
  816. MultiModules:
  817. ;If we could assume DOS 3.0 or greater, (we can't yet) we could set
  818. ;dx to (ACCESS_WRITE OR LOCK_BOTH) SHL 8 OR MD_SQO
  819. mov dx,MD_SQO
  820. call OpenChan ;al = error code (0 if no error)
  821. jne SmfExit ;brif errors
  822. ;fill si with sz for directory of .MAK file
  823. lea si,szDir ;si points to working static buffer
  824. push di ;pass pbSrc (filenameNew)
  825. push si ;pass pbDst (szDir)
  826. mov bx,[sdFilenameNew.SD_cb]
  827. push bx ;pass byte count
  828. mov BYTE PTR [bx+si],0 ;0-terminate destination
  829. call CopyBlk ;copy module name to static buffer
  830. push si ;pass szDir
  831. call FileSpec ;ax points beyond pathname
  832. xchg bx,ax ;bx points beyond pathname
  833. mov BYTE PTR [bx-1],0 ;0-terminate szDir
  834. ;Save the name of the Main Module first, so it will be loaded first
  835. ;si points to szDir
  836. ;di points to filenameNew (will be used for temp buffer)
  837. call SaveModName ;write main module's relative path
  838. call MrsDeactivate ;start writing other module names
  839. SmLoop:
  840. call NextMrsFile_All  ;make next mrs active
  841. inc ax ;test for UNDEFINED (end of mrs list)
  842. je SmDone ;brif done with all mrs's
  843. dec ax ;restore ax = module's name
  844. cmp ax,[grs.GRS_oMrsMain]
  845. je SmLoop ;brif this is MAIN mod (already output)
  846. test [mrsCur.MRS_flags2],FM2_NoPcode OR FM2_Include
  847. jne SmLoop ;skip document and include mrs's
  848. call SaveModName
  849. jmp SHORT SmLoop
  850. SmDone:
  851. push [grs.GRS_oMrsMain] ;we know the main module was active
  852. call MrsActivateCP ; on entry - reactivate it on exit
  853. call CloseChan ;close [chanCur]
  854. SmfGood:
  855. sub ax,ax
  856. SmfExit:
  857. or ax,ax ;set condition codes for caller
  858. cEnd
  859. ;*************************************************************
  860. ; ushort SaveFile()
  861. ; Purpose:
  862. ; Open the specified file and save program to it.
  863. ;
  864. ; Entry:
  865. ; mrsCur.ogNam = filename to be saved.
  866. ;    (the filename need not be 0-byte terminated)
  867. ; mrsCur.flags2 FM2_AsciiLoaded is TRUE for ASCII Save
  868. ; FOR EB: parm1 = mode for opening file
  869. ;
  870. ; Exit:
  871. ; ps.bdpSrc is used
  872. ; grs.fDirect = FALSE
  873. ; ax = 0 if no error, else Standard BASIC error code (i.e. ER_xxx)
  874. ;
  875. ;*************************************************************
  876. cProc SaveFile,<PUBLIC,FAR,NODATA>,<si>
  877. localV FileName,FILNAML
  878. localV sdFileName,<SIZE SD>
  879. cBegin
  880. mov ax,-MSG_Saving ;display Saving msg in intense video
  881. call StatusMsgCP ; to tell user we're loading
  882. call AlphaORsFree ;release table of sorted oRs's
  883. ; (user interface may have chosen
  884. ;  a new name for this mrs)
  885. push [grs.GRS_oRsCur] ;save mrs/prs - restored on exit
  886. call RtPushHandler ;save caller's runtime error handler
  887. ; could be called by LoadFile->NewStmt
  888. ; (NOTE: alters stack pointer)
  889. SetfDirect al,FALSE ;turn off direct mode
  890. mov ax,CPOFFSET SfDone ;if any runtime errors occur,
  891. call RtSetTrap ;branch to SfDone with sp,di =
  892. ;current values
  893. ; doesn't have to be recompiled
  894. call ModuleRudeEdit
  895. call SaveDeclares ;generate synthetic DECLARE stmts
  896. ; for forward-referenced
  897. mov ax,ER_OM ;default to OM error
  898. je SfDone ;brif error
  899. lea si,[sdFileName] ;cant use buffers here used for
  900. lea ax,[FileName]   ;load because we may need to save
  901. mov [si.SD_pb],ax ;current module during fileopen
  902. mov bx,[mrsCur.MRS_ogNam]
  903. call CopyOgNamPbNear ; ax = number of chars copied
  904. mov [si.SD_cb],ax
  905. call SaveMakFile ;create <filename>.MAK if main
  906. ; program of multi-module program.
  907. jne SfDone ;brif errors
  908. ;If we could assume DOS 3.0 or greater, (we can't yet) we could set
  909. ;dx to (ACCESS_WRITE OR LOCK_BOTH) SHL 8 OR MD_SQO
  910. mov dx,MD_SQO
  911. call OpenChan ;[chanCur] = channel #
  912. jne SfDone ;brif error
  913. DoAsciiSave:
  914. call AsciiSave ;al = errCode
  915. ;We're done trying to write the file, now try to close it.
  916. ;Closing the file can cause I/O errors when close flushes the buffer.
  917. ;al = 0 if no error, else standard QBI error code
  918. SfDone:
  919. sub ah,ah ;ax = error code
  920. SfDone2:
  921. xchg si,ax ;si = return value
  922. test [flagsTM],FTM_SaveProcHdr
  923. je NoShCleanup ;brif SaveProcHdr was not in critical
  924. ; section.
  925. call RelShBuf ;release temp text tbl used by
  926. ; SaveProcHdr
  927. NoShCleanup:
  928. call RtFreeTrap ;free previous trap address
  929. mov ax,CPOFFSET SfGotErr ;if any runtime errors occur,
  930. call RtSetTrap ;branch to SfGotErr with sp,bp,si,di
  931. ;set to current values
  932. call CloseChan ;close file before kill
  933. ; (sets ChanCur = 0)
  934. cCall RtFreeTrap ; release error handler
  935. test si,7FFFh ; test low 15 bits for error code
  936. je SfNoErr ;brif no error before close
  937. xor ax, ax ; no error during close
  938. ;If we got an error during save, delete partially created file
  939. SfGotErr:
  940. test si, 7fffh ; do we already have an error
  941. jnz SfTestDelFile ; brif so, use it
  942. or si, ax ; else add in new error
  943. ; Only delete the file if we actually created and started to save
  944. ; a binary file. We don't want to delete an existing file if we
  945. ; got an error on or before the open, and we also don't want to
  946. ; delete a partially written ascii file.
  947. SfTestDelFile:
  948. or si,si ; got to BinarySave?
  949. jns SfExit ; no, then don't kill the file
  950. push di
  951. mov ax,CPOFFSET SfKillErr ; trap & ignore any runtime errors
  952. cCall RtSetTrap ; in KILL 
  953. sub sp,((FILNAML+SIZE SD+2)+1) AND 0FFFEh ;[3] create a fake sd
  954.       ;    on the stack
  955. mov di,sp
  956. add di,6 ; pnt to strt of where string will be
  957. mov [di-2],di ; setup pb part of fake sd
  958. mov ax,di ; parm to CopyOgNamPbNear
  959. mov bx,[mrsCur.MRS_ogNam] ; parm to CopyOgNamPbNear
  960. call CopyOgNamPbNear ; copy name onto stack, ax = cbName
  961. sub di,4 ; di = pFakeSd
  962. mov [di],ax ; set up cb part of fake sd
  963. cCall B$KILL,<di> ; call rt to delete file
  964. add sp,((FILNAML+SIZE SD+2)+1) AND 0FFFEh ;[3] restore stack ptr
  965. SfKillErr: ; branched to if error during KILL
  966. pop di
  967. jmp SHORT SfExit
  968. SfNoErr:
  969. and [mrsCur.MRS_flags2],NOT (FM2_Modified or FM2_ReInclude) 
  970. and [mrsCur.MRS_flags3],NOT FM3_NotFound ;If the user told
  971. ;us to save the file, we have
  972. ;found it.
  973. test [mrsCur.MRS_flags2],FM2_Include
  974. je SfExit ;brif this is not an $INCLUDE file
  975. or [flagsTm],FTM_reInclude ;re-parse all $INCLUDE lines in
  976. ;all modules before next RUN
  977. SfExit:
  978. and [flagsTM],NOT FTM_SaveProcHdr ;reset critical section flag
  979. call RtPopHandler ;restore caller's runtime error handler
  980. ; (saved on stack by RtPushHandler)
  981. call RsActivateCP ;restore caller's mrs/prs
  982. call StatusMsg0CP ;tell user interface we're done saving
  983. xchg ax,si ;restore ax = error code
  984. and ah,7Fh ; clear BinarySave flag bit
  985. cEnd
  986. sEnd CP
  987. end