Miklos Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 1 | #------------------------------------------------------------------------------- |
| 2 | # Copyright (c) 2018, Arm Limited. All rights reserved. |
| 3 | # |
| 4 | # SPDX-License-Identifier: BSD-3-Clause |
| 5 | # |
| 6 | #------------------------------------------------------------------------------- |
| 7 | |
| 8 | import re |
| 9 | try: |
| 10 | from enum import Enum |
| 11 | except ImportError as e: |
| 12 | print e, "To install it, type:" |
| 13 | print "pip install enum34" |
| 14 | exit(1) |
| 15 | |
| 16 | class Verbosity(Enum): |
| 17 | debug = 3 |
| 18 | info = 2 |
| 19 | warning = 1 |
| 20 | error = 0 |
| 21 | |
| 22 | # Set default value |
| 23 | VERBOSITY = Verbosity.info |
| 24 | |
| 25 | REkeychain = "@@\w+[\.\w+]*@@" |
| 26 | REfirstkeyword = "@@\w+\.?" |
Miklos Balint | 0687dfc | 2018-06-01 13:44:00 +0200 | [diff] [blame] | 27 | emptychain = "@@@@" |
Miklos Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 28 | |
| 29 | MISSING_KEYS_ACTION = 'halt' |
| 30 | |
| 31 | def log_print(level, *args, **kwargs): |
| 32 | global VERBOSITY |
| 33 | if kwargs.get("verbosity"): |
| 34 | VERBOSITY = kwargs["verbosity"] |
| 35 | if level.value <= VERBOSITY.value: |
Miklos Balint | 3a05c9d | 2018-05-31 09:31:27 +0200 | [diff] [blame] | 36 | string = ' '.join(map(str, args)) |
Miklos Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 37 | print string |
| 38 | |
| 39 | def leaftype(x): |
| 40 | return isinstance(x, str) or isinstance(x, unicode) or \ |
| 41 | isinstance(x, type(1)) or isinstance(x, type(True)) |
| 42 | |
| 43 | def substitute(templist, chains, db, depth): |
| 44 | depth += 1 |
| 45 | log_print(Verbosity.info, "substitute(",templist, chains, db, depth,")") |
| 46 | if isinstance(db, type([])): |
Miklos Balint | 0687dfc | 2018-06-01 13:44:00 +0200 | [diff] [blame] | 47 | # db is list |
Miklos Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 48 | 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 Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 55 | transientlist = list(templist) |
Miklos Balint | 0687dfc | 2018-06-01 13:44:00 +0200 | [diff] [blame] | 56 | 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 Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 70 | # 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 Balint | 0687dfc | 2018-06-01 13:44:00 +0200 | [diff] [blame] | 95 | # db entry value is leaf |
Miklos Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 96 | 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 | |
| 138 | def 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 Balint | 3a05c9d | 2018-05-31 09:31:27 +0200 | [diff] [blame] | 153 | log_print(Verbosity.info, outstring + "<<") |
Miklos Balint | 470919c | 2018-05-22 17:51:29 +0200 | [diff] [blame] | 154 | return outlist |