initial commit: a mess of assembly code
[fmap.git] / x86_64_sse2_x87 / fasm / source / reader.inc
blobf59b2d64167993fccd8ef96c86e395dc35822642
1 \r
2 struct FileData\r
3         length dq ?\r
4         cache dd ?      ; pointer to FileCache\r
5 ends\r
6 \r
7 struct FileCache\r
8         offset dq ?\r
9         length dd ?\r
10         next dd ?       ; pointer to another FileCache\r
11 ends\r
13 read_source:\r
14 ; in:\r
15 ;  esi - source path\r
16 ; out:\r
17 ;  eax - tokenized source, null when file not found\r
18 ;  esi - source path in persistent storage\r
19         mov     ebx,[file_source_cache]\r
20         xor     ecx,ecx\r
21         call    get_from_map\r
22         jc      read_source_file\r
23         cmp     eax,-1\r
24         je      get_erroneous_source\r
25         retn\r
26     read_source_file:\r
27         mov     edx,esi\r
28         call    open\r
29         jc      source_file_not_found\r
30         xor     eax,eax\r
31         mov     edx,eax\r
32         mov     cl,2\r
33         call    lseek\r
34         jc      error_reading_file\r
35         test    edx,edx\r
36         jnz     out_of_memory\r
37         push    eax\r
38         xor     eax,eax\r
39         mov     edx,eax\r
40         mov     cl,al\r
41         call    lseek\r
42         jc      error_reading_file\r
43         pop     ecx\r
44         inc     ecx\r
45         mov     [source_text_length],ecx\r
46         call    malloc\r
47         mov     [source_text],eax\r
48         mov     edx,eax\r
49         mov     ecx,[source_text_length]\r
50         dec     ecx\r
51         mov     byte [edx+ecx],0\r
52         call    read\r
53         jc      error_reading_file\r
54         call    close\r
55         push    esi\r
56         call    tokenize_source\r
57         mov     eax,[source_text]\r
58         call    mfree\r
59         pop     esi\r
60         mov     eax,[tokenization_buffer]\r
61         xor     ecx,ecx\r
62         mov     ebx,[file_source_cache]\r
63         call    put_into_map\r
64         mov     eax,[tokenization_buffer]\r
65         retn\r
66     source_file_not_found:\r
67         xor     eax,eax\r
68         xor     ecx,ecx\r
69         mov     ebx,[file_source_cache]\r
70         call    put_into_map\r
71         xor     eax,eax\r
72         retn\r
73     error_reading_file:\r
74         or      eax,-1\r
75         xor     ecx,ecx\r
76         mov     ebx,[file_source_cache]\r
77         call    put_into_map\r
78     get_erroneous_source:\r
79         mov     ebx,esi\r
80         mov     edx,_error_reading_file\r
81         call    register_error\r
82         mov     eax,zero_value\r
83         retn\r
85 use_source:\r
86 ; in:\r
87 ;  esi - ASCIIZ source string\r
88 ; out:\r
89 ;  eax - tokenized source\r
90 ;  esi - source text in persistent storage\r
91         mov     edi,esi\r
92         xor     al,al\r
93         or      ecx,-1\r
94         repne   scasb\r
95         not     ecx\r
96         mov     [source_text_length],ecx\r
97         mov     ebx,[memory_source_cache]\r
98         xor     eax,eax\r
99         call    get_from_map\r
100         jc      adapt_memory_source\r
101         retn\r
102     adapt_memory_source:\r
103         mov     [source_text],esi\r
104         call    tokenize_source\r
105         mov     eax,[tokenization_buffer]\r
106         mov     esi,[source_text]\r
107         mov     ecx,[source_text_length]\r
108         mov     ebx,[memory_source_cache]\r
109         call    put_into_map\r
110         mov     eax,[tokenization_buffer]\r
111         retn\r
113 tokenize_source:\r
114 ; in:\r
115 ;  [source_text] - ASCIIZ text\r
116 ;  [source_text_length] = length of text (including terminating character)\r
117 ; out:\r
118 ;  [tokenization_buffer] - tokenized source\r
119 ;  [tokenization_buffer_length] = length of tokenized source\r
120         mov     ecx,[source_text_length]\r
121         shl     ecx,1\r
122         add     ecx,18\r
123         call    malloc_growable\r
124         mov     [tokenization_buffer],eax\r
125         mov     [tokenization_buffer_length],ecx\r
126         add     eax,ecx\r
127         sub     eax,[source_text]\r
128         sub     eax,[source_text_length]\r
129         mov     [buffer_end_offset],eax\r
130         mov     esi,[source_text]\r
131         mov     edi,[tokenization_buffer]\r
132         mov     [last_token],0Ah\r
133     tokenize:\r
134         mov     eax,[buffer_end_offset]\r
135         add     eax,esi\r
136         sub     eax,edi\r
137         cmp     eax,18\r
138         jae     tokenization_buffer_reserve_ok\r
139         mov     ecx,esi\r
140         sub     ecx,[source_text]\r
141         mov     eax,[source_text_length]\r
142         mul     [tokenization_buffer_length]\r
143         div     ecx\r
144         mov     ecx,eax\r
145         add     ecx,18\r
146         mov     eax,[tokenization_buffer]\r
147         call    realloc\r
148         sub     edi,[tokenization_buffer]\r
149         add     edi,eax\r
150         mov     [tokenization_buffer],eax\r
151         mov     [tokenization_buffer_length],ecx\r
152         add     eax,ecx\r
153         sub     eax,[source_text]\r
154         sub     eax,[source_text_length]\r
155         mov     [buffer_end_offset],eax\r
156     tokenization_buffer_reserve_ok:\r
157         movzx   eax,byte [esi]\r
158         inc     esi\r
159         mov     ah,[characters+eax]\r
160         cmp     ah,20h\r
161         je      control_character\r
162         test    ah,ah\r
163         jnz     make_name_token\r
164     character_token:\r
165         stosb\r
166         mov     [last_token],al\r
167         jmp     tokenize\r
168     make_string_token:\r
169         mov     dl,al\r
170         mov     byte [edi],22h\r
171         mov     [last_token],22h\r
172         add     edi,5\r
173         xor     ecx,ecx\r
174     copy_string:\r
175         mov     al,[esi]\r
176         cmp     al,0Dh\r
177         je      broken_string\r
178         cmp     al,0Ah\r
179         je      broken_string\r
180         cmp     al,1Ah\r
181         je      broken_string\r
182         test    al,al\r
183         jz      broken_string\r
184         inc     esi\r
185         cmp     al,dl\r
186         jne     copy_string_character\r
187         cmp     byte [esi],al\r
188         jne     finish_string_token\r
189         inc     esi\r
190     copy_string_character:\r
191         mov     [edi+ecx],al\r
192         inc     ecx\r
193         jmp     copy_string\r
194     broken_string:\r
195         mov     byte [edi-5],27h\r
196     finish_string_token:\r
197         mov     al,[edi-5]\r
198         mov     [edi-4],ecx\r
199         add     edi,ecx\r
200         jmp     tokenize\r
201     make_name_token:\r
202         cmp     al,22h\r
203         je      make_string_token\r
204         cmp     al,27h\r
205         je      make_string_token\r
206         mov     byte [edi],1Ah\r
207         mov     [last_token],1Ah\r
208         add     edi,5\r
209         xor     ebx,ebx\r
210         mov     ecx,FNV_OFFSET\r
211         mov     edx,ecx\r
212     hash_name:\r
213         mov     [edi+ebx],al\r
214         inc     ebx\r
215         xor     cl,al\r
216         xor     dl,ah\r
217         imul    ecx,FNV_PRIME\r
218         imul    edx,FNV_PRIME\r
219         movzx   eax,byte [esi]\r
220         inc     esi\r
221         mov     ah,[characters+eax]\r
222         cmp     ah,20h\r
223         je      finish_name_token\r
224         test    ah,ah\r
225         jnz     hash_name\r
226     finish_name_token:\r
227         mov     [edi-4],ebx\r
228         add     edi,ebx\r
229         mov     [edi],ecx\r
230         mov     [edi+4],edx\r
231         xor     ecx,ecx\r
232         mov     [edi+8],ecx\r
233         add     edi,12\r
234         cmp     ah,20h\r
235         jne     character_token\r
236     control_character:\r
237         cmp     al,20h\r
238         je      whitespace\r
239         cmp     al,9\r
240         je      whitespace\r
241         cmp     [last_token],20h\r
242         je      mark_end_of_line\r
243         inc     edi\r
244     mark_end_of_line:\r
245         mov     byte [edi-1],0Ah\r
246         mov     [last_token],0Ah\r
247         cmp     al,0Dh\r
248         je      cr\r
249         cmp     al,0Ah\r
250         je      lf\r
251         xor     al,al\r
252         stosb\r
253         mov     ecx,edi\r
254         mov     eax,[tokenization_buffer]\r
255         sub     ecx,eax\r
256         call    realloc\r
257         mov     [tokenization_buffer],eax\r
258         mov     [tokenization_buffer_length],ecx\r
259         retn\r
260     cr:\r
261         cmp     byte [esi],0Ah\r
262         jne     tokenize\r
263         inc     esi\r
264         jmp     tokenize\r
265     lf:\r
266         cmp     byte [esi],0Dh\r
267         jne     tokenize\r
268         inc     esi\r
269         jmp     tokenize\r
270     whitespace:\r
271         cmp     [last_token],0Ah\r
272         je      tokenize\r
273         cmp     [last_token],20h\r
274         je      tokenize\r
275         mov     al,20h\r
276         stosb\r
277         mov     [last_token],al\r
278         jmp     tokenize\r
280 get_file_data:\r
281 ; in:\r
282 ;  esi - file path\r
283 ; out:\r
284 ;  ebx - FileData, null when file not found\r
285 ;  esi - file path in persistent storage\r
286 ; preserves: edi\r
287         mov     ebx,[file_data_cache]\r
288         xor     ecx,ecx\r
289         call    get_from_map\r
290         jc      initialize_file_data\r
291         mov     ebx,eax\r
292         retn\r
293     initialize_file_data:\r
294         mov     edx,esi\r
295         call    open\r
296         jc      remember_file_not_found\r
297         push    edi\r
298         mov     ecx,sizeof.FileData\r
299         call    malloc_fixed\r
300         mov     edi,eax\r
301         xor     eax,eax\r
302         mov     edx,eax\r
303         mov     cl,2\r
304         call    lseek\r
305         jc      file_not_seekable\r
306         mov     dword [edi+FileData.length],eax\r
307         mov     dword [edi+FileData.length+4],edx\r
308         call    close\r
309         mov     eax,edi\r
310         xor     ecx,ecx\r
311         mov     [eax+FileData.cache],ecx\r
312         mov     ebx,[file_data_cache]\r
313         call    put_into_map\r
314         mov     ebx,edi\r
315         pop     edi\r
316         retn\r
317     file_not_seekable:\r
318         pop     edi\r
319     remember_file_not_found:\r
320         xor     eax,eax\r
321         mov     ecx,eax\r
322         mov     ebx,[file_data_cache]\r
323         call    put_into_map\r
324         xor     ebx,ebx\r
325         retn\r
327 read_file_data:\r
328 ; in:\r
329 ;  esi - file path\r
330 ;  ebx - FileData\r
331 ;  edi - buffer for data\r
332 ;  [file_offset] = offset of data\r
333 ;  [data_length] = length of data\r
334 ; out:\r
335 ;  cf set when read failed\r
336 ; preserves: esi\r
337         mov     [file_data],ebx\r
338         lea     eax,[ebx+FileData.cache]\r
339         mov     [file_cache_pointer],eax\r
340         mov     ebx,[eax]\r
341     read_from_file_cache:\r
342         mov     ecx,[data_length]\r
343         test    ecx,ecx\r
344         jz      file_data_read\r
345         test    ebx,ebx\r
346         jz      new_trailing_file_cache_entry\r
347         mov     eax,dword [file_offset]\r
348         mov     edx,dword [file_offset+4]\r
349         sub     eax,dword [ebx+FileCache.offset]\r
350         sbb     edx,dword [ebx+FileCache.offset+4]\r
351         jc      new_file_cache_entry\r
352         jnz     next_entry\r
353         mov     edx,[ebx+FileCache.length]\r
354         sub     edx,eax\r
355         jbe     next_entry\r
356         cmp     ecx,edx\r
357         jbe     length_to_read_ok\r
358         mov     ecx,edx\r
359       length_to_read_ok:\r
360         sub     [data_length],ecx\r
361         add     dword [file_offset],ecx\r
362         adc     dword [file_offset+4],0\r
363         mov     edx,esi\r
364         lea     esi,[ebx+sizeof.FileCache+eax]\r
365         mov     al,cl\r
366         shr     ecx,2\r
367         rep     movsd\r
368         mov     cl,al\r
369         and     cl,11b\r
370         rep     movsb\r
371         mov     esi,edx\r
372     next_entry:\r
373         lea     eax,[ebx+FileCache.next]\r
374         mov     [file_cache_pointer],eax\r
375         mov     ebx,[eax]\r
376         jmp     read_from_file_cache\r
377     file_data_read:\r
378         clc\r
379         retn\r
380     new_trailing_file_cache_entry:\r
381         mov     ebx,[file_data]\r
382         mov     ecx,dword [ebx+FileData.length]\r
383         mov     edx,dword [ebx+FileData.length+4]\r
384         cmp     ecx,dword [file_offset]\r
385         jne     measure_cache_gap\r
386         cmp     edx,dword [file_offset+4]\r
387         jne     measure_cache_gap\r
388         stc\r
389         retn\r
390     new_file_cache_entry:\r
391         mov     ecx,dword [ebx+FileCache.offset]\r
392         mov     edx,dword [ebx+FileCache.offset+4]\r
393       measure_cache_gap:\r
394         mov     eax,dword [file_offset]\r
395         and     eax,not 0FFFh\r
396         sub     ecx,eax\r
397         sbb     edx,dword [file_offset+4]\r
398         jnz     compute_aligned_length\r
399         cmp     ecx,[data_length]\r
400         jbe     read_into_cache\r
401       compute_aligned_length:\r
402         mov     eax,dword [file_offset]\r
403         and     eax,0FFFh\r
404         add     eax,[data_length]\r
405         dec     eax\r
406         shr     eax,12\r
407         inc     eax\r
408         shl     eax,12\r
409         test    edx,edx\r
410         jnz     use_aligned_length\r
411         cmp     eax,ecx\r
412         jae     read_into_cache\r
413       use_aligned_length:\r
414         mov     ecx,eax\r
415     read_into_cache:\r
416         push    ecx\r
417         add     ecx,sizeof.FileCache\r
418         call    malloc_fixed\r
419         mov     ebx,eax\r
420         mov     eax,[file_cache_pointer]\r
421         mov     edx,ebx\r
422         xchg    edx,[eax]\r
423         mov     [ebx+FileCache.next],edx\r
424         pop     [ebx+FileCache.length]\r
425         mov     eax,dword [file_offset]\r
426         and     eax,not 0FFFh\r
427         mov     edx,dword [file_offset+4]\r
428         mov     dword [ebx+FileCache.offset],eax\r
429         mov     dword [ebx+FileCache.offset+4],edx\r
430         push    ebx edi\r
431         mov     edi,ebx\r
432         mov     edx,esi\r
433         call    open\r
434         jc      file_access_error\r
435         mov     eax,dword [edi+FileCache.offset]\r
436         mov     edx,dword [edi+FileCache.offset+4]\r
437         xor     cl,cl\r
438         call    lseek\r
439         jc      file_access_error\r
440         lea     edx,[edi+sizeof.FileCache]\r
441         mov     ecx,[edi+FileCache.length]\r
442         call    read\r
443         jc      file_access_error\r
444         call    close\r
445         pop     edi ebx\r
446         jmp     read_from_file_cache\r
447      file_access_error:\r
448         pop     edi ebx\r
449         stc\r
450         retn\r
451