1 ;; -----------------------------------------------------------------------
3 ;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 ;; Boston MA 02111-1307, USA; either version 2 of the License, or
9 ;; (at your option) any later version; incorporated herein by reference.
11 ;; -----------------------------------------------------------------------
16 ;; Simple file handling library (open, getc, ungetc)
20 ; open,getc: Load a file a character at a time for parsing in a manner
21 ; similar to the C library getc routine. Only one simultaneous
22 ; use is supported. Note: "open" trashes the trackbuf.
24 ; open: Input: mangled filename in DS:DI
25 ; Output: ZF set on file not found or zero length
27 ; openfd: Input: file handle in SI
30 ; getc: Output: CF set on end of file
31 ; Character loaded in AL
43 mov [FSectors],eax ; Number of sectors
44 mov [FNextClust],si ; Cluster pointer
45 mov ax,[EndOfGetCBuf] ; Pointer at end of buffer ->
46 mov [FPtr],ax ; nothing loaded yet
51 stc ; If we exit here -> EOF
57 ; Buffer empty -- load another set
59 cmp ecx,trackbufsize >> SECTOR_SHIFT
61 mov ecx,trackbufsize >> SECTOR_SHIFT
62 .oksize: sub [FSectors],ecx ; Reduce remaining clusters
64 push es ; ES may be != DS, save old ES
69 call getfssec ; Load a trackbuf full of data
70 mov [FNextClust],si ; Store new next pointer
71 pop si ; SI -> newly loaded data
73 .loaded: lodsb ; Load a byte, increment SI
74 mov [FPtr],si ; Update next byte pointer
75 dec dword [FBytes] ; Update bytes left counter
80 ; ungetc: Push a character (in AL) back into the getc buffer
81 ; Note: if more than one byte is pushed back, this may cause
82 ; bytes to be written below the getc buffer boundary. If there
83 ; is a risk for this to occur, the getcbuf base address should
95 ; skipspace: Skip leading whitespace using "getc". If we hit end-of-line
96 ; or end-of-file, return with carry set; ZF = true of EOF
97 ; ZF = false for EOLN; otherwise CF = ZF = 0.
99 ; Otherwise AL = first character after whitespace
111 .eof: cmp al,al ; Set ZF
114 .eoln: add al,0FFh ; Set CF, clear ZF
118 ; getint: Load an integer from the getc file.
119 ; Return CF if error; otherwise return integer in EBX
123 .getnum: cmp di,NumBufEnd ; Last byte in NumBuf
132 call ungetc ; Unget non-numeric
133 .loaded: mov byte [di],0
135 ; Fall through to parseint
138 ; parseint: Convert an integer to a number in EBX
139 ; Get characters from string in DS:SI
141 ; DS:SI points to first character after number
143 ; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
149 xor eax,eax ; Current digit (keep eax == al)
150 mov ebx,eax ; Accumulator
152 xor bp,bp ; Used for negative flag
156 xor bp,1 ; Set unary minus flag
164 mov cl,10 ; Base = decimal
169 jb .km ; Value is zero
175 mov cl,8 ; Base = octal
178 mov al,'0' ; No numeric value accrued yet
179 mov cl,16 ; Base = hex
182 jc .km ; Not a (hex) digit
184 jae .km ; Invalid for base
185 imul ebx,ecx ; Multiply accumulated by base
186 add ebx,eax ; Add current digit
190 dec si ; Back up to last non-numeric
200 neg ebx ; Value was negative
208 .isk: shl ebx,10 ; x 2^10
210 .ism: shl ebx,20 ; x 2^20
216 NumBuf resb 15 ; Buffer to load number
217 NumBufEnd resb 1 ; Last byte in NumBuf
218 FBytes resd 1 ; Number of bytes left in getc file
219 FSectors resd 1 ; Number of sectors in getc file
220 FNextClust resw 1 ; Pointer to next cluster in d:o
221 FPtr resw 1 ; Pointer to next char in buffer
224 ; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
225 ; return CF=1 if not a hex digit
230 jb .ret ; If failure, CF == 1 already
235 .notdigit: or al,20h ; upper case -> lower case
237 jb .ret ; If failure, CF == 1 already
240 sub al,'a'-10 ; CF <- 0
247 ; getline: Get a command line, converting control characters to spaces
248 ; and collapsing streches to one; a space is appended to the
249 ; end of the string, unless the line is empty.
250 ; The line is terminated by ^J, ^Z or EOF and is written
251 ; to ES:DI. On return, DI points to first char after string.
252 ; CF is set if we hit EOF.
256 mov dl,1 ; Empty line -> empty string.
276 jnz .fillloop ; Ignore multiple spaces
277 mov al,' ' ; Ctrl -> space
280 .eoln: clc ; End of line is not end of file
283 .ret: pushf ; We want the last char to be space!