summaryrefslogtreecommitdiff
path: root/getc.inc
diff options
context:
space:
mode:
authorhpa <hpa>2002-04-26 22:17:52 +0000
committerhpa <hpa>2002-04-26 22:17:52 +0000
commitc423d62e97df05b5ebdf2dbba2ac15349b78c51c (patch)
tree794fafb372db04940305be2522954c670c6a9dee /getc.inc
parent62ca92287e71450514018da90a00da6392ec25b2 (diff)
downloadsyslinux-c423d62e97df05b5ebdf2dbba2ac15349b78c51c.tar.gz
More common code factoring: getc library, font handling code
Diffstat (limited to 'getc.inc')
-rw-r--r--getc.inc281
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