diff options
Diffstat (limited to 'scripts/lib/bsp/engine.py')
| -rw-r--r-- | scripts/lib/bsp/engine.py | 173 |
1 files changed, 170 insertions, 3 deletions
diff --git a/scripts/lib/bsp/engine.py b/scripts/lib/bsp/engine.py index 681720d20a..7d6be239da 100644 --- a/scripts/lib/bsp/engine.py +++ b/scripts/lib/bsp/engine.py | |||
| @@ -756,6 +756,8 @@ class CheckInputLine(ListValInputLine): | |||
| 756 | return None | 756 | return None |
| 757 | 757 | ||
| 758 | 758 | ||
| 759 | dirname_substitutions = {} | ||
| 760 | |||
| 759 | class SubstrateBase(object): | 761 | class SubstrateBase(object): |
| 760 | """ | 762 | """ |
| 761 | Base class for both expanded and unexpanded file and dir container | 763 | Base class for both expanded and unexpanded file and dir container |
| @@ -764,6 +766,7 @@ class SubstrateBase(object): | |||
| 764 | def __init__(self, filename, filebase, out_filebase): | 766 | def __init__(self, filename, filebase, out_filebase): |
| 765 | self.filename = filename | 767 | self.filename = filename |
| 766 | self.filebase = filebase | 768 | self.filebase = filebase |
| 769 | self.translated_filename = filename | ||
| 767 | self.out_filebase = out_filebase | 770 | self.out_filebase = out_filebase |
| 768 | self.raw_lines = [] | 771 | self.raw_lines = [] |
| 769 | self.expanded_lines = [] | 772 | self.expanded_lines = [] |
| @@ -869,6 +872,167 @@ class SubstrateBase(object): | |||
| 869 | 872 | ||
| 870 | return self.expand_input_tag(tag, lineno) | 873 | return self.expand_input_tag(tag, lineno) |
| 871 | 874 | ||
| 875 | def append_translated_filename(self, filename): | ||
| 876 | """ | ||
| 877 | Simply append filename to translated_filename | ||
| 878 | """ | ||
| 879 | self.translated_filename = os.path.join(self.translated_filename, filename) | ||
| 880 | |||
| 881 | def get_substituted_file_or_dir_name(self, first_line, tag): | ||
| 882 | """ | ||
| 883 | If file or dir names contain name substitutions, return the name | ||
| 884 | to substitute. Note that this is just the file or dirname and | ||
| 885 | doesn't include the path. | ||
| 886 | """ | ||
| 887 | filename = first_line.find(tag) | ||
| 888 | if filename != -1: | ||
| 889 | filename += len(tag) | ||
| 890 | substituted_filename = first_line[filename:].strip() | ||
| 891 | this = substituted_filename.find(" this") | ||
| 892 | if this != -1: | ||
| 893 | head, tail = os.path.split(self.filename) | ||
| 894 | substituted_filename = substituted_filename[:this + 1] + tail | ||
| 895 | if tag == DIRNAME_TAG: # get rid of .noinstall in dirname | ||
| 896 | substituted_filename = substituted_filename.split('.')[0] | ||
| 897 | |||
| 898 | return substituted_filename | ||
| 899 | |||
| 900 | def get_substituted_filename(self, first_line): | ||
| 901 | """ | ||
| 902 | If a filename contains a name substitution, return the name to | ||
| 903 | substitute. Note that this is just the filename and doesn't | ||
| 904 | include the path. | ||
| 905 | """ | ||
| 906 | return self.get_substituted_file_or_dir_name(first_line, FILENAME_TAG) | ||
| 907 | |||
| 908 | def get_substituted_dirname(self, first_line): | ||
| 909 | """ | ||
| 910 | If a dirname contains a name substitution, return the name to | ||
| 911 | substitute. Note that this is just the dirname and doesn't | ||
| 912 | include the path. | ||
| 913 | """ | ||
| 914 | return self.get_substituted_file_or_dir_name(first_line, DIRNAME_TAG) | ||
| 915 | |||
| 916 | def substitute_filename(self, first_line): | ||
| 917 | """ | ||
| 918 | Find the filename in first_line and append it to translated_filename. | ||
| 919 | """ | ||
| 920 | substituted_filename = self.get_substituted_filename(first_line) | ||
| 921 | self.append_translated_filename(substituted_filename); | ||
| 922 | |||
| 923 | def substitute_dirname(self, first_line): | ||
| 924 | """ | ||
| 925 | Find the dirname in first_line and append it to translated_filename. | ||
| 926 | """ | ||
| 927 | substituted_dirname = self.get_substituted_dirname(first_line) | ||
| 928 | self.append_translated_filename(substituted_dirname); | ||
| 929 | |||
| 930 | def is_filename_substitution(self, line): | ||
| 931 | """ | ||
| 932 | Do we have a filename subustition? | ||
| 933 | """ | ||
| 934 | if line.find(FILENAME_TAG) != -1: | ||
| 935 | return True | ||
| 936 | return False | ||
| 937 | |||
| 938 | def is_dirname_substitution(self, line): | ||
| 939 | """ | ||
| 940 | Do we have a dirname subustition? | ||
| 941 | """ | ||
| 942 | if line.find(DIRNAME_TAG) != -1: | ||
| 943 | return True | ||
| 944 | return False | ||
| 945 | |||
| 946 | def translate_dirname(self, first_line): | ||
| 947 | """ | ||
| 948 | Just save the first_line mapped by filename. The later pass | ||
| 949 | through the directories will look for a dirname.noinstall | ||
| 950 | match and grab the substitution line. | ||
| 951 | """ | ||
| 952 | dirname_substitutions[self.filename] = first_line | ||
| 953 | |||
| 954 | def translate_dirnames_in_path(self, path): | ||
| 955 | """ | ||
| 956 | Translate dirnames below this file or dir, not including tail. | ||
| 957 | dirname_substititions is keyed on actual untranslated filenames. | ||
| 958 | translated_path contains the subsititutions for each element. | ||
| 959 | """ | ||
| 960 | remainder = path[len(self.filebase)+1:] | ||
| 961 | translated_path = untranslated_path = self.filebase | ||
| 962 | |||
| 963 | untranslated_dirs = remainder.split(os.sep) | ||
| 964 | |||
| 965 | for dir in untranslated_dirs: | ||
| 966 | key = os.path.join(untranslated_path, dir + '.noinstall') | ||
| 967 | try: | ||
| 968 | first_line = dirname_substitutions[key] | ||
| 969 | except KeyError: | ||
| 970 | translated_path = os.path.join(translated_path, dir) | ||
| 971 | untranslated_path = os.path.join(untranslated_path, dir) | ||
| 972 | continue | ||
| 973 | substituted_dir = self.get_substituted_dirname(first_line) | ||
| 974 | translated_path = os.path.join(translated_path, substituted_dir) | ||
| 975 | untranslated_path = os.path.join(untranslated_path, dir) | ||
| 976 | |||
| 977 | return translated_path | ||
| 978 | |||
| 979 | def translate_file_or_dir_name(self): | ||
| 980 | """ | ||
| 981 | Originally we were allowed to use open/close/assign tags and python | ||
| 982 | code in the filename, which fit in nicely with the way we | ||
| 983 | processed the templates and generated code. Now that we can't | ||
| 984 | do that, we make those tags proper file contents and have this | ||
| 985 | pass substitute the nice but non-functional names with those | ||
| 986 | 'strange' ones, and then proceed as usual. | ||
| 987 | |||
| 988 | So, if files or matching dir<.noinstall> files contain | ||
| 989 | filename substitutions, this function translates them into the | ||
| 990 | corresponding 'strange' names, which future passes will expand | ||
| 991 | as they always have. The resulting pathname is kept in the | ||
| 992 | file or directory's translated_filename. Another way to think | ||
| 993 | about it is that self.filename is the input filename, and | ||
| 994 | translated_filename is the output filename before expansion. | ||
| 995 | """ | ||
| 996 | # remove leaf file or dirname | ||
| 997 | head, tail = os.path.split(self.filename) | ||
| 998 | translated_path = self.translate_dirnames_in_path(head) | ||
| 999 | self.translated_filename = translated_path | ||
| 1000 | |||
| 1001 | # This is a dirname - does it have a matching .noinstall with | ||
| 1002 | # a substitution? If so, apply the dirname subsititution. | ||
| 1003 | if not os.path.isfile(self.filename): | ||
| 1004 | key = self.filename + ".noinstall" | ||
| 1005 | try: | ||
| 1006 | first_line = dirname_substitutions[key] | ||
| 1007 | except KeyError: | ||
| 1008 | self.append_translated_filename(tail) | ||
| 1009 | return | ||
| 1010 | self.substitute_dirname(first_line) | ||
| 1011 | return | ||
| 1012 | |||
| 1013 | f = open(self.filename) | ||
| 1014 | first_line = f.readline() | ||
| 1015 | f.close() | ||
| 1016 | |||
| 1017 | # This is a normal filename not needing translation, just use | ||
| 1018 | # it as-is. | ||
| 1019 | if not first_line or not first_line.startswith("#"): | ||
| 1020 | self.append_translated_filename(tail) | ||
| 1021 | return | ||
| 1022 | |||
| 1023 | # If we have a filename substitution (first line in the file | ||
| 1024 | # is a FILENAME_TAG line) do the substitution now. If we have | ||
| 1025 | # a dirname substitution (DIRNAME_TAG in dirname.noinstall | ||
| 1026 | # meta-file), hash it so we can apply it when we see the | ||
| 1027 | # matching dirname later. Otherwise we have a regular | ||
| 1028 | # filename, just use it as-is. | ||
| 1029 | if self.is_filename_substitution(first_line): | ||
| 1030 | self.substitute_filename(first_line) | ||
| 1031 | elif self.is_dirname_substitution(first_line): | ||
| 1032 | self.translate_dirname(first_line) | ||
| 1033 | else: | ||
| 1034 | self.append_translated_filename(tail) | ||
| 1035 | |||
| 872 | def expand_file_or_dir_name(self): | 1036 | def expand_file_or_dir_name(self): |
| 873 | """ | 1037 | """ |
| 874 | Expand file or dir names into codeline. Dirnames and | 1038 | Expand file or dir names into codeline. Dirnames and |
| @@ -878,7 +1042,7 @@ class SubstrateBase(object): | |||
| 878 | """ | 1042 | """ |
| 879 | lineno = 0 | 1043 | lineno = 0 |
| 880 | 1044 | ||
| 881 | line = self.filename[len(self.filebase):] | 1045 | line = self.translated_filename[len(self.filebase):] |
| 882 | if line.startswith("/"): | 1046 | if line.startswith("/"): |
| 883 | line = line[1:] | 1047 | line = line[1:] |
| 884 | opentag_start = -1 | 1048 | opentag_start = -1 |
| @@ -897,7 +1061,6 @@ class SubstrateBase(object): | |||
| 897 | self.parse_error("No close tag found for open tag", lineno, line) | 1061 | self.parse_error("No close tag found for open tag", lineno, line) |
| 898 | # we have a {{ tag i.e. code | 1062 | # we have a {{ tag i.e. code |
| 899 | tag = line[opentag_start + len(OPEN_TAG):end].strip() | 1063 | tag = line[opentag_start + len(OPEN_TAG):end].strip() |
| 900 | |||
| 901 | if not tag.lstrip().startswith(IF_TAG): | 1064 | if not tag.lstrip().startswith(IF_TAG): |
| 902 | self.parse_error("Only 'if' tags are allowed in file or directory names", | 1065 | self.parse_error("Only 'if' tags are allowed in file or directory names", |
| 903 | lineno, line) | 1066 | lineno, line) |
| @@ -933,6 +1096,7 @@ class SubstrateBase(object): | |||
| 933 | Expand the file or dir name first, eventually this ends up | 1096 | Expand the file or dir name first, eventually this ends up |
| 934 | creating the file or dir. | 1097 | creating the file or dir. |
| 935 | """ | 1098 | """ |
| 1099 | self.translate_file_or_dir_name() | ||
| 936 | self.expand_file_or_dir_name() | 1100 | self.expand_file_or_dir_name() |
| 937 | 1101 | ||
| 938 | 1102 | ||
| @@ -955,6 +1119,9 @@ class SubstrateFile(SubstrateBase): | |||
| 955 | self.read() | 1119 | self.read() |
| 956 | 1120 | ||
| 957 | for lineno, line in enumerate(self.raw_lines): | 1121 | for lineno, line in enumerate(self.raw_lines): |
| 1122 | # only first line can be a filename substitition | ||
| 1123 | if lineno == 0 and line.startswith("#") and FILENAME_TAG in line: | ||
| 1124 | continue # skip it - we've already expanded it | ||
| 958 | expanded_line = self.expand_tag(line, lineno + 1) # humans not 0-based | 1125 | expanded_line = self.expand_tag(line, lineno + 1) # humans not 0-based |
| 959 | if not expanded_line: | 1126 | if not expanded_line: |
| 960 | expanded_line = NormalLine(line.rstrip()) | 1127 | expanded_line = NormalLine(line.rstrip()) |
| @@ -1141,7 +1308,7 @@ def gather_inputlines(files): | |||
| 1141 | for file in files: | 1308 | for file in files: |
| 1142 | if isinstance(file, SubstrateFile): | 1309 | if isinstance(file, SubstrateFile): |
| 1143 | group = None | 1310 | group = None |
| 1144 | basename = os.path.basename(file.filename) | 1311 | basename = os.path.basename(file.translated_filename) |
| 1145 | 1312 | ||
| 1146 | codeline = conditional_filename(basename) | 1313 | codeline = conditional_filename(basename) |
| 1147 | if codeline: | 1314 | if codeline: |
