Subversion Repositories Kolibri OS

Rev

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