Magellan Linux

Contents of /trunk/mkinitrd-magellan/isolinux/getc.inc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1133 - (show annotations) (download)
Thu Aug 19 09:50:43 2010 UTC (13 years, 8 months ago) by niro
File size: 9048 byte(s)
-updated to isolinux-3.86
1 ;; -----------------------------------------------------------------------
2 ;;
3 ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
4 ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
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 ;; WARNING: This interface uses the real_mode_seg/comboot_seg.
20 ;;
21
22 MAX_GETC_LG2 equ 4 ; Max number of file nesting
23 MAX_GETC equ (1 << MAX_GETC_LG2)
24 bytes_per_getc_lg2 equ 16-MAX_GETC_LG2
25 bytes_per_getc equ (1 << bytes_per_getc_lg2)
26 secs_per_getc equ bytes_per_getc/SECTOR_SIZE
27 MAX_UNGET equ 9 ; Max bytes that can be pushed back
28
29 struc getc_file
30 gc_file resw 1 ; File pointer
31 gc_bufbytes resw 1 ; Bytes left in buffer
32 gc_bufdata resw 1 ; Pointer to data in buffer
33 gc_unget_cnt resb 1 ; Character pushed back count
34 gc_unget_buf resb MAX_UNGET ; Character pushed back buffer
35 endstruc
36 getc_file_lg2 equ 4 ; Size of getc_file as a power of 2
37
38 %ifndef DEPEND
39 %if (getc_file_size != (1 << getc_file_lg2))
40 %error "getc_file_size != (1 << getc_file_lg2)"
41 %endif
42 %endif
43
44 ;
45 ; open,getc: Load a file a character at a time for parsing in a manner
46 ; similar to the C library getc routine.
47 ; Up to MAX_GETC files can be open at the same time,
48 ; they are accessed in a stack-like fashion.
49 ;
50 ; All routines assume CS == DS.
51 ;
52 ; open: Input: mangled filename in DS:DI
53 ; Output: ZF set on file not found or zero length
54 ;
55 ; openfd: Input: file handle in SI, file size in EAX
56 ; Output: ZF set on getc stack overflow
57 ;
58 ; getc: Output: CF set on end of file
59 ; Character loaded in AL
60 ;
61 ; close: Output: CF set if nothing open
62 ;
63 open:
64 call searchdir
65 jz openfd.ret
66 openfd:
67 push bx
68
69 mov bx,[CurrentGetC]
70 sub bx,getc_file_size
71 cmp bx,GetCStack
72 jb .stack_full ; Excessive nesting
73 mov [CurrentGetC],bx
74
75 mov [bx+gc_file],si ; File pointer
76 xor ax,ax
77 mov [bx+gc_bufbytes],ax ; Buffer empty
78 mov [bx+gc_unget_cnt],al ; ungetc buffer empty
79
80 inc ax ; ZF <- 0
81 pop bx
82 .ret: ret
83
84 .stack_full:
85 call close_file
86 xor ax,ax ; ZF <- 1
87 pop bx
88 ret
89
90 getc:
91 push bx
92 push si
93 push di
94 push es
95
96 mov di,[CurrentGetC]
97 movzx bx,byte [di+gc_unget_cnt]
98 and bx,bx
99 jnz .have_unget
100
101 mov si,real_mode_seg ; Borrow the real_mode_seg
102 mov es,si
103
104 .got_data:
105 sub word [di+gc_bufbytes],1
106 jc .get_data ; Was it zero already?
107 mov si,[di+gc_bufdata]
108 mov al,[es:si]
109 inc si
110 mov [di+gc_bufdata],si
111 .done:
112 clc
113 .ret:
114 pop es
115 pop di
116 pop si
117 pop bx
118 ret
119 .have_unget:
120 dec bx
121 mov al,[di+bx+gc_unget_buf]
122 mov [di+gc_unget_cnt],bl
123 jmp .done
124
125 .get_data:
126 pushad
127 ; Compute start of buffer
128 mov bx,di
129 sub bx,GetCStack
130 shl bx,bytes_per_getc_lg2-getc_file_lg2
131
132 mov [di+gc_bufdata],bx
133 mov si,[di+gc_file]
134 and si,si
135 mov [di+gc_bufbytes],si ; In case SI == 0
136 jz .empty
137 mov cx,bytes_per_getc >> SECTOR_SHIFT
138 call getfssec
139 mov [di+gc_bufbytes],cx
140 mov [di+gc_file],si
141 jcxz .empty
142 popad
143 TRACER 'd'
144 jmp .got_data
145
146 .empty:
147 TRACER 'e'
148 ; [di+gc_bufbytes] is zero already, thus we will continue
149 ; to get EOF on any further attempts to read the file.
150 popad
151 xor al,al ; Return a predictable zero
152 stc
153 jmp .ret
154
155 ;
156 ; This is similar to getc, except that we read up to CX bytes and
157 ; store them in ES:DI. Eventually this could get optimized...
158 ;
159 ; On return, CX and DI are adjusted by the number of bytes actually read.
160 ;
161 readc:
162 push ax
163 .loop:
164 call getc
165 jc .out
166 stosb
167 loop .loop
168 .out:
169 pop ax
170 ret
171
172 ;
173 ; close: close the top of the getc stack
174 ;
175 close:
176 push bx
177 push si
178 mov bx,[CurrentGetC]
179 mov si,[bx+gc_file]
180 call close_file
181 add bx,getc_file_size
182 mov [CurrentGetC],bx
183 pop si
184 pop bx
185 ret
186
187 ;
188 ; ungetc: Push a character (in AL) back into the getc buffer
189 ; Note: if more than MAX_UNGET bytes are pushed back, all
190 ; hell will break loose.
191 ;
192 ungetc:
193 push di
194 push bx
195 mov di,[CurrentGetC]
196 movzx bx,[di+gc_unget_cnt]
197 mov [bx+di+gc_unget_buf],al
198 inc bx
199 mov [di+gc_unget_cnt],bl
200 pop bx
201 pop di
202 ret
203
204 ;
205 ; skipspace: Skip leading whitespace using "getc". If we hit end-of-line
206 ; or end-of-file, return with carry set; ZF = true of EOF
207 ; ZF = false for EOLN; otherwise CF = ZF = 0.
208 ;
209 ; Otherwise AL = first character after whitespace
210 ;
211 skipspace:
212 .loop: call getc
213 jc .eof
214 cmp al,1Ah ; DOS EOF
215 je .eof
216 cmp al,0Ah
217 je .eoln
218 cmp al,' '
219 jbe .loop
220 ret ; CF = ZF = 0
221 .eof: cmp al,al ; Set ZF
222 stc ; Set CF
223 ret
224 .eoln: add al,0FFh ; Set CF, clear ZF
225 ret
226
227 ;
228 ; getint: Load an integer from the getc file.
229 ; Return CF if error; otherwise return integer in EBX
230 ;
231 getint:
232 mov di,NumBuf
233 .getnum: cmp di,NumBufEnd ; Last byte in NumBuf
234 jae .loaded
235 push di
236 call getc
237 pop di
238 jc .loaded
239 stosb
240 cmp al,'-'
241 jnb .getnum
242 call ungetc ; Unget non-numeric
243 .loaded: mov byte [di],0
244 mov si,NumBuf
245 ; Fall through to parseint
246 ;
247 ; parseint: Convert an integer to a number in EBX
248 ; Get characters from string in DS:SI
249 ; Return CF on error
250 ; DS:SI points to first character after number
251 ;
252 ; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+[KMG]
253 ;
254 parseint:
255 push eax
256 push ecx
257 push bp
258 xor eax,eax ; Current digit (keep eax == al)
259 mov ebx,eax ; Accumulator
260 mov ecx,ebx ; Base
261 xor bp,bp ; Used for negative flag
262 .begin: lodsb
263 cmp al,'-'
264 jne .not_minus
265 xor bp,1 ; Set unary minus flag
266 jmp short .begin
267 .not_minus:
268 cmp al,'0'
269 jb .err
270 je .octhex
271 cmp al,'9'
272 ja .err
273 mov cl,10 ; Base = decimal
274 jmp short .foundbase
275 .octhex:
276 lodsb
277 cmp al,'0'
278 jb .km ; Value is zero
279 or al,20h ; Downcase
280 cmp al,'x'
281 je .ishex
282 cmp al,'7'
283 ja .err
284 mov cl,8 ; Base = octal
285 jmp short .foundbase
286 .ishex:
287 mov al,'0' ; No numeric value accrued yet
288 mov cl,16 ; Base = hex
289 .foundbase:
290 call unhexchar
291 jc .km ; Not a (hex) digit
292 cmp al,cl
293 jae .km ; Invalid for base
294 imul ebx,ecx ; Multiply accumulated by base
295 add ebx,eax ; Add current digit
296 lodsb
297 jmp short .foundbase
298 .km:
299 dec si ; Back up to last non-numeric
300 lodsb
301 or al,20h
302 cmp al,'k'
303 je .isk
304 cmp al,'m'
305 je .ism
306 cmp al,'g'
307 je .isg
308 dec si ; Back up
309 .fini: and bp,bp
310 jz .ret ; CF=0!
311 neg ebx ; Value was negative
312 .done: clc
313 .ret: pop bp
314 pop ecx
315 pop eax
316 ret
317 .err: stc
318 jmp short .ret
319 .isg: shl ebx,10 ; * 2^30
320 .ism: shl ebx,10 ; * 2^20
321 .isk: shl ebx,10 ; * 2^10
322 jmp .fini
323
324 section .bss1
325 alignb 4
326 NumBuf resb 15 ; Buffer to load number
327 NumBufEnd resb 1 ; Last byte in NumBuf
328
329 GetCStack resb getc_file_size*MAX_GETC
330 .end equ $
331
332 section .data
333 CurrentGetC dw GetCStack.end ; GetCStack empty
334
335 ;
336 ; unhexchar: Convert a hexadecimal digit in AL to the equivalent number;
337 ; return CF=1 if not a hex digit
338 ;
339 section .text
340 unhexchar:
341 cmp al,'0'
342 jb .ret ; If failure, CF == 1 already
343 cmp al,'9'
344 ja .notdigit
345 sub al,'0' ; CF <- 0
346 ret
347 .notdigit: or al,20h ; upper case -> lower case
348 cmp al,'a'
349 jb .ret ; If failure, CF == 1 already
350 cmp al,'f'
351 ja .err
352 sub al,'a'-10 ; CF <- 0
353 ret
354 .err: stc
355 .ret: ret
356
357 ;
358 ;
359 ; getline: Get a command line, converting control characters to spaces
360 ; and collapsing streches to one; a space is appended to the
361 ; end of the string, unless the line is empty.
362 ; The line is terminated by ^J, ^Z or EOF and is written
363 ; to ES:DI. On return, DI points to first char after string.
364 ; CF is set if we hit EOF.
365 ;
366 getline:
367 call skipspace
368 mov dl,1 ; Empty line -> empty string.
369 jz .eof ; eof
370 jc .eoln ; eoln
371 call ungetc
372 .fillloop: push dx
373 push di
374 call getc
375 pop di
376 pop dx
377 jc .ret ; CF set!
378 cmp al,' '
379 jna .ctrl
380 xor dx,dx
381 .store: stosb
382 jmp short .fillloop
383 .ctrl: cmp al,10
384 je .ret ; CF clear!
385 cmp al,26
386 je .eof
387 and dl,dl
388 jnz .fillloop ; Ignore multiple spaces
389 mov al,' ' ; Ctrl -> space
390 inc dx
391 jmp short .store
392 .eoln: clc ; End of line is not end of file
393 jmp short .ret
394 .eof: stc
395 .ret: pushf ; We want the last char to be space!
396 and dl,dl
397 jnz .xret
398 mov al,' '
399 stosb
400 .xret: popf
401 ret
402
403 ;
404 ; parseint_esdi:
405 ; Same as parseint, but takes the input in ES:DI
406 ;
407 parseint_esdi:
408 push ds
409 push es
410 pop ds
411 xchg si,di
412 call parseint
413 xchg si,di
414 pop ds
415 ret