2012-05-21 04:12:37 -07:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2010-05-24 23:35:35 -07:00
|
|
|
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import re
|
|
|
|
import string
|
|
|
|
|
|
|
|
defines = dict()
|
|
|
|
|
2012-03-18 13:07:25 -07:00
|
|
|
def parseShaderName(shadername):
|
|
|
|
name = ""
|
|
|
|
params = {}
|
|
|
|
inparams = None
|
|
|
|
inparam = None
|
|
|
|
curparams = []
|
|
|
|
for c in shadername:
|
|
|
|
if c == '<':
|
|
|
|
inparams = ''
|
|
|
|
elif c == ':':
|
|
|
|
if inparams is None:
|
|
|
|
raise Exception(": in shader name")
|
|
|
|
inparam = ''
|
|
|
|
elif c == ',':
|
|
|
|
if inparams is None:
|
|
|
|
raise Exception(", in shader name")
|
|
|
|
if inparam is None:
|
|
|
|
raise Exception("no values for parameter " + inparams)
|
|
|
|
curparams.append(inparam)
|
|
|
|
inparam = ''
|
|
|
|
elif c == '>':
|
|
|
|
if inparams is None:
|
|
|
|
raise Exception("> in shader name")
|
|
|
|
if inparam is None:
|
|
|
|
raise Exception("no values for parameter " + inparams)
|
|
|
|
curparams.append(inparam)
|
|
|
|
params[inparams] = curparams
|
|
|
|
name += '$' + inparams + '$'
|
|
|
|
inparams = None
|
|
|
|
inparam = None
|
|
|
|
else:
|
|
|
|
if inparam is not None:
|
|
|
|
inparam += c
|
|
|
|
elif inparams is not None:
|
|
|
|
inparams += c
|
|
|
|
else:
|
|
|
|
name += c
|
|
|
|
return (name, params)
|
|
|
|
|
2010-05-24 23:35:35 -07:00
|
|
|
def emitShader(fp, shadername, shaderlines):
|
2012-03-18 13:07:25 -07:00
|
|
|
(parsedname, params) = parseShaderName(shadername)
|
2010-05-24 23:35:35 -07:00
|
|
|
eolContinue = "\\n\\\n";
|
2012-03-18 13:07:25 -07:00
|
|
|
pvals = ['']
|
|
|
|
pname = ''
|
|
|
|
pnames = params.keys()
|
|
|
|
if len(pnames) > 1:
|
|
|
|
raise Exception("Currently only supports zero or one parameters to a @shader")
|
|
|
|
if pnames:
|
|
|
|
pname = pnames[0]
|
|
|
|
pvals = params[pname]
|
|
|
|
for pval in pvals:
|
|
|
|
name = parsedname.replace('$' + pname + '$', pval, 1);
|
2012-03-26 15:13:34 -07:00
|
|
|
fp.write("static const char %s[] = \"/* %s */%s" % (name,name,eolContinue))
|
2012-03-18 13:07:25 -07:00
|
|
|
for line in shaderlines:
|
|
|
|
line = line.replace("\\", "\\\\")
|
|
|
|
while line.find('$') != -1:
|
|
|
|
expansions = re.findall('\$\S+\$', line)
|
|
|
|
for m in expansions:
|
|
|
|
mkey = m[1:-1]
|
|
|
|
mkey = mkey.replace('<' + pname + '>', '<' + pval + '>')
|
|
|
|
if not defines.has_key(mkey):
|
|
|
|
print "Error: Undefined expansion used: '%s'" % (m,)
|
|
|
|
sys.exit(1)
|
|
|
|
mval = defines[mkey]
|
|
|
|
if type(mval) == str:
|
|
|
|
line = line.replace(m, mval)
|
|
|
|
elif type(mval) == list:
|
|
|
|
line = line.replace(m, eolContinue.join(mval) + eolContinue);
|
|
|
|
else:
|
|
|
|
print "Internal Error: Unknown type in defines array: '%s'" % (str(type(mval)),)
|
2010-05-24 23:35:35 -07:00
|
|
|
|
2012-03-18 13:07:25 -07:00
|
|
|
fp.write("%s%s" % (line,eolContinue))
|
|
|
|
fp.write("\";\n\n");
|
2010-05-24 23:35:35 -07:00
|
|
|
|
|
|
|
def genShaders(infile, outfile):
|
|
|
|
source = open(infile, "r").readlines()
|
|
|
|
desthdr = open(outfile, "w+")
|
|
|
|
|
2012-03-26 15:13:34 -07:00
|
|
|
desthdr.write("/* AUTOMATICALLY GENERATED from " + infile + " */\n");
|
2010-05-24 23:35:35 -07:00
|
|
|
desthdr.write("/* DO NOT EDIT! */\n\n");
|
|
|
|
|
|
|
|
global defines
|
|
|
|
|
|
|
|
indefine = None
|
|
|
|
inshader = None
|
|
|
|
|
|
|
|
inblock = False
|
|
|
|
linebuffer = []
|
|
|
|
|
|
|
|
for line in source:
|
|
|
|
# strip comments, if not inblock
|
|
|
|
if not inblock and line.startswith("//"):
|
|
|
|
continue
|
|
|
|
line = string.strip(line)
|
|
|
|
|
|
|
|
if len(line) == 0:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if line[0] == '@':
|
|
|
|
cmd = line
|
|
|
|
rest = ''
|
|
|
|
|
|
|
|
if line.find(' ') != -1:
|
|
|
|
cmd = line[0:line.find(' ')]
|
|
|
|
rest = string.strip(line[len(cmd) + 1:])
|
|
|
|
|
|
|
|
if cmd == "@define":
|
|
|
|
if inblock:
|
|
|
|
raise Exception("@define inside a block!")
|
|
|
|
space = rest.find(' ')
|
|
|
|
if space != -1:
|
|
|
|
defines[rest[0:space]] = rest[space+1:]
|
|
|
|
else:
|
|
|
|
indefine = rest
|
|
|
|
inblock = True
|
|
|
|
elif cmd == "@shader":
|
|
|
|
if inblock:
|
|
|
|
raise Exception("@shader inside a block!")
|
|
|
|
if len(rest) == 0:
|
|
|
|
raise Exception("@shader without a name!")
|
|
|
|
inshader = rest
|
|
|
|
inblock = True
|
|
|
|
elif cmd == "@end":
|
|
|
|
if indefine is not None:
|
|
|
|
if type(linebuffer) == list:
|
|
|
|
for i in range(len(linebuffer)):
|
|
|
|
linebuffer[i] = linebuffer[i].replace("\\", "\\\\")
|
|
|
|
defines[indefine] = linebuffer
|
|
|
|
elif inshader is not None:
|
|
|
|
emitShader(desthdr, inshader, linebuffer)
|
|
|
|
else:
|
|
|
|
raise Exception("@end outside of a block!")
|
|
|
|
indefine = None
|
|
|
|
inshader = None
|
|
|
|
inblock = None
|
|
|
|
linebuffer = []
|
|
|
|
else:
|
|
|
|
raise Exception("Unknown command: %s" % (cmd,))
|
|
|
|
else:
|
|
|
|
if inblock:
|
|
|
|
linebuffer.append(line)
|
|
|
|
|
|
|
|
if (len(sys.argv) != 3):
|
|
|
|
print "Usage: %s infile.txt outfile.h" % (sys.argv[0],)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
genShaders(sys.argv[1], sys.argv[2])
|