Subversion Repositories Kolibri OS

Rev

Rev 8958 | Rev 8963 | 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.    - Add methods to dump stuff to file
  8. """
  9.  
  10. # Parameters
  11. # Path to doxygen folder to make doxygen files in: -o <path>
  12. doxygen_src_path = 'docs/doxygen'
  13. # Remove generated doxygen files: --clean
  14. clean_generated_stuff = False
  15. # Dump all defined symbols: --dump
  16. dump_symbols = False
  17. # Print symbol stats: --stats
  18. print_stats = False
  19. # Do not write warnings file: --nowarn
  20. enable_warnings = True
  21.  
  22. # Constants
  23. link_root = "http://websvn.kolibrios.org/filedetails.php?repname=Kolibri+OS&path=/kernel/trunk"
  24.  
  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.  
  1157. # Warning list
  1158. warnings = ""
  1159.  
  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")
  1166. parser.add_argument("--nowarn", help="Do not write warnings file", action="store_true")
  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
  1172. enable_warnings = not args.nowarn
  1173.  
  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 = []
  1184.  
  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]
  1329.                 self.name = name
  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"<a href='{link_root}/{self.file}#line-{self.line}'>{self.file}:{self.line}</a>\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)
  1375.                 self.type = type
  1376.                 self.init = init
  1377.  
  1378.         def dump(self):
  1379.                 super().dump()
  1380.                 print(f"Variable")
  1381.  
  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)
  1396.  
  1397. class AsmFunction(AsmElement):
  1398.         def __init__(self, location, name, comment):
  1399.                 super().__init__(location, name, comment)
  1400.  
  1401.         def dump(self):
  1402.                 super().dump()
  1403.                 print(f"Function")
  1404.  
  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)
  1416.  
  1417. class AsmLabel(AsmElement):
  1418.         def __init__(self, location, name, comment):
  1419.                 super().__init__(location, name, comment)
  1420.  
  1421.         def dump(self):
  1422.                 super().dump()
  1423.                 print(f"Label")
  1424.  
  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)
  1436.  
  1437. class AsmMacro(AsmElement):
  1438.         def __init__(self, location, name, comment, args):
  1439.                 super().__init__(location, name, comment)
  1440.                 self.args = args
  1441.  
  1442.         def dump(self):
  1443.                 super().dump()
  1444.                 print(f"Macro")
  1445.                 print(f"Parameters: {self.args}")
  1446.  
  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)
  1470.  
  1471. class AsmStruct(AsmElement):
  1472.         def __init__(self, location, name, comment, members):
  1473.                 super().__init__(location, name, comment)
  1474.                 self.members = members
  1475.  
  1476.         def dump(self):
  1477.                 super().dump()
  1478.                 print(f"Struct")
  1479.  
  1480.         def emit(self, dest):
  1481.                 # Build doxycomment
  1482.                 doxycomment = ''
  1483.                 doxycomment += self.comment
  1484.                 if '@brief' not in doxycomment:
  1485.                         doxycomment = '@brief ' + doxycomment
  1486.                 doxycomment += '\n'
  1487.                 # Build declaration
  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 += '};'
  1493.                 # Emit this
  1494.                 super().emit(dest, doxycomment, declaration)
  1495.  
  1496. class AsmUnion(AsmElement):
  1497.         def __init__(self, location, name, comment, members):
  1498.                 super().__init__(location, name, comment)
  1499.                 self.members = members
  1500.  
  1501.         def dump(self):
  1502.                 super().dump()
  1503.                 print(f"Union")
  1504.  
  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)
  1515.  
  1516. class VariableNameIsMacroName:
  1517.         def __init__(self, name):
  1518.                 self.name = name
  1519.  
  1520. def is_id(c):
  1521.         return c.isprintable() and c not in "+-/*=<>()[]{};:,|&~#`'\" \n\r\t\v"
  1522.  
  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()
  1531.         # Read macro name
  1532.         name = ""
  1533.         while is_id(r.curr()) or r.curr() == '#':
  1534.                 name += r.step()
  1535.         # Skip spaces after macro name
  1536.         r.skip_spaces()
  1537.         # Find all arguments
  1538.         args = []
  1539.         arg = ''
  1540.         while r.curr() and r.curr() != ';' and r.curr() != '{':
  1541.                 # Collect identifier
  1542.                 if is_id(r.curr()):
  1543.                         arg += r.step()
  1544.                 # Save the collected identifier
  1545.                 elif r.curr() == ',':
  1546.                         args.append(arg)
  1547.                         arg = ''
  1548.                         r.step()
  1549.                 # Just push the '['
  1550.                 elif r.curr() == '[':
  1551.                         args.append(r.step())
  1552.                 # Just push the identifier and get ']' ready to be pushed on next comma
  1553.                 elif r.curr() == ']':
  1554.                         args.append(arg)
  1555.                         arg = r.step()
  1556.                 # Just push the identifier and get '*' ready to be pushed on next comma
  1557.                 elif r.curr() == '*':
  1558.                         args.append(arg)
  1559.                         arg = r.step()
  1560.                 # Just skip whitespaces
  1561.                 elif r.curr().isspace():
  1562.                         r.step()
  1563.                 # Something unexpected
  1564.                 else:
  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
  1569.         if arg != '':
  1570.                 args.append(arg)
  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
  1577.         # Find end of the macro
  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()
  1587.         # Build the output
  1588.         return AsmMacro(location, name, comment, args)
  1589.  
  1590. def parse_variable(r, first_word = None):
  1591.         global warnings
  1592.         location = r.location()
  1593.  
  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 till end of the line to get a comment from the reader
  1650.         while r.curr() != '':
  1651.                 r.step()
  1652.         # Build the result
  1653.         return AsmVariable(location, name, r.comment, var_type, value)
  1654.  
  1655. def parse_after_struct(r, as_union = True):
  1656.         global warnings
  1657.         location = r.location()
  1658.  
  1659.         # Skip spaces after "struct" keyword
  1660.         r.skip_spaces()
  1661.         # Read struct name
  1662.         name = ""
  1663.         while is_id(r.curr()):
  1664.                 name += r.step()
  1665.         # Read till end of the line and get the comment from the reader
  1666.         while r.curr() != '':
  1667.                 r.step()
  1668.         comment = r.comment
  1669.         # Get to the next line to parse struct members
  1670.         r.nextline()
  1671.         # Parse struct members
  1672.         members = []
  1673.         while True:
  1674.                 r.skip_spaces()
  1675.                 var = parse_variable(r)
  1676.                 if type(var) == AsmVariable:
  1677.                         members.append(var)
  1678.                 elif type(var) == str:
  1679.                         if var == 'union':
  1680.                                 # Parse the union as a struct
  1681.                                 union = parse_after_struct(r, as_union = True)
  1682.                                 members.append(union)
  1683.                                 # Skip the ends of the union
  1684.                                 r.nextline()
  1685.                         elif r.curr() == ':':
  1686.                                 warnings += f"{r.location()}: Skept the label in the struct\n"
  1687.                         else:
  1688.                                 raise Exception(f"Garbage in struct member at {location} (got '{var}' identifier)")
  1689.                 elif type(var) == VariableNameIsMacroName:
  1690.                         if var.name == 'ends':
  1691.                                 break
  1692.                 r.nextline()
  1693.         # Return the result
  1694.         if as_union:
  1695.                 return AsmStruct(location, name, comment, members)
  1696.         else:
  1697.                 return AsmUnion(location, name, comment, members)
  1698.  
  1699. def get_declarations(asm_file_contents, asm_file_name):
  1700.         cwd = os.path.abspath(os.path.dirname(sys.argv[0]))
  1701.         asm_file_name = os.path.realpath(asm_file_name)
  1702.         asm_file_name = asm_file_name[len(cwd) + 1:]
  1703.  
  1704.         r = AsmReader(asm_file_name)
  1705.  
  1706.         while not r.no_lines():
  1707.                 # Skip leading spaces
  1708.                 r.skip_spaces()
  1709.                 # Skip the line if it's starting with a comment
  1710.                 if r.curr() == ';':
  1711.                         r.nextline()
  1712.                         continue
  1713.                 # Get first word
  1714.                 first_word = ""
  1715.                 while is_id(r.curr()):
  1716.                         first_word += r.step()
  1717.                 # Match macro declaration
  1718.                 if first_word == "macro":
  1719.                         macro = parse_after_macro(r)
  1720.                         elements.append(macro)
  1721.                         macro_names.append(macro.name)
  1722.                 # Match structure declaration
  1723.                 elif first_word == "struct":
  1724.                         struct = parse_after_struct(r)
  1725.                         elements.append(struct)
  1726.                         struct_names.append(struct.name)
  1727.                 # Match function definition
  1728.                 elif first_word == "proc":
  1729.                         # Skip spaces after "proc"
  1730.                         r.skip_spaces()
  1731.                         # Get proc name
  1732.                         name = ""
  1733.                         while is_id(r.curr()):
  1734.                                 name += r.step()
  1735.                         # Get to the end of the line to get the comment from the reader
  1736.                         while r.curr() != '':
  1737.                                 r.step()
  1738.                         comment = r.get_comment()
  1739.                         # Create the function
  1740.                         elements.append(AsmFunction(r.location(), name, comment))
  1741.                 elif first_word == 'format':
  1742.                         # Skip the format directive
  1743.                         pass
  1744.                 elif first_word == 'include':
  1745.                         # Skip the include directive
  1746.                         pass
  1747.                 elif first_word == 'if':
  1748.                         # Skip the conditional directive
  1749.                         pass
  1750.                 elif first_word == 'repeat':
  1751.                         # Skip the repeat directive
  1752.                         pass
  1753.                 elif first_word == 'purge':
  1754.                         while True:
  1755.                                 # Skip spaces after the 'purge' keyword or after the comma what separated the previous macro name
  1756.                                 r.skip_spaces()
  1757.                                 # Get the purged macro name
  1758.                                 name = ''
  1759.                                 while is_id(r.curr()):
  1760.                                         name += r.step()
  1761.                                 # Remove the purged macro from the macro names list
  1762.                                 try:
  1763.                                         macro_names.remove(name)
  1764.                                 except:
  1765.                                         pass
  1766.                                 # Skip spaces after the name
  1767.                                 r.skip_spaces()
  1768.                                 # If it's comma (',') after then that's not the last purged macro, continue purging
  1769.                                 if r.curr() == ',':
  1770.                                         r.step()
  1771.                                         continue
  1772.                                 # Here we purged all the macros should be purged
  1773.                                 break
  1774.                 # Match label or a variable
  1775.                 elif len(first_word) != 0:
  1776.                         # Skip spaces after the identifier
  1777.                         r.skip_spaces()
  1778.                         # Match a variable
  1779.                         var = parse_variable(r, first_word)
  1780.                         if type(var) == AsmVariable:
  1781.                                 elements.append(var)
  1782.                         # If it wasn't a variable but there was an identifier
  1783.                         # Maybe that's a label and the identifier is the label name
  1784.                         # The parse_variable returns the first found or supplied identifier
  1785.                         # In this case it returns the first_word which is supplied
  1786.                         # If it didn't match a type identifier after the word
  1787.                         elif type(var) == str:
  1788.                                 name = var
  1789.                                 # Match label beginning (':' after name)
  1790.                                 if r.curr() == ':':
  1791.                                         # Get to the end of the line and get the coment from the reader
  1792.                                         while r.curr() != '':
  1793.                                                 r.step()
  1794.                                         comment = r.comment
  1795.                                         # Only handle non-local labels
  1796.                                         if name[0] != '.' and name != "@@" and name != "$Revision":
  1797.                                                 elements.append(AsmLabel(r.location(), name, comment))
  1798.                                 elif r.curr() == '=':
  1799.                                         # Add the equated constant (name = value) to equated constants list
  1800.                                         equated_constant_names.append(first_word)
  1801.                         elif type(var) == tuple:
  1802.                                 (word_one, word_two) = var
  1803.                                 if word_two == 'equ':
  1804.                                         # Add the name to equ names list
  1805.                                         equ_names.append(word_one)
  1806.                 r.nextline()
  1807.  
  1808. def handle_file(handled_files, asm_file_name, subdir = "."):
  1809.         print(f"Parsing {asm_file_name}")
  1810.         handled_files.append(asm_file_name)
  1811.         try:
  1812.                 asm_file_contents = open(asm_file_name, "r", encoding="utf-8").read()
  1813.         except:
  1814.                 return
  1815.         include_directive_pattern = re.compile(r'include (["\'])(.*)\1')
  1816.         includes = include_directive_pattern.findall(asm_file_contents)
  1817.         for include in includes:
  1818.                 include = include[1].replace('\\', '/');
  1819.                 full_path = subdir + '/' + include;
  1820.                 if full_path not in handled_files:
  1821.                         new_subdir = full_path.rsplit('/', 1)[0]
  1822.                         handle_file(handled_files, full_path, new_subdir)
  1823.         get_declarations(asm_file_contents, asm_file_name)
  1824.         return handled_files
  1825.  
  1826. kernel_files = []
  1827.  
  1828. handle_file(kernel_files, "./kernel.asm");
  1829.  
  1830. if dump_symbols:
  1831.         for asm_element in elements:
  1832.                 asm_element.dump()
  1833.  
  1834. if print_stats:
  1835.         print("--stats is not nimplmented")
  1836.  
  1837. print(f"Writing doumented sources to {doxygen_src_path}")
  1838.  
  1839. i = 0
  1840. for element in elements:
  1841.         print(f"[{i + 1}/{len(elements)}] Emitting {element.name} from {element.location}")
  1842.         element.emit(doxygen_src_path)
  1843.         i += 1
  1844.  
  1845. if enable_warnings:
  1846.         open('asmxygen.txt', "w", encoding = "utf-8").write(warnings)
  1847.