Annotation of /tags/mkinitrd-6_4_0/isolinux/getc.inc
Parent Directory | Revision Log
Revision 1133 -
(hide annotations)
(download)
Thu Aug 19 09:50:43 2010 UTC (14 years, 1 month ago) by niro
Original Path: trunk/mkinitrd-magellan/isolinux/getc.inc
File size: 9048 byte(s)
Thu Aug 19 09:50:43 2010 UTC (14 years, 1 month ago) by niro
Original Path: trunk/mkinitrd-magellan/isolinux/getc.inc
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 |