summaryrefslogtreecommitdiffstats
path: root/xlators/experimental/fdl/src/gen_dumper.py
blob: c15f7c8870daa3ab9096d415b4c7d8b65b873ad6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/python2

from __future__ import print_function
import os
import re
import sys

curdir = os.path.dirname (sys.argv[0])
gendir = os.path.join (curdir, '../../../../libglusterfs/src')
sys.path.append (gendir)
from generator import ops, fop_subs, cbk_subs, generate

# See the big header comment at the start of gen_fdl.py to see how the stages
# fit together.  The big difference here is that *all* of the C code is in the
# template file as labelled fragments, instead of as Python strings.  That
# makes it much easier to edit in one place, with proper syntax highlighting
# and indentation.
#
#   Stage 1 uses type-specific fragments to generate FUNCTION_BODY, instead of
#   LEN_*_TEMPLATE and SERLZ_*_TEMPLATE to generate LEN_CODE and SER_CODE.
#
#   Stage 2 uses the FOP and CASE fragments instead of RECON_TEMPLATE and
#   FOP_TEMPLATE.  The expanded FOP code (including FUNCTION_BODY substitution
#   in the middle of each function) is emitted immediately; the expanded CASE
#   code is saved for the next stage.
#
#   Stage 3 uses the PROLOG and EPILOG fragments, with the expanded CASE code
#   in the middle of EPILOG, to generate the whole output file.
#
# Another way of looking at it is to consider how the fragments appear in
# the final output:
#
#   PROLOG
#   FOP (expanded for CREATE)
#       FOP before FUNCTION_BODY
#       LOC, INTEGER, GFID, etc. (one per arg, by type)
#       FOP after FUNCTION_BODY
#   FOP (expanded for WRITEV)
#       FOP before FUNCTION_BODY
#       GFID, VECTOR, etc. (on per arg, by type)
#       FOP after FUNCTION_BODY
#   (more FOPs)
#   EPILOG
#       EPILOG before CASE
#       CASE statements (one per fop)
#       EPILOG after CASE

typemap = {
	'dict_t *':				( "DICT",		""),
	'fd_t *':				( "GFID",		""),
	'dev_t':				( "DOUBLE",		"%ld (0x%lx)"),
	'gf_xattrop_flags_t':	( "INTEGER",	"%d (0x%x)"),
	'int32_t':				( "INTEGER",	"%d (0x%x)"),
	'mode_t':				( "INTEGER",	"%d (0x%x)"),
	'off_t':				( "DOUBLE",		"%ld (0x%lx)"),
	'size_t':				( "DOUBLE",		"%ld (0x%lx)"),
	'uint32_t':				( "INTEGER",	"%d (0x%x)"),
	'loc_t *':				( "LOC",		""),
	'const char *':			( "STRING",		""),
	'struct iovec *':		( "VECTOR",		""),
	'struct iatt *':		( "IATT",		""),
}

def get_special_subs (args):
	code = ""
	for arg in args:
		if (arg[0] != 'fop-arg') or (len(arg) < 4):
			continue
		recon_type, recon_fmt = typemap[arg[2]]
		code += fragments[recon_type].replace("@ARGNAME@", arg[3])		\
									 .replace("@FORMAT@", recon_fmt)
	return code

def gen_functions ():
	code = ""
	for name, value in ops.items():
		if "journal" not in [ x[0] for x in value ]:
			continue
		fop_subs[name]["@FUNCTION_BODY@"] = get_special_subs(value)
		# Print the FOP fragment with @FUNCTION_BODY@ in the middle.
		code += generate(fragments["FOP"], name, fop_subs)
	return code

def gen_cases ():
	code = ""
	for name, value in ops.items():
		if "journal" not in [ x[0] for x in value ]:
			continue
		# Add the CASE fragment for this fop.
		code += generate(fragments["CASE"], name, fop_subs)
	return code

def load_fragments (path="recon-tmpl.c"):
	pragma_re = re.compile('pragma fragment (.*)')
	cur_symbol = None
	cur_value = ""
	result = {}
	for line in open(path, "r").readlines():
		m = pragma_re.search(line)
		if m:
			if cur_symbol:
				result[cur_symbol] = cur_value
			cur_symbol = m.group(1)
			cur_value = ""
		else:
			cur_value += line
	if cur_symbol:
		result[cur_symbol] = cur_value
	return result

if __name__ == "__main__":
	fragments = load_fragments(sys.argv[1])
	print("/* BEGIN GENERATED CODE - DO NOT MODIFY */")
	print(fragments["PROLOG"])
	print(gen_functions())
	print(fragments["EPILOG"].replace("@SWITCH_BODY@", gen_cases()))
	print("/* END GENERATED CODE */")