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: |