syslinux-3.08-2 sources from FC4
[bootcd.git] / syslinux / getc.inc
1 ;; $Id: getc.inc,v 1.6 2004/12/17 06:42:01 hpa Exp $
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 ;;   Boston 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 openfd.ret
37 openfd:
38                 pushf
39                 mov [FBytes],ax
40                 mov [FBytes+2],dx
41                 mov eax,[FBytes]
42                 add eax,SECTOR_SIZE-1
43                 shr eax,SECTOR_SHIFT
44                 mov [FSectors],eax      ; Number of sectors
45                 mov [FNextClust],si     ; Cluster pointer
46                 mov ax,[EndOfGetCBuf]   ; Pointer at end of buffer ->
47                 mov [FPtr],ax           ;  nothing loaded yet
48                 popf                    ; Restore no ZF
49 .ret:           ret
50
51 getc:
52                 stc                     ; If we exit here -> EOF
53                 mov ecx,[FBytes]
54                 jecxz .ret
55                 mov si,[FPtr]
56                 cmp si,[EndOfGetCBuf]
57                 jb .loaded
58                 ; Buffer empty -- load another set
59                 mov ecx,[FSectors]
60                 cmp ecx,trackbufsize >> SECTOR_SHIFT
61                 jna .oksize
62                 mov ecx,trackbufsize >> SECTOR_SHIFT
63 .oksize:        sub [FSectors],ecx      ; Reduce remaining clusters
64                 mov si,[FNextClust]
65                 push es                 ; ES may be != DS, save old ES
66                 push ds
67                 pop es
68                 mov bx,getcbuf
69                 push bx
70                 call getfssec           ; Load a trackbuf full of data
71                 mov [FNextClust],si     ; Store new next pointer
72                 pop si                  ; SI -> newly loaded data
73                 pop es                  ; Restore ES
74 .loaded:        lodsb                   ; Load a byte, increment SI
75                 mov [FPtr],si           ; Update next byte pointer
76                 dec dword [FBytes]      ; Update bytes left counter
77                 clc                     ; Not EOF
78 .ret:           ret
79
80 ;
81 ; ungetc:       Push a character (in AL) back into the getc buffer
82 ;               Note: if more than one byte is pushed back, this may cause
83 ;               bytes to be written below the getc buffer boundary.  If there
84 ;               is a risk for this to occur, the getcbuf base address should
85 ;               be moved up.
86 ;
87 ungetc:
88                 mov si,[FPtr]
89                 dec si
90                 mov [si],al
91                 mov [FPtr],si
92                 inc dword [FBytes]
93                 ret
94
95 ;
96 ; skipspace:    Skip leading whitespace using "getc".  If we hit end-of-line
97 ;               or end-of-file, return with carry set; ZF = true of EOF
98 ;               ZF = false for EOLN; otherwise CF = ZF = 0.
99 ;
100 ;               Otherwise AL = first character after whitespace
101 ;
102 skipspace:
103 .loop:          call getc
104                 jc .eof
105                 cmp al,1Ah                      ; DOS EOF
106                 je .eof
107                 cmp al,0Ah
108                 je .eoln
109                 cmp al,' '
110                 jbe .loop
111                 ret                             ; CF = ZF = 0
112 .eof:           cmp al,al                       ; Set ZF
113                 stc                             ; Set CF
114                 ret
115 .eoln:          add al,0FFh                     ; Set CF, clear ZF
116                 ret
117
118 ;
119 ; getint:       Load an integer from the getc file.
120 ;               Return CF if error; otherwise return integer in EBX
121 ;
122 getint:
123                 mov di,NumBuf
124 .getnum:        cmp di,NumBufEnd        ; Last byte in NumBuf
125                 jae .loaded
126                 push di
127                 call getc
128                 pop di
129                 jc .loaded
130                 stosb
131                 cmp al,'-'
132                 jnb .getnum
133                 call ungetc             ; Unget non-numeric
134 .loaded:        mov byte [di],0
135                 mov si,NumBuf
136                 ; Fall through to parseint
137
138 ;
139 ; parseint:     Convert an integer to a number in EBX
140 ;               Get characters from string in DS:SI
141 ;               Return CF on error
142 ;               DS:SI points to first character after number
143 ;
144 ;               Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M
145 ;
146 parseint:
147                 push eax
148                 push ecx
149                 push bp
150                 xor eax,eax             ; Current digit (keep eax == al)
151                 mov ebx,eax             ; Accumulator
152                 mov ecx,ebx             ; Base
153                 xor bp,bp               ; Used for negative flag
154 .begin:         lodsb
155                 cmp al,'-'
156                 jne .not_minus
157                 xor bp,1                ; Set unary minus flag
158                 jmp short .begin
159 .not_minus:
160                 cmp al,'0'
161                 jb .err
162                 je .octhex
163                 cmp al,'9'
164                 ja .err
165                 mov cl,10               ; Base = decimal
166                 jmp short .foundbase
167 .octhex:
168                 lodsb
169                 cmp al,'0'
170                 jb .km          ; Value is zero
171                 or al,20h               ; Downcase
172                 cmp al,'x'
173                 je .ishex
174                 cmp al,'7'
175                 ja .err
176                 mov cl,8                ; Base = octal
177                 jmp short .foundbase
178 .ishex:
179                 mov al,'0'              ; No numeric value accrued yet
180                 mov cl,16               ; Base = hex
181 .foundbase:
182                 call unhexchar
183                 jc .km                ; Not a (hex) digit
184                 cmp al,cl
185                 jae .km         ; Invalid for base
186                 imul ebx,ecx            ; Multiply accumulated by base
187                 add ebx,eax             ; Add current digit
188                 lodsb
189                 jmp short .foundbase
190 .km:
191                 dec si                  ; Back up to last non-numeric
192                 lodsb
193                 or al,20h
194                 cmp al,'k'
195                 je .isk
196                 cmp al,'m'
197                 je .ism
198                 dec si                  ; Back up
199 .fini:          and bp,bp
200                 jz .ret         ; CF=0!
201                 neg ebx                 ; Value was negative
202 .done:          clc
203 .ret:           pop bp
204                 pop ecx
205                 pop eax
206                 ret
207 .err:           stc
208                 jmp short .ret
209 .isk:           shl ebx,10              ; x 2^10
210                 jmp short .done
211 .ism:           shl ebx,20              ; x 2^20
212                 jmp short .done
213
214
215                 section .bss
216                 alignb 4
217 NumBuf          resb 15                 ; Buffer to load number
218 NumBufEnd       resb 1                  ; Last byte in NumBuf
219 FBytes          resd 1                  ; Number of bytes left in getc file
220 FSectors        resd 1                  ; Number of sectors in getc file
221 FNextClust      resw 1                  ; Pointer to next cluster in d:o
222 FPtr            resw 1                  ; Pointer to next char in buffer
223
224 ;
225 ; unhexchar:    Convert a hexadecimal digit in AL to the equivalent number;
226 ;               return CF=1 if not a hex digit
227 ;
228                 section .text
229 unhexchar:
230                 cmp al,'0'
231                 jb .ret                 ; If failure, CF == 1 already
232                 cmp al,'9'
233                 ja .notdigit
234                 sub al,'0'              ; CF <- 0
235                 ret
236 .notdigit:      or al,20h               ; upper case -> lower case
237                 cmp al,'a'
238                 jb .ret                 ; If failure, CF == 1 already
239                 cmp al,'f'
240                 ja .err
241                 sub al,'a'-10           ; CF <- 0
242                 ret
243 .err:           stc
244 .ret:           ret
245
246 ;
247 ;
248 ; getline:      Get a command line, converting control characters to spaces
249 ;               and collapsing streches to one; a space is appended to the
250 ;               end of the string, unless the line is empty.
251 ;               The line is terminated by ^J, ^Z or EOF and is written
252 ;               to ES:DI.  On return, DI points to first char after string.
253 ;               CF is set if we hit EOF.
254 ;
255 getline:
256                 call skipspace
257                 mov dl,1                ; Empty line -> empty string.
258                 jz .eof               ; eof
259                 jc .eoln              ; eoln
260                 call ungetc
261 .fillloop:      push dx
262                 push di
263                 call getc
264                 pop di
265                 pop dx
266                 jc .ret         ; CF set!
267                 cmp al,' '
268                 jna .ctrl
269                 xor dx,dx
270 .store:         stosb
271                 jmp short .fillloop
272 .ctrl:          cmp al,10
273                 je .ret         ; CF clear!
274                 cmp al,26
275                 je .eof
276                 and dl,dl
277                 jnz .fillloop           ; Ignore multiple spaces
278                 mov al,' '              ; Ctrl -> space
279                 inc dx
280                 jmp short .store
281 .eoln:          clc                     ; End of line is not end of file
282                 jmp short .ret
283 .eof:           stc
284 .ret:           pushf                   ; We want the last char to be space!
285                 and dl,dl
286                 jnz .xret
287                 mov al,' '
288                 stosb
289 .xret:          popf
290                 ret