Rev 9030 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8834 | Boppan | 1 | import re |
8825 | Boppan | 2 | import os |
8837 | Boppan | 3 | import argparse |
8957 | Boppan | 4 | import sys |
8990 | Boppan | 5 | import pickle |
8825 | Boppan | 6 | |
8834 | Boppan | 7 | # Parameters |
8837 | Boppan | 8 | # Path to doxygen folder to make doxygen files in: -o |
8834 | Boppan | 9 | doxygen_src_path = 'docs/doxygen' |
8837 | Boppan | 10 | # Remove generated doxygen files: --clean |
11 | clean_generated_stuff = False |
||
12 | # Dump all defined symbols: --dump |
||
8834 | Boppan | 13 | dump_symbols = False |
8837 | Boppan | 14 | # Print symbol stats: --stats |
8834 | Boppan | 15 | print_stats = False |
8855 | Boppan | 16 | # Do not write warnings file: --nowarn |
17 | enable_warnings = True |
||
8825 | Boppan | 18 | |
8837 | Boppan | 19 | # Constants |
20 | link_root = "http://websvn.kolibrios.org/filedetails.php?repname=Kolibri+OS&path=/kernel/trunk" |
||
21 | |||
8957 | Boppan | 22 | # fasm keywords |
23 | keywords = [ |
||
24 | # Generic keywords |
||
25 | "align", |
||
26 | "equ", |
||
27 | "org", |
||
28 | "while", |
||
29 | "load", |
||
30 | "store", |
||
31 | "times", |
||
32 | "repeat", |
||
33 | "virtual", |
||
34 | "display", |
||
35 | "err", |
||
36 | "assert", |
||
37 | "if", |
||
38 | # Instructions |
||
39 | "aaa", |
||
40 | "aad", |
||
41 | "aam", |
||
42 | "aas", |
||
43 | "adc", |
||
44 | "adcx", |
||
45 | "add", |
||
46 | "addpd", |
||
47 | "addps", |
||
48 | "addsd", |
||
49 | "addss", |
||
50 | "addsubpd", |
||
51 | "addsubps", |
||
52 | "adox", |
||
53 | "aesdec", |
||
54 | "aesdeclast", |
||
55 | "aesenc", |
||
56 | "aesenclast", |
||
57 | "aesimc", |
||
58 | "aeskeygenassist", |
||
59 | "and", |
||
60 | "andn", |
||
61 | "andnpd", |
||
62 | "andnps", |
||
63 | "andpd", |
||
64 | "andps", |
||
65 | "arpl", |
||
66 | "bextr", |
||
67 | "blendpd", |
||
68 | "blendps", |
||
69 | "blendvpd", |
||
70 | "blendvps", |
||
71 | "blsi", |
||
72 | "blsmsk", |
||
73 | "blsr", |
||
74 | "bndcl", |
||
75 | "bndcn", |
||
76 | "bndcu", |
||
77 | "bndldx", |
||
78 | "bndmk", |
||
79 | "bndmov", |
||
80 | "bndstx", |
||
81 | "bound", |
||
82 | "bsf", |
||
83 | "bsr", |
||
84 | "bswap", |
||
85 | "bt", |
||
86 | "btc", |
||
87 | "btr", |
||
88 | "bts", |
||
89 | "bzhi", |
||
90 | "call", |
||
91 | "cbw", |
||
92 | "cdq", |
||
93 | "cdqe", |
||
94 | "clac", |
||
95 | "clc", |
||
96 | "cld", |
||
97 | "cldemote", |
||
98 | "clflush", |
||
99 | "clflushopt", |
||
100 | "cli", |
||
101 | "clts", |
||
102 | "clwb", |
||
103 | "cmc", |
||
104 | "cmova", |
||
105 | "cmovae", |
||
106 | "cmovb", |
||
107 | "cmovbe", |
||
108 | "cmovc", |
||
109 | "cmove", |
||
110 | "cmovg", |
||
111 | "cmovge", |
||
112 | "cmovl", |
||
113 | "cmovle", |
||
114 | "cmovna", |
||
115 | "cmovnae", |
||
116 | "cmovnb", |
||
117 | "cmovnbe", |
||
118 | "cmovnc", |
||
119 | "cmovne", |
||
120 | "cmovng", |
||
121 | "cmovnge", |
||
122 | "cmovnl", |
||
123 | "cmovnle", |
||
124 | "cmovno", |
||
125 | "cmovnp", |
||
126 | "cmovns", |
||
127 | "cmovnz", |
||
128 | "cmovo", |
||
129 | "cmovp", |
||
130 | "cmovpe", |
||
131 | "cmovpo", |
||
132 | "cmovs", |
||
133 | "cmovz", |
||
134 | "cmp", |
||
135 | "cmppd", |
||
136 | "cmpps", |
||
137 | "cmps", |
||
138 | "cmpsb", |
||
139 | "cmpsd", |
||
140 | "cmpsd", |
||
141 | "cmpsq", |
||
142 | "cmpss", |
||
143 | "cmpsw", |
||
144 | "cmpxchg", |
||
145 | "cmpxchg16b", |
||
146 | "cmpxchg8b", |
||
147 | "comisd", |
||
148 | "comiss", |
||
149 | "cpuid", |
||
150 | "cqo", |
||
151 | "crc32", |
||
152 | "cvtdq2pd", |
||
153 | "cvtdq2ps", |
||
154 | "cvtpd2dq", |
||
155 | "cvtpd2pi", |
||
156 | "cvtpd2ps", |
||
157 | "cvtpi2pd", |
||
158 | "cvtpi2ps", |
||
159 | "cvtps2dq", |
||
160 | "cvtps2pd", |
||
161 | "cvtps2pi", |
||
162 | "cvtsd2si", |
||
163 | "cvtsd2ss", |
||
164 | "cvtsi2sd", |
||
165 | "cvtsi2ss", |
||
166 | "cvtss2sd", |
||
167 | "cvtss2si", |
||
168 | "cvttpd2dq", |
||
169 | "cvttpd2pi", |
||
170 | "cvttps2dq", |
||
171 | "cvttps2pi", |
||
172 | "cvttsd2si", |
||
173 | "cvttss2si", |
||
174 | "cwd", |
||
175 | "cwde", |
||
176 | "daa", |
||
177 | "das", |
||
178 | "dec", |
||
179 | "div", |
||
180 | "divpd", |
||
181 | "divps", |
||
182 | "divsd", |
||
183 | "divss", |
||
184 | "dppd", |
||
185 | "dpps", |
||
186 | "emms", |
||
187 | "enter", |
||
188 | "extractps", |
||
189 | "f2xm1", |
||
190 | "fabs", |
||
191 | "fadd", |
||
192 | "faddp", |
||
193 | "fbld", |
||
194 | "fbstp", |
||
195 | "fchs", |
||
196 | "fclex", |
||
197 | "fcmova", |
||
198 | "fcmovae", |
||
199 | "fcmovb", |
||
200 | "fcmovbe", |
||
201 | "fcmovc", |
||
202 | "fcmove", |
||
203 | "fcmovg", |
||
204 | "fcmovge", |
||
205 | "fcmovl", |
||
206 | "fcmovle", |
||
207 | "fcmovna", |
||
208 | "fcmovnae", |
||
209 | "fcmovnb", |
||
210 | "fcmovnbe", |
||
211 | "fcmovnc", |
||
212 | "fcmovne", |
||
213 | "fcmovng", |
||
214 | "fcmovnge", |
||
215 | "fcmovnl", |
||
216 | "fcmovnle", |
||
217 | "fcmovno", |
||
218 | "fcmovnp", |
||
219 | "fcmovns", |
||
220 | "fcmovnz", |
||
221 | "fcmovo", |
||
222 | "fcmovp", |
||
223 | "fcmovpe", |
||
224 | "fcmovpo", |
||
225 | "fcmovs", |
||
226 | "fcmovz", |
||
227 | "fcom", |
||
228 | "fcomi", |
||
229 | "fcomip", |
||
230 | "fcomp", |
||
231 | "fcompp", |
||
232 | "fcos", |
||
233 | "fdecstp", |
||
234 | "fdiv", |
||
235 | "fdivp", |
||
236 | "fdivr", |
||
237 | "fdivrp", |
||
238 | "ffree", |
||
239 | "fiadd", |
||
240 | "ficom", |
||
241 | "ficomp", |
||
242 | "fidiv", |
||
243 | "fidivr", |
||
244 | "fild", |
||
245 | "fimul", |
||
246 | "fincstp", |
||
247 | "finit", |
||
248 | "fist", |
||
249 | "fistp", |
||
250 | "fisttp", |
||
251 | "fisub", |
||
252 | "fisubr", |
||
253 | "fld", |
||
254 | "fld1", |
||
255 | "fldcw", |
||
256 | "fldenv", |
||
257 | "fldl2e", |
||
258 | "fldl2t", |
||
259 | "fldlg2", |
||
260 | "fldln2", |
||
261 | "fldpi", |
||
262 | "fldz", |
||
263 | "fmul", |
||
264 | "fmulp", |
||
265 | "fnclex", |
||
266 | "fninit", |
||
267 | "fnop", |
||
268 | "fnsave", |
||
269 | "fnstcw", |
||
270 | "fnstenv", |
||
271 | "fnstsw", |
||
272 | "fpatan", |
||
273 | "fprem", |
||
274 | "fprem1", |
||
275 | "fptan", |
||
276 | "frndint", |
||
277 | "frstor", |
||
278 | "fsave", |
||
279 | "fscale", |
||
280 | "fsin", |
||
281 | "fsincos", |
||
282 | "fsqrt", |
||
283 | "fst", |
||
284 | "fstcw", |
||
285 | "fstenv", |
||
286 | "fstp", |
||
287 | "fstsw", |
||
288 | "fsub", |
||
289 | "fsubp", |
||
290 | "fsubr", |
||
291 | "fsubrp", |
||
292 | "ftst", |
||
293 | "fucom", |
||
294 | "fucomi", |
||
295 | "fucomip", |
||
296 | "fucomp", |
||
297 | "fucompp", |
||
298 | "fwait", |
||
299 | "fxam", |
||
300 | "fxch", |
||
301 | "fxrstor", |
||
302 | "fxsave", |
||
303 | "fxtract", |
||
304 | "fyl2x", |
||
305 | "fyl2xp1", |
||
306 | "gf2p8affineinvqb", |
||
307 | "gf2p8affineqb", |
||
308 | "gf2p8mulb", |
||
309 | "haddpd", |
||
310 | "haddps", |
||
311 | "hlt", |
||
312 | "hsubpd", |
||
313 | "hsubps", |
||
314 | "idiv", |
||
315 | "imul", |
||
316 | "in", |
||
317 | "inc", |
||
318 | "ins", |
||
319 | "insb", |
||
320 | "insd", |
||
321 | "insertps", |
||
322 | "insw", |
||
323 | "int", |
||
324 | "int1", |
||
325 | "int3", |
||
326 | "into", |
||
327 | "invd", |
||
328 | "invlpg", |
||
329 | "invpcid", |
||
330 | "iret", |
||
331 | "iretd", |
||
332 | "jmp", |
||
333 | "ja", |
||
334 | "jae", |
||
335 | "jb", |
||
336 | "jbe", |
||
337 | "jc", |
||
338 | "jcxz", |
||
339 | "jecxz", |
||
340 | "je", |
||
341 | "jg", |
||
342 | "jge", |
||
343 | "jl", |
||
344 | "jle", |
||
345 | "jna", |
||
346 | "jnae", |
||
347 | "jnb", |
||
348 | "jnbe", |
||
349 | "jnc", |
||
350 | "jne", |
||
351 | "jng", |
||
352 | "jnge", |
||
353 | "jnl", |
||
354 | "jnle", |
||
355 | "jno", |
||
356 | "jnp", |
||
357 | "jns", |
||
358 | "jnz", |
||
359 | "jo", |
||
360 | "jp", |
||
361 | "jpe", |
||
362 | "jpo", |
||
363 | "js", |
||
364 | "jz", |
||
365 | "kaddb", |
||
366 | "kaddd", |
||
367 | "kaddq", |
||
368 | "kaddw", |
||
369 | "kandb", |
||
370 | "kandd", |
||
371 | "kandnb", |
||
372 | "kandnd", |
||
373 | "kandnq", |
||
374 | "kandnw", |
||
375 | "kandq", |
||
376 | "kandw", |
||
377 | "kmovb", |
||
378 | "kmovd", |
||
379 | "kmovq", |
||
380 | "kmovw", |
||
381 | "knotb", |
||
382 | "knotd", |
||
383 | "knotq", |
||
384 | "knotw", |
||
385 | "korb", |
||
386 | "kord", |
||
387 | "korq", |
||
388 | "kortestb", |
||
389 | "kortestd", |
||
390 | "kortestq", |
||
391 | "kortestw", |
||
392 | "korw", |
||
393 | "kshiftlb", |
||
394 | "kshiftld", |
||
395 | "kshiftlq", |
||
396 | "kshiftlw", |
||
397 | "kshiftrb", |
||
398 | "kshiftrd", |
||
399 | "kshiftrq", |
||
400 | "kshiftrw", |
||
401 | "ktestb", |
||
402 | "ktestd", |
||
403 | "ktestq", |
||
404 | "ktestw", |
||
405 | "kunpckbw", |
||
406 | "kunpckdq", |
||
407 | "kunpckwd", |
||
408 | "kxnorb", |
||
409 | "kxnord", |
||
410 | "kxnorq", |
||
411 | "kxnorw", |
||
412 | "kxorb", |
||
413 | "kxord", |
||
414 | "kxorq", |
||
415 | "kxorw", |
||
416 | "lahf", |
||
417 | "lar", |
||
418 | "lddqu", |
||
419 | "ldmxcsr", |
||
420 | "lds", |
||
421 | "lea", |
||
422 | "leave", |
||
423 | "les", |
||
424 | "lfence", |
||
425 | "lfs", |
||
426 | "lgdt", |
||
427 | "lgs", |
||
428 | "lidt", |
||
429 | "lldt", |
||
430 | "lmsw", |
||
431 | "lock", |
||
432 | "lods", |
||
433 | "lodsb", |
||
434 | "lodsd", |
||
435 | "lodsq", |
||
436 | "lodsw", |
||
437 | "loop", |
||
438 | "loopa", |
||
439 | "loopae", |
||
440 | "loopb", |
||
441 | "loopbe", |
||
442 | "loopc", |
||
443 | "loope", |
||
444 | "loopg", |
||
445 | "loopge", |
||
446 | "loopl", |
||
447 | "loople", |
||
448 | "loopna", |
||
449 | "loopnae", |
||
450 | "loopnb", |
||
451 | "loopnbe", |
||
452 | "loopnc", |
||
453 | "loopne", |
||
454 | "loopng", |
||
455 | "loopnge", |
||
456 | "loopnl", |
||
457 | "loopnle", |
||
458 | "loopno", |
||
459 | "loopnp", |
||
460 | "loopns", |
||
461 | "loopnz", |
||
462 | "loopo", |
||
463 | "loopp", |
||
464 | "looppe", |
||
465 | "looppo", |
||
466 | "loops", |
||
467 | "loopz", |
||
468 | "lsl", |
||
469 | "lss", |
||
470 | "ltr", |
||
471 | "lzcnt", |
||
472 | "maskmovdqu", |
||
473 | "maskmovq", |
||
474 | "maxpd", |
||
475 | "maxps", |
||
476 | "maxsd", |
||
477 | "maxss", |
||
478 | "mfence", |
||
479 | "minpd", |
||
480 | "minps", |
||
481 | "minsd", |
||
482 | "minss", |
||
483 | "monitor", |
||
484 | "mov", |
||
485 | "movapd", |
||
486 | "movaps", |
||
487 | "movbe", |
||
488 | "movd", |
||
489 | "movddup", |
||
490 | "movdir64b", |
||
491 | "movdiri", |
||
492 | "movdq2q", |
||
493 | "movdqa", |
||
494 | "movdqu", |
||
495 | "movhlps", |
||
496 | "movhpd", |
||
497 | "movhps", |
||
498 | "movlhps", |
||
499 | "movlpd", |
||
500 | "movlps", |
||
501 | "movmskpd", |
||
502 | "movmskps", |
||
503 | "movntdq", |
||
504 | "movntdqa", |
||
505 | "movnti", |
||
506 | "movntpd", |
||
507 | "movntps", |
||
508 | "movntq", |
||
509 | "movq", |
||
510 | "movq", |
||
511 | "movq2dq", |
||
512 | "movs", |
||
513 | "movsb", |
||
514 | "movsd", |
||
515 | "movsd", |
||
516 | "movshdup", |
||
517 | "movsldup", |
||
518 | "movsq", |
||
519 | "movss", |
||
520 | "movsw", |
||
521 | "movsx", |
||
522 | "movsxd", |
||
523 | "movupd", |
||
524 | "movups", |
||
525 | "movzx", |
||
526 | "mpsadbw", |
||
527 | "mul", |
||
528 | "mulpd", |
||
529 | "mulps", |
||
530 | "mulsd", |
||
531 | "mulss", |
||
532 | "mulx", |
||
533 | "mwait", |
||
534 | "neg", |
||
535 | "nop", |
||
536 | "not", |
||
537 | "or", |
||
538 | "orpd", |
||
539 | "orps", |
||
540 | "out", |
||
541 | "outs", |
||
542 | "outsb", |
||
543 | "outsd", |
||
544 | "outsw", |
||
545 | "pabsb", |
||
546 | "pabsd", |
||
547 | "pabsq", |
||
548 | "pabsw", |
||
549 | "packssdw", |
||
550 | "packsswb", |
||
551 | "packusdw", |
||
552 | "packuswb", |
||
553 | "paddb", |
||
554 | "paddd", |
||
555 | "paddq", |
||
556 | "paddsb", |
||
557 | "paddsw", |
||
558 | "paddusb", |
||
559 | "paddusw", |
||
560 | "paddw", |
||
561 | "palignr", |
||
562 | "pand", |
||
563 | "pandn", |
||
564 | "pause", |
||
565 | "pavgb", |
||
566 | "pavgw", |
||
567 | "pblendvb", |
||
568 | "pblendw", |
||
569 | "pclmulqdq", |
||
570 | "pcmpeqb", |
||
571 | "pcmpeqd", |
||
572 | "pcmpeqq", |
||
573 | "pcmpeqw", |
||
574 | "pcmpestri", |
||
575 | "pcmpestrm", |
||
576 | "pcmpgtb", |
||
577 | "pcmpgtd", |
||
578 | "pcmpgtq", |
||
579 | "pcmpgtw", |
||
580 | "pcmpistri", |
||
581 | "pcmpistrm", |
||
582 | "pdep", |
||
583 | "pext", |
||
584 | "pextrb", |
||
585 | "pextrd", |
||
586 | "pextrq", |
||
587 | "pextrw", |
||
588 | "phaddd", |
||
589 | "phaddsw", |
||
590 | "phaddw", |
||
591 | "phminposuw", |
||
592 | "phsubd", |
||
593 | "phsubsw", |
||
594 | "phsubw", |
||
595 | "pinsrb", |
||
596 | "pinsrd", |
||
597 | "pinsrq", |
||
598 | "pinsrw", |
||
599 | "pmaddubsw", |
||
600 | "pmaddwd", |
||
601 | "pmaxsb", |
||
602 | "pmaxsd", |
||
603 | "pmaxsq", |
||
604 | "pmaxsw", |
||
605 | "pmaxub", |
||
606 | "pmaxud", |
||
607 | "pmaxuq", |
||
608 | "pmaxuw", |
||
609 | "pminsb", |
||
610 | "pminsd", |
||
611 | "pminsq", |
||
612 | "pminsw", |
||
613 | "pminub", |
||
614 | "pminud", |
||
615 | "pminuq", |
||
616 | "pminuw", |
||
617 | "pmovmskb", |
||
618 | "pmovsx", |
||
619 | "pmovzx", |
||
620 | "pmuldq", |
||
621 | "pmulhrsw", |
||
622 | "pmulhuw", |
||
623 | "pmulhw", |
||
624 | "pmulld", |
||
625 | "pmullq", |
||
626 | "pmullw", |
||
627 | "pmuludq", |
||
628 | "pop", |
||
629 | "popa", |
||
630 | "popad", |
||
631 | "popcnt", |
||
632 | "popf", |
||
633 | "popfd", |
||
634 | "popfq", |
||
635 | "por", |
||
636 | "prefetchw", |
||
637 | "prefetchh", |
||
638 | "psadbw", |
||
639 | "pshufb", |
||
640 | "pshufd", |
||
641 | "pshufhw", |
||
642 | "pshuflw", |
||
643 | "pshufw", |
||
644 | "psignb", |
||
645 | "psignd", |
||
646 | "psignw", |
||
647 | "pslld", |
||
648 | "pslldq", |
||
649 | "psllq", |
||
650 | "psllw", |
||
651 | "psrad", |
||
652 | "psraq", |
||
653 | "psraw", |
||
654 | "psrld", |
||
655 | "psrldq", |
||
656 | "psrlq", |
||
657 | "psrlw", |
||
658 | "psubb", |
||
659 | "psubd", |
||
660 | "psubq", |
||
661 | "psubsb", |
||
662 | "psubsw", |
||
663 | "psubusb", |
||
664 | "psubusw", |
||
665 | "psubw", |
||
666 | "ptest", |
||
667 | "ptwrite", |
||
668 | "punpckhbw", |
||
669 | "punpckhdq", |
||
670 | "punpckhqdq", |
||
671 | "punpckhwd", |
||
672 | "punpcklbw", |
||
673 | "punpckldq", |
||
674 | "punpcklqdq", |
||
675 | "punpcklwd", |
||
676 | "push", |
||
677 | "pushw", |
||
678 | "pushd", |
||
679 | "pusha", |
||
680 | "pushad", |
||
681 | "pushf", |
||
682 | "pushfd", |
||
683 | "pushfq", |
||
684 | "pxor", |
||
685 | "rcl", |
||
686 | "rcpps", |
||
687 | "rcpss", |
||
688 | "rcr", |
||
689 | "rdfsbase", |
||
690 | "rdgsbase", |
||
691 | "rdmsr", |
||
692 | "rdpid", |
||
693 | "rdpkru", |
||
694 | "rdpmc", |
||
695 | "rdrand", |
||
696 | "rdseed", |
||
697 | "rdtsc", |
||
698 | "rdtscp", |
||
699 | "rep", |
||
700 | "repe", |
||
701 | "repne", |
||
702 | "repnz", |
||
703 | "repz", |
||
704 | "ret", |
||
705 | "rol", |
||
706 | "ror", |
||
707 | "rorx", |
||
708 | "roundpd", |
||
709 | "roundps", |
||
710 | "roundsd", |
||
711 | "roundss", |
||
712 | "rsm", |
||
713 | "rsqrtps", |
||
714 | "rsqrtss", |
||
715 | "sahf", |
||
716 | "sal", |
||
717 | "sar", |
||
718 | "sarx", |
||
719 | "sbb", |
||
720 | "scas", |
||
721 | "scasb", |
||
722 | "scasd", |
||
723 | "scasw", |
||
724 | "seta", |
||
725 | "setae", |
||
726 | "setb", |
||
727 | "setbe", |
||
728 | "setc", |
||
729 | "sete", |
||
730 | "setg", |
||
731 | "setge", |
||
732 | "setl", |
||
733 | "setle", |
||
734 | "setna", |
||
735 | "setnae", |
||
736 | "setnb", |
||
737 | "setnbe", |
||
738 | "setnc", |
||
739 | "setne", |
||
740 | "setng", |
||
741 | "setnge", |
||
742 | "setnl", |
||
743 | "setnle", |
||
744 | "setno", |
||
745 | "setnp", |
||
746 | "setns", |
||
747 | "setnz", |
||
748 | "seto", |
||
749 | "setp", |
||
750 | "setpe", |
||
751 | "setpo", |
||
752 | "sets", |
||
753 | "setz", |
||
754 | "sfence", |
||
755 | "sgdt", |
||
756 | "sha1msg1", |
||
757 | "sha1msg2", |
||
758 | "sha1nexte", |
||
759 | "sha1rnds4", |
||
760 | "sha256msg1", |
||
761 | "sha256msg2", |
||
762 | "sha256rnds2", |
||
763 | "shl", |
||
764 | "shld", |
||
765 | "shlx", |
||
766 | "shr", |
||
767 | "shrd", |
||
768 | "shrx", |
||
769 | "shufpd", |
||
770 | "shufps", |
||
771 | "sidt", |
||
772 | "sldt", |
||
773 | "smsw", |
||
774 | "sqrtpd", |
||
775 | "sqrtps", |
||
776 | "sqrtsd", |
||
777 | "sqrtss", |
||
778 | "stac", |
||
779 | "stc", |
||
780 | "std", |
||
781 | "sti", |
||
782 | "stmxcsr", |
||
783 | "stos", |
||
784 | "stosb", |
||
785 | "stosd", |
||
786 | "stosq", |
||
787 | "stosw", |
||
788 | "str", |
||
789 | "sub", |
||
790 | "subpd", |
||
791 | "subps", |
||
792 | "subsd", |
||
793 | "subss", |
||
794 | "swapgs", |
||
795 | "syscall", |
||
796 | "sysenter", |
||
797 | "sysexit", |
||
798 | "sysret", |
||
799 | "test", |
||
800 | "tpause", |
||
801 | "tzcnt", |
||
802 | "ucomisd", |
||
803 | "ucomiss", |
||
804 | "ud", |
||
805 | "umonitor", |
||
806 | "umwait", |
||
807 | "unpckhpd", |
||
808 | "unpckhps", |
||
809 | "unpcklpd", |
||
810 | "unpcklps", |
||
811 | "valignd", |
||
812 | "valignq", |
||
813 | "vblendmpd", |
||
814 | "vblendmps", |
||
815 | "vbroadcast", |
||
816 | "vcompresspd", |
||
817 | "vcompressps", |
||
818 | "vcvtpd2qq", |
||
819 | "vcvtpd2udq", |
||
820 | "vcvtpd2uqq", |
||
821 | "vcvtph2ps", |
||
822 | "vcvtps2ph", |
||
823 | "vcvtps2qq", |
||
824 | "vcvtps2udq", |
||
825 | "vcvtps2uqq", |
||
826 | "vcvtqq2pd", |
||
827 | "vcvtqq2ps", |
||
828 | "vcvtsd2usi", |
||
829 | "vcvtss2usi", |
||
830 | "vcvttpd2qq", |
||
831 | "vcvttpd2udq", |
||
832 | "vcvttpd2uqq", |
||
833 | "vcvttps2qq", |
||
834 | "vcvttps2udq", |
||
835 | "vcvttps2uqq", |
||
836 | "vcvttsd2usi", |
||
837 | "vcvttss2usi", |
||
838 | "vcvtudq2pd", |
||
839 | "vcvtudq2ps", |
||
840 | "vcvtuqq2pd", |
||
841 | "vcvtuqq2ps", |
||
842 | "vcvtusi2sd", |
||
843 | "vcvtusi2ss", |
||
844 | "vdbpsadbw", |
||
845 | "verr", |
||
846 | "verw", |
||
847 | "vexpandpd", |
||
848 | "vexpandps", |
||
849 | "vextractf128", |
||
850 | "vextractf32x4", |
||
851 | "vextractf32x8", |
||
852 | "vextractf64x2", |
||
853 | "vextractf64x4", |
||
854 | "vextracti128", |
||
855 | "vextracti32x4", |
||
856 | "vextracti32x8", |
||
857 | "vextracti64x2", |
||
858 | "vextracti64x4", |
||
859 | "vfixupimmpd", |
||
860 | "vfixupimmps", |
||
861 | "vfixupimmsd", |
||
862 | "vfixupimmss", |
||
863 | "vfmadd132pd", |
||
864 | "vfmadd132ps", |
||
865 | "vfmadd132sd", |
||
866 | "vfmadd132ss", |
||
867 | "vfmadd213pd", |
||
868 | "vfmadd213ps", |
||
869 | "vfmadd213sd", |
||
870 | "vfmadd213ss", |
||
871 | "vfmadd231pd", |
||
872 | "vfmadd231ps", |
||
873 | "vfmadd231sd", |
||
874 | "vfmadd231ss", |
||
875 | "vfmaddsub132pd", |
||
876 | "vfmaddsub132ps", |
||
877 | "vfmaddsub213pd", |
||
878 | "vfmaddsub213ps", |
||
879 | "vfmaddsub231pd", |
||
880 | "vfmaddsub231ps", |
||
881 | "vfmsub132pd", |
||
882 | "vfmsub132ps", |
||
883 | "vfmsub132sd", |
||
884 | "vfmsub132ss", |
||
885 | "vfmsub213pd", |
||
886 | "vfmsub213ps", |
||
887 | "vfmsub213sd", |
||
888 | "vfmsub213ss", |
||
889 | "vfmsub231pd", |
||
890 | "vfmsub231ps", |
||
891 | "vfmsub231sd", |
||
892 | "vfmsub231ss", |
||
893 | "vfmsubadd132pd", |
||
894 | "vfmsubadd132ps", |
||
895 | "vfmsubadd213pd", |
||
896 | "vfmsubadd213ps", |
||
897 | "vfmsubadd231pd", |
||
898 | "vfmsubadd231ps", |
||
899 | "vfnmadd132pd", |
||
900 | "vfnmadd132ps", |
||
901 | "vfnmadd132sd", |
||
902 | "vfnmadd132ss", |
||
903 | "vfnmadd213pd", |
||
904 | "vfnmadd213ps", |
||
905 | "vfnmadd213sd", |
||
906 | "vfnmadd213ss", |
||
907 | "vfnmadd231pd", |
||
908 | "vfnmadd231ps", |
||
909 | "vfnmadd231sd", |
||
910 | "vfnmadd231ss", |
||
911 | "vfnmsub132pd", |
||
912 | "vfnmsub132ps", |
||
913 | "vfnmsub132sd", |
||
914 | "vfnmsub132ss", |
||
915 | "vfnmsub213pd", |
||
916 | "vfnmsub213ps", |
||
917 | "vfnmsub213sd", |
||
918 | "vfnmsub213ss", |
||
919 | "vfnmsub231pd", |
||
920 | "vfnmsub231ps", |
||
921 | "vfnmsub231sd", |
||
922 | "vfnmsub231ss", |
||
923 | "vfpclasspd", |
||
924 | "vfpclassps", |
||
925 | "vfpclasssd", |
||
926 | "vfpclassss", |
||
927 | "vgatherdpd", |
||
928 | "vgatherdpd", |
||
929 | "vgatherdps", |
||
930 | "vgatherdps", |
||
931 | "vgatherqpd", |
||
932 | "vgatherqpd", |
||
933 | "vgatherqps", |
||
934 | "vgatherqps", |
||
935 | "vgetexppd", |
||
936 | "vgetexpps", |
||
937 | "vgetexpsd", |
||
938 | "vgetexpss", |
||
939 | "vgetmantpd", |
||
940 | "vgetmantps", |
||
941 | "vgetmantsd", |
||
942 | "vgetmantss", |
||
943 | "vinsertf128", |
||
944 | "vinsertf32x4", |
||
945 | "vinsertf32x8", |
||
946 | "vinsertf64x2", |
||
947 | "vinsertf64x4", |
||
948 | "vinserti128", |
||
949 | "vinserti32x4", |
||
950 | "vinserti32x8", |
||
951 | "vinserti64x2", |
||
952 | "vinserti64x4", |
||
953 | "vmaskmov", |
||
954 | "vmovdqa32", |
||
955 | "vmovdqa64", |
||
956 | "vmovdqu16", |
||
957 | "vmovdqu32", |
||
958 | "vmovdqu64", |
||
959 | "vmovdqu8", |
||
960 | "vpblendd", |
||
961 | "vpblendmb", |
||
962 | "vpblendmd", |
||
963 | "vpblendmq", |
||
964 | "vpblendmw", |
||
965 | "vpbroadcast", |
||
966 | "vpbroadcastb", |
||
967 | "vpbroadcastd", |
||
968 | "vpbroadcastm", |
||
969 | "vpbroadcastq", |
||
970 | "vpbroadcastw", |
||
971 | "vpcmpb", |
||
972 | "vpcmpd", |
||
973 | "vpcmpq", |
||
974 | "vpcmpub", |
||
975 | "vpcmpud", |
||
976 | "vpcmpuq", |
||
977 | "vpcmpuw", |
||
978 | "vpcmpw", |
||
979 | "vpcompressd", |
||
980 | "vpcompressq", |
||
981 | "vpconflictd", |
||
982 | "vpconflictq", |
||
983 | "vperm2f128", |
||
984 | "vperm2i128", |
||
985 | "vpermb", |
||
986 | "vpermd", |
||
987 | "vpermi2b", |
||
988 | "vpermi2d", |
||
989 | "vpermi2pd", |
||
990 | "vpermi2ps", |
||
991 | "vpermi2q", |
||
992 | "vpermi2w", |
||
993 | "vpermilpd", |
||
994 | "vpermilps", |
||
995 | "vpermpd", |
||
996 | "vpermps", |
||
997 | "vpermq", |
||
998 | "vpermt2b", |
||
999 | "vpermt2d", |
||
1000 | "vpermt2pd", |
||
1001 | "vpermt2ps", |
||
1002 | "vpermt2q", |
||
1003 | "vpermt2w", |
||
1004 | "vpermw", |
||
1005 | "vpexpandd", |
||
1006 | "vpexpandq", |
||
1007 | "vpgatherdd", |
||
1008 | "vpgatherdd", |
||
1009 | "vpgatherdq", |
||
1010 | "vpgatherdq", |
||
1011 | "vpgatherqd", |
||
1012 | "vpgatherqd", |
||
1013 | "vpgatherqq", |
||
1014 | "vpgatherqq", |
||
1015 | "vplzcntd", |
||
1016 | "vplzcntq", |
||
1017 | "vpmadd52huq", |
||
1018 | "vpmadd52luq", |
||
1019 | "vpmaskmov", |
||
1020 | "vpmovb2m", |
||
1021 | "vpmovd2m", |
||
1022 | "vpmovdb", |
||
1023 | "vpmovdw", |
||
1024 | "vpmovm2b", |
||
1025 | "vpmovm2d", |
||
1026 | "vpmovm2q", |
||
1027 | "vpmovm2w", |
||
1028 | "vpmovq2m", |
||
1029 | "vpmovqb", |
||
1030 | "vpmovqd", |
||
1031 | "vpmovqw", |
||
1032 | "vpmovsdb", |
||
1033 | "vpmovsdw", |
||
1034 | "vpmovsqb", |
||
1035 | "vpmovsqd", |
||
1036 | "vpmovsqw", |
||
1037 | "vpmovswb", |
||
1038 | "vpmovusdb", |
||
1039 | "vpmovusdw", |
||
1040 | "vpmovusqb", |
||
1041 | "vpmovusqd", |
||
1042 | "vpmovusqw", |
||
1043 | "vpmovuswb", |
||
1044 | "vpmovw2m", |
||
1045 | "vpmovwb", |
||
1046 | "vpmultishiftqb", |
||
1047 | "vprold", |
||
1048 | "vprolq", |
||
1049 | "vprolvd", |
||
1050 | "vprolvq", |
||
1051 | "vprord", |
||
1052 | "vprorq", |
||
1053 | "vprorvd", |
||
1054 | "vprorvq", |
||
1055 | "vpscatterdd", |
||
1056 | "vpscatterdq", |
||
1057 | "vpscatterqd", |
||
1058 | "vpscatterqq", |
||
1059 | "vpsllvd", |
||
1060 | "vpsllvq", |
||
1061 | "vpsllvw", |
||
1062 | "vpsravd", |
||
1063 | "vpsravq", |
||
1064 | "vpsravw", |
||
1065 | "vpsrlvd", |
||
1066 | "vpsrlvq", |
||
1067 | "vpsrlvw", |
||
1068 | "vpternlogd", |
||
1069 | "vpternlogq", |
||
1070 | "vptestmb", |
||
1071 | "vptestmd", |
||
1072 | "vptestmq", |
||
1073 | "vptestmw", |
||
1074 | "vptestnmb", |
||
1075 | "vptestnmd", |
||
1076 | "vptestnmq", |
||
1077 | "vptestnmw", |
||
1078 | "vrangepd", |
||
1079 | "vrangeps", |
||
1080 | "vrangesd", |
||
1081 | "vrangess", |
||
1082 | "vrcp14pd", |
||
1083 | "vrcp14ps", |
||
1084 | "vrcp14sd", |
||
1085 | "vrcp14ss", |
||
1086 | "vreducepd", |
||
1087 | "vreduceps", |
||
1088 | "vreducesd", |
||
1089 | "vreducess", |
||
1090 | "vrndscalepd", |
||
1091 | "vrndscaleps", |
||
1092 | "vrndscalesd", |
||
1093 | "vrndscaless", |
||
1094 | "vrsqrt14pd", |
||
1095 | "vrsqrt14ps", |
||
1096 | "vrsqrt14sd", |
||
1097 | "vrsqrt14ss", |
||
1098 | "vscalefpd", |
||
1099 | "vscalefps", |
||
1100 | "vscalefsd", |
||
1101 | "vscalefss", |
||
1102 | "vscatterdpd", |
||
1103 | "vscatterdps", |
||
1104 | "vscatterqpd", |
||
1105 | "vscatterqps", |
||
1106 | "vshuff32x4", |
||
1107 | "vshuff64x2", |
||
1108 | "vshufi32x4", |
||
1109 | "vshufi64x2", |
||
1110 | "vtestpd", |
||
1111 | "vtestps", |
||
1112 | "vzeroall", |
||
1113 | "vzeroupper", |
||
1114 | "wait", |
||
1115 | "wbinvd", |
||
1116 | "wrfsbase", |
||
1117 | "wrgsbase", |
||
1118 | "wrmsr", |
||
1119 | "wrpkru", |
||
1120 | "xabort", |
||
1121 | "xacquire", |
||
1122 | "xadd", |
||
1123 | "xbegin", |
||
1124 | "xchg", |
||
1125 | "xend", |
||
1126 | "xgetbv", |
||
1127 | "xlat", |
||
1128 | "xlatb", |
||
1129 | "xor", |
||
1130 | "xorpd", |
||
1131 | "xorps", |
||
1132 | "xrelease", |
||
1133 | "xrstor", |
||
1134 | "xrstors", |
||
1135 | "xsave", |
||
1136 | "xsavec", |
||
1137 | "xsaveopt", |
||
1138 | "xsaves", |
||
1139 | "xsetbv", |
||
1140 | "xtest" |
||
1141 | ] |
||
1142 | |||
1143 | fasm_types = [ |
||
1144 | "db", "rb", |
||
1145 | "dw", "rw", |
||
1146 | "dd", "rd", |
||
1147 | "dp", "rp", |
||
1148 | "df", "rf", |
||
1149 | "dq", "rq", |
||
1150 | "dt", "rt", |
||
1151 | "du", |
||
1152 | ] |
||
1153 | |||
8976 | Boppan | 1154 | # Dict where an identifier is assicoated with a string |
1155 | # The string contains characters specifying flags |
||
1156 | # Available flags: |
||
1157 | # k - Keyword |
||
1158 | # m - Macro name |
||
1159 | # t - fasm data Type name (db, rq, etc.) |
||
1160 | # s - Struct type name |
||
1161 | # e - equated constant (name equ value) |
||
1162 | # = - set constants (name = value) |
||
1163 | ID_KIND_KEYWORD = 'k' |
||
1164 | ID_KIND_MACRO_NAME = 'm' |
||
1165 | ID_KIND_FASM_TYPE = 't' |
||
1166 | ID_KIND_STRUCT_NAME = 's' |
||
1167 | ID_KIND_EQUATED_CONSTANT = 'e' |
||
1168 | ID_KIND_SET_CONSTANT = '=' |
||
1169 | id2kind = {} |
||
1170 | |||
1171 | # Add kind flag to identifier in id2kind |
||
1172 | def id_add_kind(identifier, kind): |
||
1173 | if identifier not in id2kind: |
||
1174 | id2kind[identifier] = '' |
||
1175 | id2kind[identifier] += kind |
||
1176 | |||
1177 | # Remove kind flag of identifier in id2kind |
||
1178 | def id_remove_kind(identifier, kind): |
||
1179 | if identifier in id2kind: |
||
1180 | if kind in id2kind[identifier]: |
||
1181 | id2kind[identifier] = id2kind[identifier].replace(kind, '') |
||
1182 | |||
1183 | # Get kind of an identifier |
||
1184 | def id_get_kind(identifier): |
||
1185 | if identifier in id2kind: |
||
1186 | return id2kind[identifier] |
||
1187 | else: |
||
1188 | return '' |
||
1189 | |||
1190 | for keyword in keywords: |
||
1191 | id_add_kind(keyword, ID_KIND_KEYWORD) |
||
1192 | |||
1193 | for fasm_type in fasm_types: |
||
1194 | id_add_kind(fasm_type, ID_KIND_FASM_TYPE) |
||
1195 | |||
8855 | Boppan | 1196 | # Warning list |
1197 | warnings = "" |
||
1198 | |||
8837 | Boppan | 1199 | # Parse arguments |
1200 | parser = argparse.ArgumentParser() |
||
1201 | parser.add_argument("-o", help="Doxygen output folder") |
||
1202 | parser.add_argument("--clean", help="Remove generated files", action="store_true") |
||
1203 | parser.add_argument("--dump", help="Dump all defined symbols", action="store_true") |
||
1204 | parser.add_argument("--stats", help="Print symbol stats", action="store_true") |
||
8855 | Boppan | 1205 | parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true") |
8976 | Boppan | 1206 | parser.add_argument("--noemit", help="Do not emit doxygen files (for testing)", action="store_true") |
8837 | Boppan | 1207 | args = parser.parse_args() |
1208 | doxygen_src_path = args.o if args.o else 'docs/doxygen' |
||
1209 | clean_generated_stuff = args.clean |
||
1210 | dump_symbols = args.dump |
||
1211 | print_stats = args.stats |
||
8855 | Boppan | 1212 | enable_warnings = not args.nowarn |
8976 | Boppan | 1213 | noemit = args.noemit |
8837 | Boppan | 1214 | |
8957 | Boppan | 1215 | # Variables, functions, labels, macros, structure types |
1216 | elements = [] |
||
8825 | Boppan | 1217 | |
8957 | Boppan | 1218 | class LegacyAsmReader: |
1219 | def __init__(self, file): |
||
1220 | self.file = file |
||
1221 | self.lines = open(file, "r", encoding="utf-8").readlines() |
||
1222 | self.line_idx = 0 |
||
1223 | self.i = 0 |
||
1224 | |||
1225 | def curr(self): |
||
1226 | try: return self.lines[self.line_idx][self.i] |
||
1227 | except: return '' |
||
1228 | |||
1229 | def step(self): |
||
1230 | c = self.curr() |
||
1231 | self.i += 1 |
||
1232 | # Wrap the line if '\\' followed by whitespaces and/or comment |
||
1233 | while self.curr() == '\\': |
||
1234 | i_of_backslash = self.i |
||
1235 | self.i += 1 |
||
1236 | while self.curr().isspace(): |
||
1237 | self.i += 1 |
||
1238 | if self.curr() == ';' or self.curr() == '': |
||
1239 | self.line_idx += 1 |
||
1240 | self.i = 0 |
||
1241 | else: |
||
1242 | # There's something other than a comment after the backslash |
||
1243 | # So don't interpret the backslash as a line wrap |
||
1244 | self.i = i_of_backslash |
||
1245 | break |
||
1246 | return c |
||
1247 | |||
1248 | def nextline(self): |
||
1249 | c = self.curr() |
||
1250 | while c != '': |
||
1251 | c = self.step() |
||
1252 | self.line_idx += 1 |
||
1253 | self.i = 0 |
||
1254 | |||
1255 | def no_lines(self): |
||
1256 | if self.line_idx >= len(self.lines): |
||
1257 | return True |
||
1258 | return False |
||
1259 | |||
1260 | def location(self): |
||
1261 | return f"{self.file}:{self.line_idx + 1}" |
||
1262 | |||
1263 | def skip_spaces(self): |
||
1264 | while self.curr().isspace(): |
||
1265 | self.step() |
||
1266 | |||
1267 | class AsmReaderRecognizingStrings(LegacyAsmReader): |
||
1268 | def __init__(self, file): |
||
1269 | super().__init__(file) |
||
1270 | self.in_string = None |
||
1271 | self.should_recognize_strings = True |
||
1272 | |||
1273 | def step(self): |
||
1274 | c = super().step() |
||
1275 | if self.should_recognize_strings and (c == '"' or c == "'"): |
||
1276 | # If just now we was at the double or single quotation mark |
||
1277 | # and we aren't in a string yet |
||
1278 | # then say "we are in a string openned with this quotation mark now" |
||
1279 | if self.in_string == None: |
||
1280 | self.in_string = c |
||
1281 | # If just now we was at the double or single quotation mark |
||
1282 | # and we are in the string entered with the same quotation mark |
||
1283 | # then say "we aren't in a string anymore" |
||
1284 | elif self.in_string == c: |
||
1285 | self.in_string = None |
||
1286 | return c |
||
1287 | |||
1288 | class AsmReaderReadingComments(AsmReaderRecognizingStrings): |
||
1289 | def __init__(self, file): |
||
1290 | super().__init__(file) |
||
1291 | self.status = dict() |
||
1292 | self.status_reset() |
||
1293 | self.comment = '' |
||
1294 | |||
1295 | def status_reset(self): |
||
1296 | # If the line has non-comment code |
||
8974 | Boppan | 1297 | self.status_has_code = False |
8957 | Boppan | 1298 | # If the line has a comment at the end |
8974 | Boppan | 1299 | self.status_has_comment = False |
8957 | Boppan | 1300 | # Let it recognize strings further, we are definitely out of a comment |
1301 | self.should_recognize_strings = True |
||
1302 | |||
1303 | def status_set_has_comment(self): |
||
8974 | Boppan | 1304 | self.status_has_comment = True |
8957 | Boppan | 1305 | # Don't let it recognize strings cause we are in a comment now |
1306 | self.should_recognize_strings = False |
||
1307 | |||
1308 | def status_set_has_code(self): |
||
8974 | Boppan | 1309 | self.status_has_code = True |
8957 | Boppan | 1310 | |
1311 | def update_status(self): |
||
1312 | # If we aren't in a comment and we aren't in a string - say we are now in a comment if ';' met |
||
8974 | Boppan | 1313 | if not self.status_has_comment and not self.in_string and self.curr() == ';': |
8957 | Boppan | 1314 | self.status_set_has_comment() |
1315 | # Else if we are in a comment - collect the comment |
||
8974 | Boppan | 1316 | elif self.status_has_comment: |
8957 | Boppan | 1317 | self.comment += self.curr() |
1318 | # Else if there's some non-whitespace character out of a comment |
||
1319 | # then the line has code |
||
8974 | Boppan | 1320 | elif not self.status_has_comment and not self.curr().isspace(): |
8957 | Boppan | 1321 | self.status_set_has_code() |
1322 | |||
1323 | def step(self): |
||
1324 | # Get to the next character |
||
1325 | c = super().step() |
||
1326 | # Update status of the line according to the next character |
||
1327 | self.update_status() |
||
1328 | return c |
||
1329 | |||
1330 | def nextline(self): |
||
1331 | super().nextline() |
||
1332 | # If the line we leave was not a comment-only line |
||
1333 | # then forget the collected comment |
||
1334 | # Otherwise the collected comment should be complemented by comment from next line in step() |
||
8974 | Boppan | 1335 | if self.status_has_code: |
8957 | Boppan | 1336 | self.comment = '' |
1337 | # Reset the line status (now it's the status of the new line) |
||
1338 | self.status_reset() |
||
1339 | # Set new status for this line according to the first character in the line |
||
1340 | self.update_status() |
||
1341 | |||
8963 | Boppan | 1342 | class AsmReaderFetchingIdentifiers(AsmReaderReadingComments): |
8957 | Boppan | 1343 | def __init__(self, file): |
1344 | super().__init__(file) |
||
1345 | |||
8963 | Boppan | 1346 | def fetch_identifier(self): |
1347 | self.skip_spaces() |
||
1348 | result = '' |
||
1349 | while is_id(self.curr()): |
||
1350 | result += self.step() |
||
1351 | return result |
||
1352 | |||
1353 | class AsmReader(AsmReaderFetchingIdentifiers): |
||
1354 | def __init__(self, file): |
||
1355 | super().__init__(file) |
||
1356 | |||
8957 | Boppan | 1357 | created_files = [] |
1358 | |||
1359 | class AsmElement: |
||
1360 | def __init__(self, location, name, comment): |
||
8980 | Boppan | 1361 | global warnings |
1362 | |||
8990 | Boppan | 1363 | # If the element was constructed during this execution then the element is new |
1364 | self.new = True |
||
8957 | Boppan | 1365 | self.location = location |
1366 | self.file = self.location.split(':')[0].replace('\\', '/') |
||
1367 | self.line = self.location.split(':')[1] |
||
8855 | Boppan | 1368 | self.name = name |
8957 | Boppan | 1369 | self.comment = comment |
1370 | |||
8980 | Boppan | 1371 | if self.comment == '': |
1372 | warnings += f'{self.location}: Undocumented element\n' |
||
1373 | |||
8957 | Boppan | 1374 | def dump(self): |
9030 | Boppan | 1375 | print(f"\n{self.location}: {self.name}") |
8957 | Boppan | 1376 | print(f"{self.comment}") |
1377 | |||
1378 | def emit(self, dest, doxycomment = '', declaration = ''): |
||
8977 | Boppan | 1379 | # Do not emit anything if the symbol is marked as hidden in its comment |
1380 | if '@dont_give_a_doxygen' in self.comment: |
||
1381 | return |
||
1382 | |||
8957 | Boppan | 1383 | global warnings |
1384 | # Redefine default declaration |
||
1385 | if declaration == '': |
||
1386 | declaration = f'#define {self.name}' |
||
1387 | # Check doxycomment |
||
1388 | if not doxycomment.endswith('\n'): |
||
1389 | doxycomment += '\n' |
||
1390 | if doxycomment.split('@brief ')[1][0].islower(): |
||
1391 | warnings += f"{self.location}: Brief comment starting from lowercase\n" |
||
1392 | # Build contents to emit |
||
1393 | contents = '' |
||
1394 | contents += '/**\n' |
||
1395 | contents += doxycomment |
||
1396 | contents += (f"@par Source\n" + |
||
1397 | f"{self.file}:{self.line}\n") |
||
1398 | contents += '*/\n' |
||
1399 | contents += declaration |
||
1400 | contents += '\n\n' |
||
1401 | # Get path to file to emit this |
||
1402 | full_path = dest + '/' + self.file |
||
1403 | # Remove the file on first access if it was created by previous generation |
||
1404 | if full_path not in created_files: |
||
1405 | if os.path.isfile(full_path): |
||
1406 | os.remove(full_path) |
||
1407 | created_files.append(full_path) |
||
1408 | # Create directories need for the file |
||
1409 | os.makedirs(os.path.dirname(full_path), exist_ok=True) |
||
1410 | f = open(full_path, "a") |
||
1411 | contents = ''.join([i if ord(i) < 128 else '?' for i in contents]) |
||
1412 | f.write(contents) |
||
1413 | f.close() |
||
1414 | |||
1415 | class AsmVariable(AsmElement): |
||
1416 | def __init__(self, location, name, comment, type, init): |
||
1417 | super().__init__(location, name, comment) |
||
8855 | Boppan | 1418 | self.type = type |
1419 | self.init = init |
||
1420 | |||
8957 | Boppan | 1421 | def dump(self): |
1422 | super().dump() |
||
9030 | Boppan | 1423 | print(f"(Variable)\n---") |
8855 | Boppan | 1424 | |
8957 | Boppan | 1425 | def emit(self, dest): |
1426 | # Build doxycomment specific for the variable |
||
1427 | doxycomment = '' |
||
1428 | doxycomment += self.comment |
||
1429 | if '@brief' not in doxycomment: |
||
1430 | doxycomment = '@brief ' + doxycomment |
||
1431 | doxycomment += (f"@par Initial value\n" + |
||
1432 | f"{self.init}\n") |
||
1433 | # Build the declaration |
||
1434 | name = self.name.replace(".", "_") |
||
1435 | var_type = self.type.replace(".", "_") |
||
1436 | declaration = f"{var_type} {name};" |
||
1437 | # Emit this |
||
1438 | super().emit(dest, doxycomment, declaration) |
||
8855 | Boppan | 1439 | |
8957 | Boppan | 1440 | class AsmFunction(AsmElement): |
8963 | Boppan | 1441 | def __init__(self, location, name, comment, calling_convention, args, used_regs): |
8957 | Boppan | 1442 | super().__init__(location, name, comment) |
8963 | Boppan | 1443 | self.calling_convention = calling_convention |
1444 | self.args = args |
||
1445 | self.used_regs = used_regs |
||
8855 | Boppan | 1446 | |
8957 | Boppan | 1447 | def dump(self): |
1448 | super().dump() |
||
9030 | Boppan | 1449 | print(f"(Function)\n---") |
8855 | Boppan | 1450 | |
8957 | Boppan | 1451 | def emit(self, dest): |
1452 | # Build doxycomment specific for the variable |
||
1453 | doxycomment = '' |
||
1454 | doxycomment += self.comment |
||
1455 | if '@brief' not in doxycomment: |
||
1456 | doxycomment = '@brief ' + doxycomment |
||
9028 | Boppan | 1457 | # If there was no arguments, maybe that's just a label |
1458 | # then parse parameters from its comment |
||
1459 | if len(self.args) == 0 and '@param' in self.comment: |
||
1460 | i = 0 |
||
1461 | while '@param' in self.comment[i:]: |
||
1462 | i = self.comment.index('@param', i) |
||
1463 | # Skip '@param' |
||
1464 | i += len('@param') |
||
1465 | # Skip spaces after '@param' |
||
1466 | while self.comment[i].isspace(): |
||
1467 | i += 1 |
||
1468 | # Get the parameter name |
||
1469 | name = '' |
||
1470 | while is_id(self.comment[i]): |
||
1471 | name += self.comment[i] |
||
1472 | i += 1 |
||
1473 | # Save the parameter |
||
1474 | self.args.append((name, 'arg_t')) |
||
8963 | Boppan | 1475 | # Build the arg list for declaration |
1476 | arg_list = '(' |
||
1477 | if len(self.args) > 0: |
||
1478 | argc = 0 |
||
1479 | for arg in self.args: |
||
1480 | if argc != 0: |
||
1481 | arg_list += ", " |
||
1482 | arg_list += f"{arg[1]} {arg[0]}" |
||
1483 | argc += 1 |
||
1484 | arg_list += ')' |
||
8957 | Boppan | 1485 | # Build the declaration |
1486 | name = self.name.replace(".", "_") |
||
8963 | Boppan | 1487 | declaration = f"void {name}{arg_list};" |
8957 | Boppan | 1488 | # Emit this |
1489 | super().emit(dest, doxycomment, declaration) |
||
8855 | Boppan | 1490 | |
8957 | Boppan | 1491 | class AsmLabel(AsmElement): |
1492 | def __init__(self, location, name, comment): |
||
1493 | super().__init__(location, name, comment) |
||
8855 | Boppan | 1494 | |
8957 | Boppan | 1495 | def dump(self): |
1496 | super().dump() |
||
9030 | Boppan | 1497 | print(f"(Label)\n---") |
8855 | Boppan | 1498 | |
8957 | Boppan | 1499 | def emit(self, dest): |
1500 | # Build doxycomment specific for the variable |
||
1501 | doxycomment = '' |
||
1502 | doxycomment += self.comment |
||
1503 | if '@brief' not in doxycomment: |
||
1504 | doxycomment = '@brief ' + doxycomment |
||
1505 | # Build the declaration |
||
1506 | name = self.name.replace(".", "_") |
||
1507 | declaration = f"label {name};" |
||
1508 | # Emit this |
||
1509 | super().emit(dest, doxycomment, declaration) |
||
8855 | Boppan | 1510 | |
8957 | Boppan | 1511 | class AsmMacro(AsmElement): |
1512 | def __init__(self, location, name, comment, args): |
||
1513 | super().__init__(location, name, comment) |
||
1514 | self.args = args |
||
8855 | Boppan | 1515 | |
8957 | Boppan | 1516 | def dump(self): |
1517 | super().dump() |
||
9030 | Boppan | 1518 | print(f"(Macro)\n---") |
8855 | Boppan | 1519 | |
8957 | Boppan | 1520 | def emit(self, dest): |
1521 | # Construct arg list without '['s, ']'s and '*'s |
||
1522 | args = [arg for arg in self.args if arg not in "[]*"] |
||
1523 | # Construct C-like arg list |
||
1524 | arg_list = "" |
||
1525 | if len(args) > 0: |
||
1526 | arg_list += '(' |
||
1527 | argc = 0 |
||
1528 | for arg in args: |
||
1529 | if argc != 0: |
||
1530 | arg_list += ", " |
||
1531 | arg_list += arg |
||
1532 | argc += 1 |
||
1533 | arg_list += ')' |
||
1534 | # Build doxycomment |
||
1535 | doxycomment = '' |
||
1536 | doxycomment += self.comment |
||
1537 | if '@brief' not in doxycomment: |
||
1538 | doxycomment = '@brief ' + doxycomment |
||
1539 | # Build declaration |
||
1540 | declaration = f"#define {self.name}{arg_list}" |
||
1541 | # Emit this |
||
1542 | super().emit(dest, doxycomment, declaration) |
||
8855 | Boppan | 1543 | |
8957 | Boppan | 1544 | class AsmStruct(AsmElement): |
1545 | def __init__(self, location, name, comment, members): |
||
1546 | super().__init__(location, name, comment) |
||
1547 | self.members = members |
||
8855 | Boppan | 1548 | |
8957 | Boppan | 1549 | def dump(self): |
1550 | super().dump() |
||
9030 | Boppan | 1551 | print(f"(Struct)\n---") |
8855 | Boppan | 1552 | |
8957 | Boppan | 1553 | def emit(self, dest): |
1554 | # Build doxycomment |
||
1555 | doxycomment = '' |
||
1556 | doxycomment += self.comment |
||
1557 | if '@brief' not in doxycomment: |
||
1558 | doxycomment = '@brief ' + doxycomment |
||
8958 | Boppan | 1559 | doxycomment += '\n' |
8957 | Boppan | 1560 | # Build declaration |
8958 | Boppan | 1561 | declaration = f"struct {self.name}" + " {\n" |
1562 | for member in self.members: |
||
1563 | if type(member) == AsmVariable: |
||
1564 | declaration += f'\t{member.type} {member.name}; /**< {member.comment} */\n' |
||
1565 | declaration += '};' |
||
8957 | Boppan | 1566 | # Emit this |
1567 | super().emit(dest, doxycomment, declaration) |
||
8855 | Boppan | 1568 | |
8957 | Boppan | 1569 | class AsmUnion(AsmElement): |
1570 | def __init__(self, location, name, comment, members): |
||
1571 | super().__init__(location, name, comment) |
||
1572 | self.members = members |
||
8855 | Boppan | 1573 | |
8957 | Boppan | 1574 | def dump(self): |
1575 | super().dump() |
||
9030 | Boppan | 1576 | print(f"(Union)\n---") |
8855 | Boppan | 1577 | |
8957 | Boppan | 1578 | def emit(self, dest): |
1579 | # Build doxycomment |
||
1580 | doxycomment = '' |
||
1581 | doxycomment += self.comment |
||
1582 | if '@brief' not in doxycomment: |
||
1583 | doxycomment = '@brief ' + doxycomment |
||
1584 | # Build declaration |
||
1585 | declaration = f"union {self.name}" + " {};" |
||
1586 | # Emit this |
||
1587 | super().emit(dest, doxycomment, declaration) |
||
8855 | Boppan | 1588 | |
8957 | Boppan | 1589 | class VariableNameIsMacroName: |
1590 | def __init__(self, name): |
||
1591 | self.name = name |
||
8855 | Boppan | 1592 | |
8957 | Boppan | 1593 | def is_id(c): |
1594 | return c.isprintable() and c not in "+-/*=<>()[]{};:,|&~#`'\" \n\r\t\v" |
||
8855 | Boppan | 1595 | |
8957 | Boppan | 1596 | def is_starts_as_id(s): |
1597 | return not s[0].isdigit() |
||
1598 | |||
1599 | def parse_after_macro(r): |
||
1600 | location = r.location() |
||
1601 | |||
1602 | # Skip spaces after the "macro" keyword |
||
1603 | r.skip_spaces() |
||
8855 | Boppan | 1604 | # Read macro name |
1605 | name = "" |
||
8957 | Boppan | 1606 | while is_id(r.curr()) or r.curr() == '#': |
1607 | name += r.step() |
||
8855 | Boppan | 1608 | # Skip spaces after macro name |
8957 | Boppan | 1609 | r.skip_spaces() |
8855 | Boppan | 1610 | # Find all arguments |
1611 | args = [] |
||
1612 | arg = '' |
||
8957 | Boppan | 1613 | while r.curr() and r.curr() != ';' and r.curr() != '{': |
8855 | Boppan | 1614 | # Collect identifier |
8957 | Boppan | 1615 | if is_id(r.curr()): |
1616 | arg += r.step() |
||
8855 | Boppan | 1617 | # Save the collected identifier |
8957 | Boppan | 1618 | elif r.curr() == ',': |
8855 | Boppan | 1619 | args.append(arg) |
1620 | arg = '' |
||
8957 | Boppan | 1621 | r.step() |
8855 | Boppan | 1622 | # Just push the '[' |
8957 | Boppan | 1623 | elif r.curr() == '[': |
1624 | args.append(r.step()) |
||
8855 | Boppan | 1625 | # Just push the identifier and get ']' ready to be pushed on next comma |
8957 | Boppan | 1626 | elif r.curr() == ']': |
8855 | Boppan | 1627 | args.append(arg) |
8957 | Boppan | 1628 | arg = r.step() |
8855 | Boppan | 1629 | # Just push the identifier and get '*' ready to be pushed on next comma |
8957 | Boppan | 1630 | elif r.curr() == '*': |
8855 | Boppan | 1631 | args.append(arg) |
8957 | Boppan | 1632 | arg = r.step() |
8855 | Boppan | 1633 | # Just skip whitespaces |
8957 | Boppan | 1634 | elif r.curr().isspace(): |
1635 | r.step() |
||
8855 | Boppan | 1636 | # Something unexpected |
1637 | else: |
||
8957 | Boppan | 1638 | raise Exception(f"Unexpected symbol '{r.curr()}' at index #{r.i} " + |
1639 | f"in the macro declaration at {location} " + |
||
1640 | f"(line: {r.lines[r.line_idx]})\n''") |
||
1641 | # Append the last argument |
||
8855 | Boppan | 1642 | if arg != '': |
1643 | args.append(arg) |
||
8957 | Boppan | 1644 | # Skip t spaces after the argument list |
1645 | r.skip_spaces() |
||
1646 | # Get a comment if it is: read till the end of the line and get the comment from the reader |
||
1647 | while r.curr() != '': |
||
1648 | r.step() |
||
1649 | comment = r.comment |
||
8855 | Boppan | 1650 | # Find end of the macro |
8957 | Boppan | 1651 | prev = '' |
1652 | while True: |
||
1653 | if r.curr() == '}' and prev != '\\': |
||
1654 | break |
||
1655 | elif r.curr() == '': |
||
1656 | prev = '' |
||
1657 | r.nextline() |
||
1658 | continue |
||
1659 | prev = r.step() |
||
8855 | Boppan | 1660 | # Build the output |
8957 | Boppan | 1661 | return AsmMacro(location, name, comment, args) |
8855 | Boppan | 1662 | |
8957 | Boppan | 1663 | def parse_variable(r, first_word = None): |
1664 | global warnings |
||
1665 | location = r.location() |
||
8825 | Boppan | 1666 | |
8957 | Boppan | 1667 | # Skip spaces before variable name |
1668 | r.skip_spaces() |
||
1669 | # Get variable name |
||
1670 | name = "" |
||
1671 | # Read it if it was not supplied |
||
1672 | if first_word == None: |
||
1673 | while is_id(r.curr()): |
||
1674 | name += r.step() |
||
1675 | # Or use the supplied one instead |
||
1676 | else: |
||
1677 | name = first_word |
||
1678 | # Check the name |
||
1679 | # If it's 0 len, that means threr's something else than an identifier at the beginning |
||
1680 | if len(name) == 0: |
||
1681 | return None |
||
1682 | # If it starts from digit or othervice illegally it's illegal |
||
1683 | if not is_starts_as_id(name): |
||
1684 | return None |
||
8976 | Boppan | 1685 | # Get kind of the identifier from id2kind table |
1686 | kind = id_get_kind(name) |
||
8957 | Boppan | 1687 | # If it's a keyword, that's not a variable declaration |
8976 | Boppan | 1688 | if ID_KIND_KEYWORD in kind: |
8957 | Boppan | 1689 | return None |
1690 | # If it's a macro name, that's not a variable declaration |
||
8976 | Boppan | 1691 | if ID_KIND_MACRO_NAME in kind: |
8957 | Boppan | 1692 | return VariableNameIsMacroName(name) |
1693 | # If it's a datatype or a structure name that's not a variable declaration: that's just a data |
||
1694 | # don't document just a data for now |
||
8976 | Boppan | 1695 | if ID_KIND_STRUCT_NAME in kind or ID_KIND_FASM_TYPE in kind: |
8957 | Boppan | 1696 | return None |
1697 | # Skip spaces before type name |
||
1698 | r.skip_spaces() |
||
1699 | # Read type name |
||
1700 | var_type = "" |
||
1701 | while is_id(r.curr()): |
||
1702 | var_type += r.step() |
||
1703 | # Check the type name |
||
1704 | if len(var_type) == 0: |
||
1705 | # If there's no type identifier after the name |
||
1706 | # maybe the name is something meaningful for the next parser |
||
1707 | # return it |
||
1708 | return name |
||
1709 | # If it starts from digit or othervice illegally it's illegal |
||
1710 | if not is_starts_as_id(var_type): |
||
1711 | return None |
||
8976 | Boppan | 1712 | # Get kind of type identifier |
1713 | type_kind = id_get_kind(var_type) |
||
8957 | Boppan | 1714 | # If it's a keyword, that's not a variable declaration |
1715 | # return the two words of the lexical structure |
||
8976 | Boppan | 1716 | if ID_KIND_KEYWORD in type_kind: |
8957 | Boppan | 1717 | return (name, var_type) |
1718 | # Skip spaces before the value |
||
1719 | r.skip_spaces() |
||
1720 | # Read the value until the comment or end of the line |
||
1721 | value = "" |
||
1722 | while r.curr() != ';' and r.curr() != '' and r.curr() != '\n': |
||
1723 | value += r.step() |
||
1724 | # Skip spaces after the value |
||
1725 | r.skip_spaces() |
||
8961 | Boppan | 1726 | # Read till end of the line to get a comment from the reader |
1727 | while r.curr() != '': |
||
8957 | Boppan | 1728 | r.step() |
8961 | Boppan | 1729 | # Build the result |
8957 | Boppan | 1730 | return AsmVariable(location, name, r.comment, var_type, value) |
8825 | Boppan | 1731 | |
8957 | Boppan | 1732 | def parse_after_struct(r, as_union = True): |
1733 | global warnings |
||
1734 | location = r.location() |
||
8825 | Boppan | 1735 | |
8957 | Boppan | 1736 | # Skip spaces after "struct" keyword |
1737 | r.skip_spaces() |
||
1738 | # Read struct name |
||
1739 | name = "" |
||
1740 | while is_id(r.curr()): |
||
1741 | name += r.step() |
||
1742 | # Read till end of the line and get the comment from the reader |
||
1743 | while r.curr() != '': |
||
1744 | r.step() |
||
1745 | comment = r.comment |
||
1746 | # Get to the next line to parse struct members |
||
1747 | r.nextline() |
||
1748 | # Parse struct members |
||
1749 | members = [] |
||
1750 | while True: |
||
1751 | r.skip_spaces() |
||
1752 | var = parse_variable(r) |
||
1753 | if type(var) == AsmVariable: |
||
1754 | members.append(var) |
||
1755 | elif type(var) == str: |
||
1756 | if var == 'union': |
||
1757 | # Parse the union as a struct |
||
1758 | union = parse_after_struct(r, as_union = True) |
||
1759 | members.append(union) |
||
1760 | # Skip the ends of the union |
||
1761 | r.nextline() |
||
1762 | elif r.curr() == ':': |
||
1763 | warnings += f"{r.location()}: Skept the label in the struct\n" |
||
1764 | else: |
||
1765 | raise Exception(f"Garbage in struct member at {location} (got '{var}' identifier)") |
||
1766 | elif type(var) == VariableNameIsMacroName: |
||
1767 | if var.name == 'ends': |
||
1768 | break |
||
1769 | r.nextline() |
||
1770 | # Return the result |
||
1771 | if as_union: |
||
1772 | return AsmStruct(location, name, comment, members) |
||
1773 | else: |
||
1774 | return AsmUnion(location, name, comment, members) |
||
8825 | Boppan | 1775 | |
8963 | Boppan | 1776 | def parse_after_proc(r): |
1777 | # Get proc name |
||
1778 | name = r.fetch_identifier() |
||
1779 | # Next identifier after the proc name |
||
1780 | identifier = r.fetch_identifier() |
||
1781 | # Check if the id is 'stdcall' or 'c' (calling convention specifier) |
||
1782 | # and if so - save the convention and lookup the next identifier |
||
1783 | calling_convention = '' |
||
1784 | if identifier == 'stdcall' or identifier == 'c': |
||
1785 | calling_convention = identifier |
||
1786 | # If next is a comma, just skip it |
||
1787 | if r.curr() == ',': |
||
1788 | r.step() |
||
1789 | # Read the next identifier |
||
1790 | identifier = r.fetch_identifier() |
||
1791 | # Check if the id is 'uses' (used register list specifier) |
||
1792 | # and if so save the used register list |
||
1793 | used_regs = [] |
||
1794 | if identifier == 'uses': |
||
1795 | # Read the registers |
||
1796 | while True: |
||
1797 | reg_name = r.fetch_identifier() |
||
1798 | if reg_name != '': |
||
1799 | used_regs.append(reg_name) |
||
1800 | else: |
||
1801 | break |
||
1802 | # If next is a comma, just skip it |
||
1803 | if r.curr() == ',': |
||
1804 | r.step() |
||
1805 | # Read the next identifier |
||
1806 | identifier = r.fetch_identifier() |
||
1807 | # Check if there are argument identifiers |
||
1808 | args = [] |
||
1809 | while identifier != '': |
||
1810 | arg_name = identifier |
||
1811 | arg_type = 'arg_t' |
||
1812 | # Skip spaces after argument name |
||
1813 | r.skip_spaces() |
||
1814 | # If there's a ':' after the name - the next identifier is type |
||
1815 | if r.curr() == ':': |
||
1816 | r.step() |
||
1817 | arg_type = r.fetch_identifier() |
||
1818 | # If there's a comma - there's one more argument |
||
1819 | # else no arguments anymore |
||
1820 | if r.curr() == ',': |
||
1821 | r.step() |
||
1822 | identifier = r.fetch_identifier() |
||
1823 | else: |
||
1824 | identifier = '' |
||
1825 | args.append((arg_name, arg_type)) |
||
1826 | # Get to the end of the line and get a comment from the reader |
||
1827 | while r.curr() != '': |
||
1828 | r.step() |
||
8973 | Boppan | 1829 | comment = r.comment |
8963 | Boppan | 1830 | # Build the element |
1831 | return AsmFunction(r.location(), name, comment, calling_convention, args, used_regs) |
||
1832 | |||
8957 | Boppan | 1833 | def get_declarations(asm_file_contents, asm_file_name): |
1834 | r = AsmReader(asm_file_name) |
||
8825 | Boppan | 1835 | |
8957 | Boppan | 1836 | while not r.no_lines(): |
1837 | # Skip leading spaces |
||
1838 | r.skip_spaces() |
||
1839 | # Skip the line if it's starting with a comment |
||
1840 | if r.curr() == ';': |
||
1841 | r.nextline() |
||
8825 | Boppan | 1842 | continue |
8957 | Boppan | 1843 | # Get first word |
1844 | first_word = "" |
||
1845 | while is_id(r.curr()): |
||
1846 | first_word += r.step() |
||
1847 | # Match macro declaration |
||
1848 | if first_word == "macro": |
||
1849 | macro = parse_after_macro(r) |
||
1850 | elements.append(macro) |
||
8976 | Boppan | 1851 | id_add_kind(macro.name, ID_KIND_MACRO_NAME) |
8957 | Boppan | 1852 | # Match structure declaration |
1853 | elif first_word == "struct": |
||
1854 | struct = parse_after_struct(r) |
||
1855 | elements.append(struct) |
||
8976 | Boppan | 1856 | id_add_kind(struct.name, ID_KIND_STRUCT_NAME) |
8957 | Boppan | 1857 | # Match function definition |
1858 | elif first_word == "proc": |
||
8963 | Boppan | 1859 | proc = parse_after_proc(r) |
1860 | elements.append(proc) |
||
8957 | Boppan | 1861 | elif first_word == 'format': |
1862 | # Skip the format directive |
||
1863 | pass |
||
1864 | elif first_word == 'include': |
||
1865 | # Skip the include directive |
||
1866 | pass |
||
1867 | elif first_word == 'if': |
||
1868 | # Skip the conditional directive |
||
1869 | pass |
||
1870 | elif first_word == 'repeat': |
||
1871 | # Skip the repeat directive |
||
1872 | pass |
||
1873 | elif first_word == 'purge': |
||
1874 | while True: |
||
1875 | # Skip spaces after the 'purge' keyword or after the comma what separated the previous macro name |
||
1876 | r.skip_spaces() |
||
1877 | # Get the purged macro name |
||
1878 | name = '' |
||
1879 | while is_id(r.curr()): |
||
1880 | name += r.step() |
||
1881 | # Remove the purged macro from the macro names list |
||
1882 | try: |
||
8976 | Boppan | 1883 | id_remove_kind(name, ID_KIND_MACRO_NAME) |
8957 | Boppan | 1884 | except: |
1885 | pass |
||
1886 | # Skip spaces after the name |
||
1887 | r.skip_spaces() |
||
1888 | # If it's comma (',') after then that's not the last purged macro, continue purging |
||
1889 | if r.curr() == ',': |
||
1890 | r.step() |
||
1891 | continue |
||
1892 | # Here we purged all the macros should be purged |
||
1893 | break |
||
1894 | # Match label or a variable |
||
1895 | elif len(first_word) != 0: |
||
1896 | # Skip spaces after the identifier |
||
1897 | r.skip_spaces() |
||
1898 | # Match a variable |
||
1899 | var = parse_variable(r, first_word) |
||
1900 | if type(var) == AsmVariable: |
||
1901 | elements.append(var) |
||
1902 | # If it wasn't a variable but there was an identifier |
||
1903 | # Maybe that's a label and the identifier is the label name |
||
1904 | # The parse_variable returns the first found or supplied identifier |
||
1905 | # In this case it returns the first_word which is supplied |
||
1906 | # If it didn't match a type identifier after the word |
||
1907 | elif type(var) == str: |
||
1908 | name = var |
||
1909 | # Match label beginning (':' after name) |
||
1910 | if r.curr() == ':': |
||
1911 | # Get to the end of the line and get the coment from the reader |
||
1912 | while r.curr() != '': |
||
1913 | r.step() |
||
1914 | comment = r.comment |
||
1915 | # Only handle non-local labels |
||
1916 | if name[0] != '.' and name != "@@" and name != "$Revision": |
||
8989 | Boppan | 1917 | if '@return' in comment or '@param' in comment: |
1918 | element = AsmFunction(r.location(), name, comment, '', [], []) |
||
1919 | else: |
||
1920 | element = AsmLabel(r.location(), name, comment) |
||
1921 | elements.append(element) |
||
8957 | Boppan | 1922 | elif r.curr() == '=': |
8976 | Boppan | 1923 | # Save the identifier as a set constant |
1924 | id_add_kind(first_word, ID_KIND_SET_CONSTANT) |
||
8957 | Boppan | 1925 | elif type(var) == tuple: |
1926 | (word_one, word_two) = var |
||
1927 | if word_two == 'equ': |
||
8976 | Boppan | 1928 | # Save the identifier as an equated constant |
1929 | id_add_kind(word_one, ID_KIND_EQUATED_CONSTANT) |
||
8957 | Boppan | 1930 | r.nextline() |
8825 | Boppan | 1931 | |
8966 | Boppan | 1932 | def it_neds_to_be_parsed(source_file): |
8990 | Boppan | 1933 | # If there's no symbols file saved - parse it anyway |
1934 | # cause we need to create the symbols file and use it |
||
1935 | # if we gonna generate proper doxygen |
||
1936 | if not os.path.isfile('asmxygen.elements.pickle'): |
||
1937 | return True |
||
8966 | Boppan | 1938 | dest = doxygen_src_path + '/' + source_file |
1939 | # If there's no the doxygen file it should be compiled to |
||
1940 | # then yes, we should compile it to doxygen |
||
1941 | if not os.path.isfile(dest): |
||
1942 | return True |
||
1943 | source_change_time = os.path.getmtime(source_file) |
||
1944 | dest_change_file = os.path.getmtime(dest) |
||
1945 | # If the source is newer than the doxygen it was compiled to |
||
1946 | # then the source should be recompiled (existing doxygen is old) |
||
1947 | if source_change_time > dest_change_file: |
||
1948 | return True |
||
1949 | return False |
||
1950 | |||
8834 | Boppan | 1951 | def handle_file(handled_files, asm_file_name, subdir = "."): |
8990 | Boppan | 1952 | global elements |
8966 | Boppan | 1953 | # Canonicalize the file path and get it relative to cwd |
1954 | cwd = os.path.abspath(os.path.dirname(sys.argv[0])) |
||
1955 | asm_file_name = os.path.realpath(asm_file_name) |
||
1956 | asm_file_name = asm_file_name[len(cwd) + 1:] |
||
1957 | # If it's lang.inc - skip it |
||
1958 | if asm_file_name == 'lang.inc': |
||
8967 | Boppan | 1959 | return |
1960 | # If the file was handled in this execution before - skip it |
||
1961 | if asm_file_name in handled_files: |
||
1962 | return |
||
1963 | # Say that the file was handled in this execution |
||
1964 | handled_files.append(asm_file_name) |
||
8966 | Boppan | 1965 | # Check if the file should be parsed (if it was modified or wasn't parsed yet) |
1966 | should_get_declarations = True |
||
1967 | if not it_neds_to_be_parsed(asm_file_name): |
||
1968 | print(f"Skipping {asm_file_name} (already newest)") |
||
1969 | should_get_declarations = False |
||
1970 | else: |
||
8975 | Boppan | 1971 | print(f"Handling {asm_file_name}") |
8990 | Boppan | 1972 | # Remove elements parsed from this file before if any |
1973 | elements_to_remove = [x for x in elements if x.location.split(':')[0] == asm_file_name] |
||
1974 | elements = [x for x in elements if x.location.split(':')[0] != asm_file_name] |
||
1975 | # Forget types of identifiers of names of the removed elements |
||
1976 | for element in elements_to_remove: |
||
1977 | if type(element) == AsmStruct: |
||
1978 | id_remove_kind(element.name, ID_KIND_STRUCT_NAME) |
||
1979 | elif type(element) == AsmMacro: |
||
1980 | id_remove_kind(element.name, ID_KIND_MACRO_NAME) |
||
8966 | Boppan | 1981 | # Read the source |
1982 | asm_file_contents = open(asm_file_name, "r", encoding="utf-8").read() |
||
1983 | # Find includes, fix their paths and handle em recoursively |
||
1984 | includes = re.findall(r'^include (["\'])(.*)\1', asm_file_contents, flags=re.MULTILINE) |
||
8825 | Boppan | 1985 | for include in includes: |
8957 | Boppan | 1986 | include = include[1].replace('\\', '/'); |
8825 | Boppan | 1987 | full_path = subdir + '/' + include; |
8966 | Boppan | 1988 | # If the path isn't valid, maybe that's not relative path |
1989 | if not os.path.isfile(full_path): |
||
1990 | full_path = include |
||
8967 | Boppan | 1991 | new_subdir = full_path.rsplit('/', 1)[0] |
1992 | handle_file(handled_files, full_path, new_subdir) |
||
8966 | Boppan | 1993 | # Only collect declarations from the file if it wasn't parsed before |
8975 | Boppan | 1994 | if should_get_declarations and not clean_generated_stuff: |
8966 | Boppan | 1995 | get_declarations(asm_file_contents, asm_file_name) |
8825 | Boppan | 1996 | |
1997 | kernel_files = [] |
||
1998 | |||
8990 | Boppan | 1999 | # Load remembered list of symbols |
2000 | if os.path.isfile('asmxygen.elements.pickle'): |
||
2001 | print('Reading existing dump of symbols') |
||
2002 | (elements, id2kind) = pickle.load(open('asmxygen.elements.pickle', 'rb')) |
||
2003 | |||
8834 | Boppan | 2004 | handle_file(kernel_files, "./kernel.asm"); |
8825 | Boppan | 2005 | |
8834 | Boppan | 2006 | if dump_symbols: |
9033 | Boppan | 2007 | stdout = sys.stdout |
2008 | sys.stdout = open('asmxygen.dump.txt', 'w', encoding = 'utf-8') |
||
8957 | Boppan | 2009 | for asm_element in elements: |
2010 | asm_element.dump() |
||
9033 | Boppan | 2011 | sys.stdout = stdout |
8825 | Boppan | 2012 | |
8967 | Boppan | 2013 | if clean_generated_stuff: |
2014 | kernel_files_set = set(kernel_files) |
||
2015 | for file in kernel_files: |
||
2016 | doxygen_file = f"{doxygen_src_path}/{file}" |
||
2017 | if (os.path.isfile(doxygen_file)): |
||
2018 | print(f"Removing {file}... ", end = '') |
||
2019 | os.remove(doxygen_file) |
||
2020 | print("Done.") |
||
8976 | Boppan | 2021 | elif not noemit: |
8967 | Boppan | 2022 | print(f"Writing doumented sources to {doxygen_src_path}") |
8834 | Boppan | 2023 | |
8967 | Boppan | 2024 | i = 0 |
8990 | Boppan | 2025 | new_elements = [x for x in elements if x.new] |
2026 | for element in new_elements: |
||
2027 | print(f"[{i + 1}/{len(new_elements)}] Emitting {element.name} from {element.location}") |
||
8967 | Boppan | 2028 | element.emit(doxygen_src_path) |
2029 | i += 1 |
||
8855 | Boppan | 2030 | |
8990 | Boppan | 2031 | print(f"Writing dump of symbols to asmxygen.elements.pickle") |
2032 | |||
2033 | # Now when the new elements already was written, there's no new elements anymore |
||
2034 | for element in elements: |
||
2035 | element.new = False |
||
2036 | pickle.dump((elements, id2kind), open('asmxygen.elements.pickle', 'wb')) |
||
2037 | |||
8982 | Boppan | 2038 | if print_stats: |
2039 | var_count = 0 |
||
2040 | mac_count = 0 |
||
2041 | lab_count = 0 |
||
2042 | fun_count = 0 |
||
2043 | uni_count = 0 |
||
2044 | str_count = 0 |
||
2045 | for element in elements: |
||
2046 | if type(element) == AsmVariable: |
||
2047 | var_count += 1 |
||
2048 | elif type(element) == AsmMacro: |
||
2049 | mac_count += 1 |
||
2050 | elif type(element) == AsmLabel: |
||
2051 | lab_count += 1 |
||
2052 | elif type(element) == AsmFunction: |
||
2053 | fun_count += 1 |
||
2054 | elif type(element) == AsmUnion: |
||
2055 | uni_count += 1 |
||
2056 | elif type(element) == AsmStruct: |
||
2057 | str_count += 1 |
||
2058 | print(f'Parsed variable count: {var_count}') |
||
2059 | print(f'Parsed macro count: {mac_count}') |
||
2060 | print(f'Parsed label count: {lab_count}') |
||
2061 | print(f'Parsed function count: {fun_count}') |
||
2062 | print(f'Parsed union type count: {uni_count}') |
||
2063 | print(f'Parsed structure type count: {str_count}') |
||
2064 | |||
8855 | Boppan | 2065 | if enable_warnings: |
2066 | open('asmxygen.txt', "w", encoding = "utf-8").write(warnings)>>> |