Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1133 - (hide 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 niro 532 ;; -----------------------------------------------------------------------
2     ;;
3 niro 1133 ;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved
4     ;; Copyright 2009 Intel Corporation; author: H. Peter Anvin
5     ;;
6 niro 532 ;; 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 niro 1133 ;; WARNING: This interface uses the real_mode_seg/comboot_seg.
20     ;;
21 niro 532
22 niro 1133 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 niro 532 ;
45     ; open,getc: Load a file a character at a time for parsing in a manner
46 niro 1133 ; 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 niro 532 ;
50 niro 1133 ; All routines assume CS == DS.
51     ;
52 niro 532 ; open: Input: mangled filename in DS:DI
53     ; Output: ZF set on file not found or zero length
54     ;
55 niro 1133 ; openfd: Input: file handle in SI, file size in EAX
56     ; Output: ZF set on getc stack overflow
57 niro 532 ;
58     ; getc: Output: CF set on end of file
59     ; Character loaded in AL
60     ;
61 niro 1133 ; close: Output: CF set if nothing open
62     ;
63 niro 532 open:
64     call searchdir
65     jz openfd.ret
66     openfd:
67 niro 1133 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 niro 532 .ret: ret
83    
84 niro 1133 .stack_full:
85     call close_file
86     xor ax,ax ; ZF <- 1
87     pop bx
88     ret
89    
90 niro 532 getc:
91 niro 1133 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 niro 532 pop es
115 niro 1133 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 niro 532 push bx
177 niro 1133 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 niro 532
187     ;
188     ; ungetc: Push a character (in AL) back into the getc buffer
189 niro 1133 ; Note: if more than MAX_UNGET bytes are pushed back, all
190     ; hell will break loose.
191 niro 532 ;
192     ungetc:
193 niro 1133 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 niro 532 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 niro 1133 ; Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+[KMG]
253 niro 532 ;
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 niro 1133 jae .km ; Invalid for base
294 niro 532 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 niro 1133 cmp al,'g'
307     je .isg
308 niro 532 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 niro 1133 .isg: shl ebx,10 ; * 2^30
320     .ism: shl ebx,10 ; * 2^20
321     .isk: shl ebx,10 ; * 2^10
322     jmp .fini
323 niro 532
324 niro 1133 section .bss1
325 niro 532 alignb 4
326     NumBuf resb 15 ; Buffer to load number
327     NumBufEnd resb 1 ; Last byte in NumBuf
328    
329 niro 1133 GetCStack resb getc_file_size*MAX_GETC
330     .end equ $
331    
332     section .data
333     CurrentGetC dw GetCStack.end ; GetCStack empty
334    
335 niro 532 ;
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 niro 1133 .err: stc
355 niro 532 .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 niro 1133
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