;; $Id: getc.inc,v 1.6 2004/12/17 06:42:01 hpa Exp $ ;; ----------------------------------------------------------------------- ;; ;; 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