blob: 16873383ad87bf829afb2cf91d1e6255eb9d8aaa [file] [log] [blame]
Miklos Balint470919c2018-05-22 17:51:29 +02001#-------------------------------------------------------------------------------
2# Copyright (c) 2018, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8import re
9try:
10 from enum import Enum
11except ImportError as e:
12 print e, "To install it, type:"
13 print "pip install enum34"
14 exit(1)
15
16class Verbosity(Enum):
17 debug = 3
18 info = 2
19 warning = 1
20 error = 0
21
22# Set default value
23VERBOSITY = Verbosity.info
24
25REkeychain = "@@\w+[\.\w+]*@@"
26REfirstkeyword = "@@\w+\.?"
Miklos Balint0687dfc2018-06-01 13:44:00 +020027emptychain = "@@@@"
Miklos Balint470919c2018-05-22 17:51:29 +020028
29MISSING_KEYS_ACTION = 'halt'
30
31def log_print(level, *args, **kwargs):
32 global VERBOSITY
33 if kwargs.get("verbosity"):
34 VERBOSITY = kwargs["verbosity"]
35 if level.value <= VERBOSITY.value:
Miklos Balint3a05c9d2018-05-31 09:31:27 +020036 string = ' '.join(map(str, args))
Miklos Balint470919c2018-05-22 17:51:29 +020037 print string
38
39def leaftype(x):
40 return isinstance(x, str) or isinstance(x, unicode) or \
41 isinstance(x, type(1)) or isinstance(x, type(True))
42
43def substitute(templist, chains, db, depth):
44 depth += 1
45 log_print(Verbosity.info, "substitute(",templist, chains, db, depth,")")
46 if isinstance(db, type([])):
Miklos Balint0687dfc2018-06-01 13:44:00 +020047 # db is list
Miklos Balint470919c2018-05-22 17:51:29 +020048 outlist = []
49 for instance in db:
50 log_print(Verbosity.info, "Going deeper at", depth, "for db list instance", instance)
51 outlist.extend(substitute(templist, chains, instance, depth))
52 log_print(Verbosity.info, "substitute", depth, "returning from list with", outlist)
53 return outlist
54
Miklos Balint470919c2018-05-22 17:51:29 +020055 transientlist = list(templist)
Miklos Balint0687dfc2018-06-01 13:44:00 +020056 if leaftype(db):
57 # db is leaf
58 for chain in chains:
59 if templist[chain] == emptychain:
60 transientlist[chain] = str(db)
61 else:
62 print "keychain not empty but db is"
63 transientlist[chain] = str(db) + templist[chain]
64 continue
65 chains = []
66 log_print(Verbosity.info, "substitute", depth, "returning from leaf with", transientlist)
67 return transientlist
68
69 # db is dict
Miklos Balint470919c2018-05-22 17:51:29 +020070 # find chain groups with same key
71 chaingroups = {"chains": [], "keys": []}
72 for chain in chains:
73 key = re.search('\w+', templist[chain])
74 if not key:
75 # chain does not define a leaf
76 print "chain", chain, "out of keys before reaching leaf"
77 continue
78 key = key.group(0) # convert MatchObj to string
79 for idx, groupkey in enumerate(chaingroups["keys"]):
80 if key == groupkey:
81 # insert chain in group
82 chaingroups["chains"][idx].append(chain)
83 break
84 else:
85 # key not yet in the list
86 chaingroups["keys"].append(key)
87 chaingroups["chains"].append([chain])
88
89 log_print(Verbosity.debug, chaingroups)
90
91 for groupidx, key in enumerate(chaingroups["keys"]):
92 log_print(Verbosity.info, "key lookup in", db, "for", key)
93 if key in db.keys():
94 if leaftype(db[key]):
Miklos Balint0687dfc2018-06-01 13:44:00 +020095 # db entry value is leaf
Miklos Balint470919c2018-05-22 17:51:29 +020096 for chain in chaingroups["chains"][groupidx]:
97 transientlist[chain] = str(db[key])
98 chaingroups["chains"][groupidx] = []
99 else:
100 # db node is branch
101 for chain in chaingroups["chains"][groupidx]:
102 transientlist[chain] = re.sub(REfirstkeyword, "@@", templist[chain])
103 else:
104 # key not found in database
105 if MISSING_KEYS_ACTION == 'report' or MISSING_KEYS_ACTION == 'halt':
106 print "key", key, "not found, invalid chains", chaingroups["chains"][groupidx]
107 placeholder = False
108 if MISSING_KEYS_ACTION == 'hide':
109 placeholder = ""
110 if 'replace' in MISSING_KEYS_ACTION:
111 placeholder = MISSING_KEYS_ACTION.replace("replace ", "")
112 for chain in chaingroups["chains"][groupidx]:
113 transientlist[chain] = placeholder
114 chaingroups["chains"][groupidx] = []
115 if MISSING_KEYS_ACTION == 'halt':
116 exit(1)
117 log_print(Verbosity.debug, "**** after selection chaingroups:", chaingroups, transientlist)
118 forked = False
119 for chidx, chains in enumerate(chaingroups["chains"]):
120 if chains:
121 key = chaingroups["keys"][chidx]
122 log_print(Verbosity.info, "Going deeper at", depth, "for chains", chains, "in dict", db[key])
123 if not forked:
124 outlist = substitute(transientlist, chains, db[key], depth)
125 forked = True
126 else:
127 transientlist = list(outlist)
128 outlist = list()
129 for item in transientlist:
130 outlist.extend(substitute(item, chains, db[key], depth))
131
132 if not forked:
133 outlist = [transientlist]
134
135 log_print(Verbosity.info, "substitute", depth, "returning from dict/leaf with", outlist)
136 return outlist
137
138def keyword_substitute(db, line, missing_keys):
139 global MISSING_KEYS_ACTION
140 chains = []
141 MISSING_KEYS_ACTION = missing_keys
142 log_print(Verbosity.info, line)
143 templist = re.split("(" + REkeychain + ")", line)
144 for idx, item in enumerate(templist):
145 if re.match(REkeychain, item):
146 chains.append(idx)
147 log_print(Verbosity.info, "Keychain:", item)
148 outlist = substitute(templist, chains, db, 0)
149 outstring = ""
150 for outline in outlist:
151 outstring += ''.join(outline) + "\n"
152 log_print(Verbosity.info, "generator returns with:")
Miklos Balint3a05c9d2018-05-31 09:31:27 +0200153 log_print(Verbosity.info, outstring + "<<")
Miklos Balint470919c2018-05-22 17:51:29 +0200154 return outlist