5eda2e5
#!/usr/bin/env python3
5eda2e5
#
5eda2e5
# Copyright (C) 2021 Red Hat, Inc.
5eda2e5
#
5eda2e5
# This library is free software; you can redistribute it and/or
5eda2e5
# modify it under the terms of the GNU Lesser General Public
5eda2e5
# License as published by the Free Software Foundation; either
5eda2e5
# version 2.1 of the License, or (at your option) any later version.
5eda2e5
#
5eda2e5
# This library is distributed in the hope that it will be useful,
5eda2e5
# but WITHOUT ANY WARRANTY; without even the implied warranty of
5eda2e5
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5eda2e5
# Lesser General Public License for more details.
5eda2e5
#
5eda2e5
# You should have received a copy of the GNU Lesser General Public
5eda2e5
# License along with this library.  If not, see
5eda2e5
# <http://www.gnu.org/licenses/>.
5eda2e5
5eda2e5
# About:
5eda2e5
# When provided with an interface file, this script outputs a new interface
5eda2e5
# file, where all original interfaces are enclosed in an ifndef statement
5eda2e5
# dependent on their name. All indentation inside the interface file should
5eda2e5
# be converted to tabs before running this script.
5eda2e5
# 
5eda2e5
# Known issues:
5eda2e5
# - interface already enclosed in an ifndef statement is not ignored
5eda2e5
# - "`"  and "'" inside comments are not ignored
5eda2e5
# - \t is always used for indentation - may result in mixture of spaces and tabs
5eda2e5
5eda2e5
import sys
5eda2e5
import os
5eda2e5
import re
5eda2e5
5eda2e5
if len(sys.argv) < 1:
5eda2e5
    print(("Usage: {} <policy>.if > <output>.if").format(sys.argv[0]), file=sys.stderr)
5eda2e5
    exit(os.EX_USAGE)
5eda2e5
5eda2e5
# ending index of interface
5eda2e5
end = 0
5eda2e5
with open(sys.argv[1], 'r') as f:
5eda2e5
    interfaces = f.read()
5eda2e5
    file_len = len(interfaces)
5eda2e5
5eda2e5
    while end < file_len:
5eda2e5
        start = interfaces.find("interface(`", end)
5eda2e5
        if start < 0:
5eda2e5
            #no more interfaces
5eda2e5
            print(interfaces[end:], end ="")
5eda2e5
            break
5eda2e5
        name_end = interfaces.find("'", start+11)
5eda2e5
        name = interfaces[start+11:name_end]
5eda2e5
5eda2e5
        # locate the end of the interface - i.e. ending apostrophe
5eda2e5
        reg = re.compile(r"[`']")
5eda2e5
        # skip the ' after interface name
5eda2e5
        i = name_end+1
5eda2e5
        # counter for the depth (` opens a new block, while ' closes it)
5eda2e5
        graves = 0
5eda2e5
        while i < file_len:
5eda2e5
            match = reg.search(interfaces, i)
5eda2e5
            if not match:
5eda2e5
                print("Malformed interface: {}".format(name), file=sys.stderr)
5eda2e5
                exit(1)
5eda2e5
5eda2e5
            i = match.end()
5eda2e5
            if match.group(0) == '`':
5eda2e5
                graves += 1
5eda2e5
            else:
5eda2e5
                graves -= 1
5eda2e5
                if graves == 0:
5eda2e5
                    break
5eda2e5
5eda2e5
        # keep everything between the end of previous interface and start of a new one
5eda2e5
        print(interfaces[end:start], end ="")
5eda2e5
        # interface ends in "')" -- add 1 for the edning bracket
5eda2e5
        end = i+1
5eda2e5
        # print the whole interface enclosed in "ifndef"
5eda2e5
        print("ifndef(`{}',`".format(name))
5eda2e5
        print('\n'.join([('\t' + x) if x else x for x in interfaces[start:end].split('\n')]))
5eda2e5
        print("')", end ="")