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