git-svn-id: https://buildtools.tianocore.org/svn/buildtools/trunk/BaseTools@417 7335b...
[people/mcb30/basetools.git] / Source / Python / Common / String.py
1 # Copyright (c) 2007, Intel Corporation\r
2 # All rights reserved. This program and the accompanying materials\r
3 # are licensed and made available under the terms and conditions of the BSD License\r
4 # which accompanies this distribution.    The full text of the license may be found at\r
5 # http://opensource.org/licenses/bsd-license.php\r
6 #\r
7 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
8 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
9 \r
10 #\r
11 #This file is used to define some common useful string functions\r
12 #\r
13 \r
14 import DataType\r
15 import os.path\r
16 import string\r
17 \r
18 #\r
19 # Get a value list from a string with multiple values splited with SplitTag\r
20 # The default SplitTag is DataType.TAB_VALUE_SPLIT\r
21 # 'AAA|BBB|CCC' -> ['AAA', 'BBB', 'CCC']\r
22 #\r
23 def GetSplitValueList(String, SplitTag = DataType.TAB_VALUE_SPLIT, MaxSplit = -1):\r
24     return map(lambda l: l.strip(), String.split(SplitTag, MaxSplit))\r
25 \r
26 #\r
27 # Find a key's all arches in dict, add the new arch to the list\r
28 # If not exist any arch, set the arch directly\r
29 #\r
30 def MergeArches(Dict, Key, Arch):\r
31     if Key in Dict.keys():\r
32         Dict[Key].append(Arch)\r
33     else:\r
34         Dict[Key] = Arch.split()\r
35 \r
36 #\r
37 # Parse a string with format "DEFINE <VarName> = <PATH>"\r
38 # Generate a map Defines[VarName] = PATH\r
39 # Return False if invalid format\r
40 #\r
41 def GenDefines(String, Arch, Defines):\r
42     if String.find(DataType.TAB_DEFINE + ' ') > -1:\r
43         List = String.replace(DataType.TAB_DEFINE + ' ', '').split(DataType.TAB_EQUAL_SPLIT)\r
44         if len(List) == 2:\r
45             Defines[(CleanString(List[0]), Arch)] = CleanString(List[1])\r
46             return 0\r
47         else:\r
48             return -1\r
49     \r
50     return 1\r
51 \r
52 #\r
53 # Parse a string with format "!include <Filename>"\r
54 # Return the file path\r
55 # Return False if invalid format or NOT FOUND\r
56 #\r
57 def GenInclude(String, IncludeFiles, Arch):\r
58     if String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') > -1:\r
59         IncludeFile = CleanString(String[String.upper().find(DataType.TAB_INCLUDE.upper() + ' ') + len(DataType.TAB_INCLUDE + ' ') : ])\r
60         MergeArches(IncludeFiles, IncludeFile, Arch)\r
61         return True\r
62     else:\r
63         return False\r
64     \r
65 #\r
66 # Parse a string with format "InfFilename [EXEC = ExecFilename]"\r
67 # Return (InfFilename, ExecFilename)\r
68 #\r
69 def GetExec(String):\r
70     InfFilename = ''\r
71     ExecFilename = '' \r
72     if String.find('EXEC') > -1:\r
73         InfFilename = String[ : String.find('EXEC')].strip()\r
74         ExecFilename = String[String.find('EXEC') + len('EXEC') : ].strip()\r
75     else:\r
76         InfFilename = String.strip()\r
77     \r
78     return (InfFilename, ExecFilename)\r
79 \r
80 #\r
81 # Parse a string with format "[<Family>:]<ToolFlag>=Flag"\r
82 # Return (Family, ToolFlag, Flag)\r
83 #\r
84 def GetBuildOption(String):\r
85     (Family, ToolChain, Flag) = ('', '', '')\r
86     List = GetSplitValueList(String, DataType.TAB_EQUAL_SPLIT, MaxSplit = 1)\r
87     if List[0].find(':') > -1:\r
88         Family = CleanString(List[0][ : List[0].find(':')])\r
89         ToolChain = CleanString(List[0][List[0].find(':') + 1 : ])\r
90     else:\r
91         ToolChain = CleanString(List[0])                    \r
92     Flag = CleanString(List[1])\r
93     \r
94     return (Family, ToolChain, Flag)\r
95 \r
96 #\r
97 # Parse block of the components defined in dsc file\r
98 # Return KeyValues [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]\r
99 #\r
100 def GetComponents(Lines, Key, KeyValues, CommentCharacter):\r
101     #KeyValues [ ['component name', [lib1, lib2, lib3], [bo1, bo2, bo3], [pcd1, pcd2, pcd3]], ...]\r
102     Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
103     (findBlock, findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, False, False)\r
104     ListItem = None\r
105     LibraryClassItem = []\r
106     BuildOption = []\r
107     Pcd = []\r
108     \r
109     LineList = Lines.split('\n')\r
110     for Line in LineList:\r
111         Line = CleanString(Line, CommentCharacter)\r
112         if Line == None or Line == '':\r
113             continue\r
114         \r
115         if findBlock == False:\r
116             ListItem = Line\r
117             #find '{' at line tail\r
118             if Line.endswith('{'):\r
119                 findBlock = True\r
120                 ListItem = CleanString(Line.rsplit('{', 1)[0], CommentCharacter)\r
121 \r
122         if findBlock:    \r
123             if Line.find('<LibraryClass>') != -1:\r
124                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (True, False, False, False, False, False, False)\r
125                 continue\r
126             if Line.find('<BuildOptions>') != -1:\r
127                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, True, False, False, False, False, False)\r
128                 continue\r
129             if Line.find('<PcdsFeatureFlag>') != -1:\r
130                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, True, False, False, False, False)\r
131                 continue\r
132             if Line.find('<PcdsPatchableInModule>') != -1:\r
133                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, True, False, False, False)\r
134                 continue\r
135             if Line.find('<PcdsFixedAtBuild>') != -1:\r
136                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, True, False, False)\r
137                 continue\r
138             if Line.find('<PcdsDynamic>') != -1:\r
139                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, True, False)\r
140                 continue\r
141             if Line.find('<PcdsDynamicEx>') != -1:\r
142                 (findLibraryClass, findBuildOption, findPcdsFeatureFlag, findPcdsPatchableInModule, findPcdsFixedAtBuild, findPcdsDynamic, findPcdsDynamicEx) = (False, False, False, False, False, False, True)\r
143                 continue\r
144             if Line.endswith('}'):\r
145                 #find '}' at line tail\r
146                 KeyValues.append([ListItem, LibraryClassItem, BuildOption, Pcd])\r
147                 findBlock = False\r
148                 findLibraryClass = False\r
149                 findBuildOption = False\r
150                 findPcdsFeatureFlag = False\r
151                 findPcdsPatchableInModule = False\r
152                 findPcdsFixedAtBuild = False\r
153                 findPcdsDynamic = False\r
154                 findPcdsDynamicEx = False\r
155                 LibraryClassItem = []\r
156                 BuildOption = []\r
157                 Pcd = []\r
158                 continue\r
159 \r
160         if findBlock:\r
161             if findLibraryClass:\r
162                 LibraryClassItem.append(Line)\r
163             elif findBuildOption:\r
164                 BuildOption.append(Line)\r
165             elif findPcdsFeatureFlag:\r
166                 Pcd.append((DataType.TAB_PCDS_FEATURE_FLAG, Line))\r
167             elif findPcdsPatchableInModule:\r
168                 Pcd.append((DataType.TAB_PCDS_PATCHABLE_IN_MODULE, Line))\r
169             elif findPcdsFixedAtBuild:\r
170                 Pcd.append((DataType.TAB_PCDS_FIXED_AT_BUILD, Line))\r
171             elif findPcdsDynamic:\r
172                 Pcd.append((DataType.TAB_PCDS_DYNAMIC, Line))\r
173             elif findPcdsDynamicEx:\r
174                 Pcd.append((DataType.TAB_PCDS_DYNAMIC_EX, Line))\r
175         else:\r
176             KeyValues.append([ListItem, [], [], []])\r
177         \r
178     return True\r
179 \r
180 def GetLibraryClassesWithModuleType(Lines, Key, KeyValues, CommentCharacter):\r
181     newKey = SplitModuleType(Key)\r
182     Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
183     LineList = Lines.splitlines()\r
184     for Line in LineList:\r
185         Line = CleanString(Line, CommentCharacter)\r
186         if Line != '' and Line[0] != CommentCharacter:\r
187             KeyValues.append([CleanString(Line, CommentCharacter), newKey[1]])\r
188 \r
189     return True\r
190 \r
191 def GetDynamics(Lines, Key, KeyValues, CommentCharacter):\r
192     newKey = SplitModuleType(Key)\r
193     Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
194     LineList = Lines.splitlines()\r
195     for Line in LineList:\r
196         Line = CleanString(Line, CommentCharacter)\r
197         if Line != '' and Line[0] != CommentCharacter:\r
198             KeyValues.append([CleanString(Line, CommentCharacter), newKey[1]])\r
199 \r
200     return True\r
201 \r
202 #\r
203 # Split ModuleType out of section defien to get key\r
204 # [LibraryClass.Arch.ModuleType|ModuleType|ModuleType] -> [ 'LibraryClass.Arch', ['ModuleType', 'ModuleType', 'ModuleType'] ]\r
205 #\r
206 def SplitModuleType(Key):\r
207     KeyList = Key.split(DataType.TAB_SPLIT)\r
208     KeyList.append('')                    # Fill in for arch\r
209     KeyList.append('')                    # Fill in for moduletype\r
210     ReturnValue = []\r
211     KeyValue = KeyList[0]\r
212     if KeyList[1] != '':\r
213         KeyValue = KeyValue + DataType.TAB_SPLIT + KeyList[1]\r
214     ReturnValue.append(KeyValue)\r
215     ReturnValue.append(GetSplitValueList(KeyList[2]))\r
216     \r
217     return ReturnValue\r
218     \r
219 #\r
220 # Create a normal path\r
221 # And replace DFEINE in the path\r
222 #\r
223 def NormPath(Path, Defines = {}):\r
224     if Path != '':\r
225         # Replace with Define\r
226         for Key in Defines.keys():\r
227             Path = Path.replace(Key, Defines[Key])\r
228 \r
229         # Replace '\\', '\' with '/'\r
230         Path = Path.replace('\\', '/')\r
231         Path = Path.replace('//', '/')\r
232         \r
233         # Remove ${WORKSPACE}\r
234         Path = Path.replace(DataType.TAB_WORKSPACE, '')\r
235 \r
236     return Path\r
237 \r
238 #\r
239 # Remove comments in a string\r
240 # Remove spaces\r
241 #\r
242 def CleanString(Line, CommentCharacter = DataType.TAB_COMMENT_SPLIT):\r
243     #remove whitespace\r
244     Line = Line.strip();\r
245     #remove comments\r
246     Line = Line.split(CommentCharacter, 1)[0];\r
247     #replace '\\', '\' with '/'\r
248     #Line = Line.replace('\\', '/')\r
249     #Line = Line.replace('//', '/')\r
250     #remove ${WORKSPACE}\r
251     #Line = Line.replace(DataType.TAB_WORKSPACE1, '')\r
252     #Line = Line.replace(DataType.TAB_WORKSPACE2, '')\r
253     \r
254     #remove whitespace again\r
255     Line = Line.strip();\r
256     \r
257     return Line\r
258 \r
259 def GetMultipleValuesOfKeyFromLines(Lines, Key, KeyValues, CommentCharacter):\r
260     Lines = Lines.split(DataType.TAB_SECTION_END, 1)[1]\r
261     LineList = Lines.split('\n')\r
262     for Line in LineList:\r
263         Line = CleanString(Line, CommentCharacter)\r
264         if Line != '' and Line[0] != CommentCharacter:\r
265             KeyValues += [Line]\r
266 \r
267     return True\r
268 \r
269 def GetDefineValue(String, Key, CommentCharacter):\r
270     String = CleanString(String)\r
271     return String[String.find(Key + ' ') + len(Key + ' ') : ]\r
272 \r
273 def GetSingleValueOfKeyFromLines(Lines, Dictionary, CommentCharacter, KeySplitCharacter, ValueSplitFlag, ValueSplitCharacter):\r
274     Lines = Lines.split('\n')\r
275     Keys = []\r
276     Value = ''\r
277     DefineValues = ['']\r
278     SpecValues = ['']\r
279     \r
280     for Line in Lines:\r
281         #\r
282         # Handle DEFINE and SPEC\r
283         #\r
284         if Line.find(DataType.TAB_INF_DEFINES_DEFINE + ' ') > -1:\r
285             DefineValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_DEFINE, CommentCharacter))\r
286             continue\r
287         if Line.find(DataType.TAB_INF_DEFINES_SPEC + ' ') > -1:\r
288             SpecValues.append(GetDefineValue(Line, DataType.TAB_INF_DEFINES_SPEC, CommentCharacter))\r
289             continue\r
290                 \r
291         #\r
292         # Handle Others\r
293         #\r
294         LineList = Line.split(KeySplitCharacter, 1)\r
295         if len(LineList) >= 2:\r
296             Key = LineList[0].split()\r
297             if len(Key) == 1 and Key[0][0] != CommentCharacter:\r
298                 #Remove comments and white spaces\r
299                 LineList[1] = CleanString(LineList[1], CommentCharacter)\r
300                 if ValueSplitFlag:\r
301                     Value = map(string.strip, LineList[1].replace('\\','/').split(ValueSplitCharacter))\r
302                 else:\r
303                     Value = CleanString(LineList[1], CommentCharacter).splitlines()\r
304                 \r
305                 if Key[0] not in Keys:\r
306                     Dictionary[Key[0]] = Value\r
307                     Keys.append(Key[0])\r
308                 else:\r
309                     Dictionary[Key[0]].extend(Value)                \r
310     \r
311     if DefineValues == []:\r
312         DefineValues == ['']\r
313     if SpecValues == []:\r
314         SpecValues == ['']\r
315     Dictionary[DataType.TAB_INF_DEFINES_DEFINE] = DefineValues\r
316     Dictionary[DataType.TAB_INF_DEFINES_SPEC] = SpecValues\r
317     \r
318     return True\r
319 \r
320 \r
321 if __name__ == '__main__':\r
322     print SplitModuleType('LibraryClasses.common.DXE_RUNTIME_DRIVER')\r
323     print SplitModuleType('Library.common')\r
324     print SplitModuleType('Librarsdsfwe')\r
325     print NormPath('sdfas//dsfsadf//dsfsd')\r
326     print NormPath('\\dsfsdf\\\\sd\\fsd\\dsfsdfsdf\\\\')\r