blob: c32ee6c5f4245e340b5032c4f1f3ad83a6395d50 [file] [log] [blame]
;; $Id$
;; -----------------------------------------------------------------------
;;
;; Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
;;
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;; Boston MA 02111-1307, USA; either version 2 of the License, or
;; (at your option) any later version; incorporated herein by reference.
;;
;; -----------------------------------------------------------------------
;;
;; getc.inc
;;
;; Simple file handling library (open, getc, ungetc)
;;
;
; open,getc: Load a file a character at a time for parsing in a manner
; similar to the C library getc routine. Only one simultaneous
; use is supported. Note: "open" trashes the trackbuf.
;
; open: Input: mangled filename in DS:DI
; Output: ZF set on file not found or zero length
;
; openfd: Input: file handle in SI
; Output: none
;
; getc: Output: CF set on end of file
; Character loaded in AL
;
open:
call searchdir
jz openfd.ret
openfd:
pushf
mov [FBytes],ax
mov [FBytes+2],dx
mov eax,[FBytes]
add eax,SECTOR_SIZE-1
shr eax,SECTOR_SHIFT
mov [FSectors],eax ; Number of sectors
mov [FNextClust],si ; Cluster pointer
mov ax,[EndOfGetCBuf] ; Pointer at end of buffer ->
mov [FPtr],ax ; nothing loaded yet
popf ; Restore no ZF
.ret: ret
getc:
stc ; If we exit here -> EOF
mov ecx,[FBytes]
jecxz .ret
mov si,[FPtr]
cmp si,[EndOfGetCBuf]
jb .loaded
; Buffer empty -- load another set
mov ecx,[FSectors]
cmp ecx,trackbufsize >> SECTOR_SHIFT
jna .oksize
mov ecx,trackbufsize >> SECTOR_SHIFT
.oksize: sub [FSectors],ecx ; Reduce remaining clusters
mov si,[FNextClust]
push es ; ES may be != DS, save old ES
push ds
pop es
mov bx,getcbuf
push bx
call getfssec ; Load a trackbuf full of data
mov [FNextClust],si ; Store new next pointer
pop si ; SI -> newly loaded data
pop es ; Restore ES
.loaded: lodsb ; Load a byte, increment SI
mov [FPtr],si ; Update next byte pointer
dec dword [FBytes] ; Update bytes left counter
clc ; Not EOF
.ret: ret
;
; ungetc: Push a character (in AL) back into the getc buffer
; Note: if more than one byte is pushed back, this may cause
; bytes to be written below the getc buffer boundary. If there
; is a risk for this to occur, the getcbuf base address should
; be moved up.
;
ungetc:
mov si,[FPtr]
dec si
mov [si],al
mov [FPtr],si
inc dword [FBytes]
ret
;
; skipspace: Skip leading whitespace using "getc". If we hit end-of-line
; or end-of-file, return with carry set; ZF = true of EOF
; ZF = false for EOLN; otherwise CF = ZF = 0.
;
; Otherwise AL = first character after whitespace
;
skipspace:
.loop: call getc
jc .eof
cmp al,1Ah ; DOS EOF
je .eof
cmp al,0Ah
je .eoln
cmp al,' '
jbe .loop
ret ; CF = ZF = 0
.eof: cmp al,al ; Set ZF
stc ; Set CF
ret
.eoln: add al,0FFh ; Set CF, clear ZF
ret
;
; getint: Load an integer from the getc file.
; Return CF if error; otherwise return integer in EBX
;
getint:
mov di,NumBuf
.getnum: cmp di,NumBufEnd ; Last byte in NumBuf
jae .loaded
push di
call getc
pop di
jc .loaded
stosb
cmp al,'-'
jnb .getnum
call ungetc ; Unget non-numeric
.loaded: mov byte [di],0
mov si,NumBuf
; Fall through to parseint
;
; parseint: Convert an integer to a number in EBX
; Get characters from string in DS:SI
; Return CF on error
; DS:SI points to first character after number
;
; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
;
parseint:
push eax
push ecx
push bp
xor eax,eax ; Current digit (keep eax == al)
mov ebx,eax ; Accumulator
mov ecx,ebx ; Base
xor bp,bp ; Used for negative flag
.begin: lodsb
cmp al,'-'
jne .not_minus
xor bp,1 ; Set unary minus flag
jmp short .begin
.not_minus:
cmp al,'0'
jb .err
je .octhex
cmp al,'9'
ja .err
mov cl,10 ; Base = decimal
jmp short .foundbase
.octhex:
lodsb
cmp al,'0'
jb .km ; Value is zero
or al,20h ; Downcase
cmp al,'x'
je .ishex
cmp al,'7'
ja .err
mov cl,8 ; Base = octal
jmp short .foundbase
.ishex:
mov al,'0' ; No numeric value accrued yet
mov cl,16 ; Base = hex
.foundbase:
call unhexchar
jc .km ; Not a (hex) digit
cmp al,cl
jae .km ; Invalid for base
imul ebx,ecx ; Multiply accumulated by base
add ebx,eax ; Add current digit
lodsb
jmp short .foundbase
.km:
dec si ; Back up to last non-numeric
lodsb
or al,20h
cmp al,'k'
je .isk
cmp al,'m'
je .ism
dec si ; Back up
.fini: and bp,bp
jz .ret ; CF=0!
neg ebx ; Value was negative
.done: clc
.ret: pop bp
pop ecx
pop eax
ret
.err: stc
jmp short .ret
.isk: shl ebx,10 ; x 2^10
jmp short .done
.ism: shl ebx,20 ; x 2^20
jmp short .done
section .bss
alignb 4
NumBuf resb 15 ; Buffer to load number
NumBufEnd resb 1 ; Last byte in NumBuf
FBytes resd 1 ; Number of bytes left in getc file
FSectors resd 1 ; Number of sectors in getc file
FNextClust resw 1 ; Pointer to next cluster in d:o
FPtr resw 1 ; Pointer to next char in buffer
;
; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
; return CF=1 if not a hex digit
;
section .text
unhexchar:
cmp al,'0'
jb .ret ; If failure, CF == 1 already
cmp al,'9'
ja .notdigit
sub al,'0' ; CF <- 0
ret
.notdigit: or al,20h ; upper case -> lower case
cmp al,'a'
jb .ret ; If failure, CF == 1 already
cmp al,'f'
ja .err
sub al,'a'-10 ; CF <- 0
ret
.err: stc
.ret: ret
;
;
; getline: Get a command line, converting control characters to spaces
; and collapsing streches to one; a space is appended to the
; end of the string, unless the line is empty.
; The line is terminated by ^J, ^Z or EOF and is written
; to ES:DI. On return, DI points to first char after string.
; CF is set if we hit EOF.
;
getline:
call skipspace
mov dl,1 ; Empty line -> empty string.
jz .eof ; eof
jc .eoln ; eoln
call ungetc
.fillloop: push dx
push di
call getc
pop di
pop dx
jc .ret ; CF set!
cmp al,' '
jna .ctrl
xor dx,dx
.store: stosb
jmp short .fillloop
.ctrl: cmp al,10
je .ret ; CF clear!
cmp al,26
je .eof
and dl,dl
jnz .fillloop ; Ignore multiple spaces
mov al,' ' ; Ctrl -> space
inc dx
jmp short .store
.eoln: clc ; End of line is not end of file
jmp short .ret
.eof: stc
.ret: pushf ; We want the last char to be space!
and dl,dl
jnz .xret
mov al,' '
stosb
.xret: popf
ret