Subversion Repositories Kolibri OS

Rev

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