Subversion Repositories Kolibri OS

Rev

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