Subversion Repositories Kolibri OS

Rev

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