manifest: refactor python scripts for modularity

keyword_substitution.py for single line processing script
generate_from_template.py for template file to output
  file generation for a list of files
tfm_parse_manifest_list.py for building TFM-specific
  database and generated file list and tool invocation
YAML files for test vectors, generated file list

Change-Id: I514b5abff0df5a9c48357a6b52e80fc77595109d
Signed-off-by: Miklos Balint <miklos.balint@arm.com>
diff --git a/tools/generate_from_template.py b/tools/generate_from_template.py
new file mode 100644
index 0000000..5f2153a
--- /dev/null
+++ b/tools/generate_from_template.py
@@ -0,0 +1,107 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+import os
+from keyword_substitution import keyword_substitute, Verbosity, log_print
+
+VERBOSITY = Verbosity.warning
+log_print(Verbosity.debug, "Setting verbosity to", VERBOSITY, verbosity=VERBOSITY)
+
+controlsymbol = "@!GENERATOR"
+controlblockstart = "@!GENERATOR_BLOCK_START!@"
+controlblockend = "@!GENERATOR_BLOCK_END!@"
+controlconditionstart = "@!GENERATOR_CONDITIONAL_START!@"
+controlconditionelse = "@!GENERATOR_CONDITIONAL_ELSE!@"
+controlconditionend = "@!GENERATOR_CONDITIONAL_END!@"
+control_print_iteration_counter = "@!GENERATOR_ITERATION_COUNTER!@"
+control_print_donotedit_warning = "@!GENERATOR_DONOTEDIT_WARNING!@"
+
+donotedit_warning = "/*********** " + \
+                    "WARNING: This is an auto-generated file. Do not edit!" + \
+                    " ***********/\n"
+
+# All operations assume tf-m repo root as active working directory
+
+# Functions
+def generate(db, outfile_name):
+    outfile = \
+        open(outfile_name, "w")
+    with open(outfile_name + '.template', "r") as template_file:
+        template = template_file.readlines()
+
+    output = []
+    blocks = []
+    blocklines = []
+    MISSING_KEYS_ACTION = 'replace False'
+    inblock = False
+    iteration_counter = 0
+    for lineno, line in enumerate(template):
+        if controlblockstart in line:
+            inblock = True
+            log_print(Verbosity.info, "Blockstart:", str(lineno))
+            blocklines = []
+        elif controlblockend in line:
+            inblock = False
+            iteration_counter = 0
+            log_print(Verbosity.info, "Blocklines:", str(blocklines))
+            for manifest in db:
+                print_blocked = False
+                for line in blocklines:
+                    outlist = keyword_substitute(manifest, line, MISSING_KEYS_ACTION)
+                    outstring = ""
+                    for outline in outlist:
+                        outstring += ''.join(outline)
+                    log_print(Verbosity.info, outstring)
+                    if controlconditionstart in outstring:
+                        if 'False' in outstring:
+                            log_print(Verbosity.info, "PRINT BLOCKED")
+                            print_blocked = True
+                    elif controlconditionend in outstring:
+                        log_print(Verbosity.info, "PRINT ENABLED")
+                        print_blocked = False
+                    elif controlconditionelse in outstring:
+                        log_print(Verbosity.info, "PRINT " + str(print_blocked))
+                        print_blocked = not print_blocked
+                    else:
+                        if control_print_iteration_counter in outstring:
+                            outstring = outstring.replace(
+                                            control_print_iteration_counter,
+                                            str(iteration_counter))
+                        elif controlsymbol in outstring:
+                            print "Invalid control symbol:", outstring
+                            print "exiting"
+                            exit(1)
+                        if not print_blocked:
+                            outfile.write(outstring)
+                iteration_counter += 1
+                # end for manifest in db
+            blocks.append(blocklines)
+        elif inblock:
+            # inside a generator block
+            # append line to blocklines to be processed by template generator
+            blocklines.append(line)
+        else:
+            # outside a generator block
+            if control_print_donotedit_warning in line:
+                # print do not edit warning - Note: ignore rest of input line
+                line = donotedit_warning
+            elif control_print_iteration_counter in line:
+                # line contains an iteration counter request, replace with value
+                line = line.replace(control_print_iteration_counter, str(iteration_counter))
+            elif controlsymbol in line:
+                print "Invalid control symbol:", line
+                print "exiting"
+                exit(1)
+            outfile.write(line)
+    log_print(Verbosity.debug, "Blocks:" + str(blocks))
+    outfile.close()
+# def generate()
+
+def generate_from_template_file(db, file_list):
+    for file in file_list:
+        outfile = file["output"]
+        generate(db, outfile)
diff --git a/tools/keyword_substitution.py b/tools/keyword_substitution.py
index 57d4a31..9a98aae 100644
--- a/tools/keyword_substitution.py
+++ b/tools/keyword_substitution.py
@@ -32,9 +32,7 @@
     if kwargs.get("verbosity"):
         VERBOSITY = kwargs["verbosity"]
     if level.value <= VERBOSITY.value:
-        string = ''
-        for arg in args:
-            string += str(arg) + ' '
+        string = ' '.join(map(str, args))
         print string
 
 def leaftype(x):
@@ -138,5 +136,5 @@
     for outline in outlist:
         outstring += ''.join(outline) + "\n"
     log_print(Verbosity.info, "generator returns with:")
-    log_print(Verbosity.info, outstring, "<<")
+    log_print(Verbosity.info, outstring + "<<")
     return outlist
diff --git a/tools/keyword_substitution_test_vectors.yaml b/tools/keyword_substitution_test_vectors.yaml
new file mode 100644
index 0000000..b6c975a
--- /dev/null
+++ b/tools/keyword_substitution_test_vectors.yaml
@@ -0,0 +1,126 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+    "test_list": [{
+    "description": "Test no substitution",
+    "template": "quickbrownfox",
+    "db": {"a": "b", "c": "d"},
+    "expected": "quickbrownfox\n"
+    },
+    {
+    "description": "Test simple substitution",
+    "template": "@@a@@",
+    "db": {"a": "b", "c": "d"},
+    "expected": "b\n"
+    },
+    {
+    "template": "a123",
+    "db": [{"c": "d", "a": {"a1": "lollipop", "a2": "PPAP"}},
+           {"c": "x", "a": {"a1": "candyshop", "a2": "GitS: SAC"}}],
+    "expected": "a123\na123\n"},
+    {
+    "description": "Test two independent base symbols with two substitutions",
+    "template": "@@a@@ @@c@@",
+    "db": [{"a": "b", "c": "d"}, {"a": "x", "c": "x"}],
+    "expected": ["b d\n",
+                "x x\n"]},
+    {
+    "template": "@@a@@@ @b@@c@@",
+    "db": [{"a": "b", "c": "d"}, {"a": "x", "c": "x"}],
+    "expected": ["b@ @bd\n",
+                "x@ @bx\n"]},
+    {
+    "template": "@@a.a1@@",
+    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"}],
+    "expected": "lollipop\n"},
+    {
+    "template": "@@a.a1@@ @@a.a2@@",
+    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"}, {"a": "x", "c": "x"}],
+    "expected": ["lollipop PPAP\n",
+                "x x\n"]},
+    {
+    "template": "@@a.a1@@ @@a.a2@@",
+    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"},
+           {"a": {"a1": "candyshop", "a2": "GitS: SAC"}, "c": "x"}],
+    "expected": ["lollipop PPAP\n",
+                "candyshop GitS: SAC\n"]},
+    {
+    "template": "@@a.a1@@ @@a.a2@@ @@a@@",
+    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"}, {"a": {"a1": "candyshop", "a2": "GitS: SAC"}, "c": "x"}],
+    "expected": ["lollipop PPAP @@@@\n",
+                "candyshop GitS: SAC @@@@\n"]
+    },
+    {
+    "description": "List in dict",
+    "template": "@@a.name@@",
+    "db": [{"a": [{"name": "inst1"}, {"name": "inst2"}]}],
+    "expected": ["inst1\n",
+                "inst2\n"]
+    },
+    {
+    "description": "List in dict in list",
+    "template": "@@name@@ subinstance: @@subinstlist.name@@",
+    "db": [{"name": "inst1", "subinstlist": [{"name": "subinst1"}, {"name": "subinst2"}]},
+           {"name": "inst2", "subinstlist": [{"name": "subinst3"}, {"name": "subinst4"}]}],
+    "expected": ["inst1 subinstance: subinst1\n",
+                "inst1 subinstance: subinst2\n",
+                "inst2 subinstance: subinst3\n",
+                "inst2 subinstance: subinst4\n"]
+    },
+    {
+    "description": "Chain forks: multiple diverging chains",
+    "template": "@@name@@ subinstance: @@subinstlist.name@@ @@subinst2.name@@",
+    "db": {"name": "inst1", "subinstlist": [{"name": "subinst1"}, {"name": "subinst2"}],
+                             "subinst2": [{"name": "xxx"}, {"name": "yyy"}]},
+    "expected": ["inst1 subinstance: subinst1 xxx\n",
+                "inst1 subinstance: subinst1 yyy\n",
+                "inst1 subinstance: subinst2 xxx\n",
+                "inst1 subinstance: subinst2 yyy\n"]
+    },
+    {
+    "description": "Chain forks: multiple diverging chains",
+    "template": "@@name@@: @@subinstlist.name@@ @@subinstlist2.name@@ @@subinstlist3.name@@",
+    "db": {"name": "inst1", "subinstlist1": [{"name": "subinst1"}, {"name": "subinst2"}],
+                            "subinstlist2": [{"name": "xxx"}, {"name": "yyy"}],
+                            "subinstlist3": [{"name": "aaa"}, {"name": "bbb"}]},
+    "expected": ["inst1: @@subinstlist.name@@ xxx aaa\n",
+                "inst1: @@subinstlist.name@@ xxx bbb\n",
+                "inst1: @@subinstlist.name@@ yyy aaa\n",
+                "inst1: @@subinstlist.name@@ yyy bbb\n"]
+    },
+    {
+    "description": "Chain forks: multiple diverging chains, array of root instances",
+    "template": "@@name@@ subinstance: @@subinstlist.name@@ @@subinst2.name@@",
+    "db": [{"name": "inst1", "subinstlist": [{"name": "subinst1"}, {"name": "subinst2"}],
+                             "subinst2": [{"name": "xxx"}, {"name": "yyy"}]},
+           {"name": "inst2", "subinstlist": [{"name": "subinst3"}, {"name": "subinst4"}],
+                             "subinst2": [{"name": "inst2subinstlist2subinst1"}, {"name": "inst2subinstlist2subinst2"}]}],
+    "expected": ["inst1 subinstance: subinst1 xxx\n",
+                "inst1 subinstance: subinst1 yyy\n",
+                "inst1 subinstance: subinst2 xxx\n",
+                "inst1 subinstance: subinst2 yyy\n",
+                "inst2 subinstance: subinst3 inst2subinstlist2subinst1\n",
+                "inst2 subinstance: subinst3 inst2subinstlist2subinst2\n",
+                "inst2 subinstance: subinst4 inst2subinstlist2subinst1\n",
+                "inst2 subinstance: subinst4 inst2subinstlist2subinst2\n"]
+    },
+    {
+    "description": "Chain forks: multiple diverging chains with missing subinstance",
+    "template": "@@name@@ subinstance: @@subinstlist1.name@@ @@subinstlist2.name@@",
+    "db": [{"name": "inst1", "subinstlist1": [{"name": "subinst1"}, {"name": "subinst2"}],
+                             "subinstlist2": [{"name": "xxx"}, {"name": "yyy"}]},
+           {"name": "inst2", "subinstlist1": [{"name": "subinst3"}, {"name": "subinst4"}]}],
+    "expected": ["inst1 subinstance: subinst1 xxx\n",
+                "inst1 subinstance: subinst1 yyy\n",
+                "inst1 subinstance: subinst2 xxx\n",
+                "inst1 subinstance: subinst2 yyy\n",
+                "inst2 subinstance: subinst3 @@subinstlist2.name@@\n",
+                "inst2 subinstance: subinst4 @@subinstlist2.name@@\n"]
+    }
+    ]
+}
diff --git a/tools/keyword_substitution_tests.py b/tools/keyword_substitution_tests.py
index 4936f8b..21ebc17 100644
--- a/tools/keyword_substitution_tests.py
+++ b/tools/keyword_substitution_tests.py
@@ -5,122 +5,25 @@
 #
 #-------------------------------------------------------------------------------
 
-import re
 from keyword_substitution import keyword_substitute, log_print, Verbosity
 
-tests = []
+try:
+    import yaml
+except ImportError as e:
+    print e, "To install it, type:"
+    print "pip install PyYAML"
+    exit(1)
+
 VERBOSITY = Verbosity.warning
 log_print(Verbosity.debug, "Setting verbosity to", VERBOSITY, verbosity=VERBOSITY)
-tests.append({
-    "description": "Test no substitution",
-    "template": "quickbrownfox",
-    "db": {"a": "b", "c": "d"},
-    "expected": "quickbrownfox\n"})
-tests.append({
-    "description": "Test simple substitution",
-    "template": "@@a@@",
-    "db": {"a": "b", "c": "d"},
-    "expected": "b\n"})
-tests.append({
-    "template": "a123",
-    "db": [{"c": "d", "a": {"a1": "lollipop", "a2": "PPAP"}},
-           {"c": "x", "a": {"a1": "candyshop", "a2": "GitS: SAC"}}],
-    "expected": "a123\na123\n"})
-tests.append({
-    "description": "Test two independent base symbols with two substitutions",
-    "template": "@@a@@ @@c@@",
-    "db": [{"a": "b", "c": "d"}, {"a": "x", "c": "x"}],
-    "expected": "b d\n" +
-                "x x\n"})
-tests.append({
-    "template": "@@a@@@ @b@@c@@",
-    "db": [{"a": "b", "c": "d"}, {"a": "x", "c": "x"}],
-    "expected": "b@ @bd\n" +
-                "x@ @bx\n"})
-tests.append({
-    "template": "@@a.a1@@",
-    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"}],
-    "expected": "lollipop\n"})
-tests.append({
-    "template": "@@a.a1@@ @@a.a2@@",
-    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"}, {"a": "x", "c": "x"}],
-    "expected": "lollipop PPAP\n" +
-                "x x\n"})
-tests.append({
-    "template": "@@a.a1@@ @@a.a2@@",
-    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"},
-           {"a": {"a1": "candyshop", "a2": "GitS: SAC"}, "c": "x"}],
-    "expected": "lollipop PPAP\n" +
-                "candyshop GitS: SAC\n"})
-tests.append({
-    "template": "@@a.a1@@ @@a.a2@@ @@a@@",
-    "db": [{"a": {"a1": "lollipop", "a2": "PPAP"}, "c": "d"}, {"a": {"a1": "candyshop", "a2": "GitS: SAC"}, "c": "x"}],
-    "expected": "lollipop PPAP @@@@\n" +
-                "candyshop GitS: SAC @@@@\n"})
-tests.append({
-    "description": "List in dict",
-    "template": "@@a.name@@",
-    "db": [{"a": [{"name": "inst1"}, {"name": "inst2"}]}],
-    "expected": "inst1\n" +
-                "inst2\n"})
-tests.append({
-    "description": "List in dict in list",
-    "template": "@@name@@ subinstance: @@subinstlist.name@@",
-    "db": [{"name": "inst1", "subinstlist": [{"name": "subinst1"}, {"name": "subinst2"}]},
-           {"name": "inst2", "subinstlist": [{"name": "subinst3"}, {"name": "subinst4"}]}],
-    "expected": "inst1 subinstance: subinst1\n" +
-                "inst1 subinstance: subinst2\n" +
-                "inst2 subinstance: subinst3\n" +
-                "inst2 subinstance: subinst4\n"})
-tests.append({
-    "description": "Chain forks: multiple diverging chains",
-    "template": "@@name@@ subinstance: @@subinstlist.name@@ @@subinst2.name@@",
-    "db": {"name": "inst1", "subinstlist": [{"name": "subinst1"}, {"name": "subinst2"}],
-                             "subinst2": [{"name": "xxx"}, {"name": "yyy"}]},
-    "expected": "inst1 subinstance: subinst1 xxx\n" +
-                "inst1 subinstance: subinst1 yyy\n" +
-                "inst1 subinstance: subinst2 xxx\n" +
-                "inst1 subinstance: subinst2 yyy\n"})
-tests.append({
-    "description": "Chain forks: multiple diverging chains",
-    "template": "@@name@@: @@subinstlist.name@@ @@subinstlist2.name@@ @@subinstlist3.name@@",
-    "db": {"name": "inst1", "subinstlist1": [{"name": "subinst1"}, {"name": "subinst2"}],
-                            "subinstlist2": [{"name": "xxx"}, {"name": "yyy"}],
-                            "subinstlist3": [{"name": "aaa"}, {"name": "bbb"}]},
-    "expected": "inst1: @@subinstlist.name@@ xxx aaa\n" +
-                "inst1: @@subinstlist.name@@ xxx bbb\n" +
-                "inst1: @@subinstlist.name@@ yyy aaa\n" +
-                "inst1: @@subinstlist.name@@ yyy bbb\n"})
-tests.append({
-    "description": "Chain forks: multiple diverging chains, array of root instances",
-    "template": "@@name@@ subinstance: @@subinstlist.name@@ @@subinst2.name@@",
-    "db": [{"name": "inst1", "subinstlist": [{"name": "subinst1"}, {"name": "subinst2"}],
-                             "subinst2": [{"name": "xxx"}, {"name": "yyy"}]},
-           {"name": "inst2", "subinstlist": [{"name": "subinst3"}, {"name": "subinst4"}],
-                             "subinst2": [{"name": "inst2subinstlist2subinst1"}, {"name": "inst2subinstlist2subinst2"}]}],
-    "expected": "inst1 subinstance: subinst1 xxx\n" +
-                "inst1 subinstance: subinst1 yyy\n" +
-                "inst1 subinstance: subinst2 xxx\n" +
-                "inst1 subinstance: subinst2 yyy\n" +
-                "inst2 subinstance: subinst3 inst2subinstlist2subinst1\n" +
-                "inst2 subinstance: subinst3 inst2subinstlist2subinst2\n" +
-                "inst2 subinstance: subinst4 inst2subinstlist2subinst1\n" +
-                "inst2 subinstance: subinst4 inst2subinstlist2subinst2\n"})
-tests.append({
-    "description": "Chain forks: multiple diverging chains with missing subinstance",
-    "template": "@@name@@ subinstance: @@subinstlist1.name@@ @@subinstlist2.name@@",
-    "db": [{"name": "inst1", "subinstlist1": [{"name": "subinst1"}, {"name": "subinst2"}],
-                             "subinstlist2": [{"name": "xxx"}, {"name": "yyy"}]},
-           {"name": "inst2", "subinstlist1": [{"name": "subinst3"}, {"name": "subinst4"}]}],
-    "expected": "inst1 subinstance: subinst1 xxx\n"
-                "inst1 subinstance: subinst1 yyy\n"
-                "inst1 subinstance: subinst2 xxx\n"
-                "inst1 subinstance: subinst2 yyy\n"
-                "inst2 subinstance: subinst3 @@subinstlist2.name@@\n"
-                "inst2 subinstance: subinst4 @@subinstlist2.name@@\n"})
 
 def testsuite():
-    for tcidx, test in enumerate(tests):
+    with open('keyword_substitution_test_vectors.yaml', 'r') as test_vectors_file:
+        test_yaml = yaml.load(test_vectors_file)
+        test_list = test_yaml["test_list"]
+
+    for tcidx, test in enumerate(test_list):
+        expected = ''.join(test["expected"])
         print
         log_print(Verbosity.debug, "template:", test["template"])
         log_print(Verbosity.debug, "db:", test["db"])
@@ -131,17 +34,17 @@
             outstring += ''.join(outline) + "\n"
         log_print(Verbosity.info, "Got:")
         log_print(Verbosity.info, outstring)
-        if outstring == test["expected"]:
+        if outstring == expected:
             print "Test", tcidx, "PASSED"
             test["result"] = "PASSED"
         else:
             print "Test", tcidx, "FAILED, expected:"
-            print test["expected"]
+            print expected
             test["result"] = "FAILED"
 
     print
     print "Test summary:"
-    for idx, test in enumerate(tests):
+    for idx, test in enumerate(test_list):
         print "Test", idx, test["result"]
 
 def main():
diff --git a/tools/tfm_generated_file_list.yaml b/tools/tfm_generated_file_list.yaml
new file mode 100644
index 0000000..26d5143
--- /dev/null
+++ b/tools/tfm_generated_file_list.yaml
@@ -0,0 +1,30 @@
+#-------------------------------------------------------------------------------

+# Copyright (c) 2018, Arm Limited. All rights reserved.

+#

+# SPDX-License-Identifier: BSD-3-Clause

+#

+#-------------------------------------------------------------------------------

+

+{

+  "name": "TF-M generated file list",

+  "type": "generated_file_list",

+  "version_major": 0,

+  "version_minor": 1,

+  "file_list": [

+    {

+      "name": "Secure Partition ID definitions",

+      "short_name": "tfm_partition_defs",

+      "output": "secure_fw/services/tfm_partition_defs.inc"

+    },

+    {

+        "name": "Secure Partition declarations",

+        "short_name": "tfm_partition_list",

+        "output": "secure_fw/services/tfm_partition_list.inc"

+    },

+    {

+        "name": "Secure Function list",

+        "short_name": "tfm_sfid_list",

+        "output": "secure_fw/services/tfm_sfid_list.inc"

+    }

+  ]

+}

diff --git a/tools/manifest_list.yaml b/tools/tfm_manifest_list.yaml
similarity index 79%
rename from tools/manifest_list.yaml
rename to tools/tfm_manifest_list.yaml
index f06e981..b1aa955 100644
--- a/tools/manifest_list.yaml
+++ b/tools/tfm_manifest_list.yaml
@@ -14,7 +14,7 @@
     {

       "name": "Secure Storage Service",

       "short_name": "SST",

-      "manifest": "../secure_fw/services/secure_storage/manifest.yaml",

+      "manifest": "secure_fw/services/secure_storage/manifest.yaml",

       "tfm_extensions": true,

       "version_major": 0,

       "version_minor": 1

@@ -22,7 +22,7 @@
     {

       "name": "TFM Audit Log Service",

       "short_name": "TFM_Audit_Log",

-      "manifest": "../secure_fw/services/audit_logging/manifest.yaml",

+      "manifest": "secure_fw/services/audit_logging/manifest.yaml",

       "tfm_extensions": true,

       "version_major": 0,

       "version_minor": 1

@@ -30,7 +30,7 @@
     {

       "name": "TFM Core Test Service",

       "short_name": "TFM_Core_Test",

-      "manifest": "../test/test_services/tfm_core_test/manifest.yaml",

+      "manifest": "test/test_services/tfm_core_test/manifest.yaml",

       "tfm_extensions": true,

       "conditional": "TFM_PARTITION_TEST_CORE",

       "version_major": 0,

@@ -39,7 +39,7 @@
     {

       "name": "TFM Core Test Service 2",

       "short_name": "TFM_Core_Test_2",

-      "manifest": "../test/test_services/tfm_core_test_2/manifest.yaml",

+      "manifest": "test/test_services/tfm_core_test_2/manifest.yaml",

       "tfm_extensions": true,

       "conditional": "TFM_PARTITION_TEST_CORE",

       "version_major": 0,

@@ -48,7 +48,7 @@
     {

       "name": "TFM SST Test Service",

       "short_name": "TFM_SST_Test",

-      "manifest": "../test/test_services/tfm_sst_test_service/manifest.yaml",

+      "manifest": "test/test_services/tfm_sst_test_service/manifest.yaml",

       "tfm_extensions": true,

       "conditional": "TFM_PARTITION_TEST_SST",

       "version_major": 0,

diff --git a/tools/tfm_parse_manifest_list.py b/tools/tfm_parse_manifest_list.py
index 104b9ec..76fb310 100644
--- a/tools/tfm_parse_manifest_list.py
+++ b/tools/tfm_parse_manifest_list.py
@@ -6,7 +6,8 @@
 #-------------------------------------------------------------------------------
 
 import os
-from keyword_substitution import keyword_substitute, Verbosity, log_print
+from keyword_substitution import Verbosity, log_print
+from generate_from_template import generate_from_template_file
 
 try:
     import yaml
@@ -18,32 +19,14 @@
 VERBOSITY = Verbosity.warning
 log_print(Verbosity.debug, "Setting verbosity to", VERBOSITY, verbosity=VERBOSITY)
 
-controlsymbol = "@!GENERATOR"
-controlblockstart = "@!GENERATOR_BLOCK_START!@"
-controlblockend = "@!GENERATOR_BLOCK_END!@"
-controlconditionstart = "@!GENERATOR_CONDITIONAL_START!@"
-controlconditionelse = "@!GENERATOR_CONDITIONAL_ELSE!@"
-controlconditionend = "@!GENERATOR_CONDITIONAL_END!@"
-control_print_iteration_counter = "@!GENERATOR_ITERATION_COUNTER!@"
-control_print_donotedit_warning = "@!GENERATOR_DONOTEDIT_WARNING!@"
-
-donotedit_warning = "/*********** " + \
-                    "WARNING: This is an auto-generated file. Do not edit!" + \
-                    " ***********/\n"
-
 # All operations assume tf-m repo root as active working directory
 
-# Initialisation of globals
-part_db_basename = 'tfm_partition_list.inc'
-part_defs_basename = 'tfm_partition_defs.inc'
-sfid_map_basename = 'tfm_sfid_list.inc'
-
 # Functions
 def load_manifest_list(file):
     db = []
     manifest_list = yaml.load(file)
     for item in manifest_list["manifest_list"]:
-        manifest_path = os.path.join('tools', item['manifest'])
+        manifest_path = item['manifest']
         try:
             file = open(manifest_path)
             manifest = yaml.load(file)
@@ -51,93 +34,21 @@
         except IOError:
             print "Manifest for "+item['name']+" cannot be opened at path "+item['manifest']
     return db
-# def load_yaml_file
-
-def generate(db, path, basename):
-    outfile = \
-        open(os.path.join(path, basename), "w")
-    with open(os.path.join(path, basename+'.template'), "r") as template_file:
-        template = template_file.readlines()
-
-    output = []
-    blocks = []
-    blocklines = []
-    MISSING_KEYS_ACTION = 'replace False'
-    inblock = False
-    linecnt = len(template)
-    for lineno, line in enumerate(template):
-        if controlblockstart in line:
-            inblock = True
-            log_print(Verbosity.info, "Blockstart:", str(lineno))
-            blocklines = []
-        elif controlblockend in line:
-            inblock = False
-            iteration_counter = 0
-            log_print(Verbosity.info, "Blocklines:", str(blocklines))
-            for manifest in db:
-                print_blocked = False
-                for line in blocklines:
-                    outlist = keyword_substitute(manifest, line, MISSING_KEYS_ACTION)
-                    outstring = ""
-                    for outline in outlist:
-                        outstring += ''.join(outline)
-                    log_print(Verbosity.info, outstring)
-                    if controlconditionstart in outstring:
-                        if 'False' in outstring:
-                            log_print(Verbosity.info, "PRINT BLOCKED")
-                            print_blocked = True
-                    elif controlconditionend in outstring:
-                        log_print(Verbosity.info, "PRINT ENABLED")
-                        print_blocked = False
-                    elif controlconditionelse in outstring:
-                        log_print(Verbosity.info, "PRINT " + str(print_blocked))
-                        print_blocked = not print_blocked
-                    else:
-                        if control_print_iteration_counter in outstring:
-                            outstring = outstring.replace(
-                                            control_print_iteration_counter,
-                                            str(iteration_counter))
-                        elif controlsymbol in outstring:
-                            print "Invalid control symbol:", outstring
-                            print "exiting"
-                            exit(1)
-                        if not print_blocked:
-                            outfile.write(outstring)
-                iteration_counter += 1
-                # end for manifest in db
-            blocks.append(blocklines)
-        elif inblock:
-            # inside a generator block
-            # append line to blocklines to be processed by template generator
-            blocklines.append(line)
-        else:
-            # outside a generator block
-            if control_print_donotedit_warning in line:
-                # print do not edit warning - Note: ignore rest of input line
-                line = donotedit_warning
-            elif control_print_iteration_counter in line:
-                # line contains an iteration counter request, replace with value
-                line = line.replace(control_print_iteration_counter, str(iteration_counter))
-            elif controlsymbol in line:
-                print "Invalid control symbol:", line
-                print "exiting"
-                exit(1)
-            outfile.write(line)
-    log_print(Verbosity.info, "Blocks:" + str(blocks))
-    outfile.close()
-# def generate()
+# def load_manifest_list
 
 # main
 def main():
-    with open(os.path.join('tools', 'manifest_list.yaml')) \
-                                                        as manifest_list_yaml_file:
+    with open(os.path.join('tools', 'tfm_manifest_list.yaml')) \
+                                                    as manifest_list_yaml_file:
         # Read manifest list file, build database
         db = load_manifest_list(manifest_list_yaml_file)
 
-    path = os.path.join('secure_fw', 'services')
-    generate(db, path, part_db_basename)
-    generate(db, path, sfid_map_basename)
-    generate(db, path, part_defs_basename)
+    with open(os.path.join('tools', 'tfm_generated_file_list.yaml')) \
+                                                    as file_list_yaml_file:
+        # read list of files that need to be generated from templates using db
+        file_list_yaml = yaml.load(file_list_yaml_file)
+        file_list = file_list_yaml["file_list"]
+    generate_from_template_file(db, file_list)
 
 if __name__ == "__main__":
     main()