Subversion Repositories Kolibri OS

Rev

Rev 8961 | Rev 8966 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. import re
  2. import os
  3. import argparse
  4. import sys
  5.  
  6. """ TODO:
  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
  12. """
  13.  
  14. # Parameters
  15. # Path to doxygen folder to make doxygen files in: -o <path>
  16. doxygen_src_path = 'docs/doxygen'
  17. # Remove generated doxygen files: --clean
  18. clean_generated_stuff = False
  19. # Dump all defined symbols: --dump
  20. dump_symbols = False
  21. # Print symbol stats: --stats
  22. print_stats = False
  23. # Do not write warnings file: --nowarn
  24. enable_warnings = True
  25.  
  26. # Constants
  27. link_root = "http://websvn.kolibrios.org/filedetails.php?repname=Kolibri+OS&path=/kernel/trunk"
  28.  
  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.  
  1161. # Warning list
  1162. warnings = ""
  1163.  
  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")
  1170. parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true")
  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
  1176. enable_warnings = not args.nowarn
  1177.  
  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 = []
  1188.  
  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.  
  1322. class AsmReaderFetchingIdentifiers(AsmReaderReadingComments):
  1323.         def __init__(self, file):
  1324.                 super().__init__(file)
  1325.  
  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.  
  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]
  1344.                 self.name = name
  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"<a href='{link_root}/{self.file}#line-{self.line}'>{self.file}:{self.line}</a>\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)
  1390.                 self.type = type
  1391.                 self.init = init
  1392.  
  1393.         def dump(self):
  1394.                 super().dump()
  1395.                 print(f"Variable")
  1396.  
  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)
  1411.  
  1412. class AsmFunction(AsmElement):
  1413.         def __init__(self, location, name, comment, calling_convention, args, used_regs):
  1414.                 super().__init__(location, name, comment)
  1415.                 self.calling_convention = calling_convention
  1416.                 self.args = args
  1417.                 self.used_regs = used_regs
  1418.  
  1419.         def dump(self):
  1420.                 super().dump()
  1421.                 print(f"Function")
  1422.  
  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
  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 += ')'
  1439.                 # Build the declaration
  1440.                 name = self.name.replace(".", "_")
  1441.                 declaration = f"void {name}{arg_list};"
  1442.                 # Emit this
  1443.                 super().emit(dest, doxycomment, declaration)
  1444.  
  1445. class AsmLabel(AsmElement):
  1446.         def __init__(self, location, name, comment):
  1447.                 super().__init__(location, name, comment)
  1448.  
  1449.         def dump(self):
  1450.                 super().dump()
  1451.                 print(f"Label")
  1452.  
  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)
  1464.  
  1465. class AsmMacro(AsmElement):
  1466.         def __init__(self, location, name, comment, args):
  1467.                 super().__init__(location, name, comment)
  1468.                 self.args = args
  1469.  
  1470.         def dump(self):
  1471.                 super().dump()
  1472.                 print(f"Macro")
  1473.                 print(f"Parameters: {self.args}")
  1474.  
  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)
  1498.  
  1499. class AsmStruct(AsmElement):
  1500.         def __init__(self, location, name, comment, members):
  1501.                 super().__init__(location, name, comment)
  1502.                 self.members = members
  1503.  
  1504.         def dump(self):
  1505.                 super().dump()
  1506.                 print(f"Struct")
  1507.  
  1508.         def emit(self, dest):
  1509.                 # Build doxycomment
  1510.                 doxycomment = ''
  1511.                 doxycomment += self.comment
  1512.                 if '@brief' not in doxycomment:
  1513.                         doxycomment = '@brief ' + doxycomment
  1514.                 doxycomment += '\n'
  1515.                 # Build declaration
  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 += '};'
  1521.                 # Emit this
  1522.                 super().emit(dest, doxycomment, declaration)
  1523.  
  1524. class AsmUnion(AsmElement):
  1525.         def __init__(self, location, name, comment, members):
  1526.                 super().__init__(location, name, comment)
  1527.                 self.members = members
  1528.  
  1529.         def dump(self):
  1530.                 super().dump()
  1531.                 print(f"Union")
  1532.  
  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)
  1543.  
  1544. class VariableNameIsMacroName:
  1545.         def __init__(self, name):
  1546.                 self.name = name
  1547.  
  1548. def is_id(c):
  1549.         return c.isprintable() and c not in "+-/*=<>()[]{};:,|&~#`'\" \n\r\t\v"
  1550.  
  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()
  1559.         # Read macro name
  1560.         name = ""
  1561.         while is_id(r.curr()) or r.curr() == '#':
  1562.                 name += r.step()
  1563.         # Skip spaces after macro name
  1564.         r.skip_spaces()
  1565.         # Find all arguments
  1566.         args = []
  1567.         arg = ''
  1568.         while r.curr() and r.curr() != ';' and r.curr() != '{':
  1569.                 # Collect identifier
  1570.                 if is_id(r.curr()):
  1571.                         arg += r.step()
  1572.                 # Save the collected identifier
  1573.                 elif r.curr() == ',':
  1574.                         args.append(arg)
  1575.                         arg = ''
  1576.                         r.step()
  1577.                 # Just push the '['
  1578.                 elif r.curr() == '[':
  1579.                         args.append(r.step())
  1580.                 # Just push the identifier and get ']' ready to be pushed on next comma
  1581.                 elif r.curr() == ']':
  1582.                         args.append(arg)
  1583.                         arg = r.step()
  1584.                 # Just push the identifier and get '*' ready to be pushed on next comma
  1585.                 elif r.curr() == '*':
  1586.                         args.append(arg)
  1587.                         arg = r.step()
  1588.                 # Just skip whitespaces
  1589.                 elif r.curr().isspace():
  1590.                         r.step()
  1591.                 # Something unexpected
  1592.                 else:
  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
  1597.         if arg != '':
  1598.                 args.append(arg)
  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
  1605.         # Find end of the macro
  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()
  1615.         # Build the output
  1616.         return AsmMacro(location, name, comment, args)
  1617.  
  1618. def parse_variable(r, first_word = None):
  1619.         global warnings
  1620.         location = r.location()
  1621.  
  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()
  1677.         # Read till end of the line to get a comment from the reader
  1678.         while r.curr() != '':
  1679.                 r.step()
  1680.         # Build the result
  1681.         return AsmVariable(location, name, r.comment, var_type, value)
  1682.  
  1683. def parse_after_struct(r, as_union = True):
  1684.         global warnings
  1685.         location = r.location()
  1686.  
  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)
  1726.  
  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.  
  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:]
  1788.  
  1789.         r = AsmReader(asm_file_name)
  1790.  
  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()
  1797.                         continue
  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":
  1814.                         proc = parse_after_proc(r)
  1815.                         elements.append(proc)
  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()
  1882.  
  1883. def handle_file(handled_files, asm_file_name, subdir = "."):
  1884.         print(f"Parsing {asm_file_name}")
  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
  1890.         include_directive_pattern = re.compile(r'include (["\'])(.*)\1')
  1891.         includes = include_directive_pattern.findall(asm_file_contents)
  1892.         for include in includes:
  1893.                 include = include[1].replace('\\', '/');
  1894.                 full_path = subdir + '/' + include;
  1895.                 if full_path not in handled_files:
  1896.                         new_subdir = full_path.rsplit('/', 1)[0]
  1897.                         handle_file(handled_files, full_path, new_subdir)
  1898.         get_declarations(asm_file_contents, asm_file_name)
  1899.         return handled_files
  1900.  
  1901. kernel_files = []
  1902.  
  1903. handle_file(kernel_files, "./kernel.asm");
  1904.  
  1905. if dump_symbols:
  1906.         for asm_element in elements:
  1907.                 asm_element.dump()
  1908.  
  1909. if print_stats:
  1910.         print("--stats is not nimplmented")
  1911.  
  1912. print(f"Writing doumented sources to {doxygen_src_path}")
  1913.  
  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)
  1918.         i += 1
  1919.  
  1920. if enable_warnings:
  1921.         open('asmxygen.txt', "w", encoding = "utf-8").write(warnings)
  1922.