Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1132 by niro, Sat Sep 1 22:45:15 2007 UTC revision 1133 by niro, Thu Aug 19 09:50:43 2010 UTC
# Line 1  Line 1 
 ;; $Id: getc.inc,v 1.1 2007-09-01 22:44:04 niro Exp $  
1  ;; -----------------------------------------------------------------------  ;; -----------------------------------------------------------------------
2  ;;    ;;
3  ;;   Copyright 1994-2002 H. Peter Anvin - All Rights Reserved  ;;   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  ;;   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  ;;   it under the terms of the GNU General Public License as published by
# Line 16  Line 16 
16  ;;  ;;
17  ;; Simple file handling library (open, getc, ungetc)  ;; 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  ; open,getc: Load a file a character at a time for parsing in a manner
46  ; similar to the C library getc routine. Only one simultaneous  ; similar to the C library getc routine.
47  ; use is supported.  Note: "open" trashes the trackbuf.  ; 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  ; open: Input: mangled filename in DS:DI
53  ; Output: ZF set on file not found or zero length  ; Output: ZF set on file not found or zero length
54  ;  ;
55  ; openfd: Input: file handle in SI  ; openfd: Input: file handle in SI, file size in EAX
56  ; Output: none  ; Output: ZF set on getc stack overflow
57  ;  ;
58  ; getc: Output: CF set on end of file  ; getc: Output: CF set on end of file
59  ; Character loaded in AL  ; Character loaded in AL
60  ;  ;
61    ; close: Output: CF set if nothing open
62    ;
63  open:  open:
64   call searchdir   call searchdir
65   jz openfd.ret   jz openfd.ret
66  openfd:  openfd:
67   pushf   push bx
68   mov [FBytes],ax  
69   mov [FBytes+2],dx   mov bx,[CurrentGetC]
70   mov eax,[FBytes]   sub bx,getc_file_size
71   add eax,SECTOR_SIZE-1   cmp bx,GetCStack
72   shr eax,SECTOR_SHIFT   jb .stack_full ; Excessive nesting
73   mov [FSectors],eax ; Number of sectors   mov [CurrentGetC],bx
74   mov [FNextClust],si ; Cluster pointer  
75   mov ax,[EndOfGetCBuf] ; Pointer at end of buffer ->   mov [bx+gc_file],si ; File pointer
76   mov [FPtr],ax ;  nothing loaded yet   xor ax,ax
77   popf ; Restore no ZF   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  .ret: ret
83    
84    .stack_full:
85     call close_file
86     xor ax,ax ; ZF <- 1
87     pop bx
88     ret
89    
90  getc:  getc:
91   stc ; If we exit here -> EOF   push bx
92   mov ecx,[FBytes]   push si
93   jecxz .ret   push di
94   mov si,[FPtr]   push es
95   cmp si,[EndOfGetCBuf]  
96   jb .loaded   mov di,[CurrentGetC]
97   ; Buffer empty -- load another set   movzx bx,byte [di+gc_unget_cnt]
98   mov ecx,[FSectors]   and bx,bx
99   cmp ecx,trackbufsize >> SECTOR_SHIFT   jnz .have_unget
100   jna .oksize  
101   mov ecx,trackbufsize >> SECTOR_SHIFT   mov si,real_mode_seg ; Borrow the real_mode_seg
102  .oksize: sub [FSectors],ecx ; Reduce remaining clusters   mov es,si
103   mov si,[FNextClust]  
104   push es ; ES may be != DS, save old ES  .got_data:
105   push ds   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   pop es
115   mov bx,getcbuf   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   push bx
177   call getfssec ; Load a trackbuf full of data   push si
178   mov [FNextClust],si ; Store new next pointer   mov bx,[CurrentGetC]
179   pop si ; SI -> newly loaded data   mov si,[bx+gc_file]
180   pop es ; Restore ES   call close_file
181  .loaded: lodsb ; Load a byte, increment SI   add bx,getc_file_size
182   mov [FPtr],si ; Update next byte pointer   mov [CurrentGetC],bx
183   dec dword [FBytes] ; Update bytes left counter   pop si
184   clc ; Not EOF   pop bx
185  .ret: ret   ret
186    
187  ;  ;
188  ; ungetc: Push a character (in AL) back into the getc buffer  ; ungetc: Push a character (in AL) back into the getc buffer
189  ; Note: if more than one byte is pushed back, this may cause  ; Note: if more than MAX_UNGET bytes are pushed back, all
190  ; bytes to be written below the getc buffer boundary.  If there  ; hell will break loose.
 ; is a risk for this to occur, the getcbuf base address should  
 ; be moved up.  
191  ;  ;
192  ungetc:  ungetc:
193   mov si,[FPtr]   push di
194   dec si   push bx
195   mov [si],al   mov di,[CurrentGetC]
196   mov [FPtr],si   movzx bx,[di+gc_unget_cnt]
197   inc dword [FBytes]   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   ret
203    
204  ;  ;
# Line 134  getint: Line 243  getint:
243  .loaded: mov byte [di],0  .loaded: mov byte [di],0
244   mov si,NumBuf   mov si,NumBuf
245   ; Fall through to parseint   ; Fall through to parseint
   
246  ;  ;
247  ; parseint: Convert an integer to a number in EBX  ; parseint: Convert an integer to a number in EBX
248  ; Get characters from string in DS:SI  ; Get characters from string in DS:SI
249  ; Return CF on error  ; Return CF on error
250  ; DS:SI points to first character after number  ; DS:SI points to first character after number
251  ;  ;
252  ;               Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+K, val+M  ;               Syntaxes accepted: [-]dec, [-]0+oct, [-]0x+hex, val+[KMG]
253  ;  ;
254  parseint:  parseint:
255                  push eax                  push eax
# Line 182  parseint: Line 290  parseint:
290                  call unhexchar                  call unhexchar
291                  jc .km                ; Not a (hex) digit                  jc .km                ; Not a (hex) digit
292                  cmp al,cl                  cmp al,cl
293   jae .km ; Invalid for base   jae .km ; Invalid for base
294   imul ebx,ecx ; Multiply accumulated by base   imul ebx,ecx ; Multiply accumulated by base
295                  add ebx,eax             ; Add current digit                  add ebx,eax             ; Add current digit
296   lodsb   lodsb
# Line 195  parseint: Line 303  parseint:
303   je .isk   je .isk
304   cmp al,'m'   cmp al,'m'
305   je .ism   je .ism
306     cmp al,'g'
307     je .isg
308   dec si ; Back up   dec si ; Back up
309  .fini: and bp,bp  .fini: and bp,bp
310   jz .ret ; CF=0!   jz .ret ; CF=0!
# Line 206  parseint: Line 316  parseint:
316   ret   ret
317  .err: stc  .err: stc
318   jmp short .ret   jmp short .ret
319  .isk: shl ebx,10 ; x 2^10  .isg: shl ebx,10 ; * 2^30
320   jmp short .done  .ism: shl ebx,10 ; * 2^20
321  .ism: shl ebx,20 ; x 2^20  .isk: shl ebx,10 ; * 2^10
322   jmp short .done   jmp .fini
323    
324     section .bss1
  section .bss  
325   alignb 4   alignb 4
326  NumBuf resb 15 ; Buffer to load number  NumBuf resb 15 ; Buffer to load number
327  NumBufEnd resb 1 ; Last byte in NumBuf  NumBufEnd resb 1 ; Last byte in NumBuf
328  FBytes resd 1 ; Number of bytes left in getc file  
329  FSectors resd 1 ; Number of sectors in getc file  GetCStack resb getc_file_size*MAX_GETC
330  FNextClust resw 1 ; Pointer to next cluster in d:o  .end equ $
331  FPtr resw 1 ; Pointer to next char in buffer  
332     section .data
333    CurrentGetC dw GetCStack.end ; GetCStack empty
334    
335  ;  ;
336  ; unhexchar:    Convert a hexadecimal digit in AL to the equivalent number;  ; unhexchar:    Convert a hexadecimal digit in AL to the equivalent number;
# Line 240  unhexchar: Line 351  unhexchar:
351                  ja .err                  ja .err
352                  sub al,'a'-10           ; CF <- 0                  sub al,'a'-10           ; CF <- 0
353                  ret                  ret
354  .err:         stc  .err: stc
355  .ret: ret  .ret: ret
356    
357  ;  ;
# Line 288  getline: Line 399  getline:
399   stosb   stosb
400  .xret: popf  .xret: popf
401   ret   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

Legend:
Removed from v.1132  
changed lines
  Added in v.1133