2 ;; -----------------------------------------------------------------------
4 ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
6 ;; This program is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 ;; Boston MA 02111-1307, USA; either version 2 of the License, or
10 ;; (at your option) any later version; incorporated herein by reference.
12 ;; -----------------------------------------------------------------------
17 ;; Simple file handling library (open, getc, ungetc)
21 ; open,getc: Load a file a character at a time for parsing in a manner
22 ; similar to the C library getc routine. Only one simultaneous
23 ; use is supported. Note: "open" trashes the trackbuf.
25 ; open: Input: mangled filename in DS:DI
26 ; Output: ZF set on file not found or zero length
28 ; openfd: Input: file handle in SI
31 ; getc: Output: CF set on end of file
32 ; Character loaded in AL
44 mov [FSectors],eax ; Number of sectors
45 mov [FNextClust],si ; Cluster pointer
46 mov ax,[EndOfGetCBuf] ; Pointer at end of buffer ->
47 mov [FPtr],ax ; nothing loaded yet
52 stc ; If we exit here -> EOF
58 ; Buffer empty -- load another set
60 cmp ecx,trackbufsize >> SECTOR_SHIFT
62 mov ecx,trackbufsize >> SECTOR_SHIFT
63 .oksize: sub [FSectors],ecx ; Reduce remaining clusters
65 push es ; ES may be != DS, save old ES
70 call getfssec ; Load a trackbuf full of data
71 mov [FNextClust],si ; Store new next pointer
72 pop si ; SI -> newly loaded data
74 .loaded: lodsb ; Load a byte, increment SI
75 mov [FPtr],si ; Update next byte pointer
76 dec dword [FBytes] ; Update bytes left counter
81 ; ungetc: Push a character (in AL) back into the getc buffer
82 ; Note: if more than one byte is pushed back, this may cause
83 ; bytes to be written below the getc buffer boundary. If there
84 ; is a risk for this to occur, the getcbuf base address should
96 ; skipspace: Skip leading whitespace using "getc". If we hit end-of-line
97 ; or end-of-file, return with carry set; ZF = true of EOF
98 ; ZF = false for EOLN; otherwise CF = ZF = 0.
100 ; Otherwise AL = first character after whitespace
112 .eof: cmp al,al ; Set ZF
115 .eoln: add al,0FFh ; Set CF, clear ZF
119 ; getint: Load an integer from the getc file.
120 ; Return CF if error; otherwise return integer in EBX
124 .getnum: cmp di,NumBufEnd ; Last byte in NumBuf
133 call ungetc ; Unget non-numeric
134 .loaded: mov byte [di],0
136 ; Fall through to parseint
139 ; parseint: Convert an integer to a number in EBX
140 ; Get characters from string in DS:SI
142 ; DS:SI points to first character after number
144 ; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
150 xor eax,eax ; Current digit (keep eax == al)
151 mov ebx,eax ; Accumulator
153 xor bp,bp ; Used for negative flag
157 xor bp,1 ; Set unary minus flag
165 mov cl,10 ; Base = decimal
170 jb .km ; Value is zero
176 mov cl,8 ; Base = octal
179 mov al,'0' ; No numeric value accrued yet
180 mov cl,16 ; Base = hex
183 jc .km ; Not a (hex) digit
185 jae .km ; Invalid for base
186 imul ebx,ecx ; Multiply accumulated by base
187 add ebx,eax ; Add current digit
191 dec si ; Back up to last non-numeric
201 neg ebx ; Value was negative
209 .isk: shl ebx,10 ; x 2^10
211 .ism: shl ebx,20 ; x 2^20
217 NumBuf resb 15 ; Buffer to load number
218 NumBufEnd resb 1 ; Last byte in NumBuf
219 FBytes resd 1 ; Number of bytes left in getc file
220 FSectors resd 1 ; Number of sectors in getc file
221 FNextClust resw 1 ; Pointer to next cluster in d:o
222 FPtr resw 1 ; Pointer to next char in buffer
225 ; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
226 ; return CF=1 if not a hex digit
231 jb .ret ; If failure, CF == 1 already
236 .notdigit: or al,20h ; upper case -> lower case
238 jb .ret ; If failure, CF == 1 already
241 sub al,'a'-10 ; CF <- 0
248 ; getline: Get a command line, converting control characters to spaces
249 ; and collapsing streches to one; a space is appended to the
250 ; end of the string, unless the line is empty.
251 ; The line is terminated by ^J, ^Z or EOF and is written
252 ; to ES:DI. On return, DI points to first char after string.
253 ; CF is set if we hit EOF.
257 mov dl,1 ; Empty line -> empty string.
277 jnz .fillloop ; Ignore multiple spaces
278 mov al,' ' ; Ctrl -> space
281 .eoln: clc ; End of line is not end of file
284 .ret: pushf ; We want the last char to be space!