home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wunderki.zip / TCTL.ASM < prev    next >
Assembly Source File  |  1993-08-16  |  29KB  |  535 lines

  1. ;//////////////////////////////////////////////////////
  2. ;/                                                    /
  3. ;/ Run-time Library für Borland Pascal 7.0 unter OS/2 /
  4. ;/ Routinen für Text-Dateien.                         /
  5. ;/                                                    /
  6. ;/ 1993 Matthias Withopf / c't                        /
  7. ;/ Originalversion (c) 1988,92 Borland International  /
  8. ;/                                                    /
  9. ;//////////////////////////////////////////////////////
  10.  
  11.                 .286p                                         
  12.  
  13.                 _NOMACROS_ = 1                  ; keine Macros definieren
  14.                 INCLUDE SE.ASM
  15.                 INCLUDE OS2.ASM
  16.  
  17. DATA            SEGMENT WORD PUBLIC
  18.                 EXTRN   FileMode:WORD,InOutRes:WORD
  19. DATA            ENDS
  20.  
  21. CODE            SEGMENT BYTE PUBLIC
  22.                 ASSUME  CS:CODE,DS:DATA
  23.  
  24.                 EXTRN   ConvErrCode:NEAR
  25.  
  26.                 ;
  27.                 ; Assign(Var f;Name : PChar);
  28.                 ;
  29.  
  30.                 PUBLIC  AssignTextC
  31. AssignTextC     PROC    PASCAL FAR
  32.                 MOV     DL,1                    ; setze Flag für PChar-Argument
  33.                 JMP     SHORT Assign
  34. AssignTextC     ENDP
  35.  
  36.                 ;        
  37.                 ; Assign(Var f;Name : String);
  38.                 ;
  39.  
  40.                 PUBLIC  AssignText
  41. AssignText      PROC    PASCAL FAR
  42.                 XOR     DX,DX                   ; lösche Flag für PChar-Argument
  43. AssignText      ENDP
  44.  
  45.                 ;
  46.                 ; Allgemeine Assign-Prozedur.
  47.                 ;
  48.  
  49. Assign          PROC    PASCAL FAR 
  50.                 ARG     A_File : DWORD,  \
  51.                         A_Name : DWORD
  52.                 PUSH    DS                      ; rette Datensegment
  53.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  54.                 LDS     SI,A_Name               ; lese Zeiger auf Namen
  55.                 MOV     ES:[DI].fHandle,0       ; markiere Handle als ungültig
  56.                 MOV     ES:[DI].fMode,fmClosed  ; Datei ist geschlossen
  57.                 MOV     ES:[DI].fBufSize,128    ; setze Standardgröße des Buffers
  58.                 MOV     ES:[DI].fPrivate,0      ; init. private Daten
  59.                 MOV     ES:[DI].fBufPos,0       ; lösche den
  60.                 MOV     ES:[DI].fBufEnd,0       ; Datei-Buffer
  61.                 LEA     AX,[DI].fBuffer         ; initialisiere Zeiger
  62.                 MOV     ES:[DI].fBufPtr.offs,AX ; auf Buffer innerhalb
  63.                 MOV     ES:[DI].fBufPtr.segm,ES ; TextRec
  64.                 MOV     ES:[DI].fOpenProc.offs,OFFSET FileOpen ; definiere die
  65.                 MOV     ES:[DI].fOpenProc.segm,CS              ; Open-Funktion
  66.                 XOR     AX,AX                   ; lösche die 
  67.                 MOV     CX,(fName-fInOutProc)/2 ; restlichen 
  68.                 ADD     DI,fInOutProc           ; Funktionszeiger
  69.                 CLD                             ; und
  70.                 REP     STOSW                   ; UserData
  71.                 MOV     CX,79                   ; lese max. Länge des Dateinamens
  72.                 OR      DX,DX                   ; ist es PChar-Routine ?
  73.                 JNE     @@CopyNameLoop          ; ja -> weiter
  74.                 LODSB                           ; lese Längenbyte des Namens
  75.                 CMP     CL,AL                   ; ist max. Länge überschritten ?
  76.                 JBE     @@CopyNameLoop          ; nein -> ok, weiter
  77.                 MOV     CL,AL                   ; schneide Namen ab
  78.                 JCXZ    @@CopyNameEnd           ; falls Namen Leerstring -> weiter
  79. @@CopyNameLoop: LODSB                           ; lese Zeichen aus angegebenem Dateinamen
  80.                 OR      AL,AL                   ; Ende erreicht (bei PChar-Routine) ?
  81.                 JE      @@CopyNameEnd           ; ja -> Kopieren des Namens beenden
  82.                 STOSB                           ; speichere Zeichen in TextRec
  83.                 LOOP    @@CopyNameLoop          ; gesamten Namen kopieren
  84. @@CopyNameEnd:  XOR     AL,AL                   ; schließe Namen in TextRec
  85.                 STOSB                           ; mit Nullbyte ab
  86.                 POP     DS                      ; stelle Datensegment wieder her
  87.                 RET     
  88. Assign          ENDP
  89.  
  90.                 ;        
  91.                 ; Procedure SetTextBuf(var F : Text;Var Buf;Size : Word);
  92.                 ;
  93.  
  94.                 PUBLIC  BufferText
  95. BufferText      PROC    PASCAL FAR
  96.                 ARG     A_File : DWORD,    \
  97.                         A_Buf  : DWORD,    \
  98.                         A_Size : WORD
  99.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  100.                 MOV     AX,A_Size               ; setze neue 
  101.                 MOV     ES:[DI].fBufSize,AX     ; Buffer-Größe
  102.                 MOV     AX,A_Buf.offs           ; setze
  103.                 MOV     ES:[DI].fBufPtr.offs,AX ; neuen
  104.                 MOV     AX,A_Buf.segm           ; Zeiger
  105.                 MOV     ES:[DI].fBufPtr.segm,AX ; auf Buffer
  106.                 XOR     AX,AX                   ; lösche
  107.                 MOV     ES:[DI].fBufPos,AX      ; den
  108.                 MOV     ES:[DI].fBufEnd,AX      ; Datei-Buffer
  109.                 RET     
  110. BufferText      ENDP
  111.  
  112.                 ;        
  113.                 ; Procedure Reset(Var f : Text);
  114.                 ;
  115.  
  116.                 PUBLIC  ResetText
  117. ResetText       PROC    PASCAL FAR
  118.                 MOV     DX,fmInput              ; lese Dateimodus für Eingabe
  119.                 JMP     SHORT OpenText
  120. ResetText       ENDP
  121.  
  122.                 ;
  123.                 ; Procedure Rewrite(Var f : Text);
  124.                 ;
  125.  
  126.                 PUBLIC  RewriteText
  127. RewriteText     PROC    PASCAL FAR   
  128.                 MOV     DX,fmOutput             ; lese Dateimodus für Ausgabe
  129.                 JMP     SHORT OpenText
  130. RewriteText     ENDP
  131.  
  132.                 ;
  133.                 ; Procedure Append(Var f : Text);
  134.                 ;
  135.  
  136.                 PUBLIC  AppendText
  137. AppendText      PROC    PASCAL FAR
  138.                 MOV     DX,fmInOut              ; lese Dateimodus für wahlfreien Zugriff
  139. AppendText      ENDP
  140.  
  141.                 ;
  142.                 ; Öffne Datei oder lege Datei neu an.
  143.                 ; In DX wird der Dateimodus übergeben.
  144.                 ;
  145.  
  146.                 PUBLIC  OpenText
  147. OpenText        PROC    PASCAL FAR
  148.                 ARG     A_File : DWORD
  149.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  150.                 MOV     AX,ES:[DI].fMode        ; lese aktuellen Modus der Datei
  151.                 CMP     AX,fmInput              ; ist die Datei zum Lesen geöffnet ?
  152.                 JE      @@CloseFirst            ; ja -> zuerst schließen
  153.                 CMP     AX,fmOutput             ; ist die Datei zum Schreiben geöffnet ?
  154.                 JE      @@CloseFirst            ; ja -> zuerst schließen
  155.                 CMP     AX,fmClosed             ; ist die Datei geschlossen ?
  156.                 JE      @@Open                  ; ja -> ok, öffnen
  157.                 MOV     InOutRes,102            ; sonst Fehler: 'File not assigned'
  158.                 JMP     SHORT @@End             ; -> Ende
  159.  
  160. @@CloseFirst:   PUSH    DX                      ; rette neuen Dateimodus
  161.                 PUSH    ES                      ; übergebe den Zeiger
  162.                 PUSH    DI                      ; auf TextRec
  163.                 PUSH    CS                      ; schließe die Datei,
  164.                 CALL    NEAR PTR CloseText      ; bevor sie neu geöffnet wird
  165.                 POP     DX                      ; hole neuen Dateimodus zurück
  166. @@Open:         MOV     ES:[DI].fMode,DX        ; speichere neuen Dateimodus
  167.                 XOR     AX,AX                   ; lösche den
  168.                 MOV     ES:[DI].fBufPos,AX      ; Buffer
  169.                 MOV     ES:[DI].fBufEnd,AX      ; der Textdatei
  170.                 MOV     BX,fOpenProc            ; rufe Funktion 
  171.                 CALL    DoFunction              ; zum Öffnen auf
  172.                 JE      @@End                   ; falls kein Fehler -> ok, weiter
  173.                 MOV     ES:[DI].fMode,fmClosed  ; bei Fehler: setze Dateimodus auf geschlossen
  174. @@End:          RET     
  175. OpenText        ENDP
  176.  
  177.                 ;
  178.                 ; Procedure Flush(Var f : Text);
  179.                 ;
  180.  
  181.                 PUBLIC  FlushText
  182. FlushText       PROC    PASCAL FAR
  183.                 XOR     AL,AL                   ; lösche Flag für "Schließen"
  184.                 JMP     SHORT FlushClose
  185. FlushText       ENDP
  186.  
  187.                 ;        
  188.                 ; Procedure Close(Var f);
  189.                 ;
  190.  
  191.                 PUBLIC  CloseText
  192. CloseText       PROC    PASCAL FAR
  193.                 MOV     AL,1                    ; setze Flag für "Schließen"
  194. CloseText       ENDP
  195.  
  196.                 ;
  197.                 ; Flush/Close. 
  198.                 ;
  199.  
  200.                 PUBLIC  FlushClose
  201. FlushClose      PROC    PASCAL FAR
  202.                 ARG     A_File : DWORD
  203.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  204.                 CMP     ES:[DI].fMode,fmInput   ; ist Datei als Eingabe geöffnet ?
  205.                 JE      @@DontFlush             ; ja -> kein Flush nötig
  206.                 CMP     ES:[DI].fMode,fmOutput  ; ist Datei als Ausgabe geöffnet ?
  207.                 JE      @@DoFlush               ; ja -> Flush
  208.                 MOV     InOutRes,103            ; sonst Fehler: 'File not open'
  209.                 JMP     SHORT @@DontClose       ; -> Ende
  210.  
  211. @@DoFlush:      PUSH    AX                      ; rette Flag für "Schließen"
  212.                 MOV     BX,fInOutProc           ; gebe den restlichen
  213.                 CALL    DoFunction              ; Buffer-Inhalt aus
  214.                 POP     AX                      ; hole Flag für "Schließen" zurück
  215. @@DontFlush:    OR      AL,AL                   ; ist Flag für "Schließen" gesetzt ?
  216.                 JE      @@DontClose             ; nein -> weiter, nicht schließen
  217.                 MOV     BX,fCloseProc           ; schließe
  218.                 CALL    DoFunction              ; die Datei
  219.                 MOV     ES:[DI].fMode,fmClosed  ; setze Dateimodus auf 'geschlossen'
  220. @@DontClose:    RET     
  221. FlushClose      ENDP
  222.  
  223.                 ;
  224.                 ; Führe eine Funktion eines Textdatei-Gerätetreibers
  225.                 ; aus. Der Offset der Funktion innerhalb des 
  226.                 ; TextRecs wird in BX übergeben.
  227.                 ;
  228.  
  229. DoFunction      PROC    NEAR
  230.                 PUSH    ES                      ; rette Zeiger
  231.                 PUSH    DI                      ; auf TextRec
  232.                 PUSH    ES                      ; übergebe den Zeiger
  233.                 PUSH    DI                      ; auf TextRec als Argument
  234.                 CALL    DWORD PTR ES:[DI+BX]    ; rufe die gewünschte Funktion auf
  235.                 OR      AX,AX                   ; ist Fehler aufgetreten ?
  236.                 JE      @@NoErr                 ; nein -> weiter
  237.                 MOV     InOutRes,AX             ; speichere Fehlercode
  238. @@NoErr:        POP     DI                      ; hole Zeiger
  239.                 POP     ES                      ; auf TextRec zurück
  240.                 RET
  241. DoFunction      ENDP
  242.  
  243.                 ;        
  244.                 ; Read-Funktion des Standard-Text-Gerätetreibers.
  245.                 ;
  246.  
  247.                 PUBLIC  FileRead
  248. FileRead        PROC    PASCAL FAR
  249.                 ARG     A_File    : DWORD
  250.                 LOCAL   L_ReadCnt : WORD
  251.                 PUSH    DS                      ; rette Datensegment
  252.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  253.                 PUSH    ES:[DI].fHandle         ; übergebe FileHandle
  254.                 LDS     BX,ES:[DI].fBufPtr      ; übergebe Zeiger
  255.                 PUSH    DS                      ; auf den
  256.                 PUSH    BX                      ; Datei-Buffer
  257.                 PUSH    ES:[DI].fBufSize        ; übergebe Buffer-Größe
  258.                 LEA     BX,L_ReadCnt            ; übergebe Zeiger auf Word,
  259.                 PUSH    SS                      ; in dem die tatsächliche Anzahl
  260.                 PUSH    BX                      ; gelesener Bytes gespeichert wird
  261.                 CALL    DosRead                 ; lese Block aus Datei
  262.                 OR      AX,AX                   ; ist Fehler beim Lesen aufgetreten ?
  263.                 JNZ     @@Error                 ; ja -> Fehler
  264.                 MOV     AX,L_ReadCnt            ; lese Anzahl gelesener Bytes
  265.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  266.                 MOV     ES:[DI].fBufEnd,AX      ; speichere neues Buffer-Ende
  267.                 XOR     AX,AX                   ; lösche Fehlercode
  268. @@End:          MOV     ES:[DI].fBufPos,0       ; setze Position des Zeigers auf Datei-Buffers zurück
  269.                 POP     DS                      ; hole Datensegment zurück
  270.                 RET     
  271.  
  272. @@Error:        MOV     ES:[DI].fBufEnd,0       ; lösche den Datei-Buffer
  273.                 CALL    ConvErrCode             ; konvertiere Fehlercode nach OS/2-Code
  274.                 JMP     SHORT @@End             ; -> Ende
  275. FileRead        ENDP
  276.  
  277.                 ;
  278.                 ; Write-Funktion des Standard-Text-Gerätetreibers.
  279.                 ;
  280.  
  281.                 PUBLIC  FileWrite
  282. FileWrite       PROC    PASCAL FAR
  283.                 ARG     A_File     : DWORD
  284.                 LOCAL   L_WriteCnt : WORD
  285.                 PUSH    DS                      ; rette Datensegment
  286.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  287.                 PUSH    ES:[DI].fHandle         ; übergebe FileHandle
  288.                 LDS     BX,ES:[DI].fBufPtr      ; übergebe 
  289.                 PUSH    DS                      ; Zeiger auf
  290.                 PUSH    BX                      ; den Datei-Buffer
  291.                 XOR     CX,CX                   ; übergebe aktuelle
  292.                 XCHG    CX,ES:[DI].fBufPos      ; Größe des Datei-Buffers
  293.                 PUSH    CX                      ; und setze sie zurück
  294.                 LEA     BX,L_WriteCnt           ; übergebe Zeiger auf Word,
  295.                 PUSH    SS                      ; in dem die tatsächliche Anzahl
  296.                 PUSH    BX                      ; geschriebener Bytes gespeichert wird
  297.                 CALL    DosWrite                ; schreibe Block in Datei
  298.                 CALL    ConvErrCode             ; konvertiere Fehlercode nach OS/2-Code
  299.                 OR      AX,AX                   ; ist Fehler aufgetreten ?
  300.                 JNZ     @@Exit                  ; ja -> Ende
  301.                 MOV     AX,L_WriteCnt           ; lese Anzahl geschriebener Bytes
  302.                 SUB     AX,CX                   ; konnten alle Bytes geschrieben werden ?
  303.                 JE      @@Exit                  ; ja -> ok, weiter
  304.                 MOV     AX,101                  ; sonst Fehler: 'Disk write error'
  305. @@Exit:         POP     DS                      ; hole Datensegment zurück
  306.                 RET     
  307. FileWrite       ENDP
  308.  
  309.                 ;
  310.                 ; Write-Funktion des Standard-Text-Gerätetreibers
  311.                 ; für Device-Dateien.
  312.                 ;
  313.  
  314.                 PUBLIC  FileWrDev
  315. FileWrDev       PROC    PASCAL FAR
  316.                 ARG     A_File     : DWORD
  317.                 LOCAL   L_WriteCnt : WORD
  318.                 PUSH    DS                      ; rette Datensegment
  319.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  320.                 PUSH    ES:[DI].fHandle         ; übergebe FileHandle
  321.                 LDS     BX,ES:[DI].fBufPtr      ; übergebe 
  322.                 PUSH    DS                      ; Zeiger auf
  323.                 PUSH    BX                      ; den Datei-Buffer
  324.                 XOR     CX,CX                   ; übergebe aktuelle
  325.                 XCHG    CX,ES:[DI].fBufPos      ; Größe des Datei-Buffers
  326.                 PUSH    CX                      ; und setze sie zurück
  327.                 LEA     BX,L_WriteCnt           ; übergebe Zeiger auf Word,
  328.                 PUSH    SS                      ; in dem die tatsächliche Anzahl
  329.                 PUSH    BX                      ; geschriebener Bytes gespeichert wird
  330.                 CALL    DosWrite                ; sende Block an Device
  331.                 CALL    ConvErrCode             ; konvertiere Fehlercode nach OS/2-Code
  332.                 POP     DS                      ; hole Datensegment zurück
  333.                 RET     
  334. FileWrDev       ENDP
  335.  
  336.                 ;
  337.                 ; Close-Funktion des Standard-Text-Gerätetreibers.
  338.                 ;
  339.  
  340.                 PUBLIC  FileClose
  341. FileClose       PROC    PASCAL FAR
  342.                 ARG     A_File : DWORD
  343.                 LES     DI,A_File               ; lese Zeiger auf TextRec
  344.                 MOV     BX,ES:[DI].fHandle      ; lese FileHandle
  345.                 XOR     AX,AX                   ; lösche Fehlercode
  346.                 CMP     BX,2                    ; ist es Handle für Standard-I/O ?
  347.                 JBE     @@Exit                  ; ja -> nicht schließen
  348.                 PUSH    BX                      ; übergebe FileHandle
  349.                 CALL    DosClose                ; schließe Datei
  350.                 CALL    ConvErrCode             ; konvertiere Fehlercode nach OS/2-Code
  351. @@Exit:         RET     
  352. FileClose       ENDP
  353.  
  354.                 ;
  355.                 ; Open-Funktion des Standard-Text-Gerätetreibers.
  356.                 ;
  357.  
  358. FileOpen        PROC    PASCAL FAR
  359.                 ARG     A_File       : DWORD
  360.                 LOCAL   L_Handle     : WORD,  \
  361.                         L_Action     : WORD,  \
  362.                         L_FileSize   : DWORD, \
  363.                         L_FilePtr    : DWORD, \
  364.                         L_Count      : WORD,  \
  365.                         L_HandleType : WORD,  \
  366.                         L_DevAttr    : WORD
  367.                 PUSH    DS                      ; rette Datensegment
  368.                 LDS     DI,A_File               ; lese Zeiger auf TextRec
  369.                 MOV     [DI].fHandle,0          ; Handle für Standardeingabe = 0
  370.                 MOV     AX,FILE_OPEN            ; lese Flags für 
  371.                 MOV     CX,OPEN_ACCESS_READONLY ; Reset()
  372.                 CMP     [DI].fMode,fmInput      ; wird Datei zum Lesen geöffnet ?
  373.                 JE      @@ModeOk                ; ja -> ok, weiter
  374.                 MOV     CX,OPEN_ACCESS_READWRITE; lese Flags für Append()
  375.                 INC     [DI].fHandle            ; Handle für Standardausgabe = 1
  376.                 CMP     [DI].fMode,fmInOut      ; wird Datei wahlfrei geöffnet ?
  377.                 JE      @@ModeOk                ; ja -> ok, weiter
  378.                 MOV     AX,FILE_CREATE OR FILE_OPEN; lese Flags für ReWrite()
  379. @@ModeOk:       CMP     [DI].fName,0            ; ist Standardein-/ausgabe gemeint ?
  380.                 JE      @@AlreadyOpen           ; ja -> Datei nicht öffnen
  381.                 LEA     DX,[DI].fName           ; lese Zeiger auf 
  382.                 PUSH    DS                      ; den Dateinamen
  383.                 PUSH    DX                      ; und übergebe ihn als Argument
  384.                 LEA     BX,L_Handle             ; übergebe Zeiger auf 
  385.                 PUSH    SS                      ; Speicherbereich, wo
  386.                 PUSH    BX                      ; DateiHandle abgelegt wird
  387.                 LEA     BX,L_Action             ; übergebe Zeiger auf 
  388.                 PUSH    SS                      ; Speicherbereich, wo
  389.                 PUSH    BX                      ; ausgeführte Aktion abgelegt wird
  390.                 XOR     BX,BX                   ; übergebe 
  391.                 PUSH    BX                      ; Größe
  392.                 PUSH    BX                      ; von 0
  393.                 PUSH    FILE_NORMAL             ; Flag für normale Datei
  394.                 PUSH    AX                      ; übergebe Open Flags
  395.                 OR      CX,FileMode             ; setze Share-Mode
  396.                 PUSH    CX                      ; übergebe Open Mode
  397.                 PUSH    BX                      ; übergebe 0L
  398.                 PUSH    BX                      ; (reserviert)
  399.                 CALL    DosOpen                 ; öffne Datei
  400.                 CALL    ConvErrCode             ; konvertiere Fehlercode nach OS/2-Code
  401.                 OR      AX,AX                   ; Fehler aufgetreten ?
  402.                 JNZ     @@OpenError             ; ja -> Ende
  403.                 MOV     AX,L_Handle             ; lese neues DateiHandle
  404.                 MOV     [DI].fHandle,AX         ; speichern in TextRec
  405. @@AlreadyOpen:  MOV     AX,OFFSET FileRead      ; lese Zeiger auf Read-Funktion
  406.                 MOV     DX,CS                   ; in DX:AX
  407.                 XOR     CX,CX                   ; keine Flush-Funktion
  408.                 XOR     BX,BX                   ; für Eingabedatei verfügbar
  409.                 CMP     [DI].fMode,fmInput      ; ist Dateimodus Eingabe ?
  410.                 JE      @@SetTextFuncs          ; ja -> weiter
  411.                 PUSH    [DI].fHandle            ; teste, ob Datei zu einem Device führt
  412.                 LEA     BX,L_HandleType         ; übergebe Zeiger auf Word,
  413.                 PUSH    SS                      ; in dem der Handle-Typ 
  414.                 PUSH    BX                      ; gespeichert wird
  415.                 LEA     BX,L_DevAttr            ; übergebe Zeiger auf Word,
  416.                 PUSH    SS                      ; in dem die Device-Attribute
  417.                 PUSH    BX                      ; gespeichert werden
  418.                 CALL    DosQHandType            ; erfrage Typ des FileHandles
  419.                 OR      AX,AX                   ; ist Fehler aufgetreten ?
  420.                 MOV     DX,0                    ; Datei ist kein Device
  421.                 JNZ     @@NoDevice              ; Fehler -> weiter
  422.                 MOV     AX,L_HandleType         ; lese Typ des FileHandles
  423.                 AND     AX,NOT HANDTYPE_NETWORK ; maskiere Network-Flag aus
  424.                 CMP     AL,HANDTYPE_DEVICE      ; ist es Device ?
  425.                 JNZ     @@NoDevice              ; ja -> weiter
  426.                 INC     DX                      ; setze Flag für "kein Device"
  427. @@NoDevice:
  428.                 OR      DX,DX                   ; ist es Device?
  429.                 MOV     AX,OFFSET FileWrDev     ; lese Zeiger auf Write-Funktion
  430.                 MOV     DX,CS                   ; für Devices in DX:AX
  431.                 MOV     CX,AX                   ; lese Zeiger auf Flush-Funktion
  432.                 MOV     BX,DX                   ; für Devices in BX:CX
  433.                 JNE     @@IsDevice              ; falls Device -> weiter
  434.                 CMP     [DI].fMode,fmInOut      ; ist es Datei mit wahlfreiem Zugriff ?
  435.                 JNE     @@NoAppend              ; nein -> weiter
  436.                 CALL    FileAppend              ; bereite Datei-Anfügung vor
  437. @@NoAppend:     MOV     AX,OFFSET FileWrite     ; lese Zeiger auf Write-Funktion
  438.                 MOV     DX,CS                   ; für Devices in DX:AX
  439.                 XOR     CX,CX                   ; keine Flush-Funktion
  440.                 XOR     BX,BX                   ; verfügbar
  441. @@IsDevice:     MOV     [DI].fMode,fmOutput     ; setze Dateimodus für Ausgabe
  442. @@SetTextFuncs: MOV     [DI].fInOutProc.offs,AX ; speichere Zeiger auf
  443.                 MOV     [DI].fInOutProc.segm,DX ; Ein-/Ausgabe-Funktion
  444.                 MOV     [DI].fFlushProc.offs,CX ; speichere Zeiger auf
  445.                 MOV     [DI].fFlushProc.segm,BX ; Flush-Funktion
  446.                 MOV     [DI].fCloseProc.offs,OFFSET FileClose ; speichere Zeiger
  447.                 MOV     [DI].fCloseProc.segm,CS ; auf Close-Funktion    
  448.                 XOR     AX,AX                   ; lösche Fehlercode            
  449. @@OpenError:    POP     DS
  450.                 RET     
  451.  
  452.                 ;
  453.                 ; Bereite Datei-Anfügung vor, indem der Datei-Zeiger an
  454.                 ; das Ende der Datei bewegt wird und der letzte 128-Byte-
  455.                 ; Block der Datei in den Date-Buffer eingelesen wird.
  456.                 ;
  457.  
  458. FileAppend      PROC    NEAR
  459.  
  460.                 ; Bestimme Länge der Datei.
  461.  
  462.                 PUSH    [DI].fHandle            ; bestimme aktuelle Position
  463.                 XOR     AX,AX                   ; übergebe 0
  464.                 PUSH    AX                      ; als
  465.                 PUSH    AX                      ; Positionsangabe
  466.                 PUSH    FILE_END                ; vom Dateiende aus
  467.                 LEA     BX,L_FileSize           ; lese Zeiger auf Word, in dem 
  468.                 PUSH    SS                      ; die Dateigröße
  469.                 PUSH    BX                      ; gespeichert wird
  470.                 CALL    DosChgFilePtr           ; erfrage Länge der Datei
  471.                 OR      AX,AX                   ; ist Fehler aufgetreten ?
  472.                 JNZ     @@GetSizeError          ; ja -> Dateilänge := 0
  473.                 MOV     AX,L_FileSize.offs      ; lese Länge
  474.                 MOV     DX,L_FileSize.segm      ; der Datei
  475.                 SUB     AX,128                  ; berechne Position 
  476.                 SBB     DX,0                    ; des letzten 128-Byte-Blocks
  477.                 JNC     @@Seek                  ; falls Datei nicht zu kurz -> weiter
  478. @@GetSizeError: XOR     AX,AX                   ; bei Fehler
  479.                 XOR     DX,DX                   ; -> Datelänge := 0
  480.  
  481.                 ; Bewege Datei-Zeiger auf 128 Bytes vor Dateiende.
  482.  
  483. @@Seek:         PUSH    [DI].fHandle            ; übergebe FileHandle
  484.                 PUSH    DX                      ; übergebe neue Position
  485.                 PUSH    AX                      ; des Datei-Zeigers (128 Bytes vor Dateiende)
  486.                 PUSH    FILE_BEGIN              ; vom Dateianfang aus
  487.                 LEA     BX,L_FilePtr            ; lese Zeiger auf Word, in dem 
  488.                 PUSH    SS                      ; die neue Position des
  489.                 PUSH    BX                      ; Datei-Zeigers gespeichert wird
  490.                 CALL    DosChgFilePtr           ; setze Datei-Zeiger
  491.  
  492.                 ; Lese die letzten 128 Byte aus der Datei.
  493.  
  494.                 PUSH    [DI].fHandle            ; übergebe FileHandle
  495.                 LEA     BX,[DI].fBuffer         ; übergebe Zeiger
  496.                 PUSH    SS                      ; auf den
  497.                 PUSH    BX                      ; Datei-Buffer
  498.                 PUSH    128                     ; Länge := 128 Bytes
  499.                 LEA     BX,L_Count              ; übergebe Zeiger auf Word,  
  500.                 PUSH    SS                      ; in dem die Anzahl der gelesenen 
  501.                 PUSH    BX                      ; Bytes gespeichert wird
  502.                 CALL    DosRead                 ; lese 128 Bytes aus Datei
  503.                 OR      AX,AX                   ; ist Lesefehler aufgetreten ?
  504.                 MOV     AX,0                    ; für diesen Fall: 0 Bytes gelesen
  505.                 JNZ     @@ReadError             ; Fehler -> weiter
  506.                 MOV     AX,L_Count              ; lese Anzahl tatsächlich gelesener Bytes
  507. @@ReadError:    XOR     BX,BX                   ; init. Index auf Datei-Buffer
  508. @@ChkEofLoop:   CMP     BX,AX                   ; Ende des Buffers erreicht ?
  509.                 JE      @@End                   ; ja -> Ende
  510.                 CMP     [DI].fBuffer[BX],eof    ; ist EOF-Zeichen im Buffer ?
  511.                 JE      @@Truncate              ; ja -> schneide Datei ab
  512.                 INC     BX                      ; nächstes Byte im Buffer
  513.                 JMP     @@ChkEofLoop            ; auf EOF testen
  514.  
  515.                 ; Schneide Datei am EOF-Zeichen ab, alle weiteren 
  516.                 ; Bytes hinter (logischem) Dateiende werden gelöscht.
  517.  
  518. @@Truncate:     SUB     BX,AX                   ; berechne 
  519.                 MOV     AX,L_FileSize.offs      ; Position 
  520.                 MOV     DX,L_FileSize.segm      ; zum 
  521.                 ADD     AX,BX                   ; Abschneiden
  522.                 ADC     DX,0                    ; der Datei
  523.                 PUSH    [DI].fHandle            ; übergebe FileHandle
  524.                 PUSH    DX                      ; übergebe neue Länge
  525.                 PUSH    AX                      ; der Datei
  526.                 CALL    DosNewSize              ; schneide Datei ab
  527.                 CALL    ConvErrCode             ; konvertiere Fehlercode nach OS/2-Code
  528. @@End:          RET
  529. FileAppend      ENDP
  530. FileOpen        ENDP
  531.  
  532. CODE            ENDS
  533.  
  534.                 END
  535.