Fix command-line parsing bug... destroyed the flags while live... oops.
[profile/ivi/syslinux.git] / getc.inc
1 ;; $Id$
2 ;; -----------------------------------------------------------------------
3 ;;   
4 ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved
5 ;;
6 ;;   This program is free software; you can redistribute it and/or modify
7 ;;   it under the terms of the GNU General Public License as published by
8 ;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
9 ;;   Bostom MA 02111-1307, USA; either version 2 of the License, or
10 ;;   (at your option) any later version; incorporated herein by reference.
11 ;;
12 ;; -----------------------------------------------------------------------
13
14 ;;
15 ;; getc.inc
16 ;;
17 ;; Simple file handling library (open, getc, ungetc)
18 ;;
19
20 ;
21 ; open,getc:    Load a file a character at a time for parsing in a manner
22 ;               similar to the C library getc routine.  Only one simultaneous
23 ;               use is supported.  Note: "open" trashes the trackbuf.
24 ;
25 ;               open:   Input:  mangled filename in DS:DI
26 ;                       Output: ZF set on file not found or zero length
27 ;
28 ;               openfd: Input:  file handle in SI
29 ;                       Output: none
30 ;
31 ;               getc:   Output: CF set on end of file
32 ;                               Character loaded in AL
33 ;
34 open:
35                 call searchdir
36                 jz open_return
37 openfd:
38                 pushf
39                 mov [FBytes1],ax
40                 mov [FBytes2],dx
41                 add ax,[ClustSize]
42                 adc dx,byte 0
43                 sub ax,byte 1
44                 sbb dx,byte 0
45                 div word [ClustSize]
46                 mov [FClust],ax         ; Number of clusters
47                 mov [FNextClust],si     ; Cluster pointer
48                 mov ax,[EndOfGetCBuf]   ; Pointer at end of buffer ->
49                 mov [FPtr],ax           ;  nothing loaded yet
50                 popf                    ; Restore no ZF
51 open_return:    ret
52
53 getc:
54                 stc                     ; If we exit here -> EOF
55                 mov ecx,[FBytes]
56                 jecxz getc_ret
57                 mov si,[FPtr]
58                 cmp si,[EndOfGetCBuf]
59                 jb getc_loaded
60                 ; Buffer empty -- load another set
61                 mov cx,[FClust]
62                 cmp cx,[BufSafe]
63                 jna getc_oksize
64                 mov cx,[BufSafe]
65 getc_oksize:    sub [FClust],cx         ; Reduce remaining clusters
66                 mov si,[FNextClust]
67                 push es                 ; ES may be != DS, save old ES
68                 push ds
69                 pop es
70                 mov bx,getcbuf
71                 push bx
72                 call getfssec           ; Load a trackbuf full of data
73                 mov [FNextClust],si     ; Store new next pointer
74                 pop si                  ; SI -> newly loaded data
75                 pop es                  ; Restore ES
76 getc_loaded:    lodsb                   ; Load a byte, increment SI
77                 mov [FPtr],si           ; Update next byte pointer
78                 dec dword [FBytes]      ; Update bytes left counter
79                 clc                     ; Not EOF
80 getc_ret:       ret
81
82 ;
83 ; ungetc:       Push a character (in AL) back into the getc buffer
84 ;               Note: if more than one byte is pushed back, this may cause
85 ;               bytes to be written below the getc buffer boundary.  If there
86 ;               is a risk for this to occur, the getcbuf base address should
87 ;               be moved up.
88 ;
89 ungetc:
90                 mov si,[FPtr]
91                 dec si
92                 mov [si],al
93                 mov [FPtr],si
94                 inc dword [FBytes]
95                 ret
96
97 ;
98 ; skipspace:    Skip leading whitespace using "getc".  If we hit end-of-line
99 ;               or end-of-file, return with carry set; ZF = true of EOF
100 ;               ZF = false for EOLN; otherwise CF = ZF = 0.
101 ;
102 ;               Otherwise AL = first character after whitespace
103 ;
104 skipspace:
105 skipspace_loop: call getc
106                 jc skipspace_eof
107                 cmp al,1Ah                      ; DOS EOF
108                 je skipspace_eof
109                 cmp al,0Ah
110                 je skipspace_eoln
111                 cmp al,' '
112                 jbe skipspace_loop
113                 ret                             ; CF = ZF = 0
114 skipspace_eof:  cmp al,al                       ; Set ZF
115                 stc                             ; Set CF
116                 ret
117 skipspace_eoln: add al,0FFh                     ; Set CF, clear ZF
118                 ret
119
120 ;
121 ; getint:       Load an integer from the getc file.
122 ;               Return CF if error; otherwise return integer in EBX
123 ;
124 getint:
125                 mov di,NumBuf
126 gi_getnum:      cmp di,NumBufEnd        ; Last byte in NumBuf
127                 jae gi_loaded
128                 push di
129                 call getc
130                 pop di
131                 jc gi_loaded
132                 stosb
133                 cmp al,'-'
134                 jnb gi_getnum
135                 call ungetc             ; Unget non-numeric
136 gi_loaded:      mov byte [di],0
137                 mov si,NumBuf
138                 ; Fall through to parseint
139
140 ;
141 ; parseint:     Convert an integer to a number in EBX
142 ;               Get characters from string in DS:SI
143 ;               Return CF on error
144 ;               DS:SI points to first character after number
145 ;
146 ;               Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
147 ;
148 parseint:
149                 push eax
150                 push ecx
151                 push bp
152                 xor eax,eax             ; Current digit (keep eax == al)
153                 mov ebx,eax             ; Accumulator
154                 mov ecx,ebx             ; Base
155                 xor bp,bp               ; Used for negative flag
156 pi_begin:       lodsb
157                 cmp al,'-'
158                 jne pi_not_minus
159                 xor bp,1                ; Set unary minus flag
160                 jmp short pi_begin
161 pi_not_minus:
162                 cmp al,'0'
163                 jb pi_err
164                 je pi_octhex
165                 cmp al,'9'
166                 ja pi_err
167                 mov cl,10               ; Base = decimal
168                 jmp short pi_foundbase
169 pi_octhex:
170                 lodsb
171                 cmp al,'0'
172                 jb pi_km                ; Value is zero
173                 or al,20h               ; Downcase
174                 cmp al,'x'
175                 je pi_ishex
176                 cmp al,'7'
177                 ja pi_err
178                 mov cl,8                ; Base = octal
179                 jmp short pi_foundbase
180 pi_ishex:
181                 mov al,'0'              ; No numeric value accrued yet
182                 mov cl,16               ; Base = hex
183 pi_foundbase:
184                 call unhexchar
185                 jc pi_km                ; Not a (hex) digit
186                 cmp al,cl
187                 jae pi_km               ; Invalid for base
188                 imul ebx,ecx            ; Multiply accumulated by base
189                 add ebx,eax             ; Add current digit
190                 lodsb
191                 jmp short pi_foundbase
192 pi_km:
193                 dec si                  ; Back up to last non-numeric
194                 lodsb
195                 or al,20h
196                 cmp al,'k'
197                 je pi_isk
198                 cmp al,'m'
199                 je pi_ism
200                 dec si                  ; Back up
201 pi_fini:        and bp,bp
202                 jz pi_ret               ; CF=0!
203                 neg ebx                 ; Value was negative
204 pi_done:        clc
205 pi_ret:         pop bp
206                 pop ecx
207                 pop eax
208                 ret
209 pi_err:         stc
210                 jmp short pi_ret
211 pi_isk:         shl ebx,10              ; x 2^10
212                 jmp short pi_done
213 pi_ism:         shl ebx,20              ; x 2^20
214                 jmp short pi_done
215
216 ;
217 ; unhexchar:    Convert a hexadecimal digit in AL to the equivalent number;
218 ;               return CF=1 if not a hex digit
219 ;
220 unhexchar:
221                 cmp al,'0'
222                 jb uxc_ret              ; If failure, CF == 1 already
223                 cmp al,'9'
224                 ja uxc_1
225                 sub al,'0'              ; CF <- 0
226                 ret
227 uxc_1:          or al,20h               ; upper case -> lower case
228                 cmp al,'a'
229                 jb uxc_ret              ; If failure, CF == 1 already
230                 cmp al,'f'
231                 ja uxc_err
232                 sub al,'a'-10           ; CF <- 0
233                 ret
234 uxc_err:        stc
235 uxc_ret:        ret
236
237 ;
238 ;
239 ; getline:      Get a command line, converting control characters to spaces
240 ;               and collapsing streches to one; a space is appended to the
241 ;               end of the string, unless the line is empty.
242 ;               The line is terminated by ^J, ^Z or EOF and is written
243 ;               to ES:DI.  On return, DI points to first char after string.
244 ;               CF is set if we hit EOF.
245 ;
246 getline:
247                 call skipspace
248                 mov dl,1                ; Empty line -> empty string.
249                 jz gl_eof               ; eof
250                 jc gl_eoln              ; eoln
251                 call ungetc
252 gl_fillloop:    push dx
253                 push di
254                 call getc
255                 pop di
256                 pop dx
257                 jc gl_ret               ; CF set!
258                 cmp al,' '
259                 jna gl_ctrl
260                 xor dx,dx
261 gl_store:       stosb
262                 jmp short gl_fillloop
263 gl_ctrl:        cmp al,10
264                 je gl_ret               ; CF clear!
265                 cmp al,26
266                 je gl_eof
267                 and dl,dl
268                 jnz gl_fillloop         ; Ignore multiple spaces
269                 mov al,' '              ; Ctrl -> space
270                 inc dx
271                 jmp short gl_store
272 gl_eoln:        clc                     ; End of line is not end of file
273                 jmp short gl_ret
274 gl_eof:         stc
275 gl_ret:         pushf                   ; We want the last char to be space!
276                 and dl,dl
277                 jnz gl_xret
278                 mov al,' '
279                 stosb
280 gl_xret:        popf
281                 ret