1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2024-11-21 16:55:06 +00:00
notnotdnethack/util/MacroMagicMarker.py
Ron Nazarov efdb5b2dc6
Fix compilation with clang and with GCC -std=c2x
clang -std=c2x still doesn't work because clang is stricter and
doesn't allow K&R-style declarations with -std=c2x.

Also fix a few bugs/clang warnings discovered in the process.
2024-05-01 23:40:35 +01:00

145 lines
4.9 KiB
Python
Executable file

#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# Based on https://gist.github.com/NeroOneTrueKing/384ce9faa3374f8d0b2ebf1ccc0ed222
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# arguments
import sys
FILENAME = sys.argv[1] if 1 < len(sys.argv) else "include/macromagic.h"
README = sys.argv[2] if 2 < len(sys.argv) else "doc/macromagic.txt"
# constants
MAXARG = 59
MAXOUT = 29
from math import log2
from math import ceil
EXPANDO = ceil(log2(MAXARG-MAXOUT))
EXPANDMAX = 2**EXPANDO
# helper funcs
def strn(n):
return str(n//10) + str(n%10)
def largs(n):
s = ""
for i in range(1, n+1):
s = s + "_arg" + strn(i) + ', '
return s
f = open(FILENAME, 'w')
f.write("#ifndef MACROMAGIC_H\n")
f.write("#define MACROMAGIC_H\n")
f.write("//This file generated by python script. Do not edit.\n\n")
with open(README, 'r') as g:
f.write(g.read())
f.write("\n\n// O(1) macros\n")
# write O(1) macros
f.write("#define _EMPTY(...)\n")
f.write("#define _DEFER(...) __VA_ARGS__ _EMPTY()\n")
f.write("#define _EXPAND01(...) __VA_ARGS__\n")
for n in range(0, EXPANDO):
f.write("#define _EXPAND" + strn(2**(n+1)) + "(...) _EXPAND" + strn(2**n) + "(_EXPAND" + strn(2**n) + "(__VA_ARGS__))\n")
f.write("#define _DEPARENC(X) _DEPAREN(X),\n")
f.write("#define _DEPAREN(X) _ESC(_APEE X)\n")
f.write("#define _APEE(...) _APEE __VA_ARGS__\n")
f.write("#define _ESC(...) _ESC_(__VA_ARGS__)\n")
f.write("#define _ESC_(...) _ESC ## __VA_ARGS__\n")
f.write("#define _ESC_APEE\n")
f.write("\n\n// O(n) macros\n")
# write O(n) macros
f.write("#define _GET_NTH_ARG(\\\n")
for row in range(0, MAXARG//10+1):
f.write('\t')
for n in range(0, 10):
f.write('_'+str(row)+str(n)+', ')
f.write('\\\n')
f.write("\tN, ...) N\n\n")
f.write("#define NARGS(...) _GET_NTH_ARG(dummy __VA_OPT__(,) __VA_ARGS__,\\\n")
for row in range(MAXARG//10, -1, -1):
f.write('\t')
for n in range(9, -1, -1):
f.write(str(row)+str(n)+','*(n!=0 or row!=0)+' ')
f.write('\\\n')
f.write("\t)\n\n")
f.write("#define CALL_MACRO_X_FOR_EACH(x, ...)\\\n")
f.write("\t_GET_NTH_ARG(dummy __VA_OPT__(,) __VA_ARGS__,\\\n")
for row in range(MAXARG//10, -1, -1):
f.write('\t')
for n in range(9, -1, -1):
f.write('_fe_'+str(row)+str(n)+','*(n!=0 or row!=0)+' ')
f.write('\\\n')
f.write("\t)(x, ##__VA_ARGS__)\n\n")
f.write("#define _fe_00(_call, ...)\n")
f.write("#define _fe_01(_call, x)\t\t_call(x)\n")
for n in range(2, MAXARG+1):
f.write("#define _fe_" + strn(n) + "(_call, x, ...)\t_call(x) _fe_" + strn(n-1) + "(_call, __VA_ARGS__)\n")
f.write("\n")
for n in range(1, MAXOUT+1):
f.write("#define _OPEN_C" + strn(n) + "(...) __VA_ARGS__\n")
f.write("\n")
for n in range(1, MAXOUT+1):
f.write("#define SET" + strn(n) + "(" + largs(n) + "...) _EXPAND" + strn(EXPANDMAX) + "(DSET" + strn(n) + "(" + largs(n) +"## __VA_ARGS__, ))\n")
f.write("\n")
for n in range(1, MAXOUT+1):
f.write("#define DSET" + strn(n) + "(...) _SET" + strn(n) + "(__VA_ARGS__)\n")
f.write("\n")
for n in range(1, MAXOUT+1):
f.write("#define _SET" + strn(n) + "(" + largs(n) + "_nwarg, ...) SET" + strn(n) + "_DISC_ ## _nwarg (" + largs(n) +"_OPEN_ ## _nwarg, __VA_ARGS__)\n")
f.write("\n")
for n in range(1, MAXOUT+1):
f.write("#define _SET" + strn(n) + "_ID() _SET" + strn(n) + "\n")
f.write("\n")
for n in range(1, MAXOUT+1):
f.write("#define SET" + strn(n) + "_DISC_(" + largs(n) + "...) CALL_MACRO_X_FOR_EACH(_DEPARENC" + " ,"*(n>1) + largs(n-1)[:-2] + ") _DEPAREN(_arg"+strn(n)+")\n")
f.write("\n")
f.write("\n\n// O(n^2) macros\n")
# write O(n^2) macros
for n in range(1, MAXOUT+1):
for c in range(1, MAXOUT+1):
f.write("#define SET" + strn(n) + "_DISC_C" + strn(c) + "(...) SET" + strn(n) + "_REPL_C" + strn(c)+"\n")
f.write("\n")
for n in range(1, MAXOUT+1):
for c in range(1, n+1):
replargs = largs(n).replace(("_arg" + strn(c)), "_nwarg")
f.write("#define SET" + strn(n) + "_REPL_C" + strn(c) + "(" + largs(n) + "_nwarg, ...) _DEFER(_SET" + strn(n) + "_ID)()(" + replargs + "__VA_ARGS__)\n")
f.write("\n")
f.write("#endif /*MACROMAGIC_H*/\n")
f.close()