diff options
Diffstat (limited to 'getc.inc')
-rw-r--r-- | getc.inc | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/getc.inc b/getc.inc new file mode 100644 index 00000000..5a807ebd --- /dev/null +++ b/getc.inc @@ -0,0 +1,281 @@ +;; $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, +;; Bostom 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 open_return +openfd: + pushf + mov [FBytes1],ax + mov [FBytes2],dx + add ax,[ClustSize] + adc dx,byte 0 + sub ax,byte 1 + sbb dx,byte 0 + div word [ClustSize] + mov [FClust],ax ; Number of clusters + mov [FNextClust],si ; Cluster pointer + mov ax,[EndOfGetCBuf] ; Pointer at end of buffer -> + mov [FPtr],ax ; nothing loaded yet + popf ; Restore no ZF +open_return: ret + +getc: + stc ; If we exit here -> EOF + mov ecx,[FBytes] + jecxz getc_ret + mov si,[FPtr] + cmp si,[EndOfGetCBuf] + jb getc_loaded + ; Buffer empty -- load another set + mov cx,[FClust] + cmp cx,[BufSafe] + jna getc_oksize + mov cx,[BufSafe] +getc_oksize: sub [FClust],cx ; 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 +getc_loaded: lodsb ; Load a byte + mov [FPtr],si ; Update next byte pointer + dec dword [FBytes] ; Update bytes left counter + clc ; Not EOF +getc_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: +skipspace_loop: call getc + jc skipspace_eof + cmp al,1Ah ; DOS EOF + je skipspace_eof + cmp al,0Ah + je skipspace_eoln + cmp al,' ' + jbe skipspace_loop + ret ; CF = ZF = 0 +skipspace_eof: cmp al,al ; Set ZF + stc ; Set CF + ret +skipspace_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 +gi_getnum: cmp di,NumBufEnd ; Last byte in NumBuf + jae gi_loaded + push di + call getc + pop di + jc gi_loaded + stosb + cmp al,'-' + jnb gi_getnum + call ungetc ; Unget non-numeric +gi_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 +pi_begin: lodsb + cmp al,'-' + jne pi_not_minus + xor bp,1 ; Set unary minus flag + jmp short pi_begin +pi_not_minus: + cmp al,'0' + jb pi_err + je pi_octhex + cmp al,'9' + ja pi_err + mov cl,10 ; Base = decimal + jmp short pi_foundbase +pi_octhex: + lodsb + cmp al,'0' + jb pi_km ; Value is zero + or al,20h ; Downcase + cmp al,'x' + je pi_ishex + cmp al,'7' + ja pi_err + mov cl,8 ; Base = octal + jmp short pi_foundbase +pi_ishex: + mov al,'0' ; No numeric value accrued yet + mov cl,16 ; Base = hex +pi_foundbase: + call unhexchar + jc pi_km ; Not a (hex) digit + cmp al,cl + jae pi_km ; Invalid for base + imul ebx,ecx ; Multiply accumulated by base + add ebx,eax ; Add current digit + lodsb + jmp short pi_foundbase +pi_km: + dec si ; Back up to last non-numeric + lodsb + or al,20h + cmp al,'k' + je pi_isk + cmp al,'m' + je pi_ism + dec si ; Back up +pi_fini: and bp,bp + jz pi_ret ; CF=0! + neg ebx ; Value was negative +pi_done: clc +pi_ret: pop bp + pop ecx + pop eax + ret +pi_err: stc + jmp short pi_ret +pi_isk: shl ebx,10 ; x 2^10 + jmp short pi_done +pi_ism: shl ebx,20 ; x 2^20 + jmp short pi_done + +; +; unhexchar: Convert a hexadecimal digit in AL to the equivalent number; +; return CF=1 if not a hex digit +; +unhexchar: + cmp al,'0' + jb uxc_ret ; If failure, CF == 1 already + cmp al,'9' + ja uxc_1 + sub al,'0' ; CF <- 0 + ret +uxc_1: or al,20h ; upper case -> lower case + cmp al,'a' + jb uxc_ret ; If failure, CF == 1 already + cmp al,'f' + ja uxc_err + sub al,'a'-10 ; CF <- 0 + ret +uxc_err: stc +uxc_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 gl_eof ; eof + jc gl_eoln ; eoln + call ungetc +gl_fillloop: push dx + push di + call getc + pop di + pop dx + jc gl_ret ; CF set! + cmp al,' ' + jna gl_ctrl + xor dx,dx +gl_store: stosb + jmp short gl_fillloop +gl_ctrl: cmp al,10 + je gl_ret ; CF clear! + cmp al,26 + je gl_eof + and dl,dl + jnz gl_fillloop ; Ignore multiple spaces + mov al,' ' ; Ctrl -> space + inc dx + jmp short gl_store +gl_eoln: clc ; End of line is not end of file + jmp short gl_ret +gl_eof: stc +gl_ret: pushf ; We want the last char to be space! + and dl,dl + jnz gl_xret + mov al,' ' + stosb +gl_xret: popf + ret |