1 | # @file ConvertMasmToNasm.py
|
---|
2 | # This script assists with conversion of MASM assembly syntax to NASM
|
---|
3 | #
|
---|
4 | # Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
|
---|
5 | #
|
---|
6 | # SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 | #
|
---|
8 |
|
---|
9 | from __future__ import print_function
|
---|
10 |
|
---|
11 | #
|
---|
12 | # Import Modules
|
---|
13 | #
|
---|
14 | import argparse
|
---|
15 | import io
|
---|
16 | import os.path
|
---|
17 | import re
|
---|
18 | import subprocess
|
---|
19 | import sys
|
---|
20 |
|
---|
21 |
|
---|
22 | class UnsupportedConversion(Exception):
|
---|
23 | pass
|
---|
24 |
|
---|
25 |
|
---|
26 | class NoSourceFile(Exception):
|
---|
27 | pass
|
---|
28 |
|
---|
29 |
|
---|
30 | class UnsupportedArch(Exception):
|
---|
31 | unsupported = ('aarch64', 'arm', 'ebc', 'ipf')
|
---|
32 |
|
---|
33 |
|
---|
34 | class CommonUtils:
|
---|
35 |
|
---|
36 | # Version and Copyright
|
---|
37 | VersionNumber = "0.01"
|
---|
38 | __version__ = "%prog Version " + VersionNumber
|
---|
39 | __copyright__ = "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved."
|
---|
40 | __usage__ = "%prog [options] source.asm [destination.nasm]"
|
---|
41 |
|
---|
42 | def __init__(self, clone=None):
|
---|
43 | if clone is None:
|
---|
44 | self.args = self.ProcessCommandLine()
|
---|
45 | else:
|
---|
46 | self.args = clone.args
|
---|
47 |
|
---|
48 | self.unsupportedSyntaxSeen = False
|
---|
49 | self.src = self.args.source
|
---|
50 | self.keep = self.args.keep
|
---|
51 | assert(os.path.exists(self.src))
|
---|
52 | self.dirmode = os.path.isdir(self.src)
|
---|
53 | srcExt = os.path.splitext(self.src)[1]
|
---|
54 | assert (self.dirmode or srcExt != '.nasm')
|
---|
55 | self.infmode = not self.dirmode and srcExt == '.inf'
|
---|
56 | self.diff = self.args.diff
|
---|
57 | self.git = self.args.git
|
---|
58 | self.force = self.args.force
|
---|
59 |
|
---|
60 | if clone is None:
|
---|
61 | self.rootdir = os.getcwd()
|
---|
62 | self.DetectGit()
|
---|
63 | else:
|
---|
64 | self.rootdir = clone.rootdir
|
---|
65 | self.gitdir = clone.gitdir
|
---|
66 | self.gitemail = clone.gitemail
|
---|
67 |
|
---|
68 | def ProcessCommandLine(self):
|
---|
69 | parser = argparse.ArgumentParser(description=self.__copyright__)
|
---|
70 | parser.add_argument('--version', action='version',
|
---|
71 | version='%(prog)s ' + self.VersionNumber)
|
---|
72 | parser.add_argument("-q", "--quiet", action="store_true",
|
---|
73 | help="Disable all messages except FATAL ERRORS.")
|
---|
74 | parser.add_argument("--git", action="store_true",
|
---|
75 | help="Use git to create commits for each file converted")
|
---|
76 | parser.add_argument("--keep", action="append", choices=('asm', 's'),
|
---|
77 | default=[],
|
---|
78 | help="Don't remove files with this extension")
|
---|
79 | parser.add_argument("--diff", action="store_true",
|
---|
80 | help="Show diff of conversion")
|
---|
81 | parser.add_argument("-f", "--force", action="store_true",
|
---|
82 | help="Force conversion even if unsupported")
|
---|
83 | parser.add_argument('source', help='MASM input file')
|
---|
84 | parser.add_argument('dest', nargs='?',
|
---|
85 | help='NASM output file (default=input.nasm; - for stdout)')
|
---|
86 |
|
---|
87 | return parser.parse_args()
|
---|
88 |
|
---|
89 | def RootRelative(self, path):
|
---|
90 | result = path
|
---|
91 | if result.startswith(self.rootdir):
|
---|
92 | result = result[len(self.rootdir):]
|
---|
93 | while len(result) > 0 and result[0] in '/\\':
|
---|
94 | result = result[1:]
|
---|
95 | return result
|
---|
96 |
|
---|
97 | def MatchAndSetMo(self, regexp, string):
|
---|
98 | self.mo = regexp.match(string)
|
---|
99 | return self.mo is not None
|
---|
100 |
|
---|
101 | def SearchAndSetMo(self, regexp, string):
|
---|
102 | self.mo = regexp.search(string)
|
---|
103 | return self.mo is not None
|
---|
104 |
|
---|
105 | def ReplacePreserveSpacing(self, string, find, replace):
|
---|
106 | if len(find) >= len(replace):
|
---|
107 | padded = replace + (' ' * (len(find) - len(replace)))
|
---|
108 | return string.replace(find, padded)
|
---|
109 | elif find.find(replace) >= 0:
|
---|
110 | return string.replace(find, replace)
|
---|
111 | else:
|
---|
112 | lenDiff = len(replace) - len(find)
|
---|
113 | result = string
|
---|
114 | for i in range(lenDiff, -1, -1):
|
---|
115 | padded = find + (' ' * i)
|
---|
116 | result = result.replace(padded, replace)
|
---|
117 | return result
|
---|
118 |
|
---|
119 | def DetectGit(self):
|
---|
120 | lastpath = os.path.realpath(self.src)
|
---|
121 | self.gitdir = None
|
---|
122 | while True:
|
---|
123 | path = os.path.split(lastpath)[0]
|
---|
124 | if path == lastpath:
|
---|
125 | self.gitemail = None
|
---|
126 | return
|
---|
127 | candidate = os.path.join(path, '.git')
|
---|
128 | if os.path.isdir(candidate):
|
---|
129 | self.gitdir = candidate
|
---|
130 | self.gitemail = self.FormatGitEmailAddress()
|
---|
131 | return
|
---|
132 | lastpath = path
|
---|
133 |
|
---|
134 | def FormatGitEmailAddress(self):
|
---|
135 | if not self.git or not self.gitdir:
|
---|
136 | return ''
|
---|
137 |
|
---|
138 | cmd = ('git', 'config', 'user.name')
|
---|
139 | name = self.RunAndCaptureOutput(cmd).strip()
|
---|
140 | cmd = ('git', 'config', 'user.email')
|
---|
141 | email = self.RunAndCaptureOutput(cmd).strip()
|
---|
142 | if name.find(',') >= 0:
|
---|
143 | name = '"' + name + '"'
|
---|
144 | return name + ' <' + email + '>'
|
---|
145 |
|
---|
146 | def RunAndCaptureOutput(self, cmd, checkExitCode=True, pipeIn=None):
|
---|
147 | if pipeIn:
|
---|
148 | subpStdin = subprocess.PIPE
|
---|
149 | else:
|
---|
150 | subpStdin = None
|
---|
151 | p = subprocess.Popen(args=cmd, stdout=subprocess.PIPE, stdin=subpStdin)
|
---|
152 | (stdout, stderr) = p.communicate(pipeIn)
|
---|
153 | if checkExitCode:
|
---|
154 | if p.returncode != 0:
|
---|
155 | print('command:', ' '.join(cmd))
|
---|
156 | print('stdout:', stdout)
|
---|
157 | print('stderr:', stderr)
|
---|
158 | print('return:', p.returncode)
|
---|
159 | assert p.returncode == 0
|
---|
160 | return stdout.decode('utf-8', 'ignore')
|
---|
161 |
|
---|
162 | def FileUpdated(self, path):
|
---|
163 | if not self.git or not self.gitdir:
|
---|
164 | return
|
---|
165 |
|
---|
166 | cmd = ('git', 'add', path)
|
---|
167 | self.RunAndCaptureOutput(cmd)
|
---|
168 |
|
---|
169 | def FileAdded(self, path):
|
---|
170 | self.FileUpdated(path)
|
---|
171 |
|
---|
172 | def RemoveFile(self, path):
|
---|
173 | if not self.git or not self.gitdir:
|
---|
174 | return
|
---|
175 |
|
---|
176 | if self.ShouldKeepFile(path):
|
---|
177 | return
|
---|
178 |
|
---|
179 | cmd = ('git', 'rm', path)
|
---|
180 | self.RunAndCaptureOutput(cmd)
|
---|
181 |
|
---|
182 | def ShouldKeepFile(self, path):
|
---|
183 | ext = os.path.splitext(path)[1].lower()
|
---|
184 | if ext.startswith('.'):
|
---|
185 | ext = ext[1:]
|
---|
186 | return ext in self.keep
|
---|
187 |
|
---|
188 | def FileConversionFinished(self, pkg, module, src, dst):
|
---|
189 | if not self.git or not self.gitdir:
|
---|
190 | return
|
---|
191 |
|
---|
192 | if not self.args.quiet:
|
---|
193 | print('Committing: Conversion of', dst)
|
---|
194 |
|
---|
195 | prefix = ' '.join(filter(lambda a: a, [pkg, module]))
|
---|
196 | message = ''
|
---|
197 | if self.unsupportedSyntaxSeen:
|
---|
198 | message += 'ERROR! '
|
---|
199 | message += '%s: Convert %s to NASM\n' % (prefix, src)
|
---|
200 | message += '\n'
|
---|
201 | message += 'The %s script was used to convert\n' % sys.argv[0]
|
---|
202 | message += '%s to %s\n' % (src, dst)
|
---|
203 | message += '\n'
|
---|
204 | message += 'Contributed-under: TianoCore Contribution Agreement 1.0\n'
|
---|
205 | assert(self.gitemail is not None)
|
---|
206 | message += 'Signed-off-by: %s\n' % self.gitemail
|
---|
207 | message = message.encode('utf-8', 'ignore')
|
---|
208 |
|
---|
209 | cmd = ('git', 'commit', '-F', '-')
|
---|
210 | self.RunAndCaptureOutput(cmd, pipeIn=message)
|
---|
211 |
|
---|
212 |
|
---|
213 | class ConvertAsmFile(CommonUtils):
|
---|
214 |
|
---|
215 | def __init__(self, src, dst, clone):
|
---|
216 | CommonUtils.__init__(self, clone)
|
---|
217 | self.ConvertAsmFile(src, dst)
|
---|
218 | self.FileAdded(dst)
|
---|
219 | self.RemoveFile(src)
|
---|
220 |
|
---|
221 | def ConvertAsmFile(self, inputFile, outputFile=None):
|
---|
222 | self.globals = set()
|
---|
223 | self.unsupportedSyntaxSeen = False
|
---|
224 | self.inputFilename = inputFile
|
---|
225 | if not outputFile:
|
---|
226 | outputFile = os.path.splitext(inputFile)[0] + '.nasm'
|
---|
227 | self.outputFilename = outputFile
|
---|
228 |
|
---|
229 | fullSrc = os.path.realpath(inputFile)
|
---|
230 | srcParentDir = os.path.basename(os.path.split(fullSrc)[0])
|
---|
231 | maybeArch = srcParentDir.lower()
|
---|
232 | if maybeArch in UnsupportedArch.unsupported:
|
---|
233 | raise UnsupportedArch
|
---|
234 | self.ia32 = maybeArch == 'ia32'
|
---|
235 | self.x64 = maybeArch == 'x64'
|
---|
236 |
|
---|
237 | self.inputFileBase = os.path.basename(self.inputFilename)
|
---|
238 | self.outputFileBase = os.path.basename(self.outputFilename)
|
---|
239 | self.output = io.BytesIO()
|
---|
240 | if not self.args.quiet:
|
---|
241 | dirpath, src = os.path.split(self.inputFilename)
|
---|
242 | dirpath = self.RootRelative(dirpath)
|
---|
243 | dst = os.path.basename(self.outputFilename)
|
---|
244 | print('Converting:', dirpath, src, '->', dst)
|
---|
245 | lines = io.open(self.inputFilename).readlines()
|
---|
246 | self.Convert(lines)
|
---|
247 | if self.outputFilename == '-' and not self.diff:
|
---|
248 | output_data = self.output.getvalue()
|
---|
249 | if sys.version_info >= (3, 0):
|
---|
250 | output_data = output_data.decode('utf-8', 'ignore')
|
---|
251 | sys.stdout.write(output_data)
|
---|
252 | self.output.close()
|
---|
253 | else:
|
---|
254 | f = io.open(self.outputFilename, 'wb')
|
---|
255 | f.write(self.output.getvalue())
|
---|
256 | f.close()
|
---|
257 | self.output.close()
|
---|
258 |
|
---|
259 | endOfLineRe = re.compile(r'''
|
---|
260 | \s* ( ; .* )? \n $
|
---|
261 | ''',
|
---|
262 | re.VERBOSE | re.MULTILINE
|
---|
263 | )
|
---|
264 | begOfLineRe = re.compile(r'''
|
---|
265 | \s*
|
---|
266 | ''',
|
---|
267 | re.VERBOSE
|
---|
268 | )
|
---|
269 |
|
---|
270 | def Convert(self, lines):
|
---|
271 | self.proc = None
|
---|
272 | self.anonLabelCount = -1
|
---|
273 | output = self.output
|
---|
274 | self.oldAsmEmptyLineCount = 0
|
---|
275 | self.newAsmEmptyLineCount = 0
|
---|
276 | for line in lines:
|
---|
277 | mo = self.begOfLineRe.search(line)
|
---|
278 | assert mo is not None
|
---|
279 | self.indent = mo.group()
|
---|
280 | lineWithoutBeginning = line[len(self.indent):]
|
---|
281 | mo = self.endOfLineRe.search(lineWithoutBeginning)
|
---|
282 | if mo is None:
|
---|
283 | endOfLine = ''
|
---|
284 | else:
|
---|
285 | endOfLine = mo.group()
|
---|
286 | oldAsm = line[len(self.indent):len(line) - len(endOfLine)]
|
---|
287 | self.originalLine = line.rstrip()
|
---|
288 | if line.strip() == '':
|
---|
289 | self.oldAsmEmptyLineCount += 1
|
---|
290 | self.TranslateAsm(oldAsm, endOfLine)
|
---|
291 | if line.strip() != '':
|
---|
292 | self.oldAsmEmptyLineCount = 0
|
---|
293 |
|
---|
294 | procDeclRe = re.compile(r'''
|
---|
295 | (?: ASM_PFX \s* [(] \s* )?
|
---|
296 | ([\w@][\w@0-9]*) \s*
|
---|
297 | [)]? \s+
|
---|
298 | PROC
|
---|
299 | (?: \s+ NEAR | FAR )?
|
---|
300 | (?: \s+ C )?
|
---|
301 | (?: \s+ (PUBLIC | PRIVATE) )?
|
---|
302 | (?: \s+ USES ( (?: \s+ \w[\w0-9]* )+ ) )?
|
---|
303 | \s* $
|
---|
304 | ''',
|
---|
305 | re.VERBOSE | re.IGNORECASE
|
---|
306 | )
|
---|
307 |
|
---|
308 | procEndRe = re.compile(r'''
|
---|
309 | ([\w@][\w@0-9]*) \s+
|
---|
310 | ENDP
|
---|
311 | \s* $
|
---|
312 | ''',
|
---|
313 | re.VERBOSE | re.IGNORECASE
|
---|
314 | )
|
---|
315 |
|
---|
316 | varAndTypeSubRe = r' (?: [\w@][\w@0-9]* ) (?: \s* : \s* \w+ )? '
|
---|
317 | publicRe = re.compile(r'''
|
---|
318 | PUBLIC \s+
|
---|
319 | ( %s (?: \s* , \s* %s )* )
|
---|
320 | \s* $
|
---|
321 | ''' % (varAndTypeSubRe, varAndTypeSubRe),
|
---|
322 | re.VERBOSE | re.IGNORECASE
|
---|
323 | )
|
---|
324 |
|
---|
325 | varAndTypeSubRe = re.compile(varAndTypeSubRe, re.VERBOSE | re.IGNORECASE)
|
---|
326 |
|
---|
327 | macroDeclRe = re.compile(r'''
|
---|
328 | ([\w@][\w@0-9]*) \s+
|
---|
329 | MACRO
|
---|
330 | \s* $
|
---|
331 | ''',
|
---|
332 | re.VERBOSE | re.IGNORECASE
|
---|
333 | )
|
---|
334 |
|
---|
335 | sectionDeclRe = re.compile(r'''
|
---|
336 | ([\w@][\w@0-9]*) \s+
|
---|
337 | ( SECTION | ENDS )
|
---|
338 | \s* $
|
---|
339 | ''',
|
---|
340 | re.VERBOSE | re.IGNORECASE
|
---|
341 | )
|
---|
342 |
|
---|
343 | externRe = re.compile(r'''
|
---|
344 | EXTE?RN \s+ (?: C \s+ )?
|
---|
345 | ([\w@][\w@0-9]*) \s* : \s* (\w+)
|
---|
346 | \s* $
|
---|
347 | ''',
|
---|
348 | re.VERBOSE | re.IGNORECASE
|
---|
349 | )
|
---|
350 |
|
---|
351 | externdefRe = re.compile(r'''
|
---|
352 | EXTERNDEF \s+ (?: C \s+ )?
|
---|
353 | ([\w@][\w@0-9]*) \s* : \s* (\w+)
|
---|
354 | \s* $
|
---|
355 | ''',
|
---|
356 | re.VERBOSE | re.IGNORECASE
|
---|
357 | )
|
---|
358 |
|
---|
359 | protoRe = re.compile(r'''
|
---|
360 | ([\w@][\w@0-9]*) \s+
|
---|
361 | PROTO
|
---|
362 | (?: \s+ .* )?
|
---|
363 | \s* $
|
---|
364 | ''',
|
---|
365 | re.VERBOSE | re.IGNORECASE
|
---|
366 | )
|
---|
367 |
|
---|
368 | defineDataRe = re.compile(r'''
|
---|
369 | ([\w@][\w@0-9]*) \s+
|
---|
370 | ( db | dw | dd | dq ) \s+
|
---|
371 | ( .*? )
|
---|
372 | \s* $
|
---|
373 | ''',
|
---|
374 | re.VERBOSE | re.IGNORECASE
|
---|
375 | )
|
---|
376 |
|
---|
377 | equRe = re.compile(r'''
|
---|
378 | ([\w@][\w@0-9]*) \s+ EQU \s+ (\S.*?)
|
---|
379 | \s* $
|
---|
380 | ''',
|
---|
381 | re.VERBOSE | re.IGNORECASE
|
---|
382 | )
|
---|
383 |
|
---|
384 | ignoreRe = re.compile(r'''
|
---|
385 | \. (?: const |
|
---|
386 | mmx |
|
---|
387 | model |
|
---|
388 | xmm |
|
---|
389 | x?list |
|
---|
390 | [3-6]86p?
|
---|
391 | ) |
|
---|
392 | page
|
---|
393 | (?: \s+ .* )?
|
---|
394 | \s* $
|
---|
395 | ''',
|
---|
396 | re.VERBOSE | re.IGNORECASE
|
---|
397 | )
|
---|
398 |
|
---|
399 | whitespaceRe = re.compile(r'\s+', re.MULTILINE)
|
---|
400 |
|
---|
401 | def TranslateAsm(self, oldAsm, endOfLine):
|
---|
402 | assert(oldAsm.strip() == oldAsm)
|
---|
403 |
|
---|
404 | endOfLine = endOfLine.replace(self.inputFileBase, self.outputFileBase)
|
---|
405 |
|
---|
406 | oldOp = oldAsm.split()
|
---|
407 | if len(oldOp) >= 1:
|
---|
408 | oldOp = oldOp[0]
|
---|
409 | else:
|
---|
410 | oldOp = ''
|
---|
411 |
|
---|
412 | if oldAsm == '':
|
---|
413 | newAsm = oldAsm
|
---|
414 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
415 | elif oldOp in ('#include', ):
|
---|
416 | newAsm = oldAsm
|
---|
417 | self.EmitLine(oldAsm + endOfLine)
|
---|
418 | elif oldOp.lower() in ('end', 'title', 'text'):
|
---|
419 | newAsm = ''
|
---|
420 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
421 | elif oldAsm.lower() == '@@:':
|
---|
422 | self.anonLabelCount += 1
|
---|
423 | self.EmitLine(self.anonLabel(self.anonLabelCount) + ':')
|
---|
424 | elif self.MatchAndSetMo(self.ignoreRe, oldAsm):
|
---|
425 | newAsm = ''
|
---|
426 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
427 | elif oldAsm.lower() == 'ret':
|
---|
428 | for i in range(len(self.uses) - 1, -1, -1):
|
---|
429 | register = self.uses[i]
|
---|
430 | self.EmitNewContent('pop ' + register)
|
---|
431 | newAsm = 'ret'
|
---|
432 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
433 | self.uses = tuple()
|
---|
434 | elif oldOp.lower() == 'lea':
|
---|
435 | newAsm = self.ConvertLea(oldAsm)
|
---|
436 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
437 | elif oldAsm.lower() == 'end':
|
---|
438 | newAsm = ''
|
---|
439 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
440 | self.uses = tuple()
|
---|
441 | elif self.MatchAndSetMo(self.equRe, oldAsm):
|
---|
442 | equ = self.mo.group(1)
|
---|
443 | newAsm = '%%define %s %s' % (equ, self.mo.group(2))
|
---|
444 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
445 | elif self.MatchAndSetMo(self.externRe, oldAsm) or \
|
---|
446 | self.MatchAndSetMo(self.protoRe, oldAsm):
|
---|
447 | extern = self.mo.group(1)
|
---|
448 | self.NewGlobal(extern)
|
---|
449 | newAsm = 'extern ' + extern
|
---|
450 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
451 | elif self.MatchAndSetMo(self.externdefRe, oldAsm):
|
---|
452 | newAsm = ''
|
---|
453 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
454 | elif self.MatchAndSetMo(self.macroDeclRe, oldAsm):
|
---|
455 | newAsm = '%%macro %s 0' % self.mo.group(1)
|
---|
456 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
457 | elif oldOp.lower() == 'endm':
|
---|
458 | newAsm = r'%endmacro'
|
---|
459 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
460 | elif self.MatchAndSetMo(self.sectionDeclRe, oldAsm):
|
---|
461 | name = self.mo.group(1)
|
---|
462 | ty = self.mo.group(2)
|
---|
463 | if ty.lower() == 'section':
|
---|
464 | newAsm = '.' + name
|
---|
465 | else:
|
---|
466 | newAsm = ''
|
---|
467 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
468 | elif self.MatchAndSetMo(self.procDeclRe, oldAsm):
|
---|
469 | proc = self.proc = self.mo.group(1)
|
---|
470 | visibility = self.mo.group(2)
|
---|
471 | if visibility is None:
|
---|
472 | visibility = ''
|
---|
473 | else:
|
---|
474 | visibility = visibility.lower()
|
---|
475 | if visibility != 'private':
|
---|
476 | self.NewGlobal(self.proc)
|
---|
477 | proc = 'ASM_PFX(' + proc + ')'
|
---|
478 | self.EmitNewContent('global ' + proc)
|
---|
479 | newAsm = proc + ':'
|
---|
480 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
481 | uses = self.mo.group(3)
|
---|
482 | if uses is not None:
|
---|
483 | uses = tuple(filter(None, uses.split()))
|
---|
484 | else:
|
---|
485 | uses = tuple()
|
---|
486 | self.uses = uses
|
---|
487 | for register in self.uses:
|
---|
488 | self.EmitNewContent(' push ' + register)
|
---|
489 | elif self.MatchAndSetMo(self.procEndRe, oldAsm):
|
---|
490 | newAsm = ''
|
---|
491 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
492 | elif self.MatchAndSetMo(self.publicRe, oldAsm):
|
---|
493 | publics = re.findall(self.varAndTypeSubRe, self.mo.group(1))
|
---|
494 | publics = tuple(map(lambda p: p.split(':')[0].strip(), publics))
|
---|
495 | for i in range(len(publics) - 1):
|
---|
496 | name = publics[i]
|
---|
497 | self.EmitNewContent('global ASM_PFX(%s)' % publics[i])
|
---|
498 | self.NewGlobal(name)
|
---|
499 | name = publics[-1]
|
---|
500 | self.NewGlobal(name)
|
---|
501 | newAsm = 'global ASM_PFX(%s)' % name
|
---|
502 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
503 | elif self.MatchAndSetMo(self.defineDataRe, oldAsm):
|
---|
504 | name = self.mo.group(1)
|
---|
505 | ty = self.mo.group(2)
|
---|
506 | value = self.mo.group(3)
|
---|
507 | if value == '?':
|
---|
508 | value = 0
|
---|
509 | newAsm = '%s: %s %s' % (name, ty, value)
|
---|
510 | newAsm = self.CommonConversions(newAsm)
|
---|
511 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
512 | else:
|
---|
513 | newAsm = self.CommonConversions(oldAsm)
|
---|
514 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
515 |
|
---|
516 | def NewGlobal(self, name):
|
---|
517 | regex = re.compile(r'(?<![_\w\d])(?<!ASM_PFX\()(' + re.escape(name) +
|
---|
518 | r')(?![_\w\d])')
|
---|
519 | self.globals.add(regex)
|
---|
520 |
|
---|
521 | def ConvertAnonymousLabels(self, oldAsm):
|
---|
522 | newAsm = oldAsm
|
---|
523 | anonLabel = self.anonLabel(self.anonLabelCount)
|
---|
524 | newAsm = newAsm.replace('@b', anonLabel)
|
---|
525 | newAsm = newAsm.replace('@B', anonLabel)
|
---|
526 | anonLabel = self.anonLabel(self.anonLabelCount + 1)
|
---|
527 | newAsm = newAsm.replace('@f', anonLabel)
|
---|
528 | newAsm = newAsm.replace('@F', anonLabel)
|
---|
529 | return newAsm
|
---|
530 |
|
---|
531 | def anonLabel(self, count):
|
---|
532 | return '.%d' % count
|
---|
533 |
|
---|
534 | def EmitString(self, string):
|
---|
535 | self.output.write(string.encode('utf-8', 'ignore'))
|
---|
536 |
|
---|
537 | def EmitLineWithDiff(self, old, new):
|
---|
538 | newLine = (self.indent + new).rstrip()
|
---|
539 | if self.diff:
|
---|
540 | if old is None:
|
---|
541 | print('+%s' % newLine)
|
---|
542 | elif newLine != old:
|
---|
543 | print('-%s' % old)
|
---|
544 | print('+%s' % newLine)
|
---|
545 | else:
|
---|
546 | print('', newLine)
|
---|
547 | if newLine != '':
|
---|
548 | self.newAsmEmptyLineCount = 0
|
---|
549 | self.EmitString(newLine + '\r\n')
|
---|
550 |
|
---|
551 | def EmitLine(self, string):
|
---|
552 | self.EmitLineWithDiff(self.originalLine, string)
|
---|
553 |
|
---|
554 | def EmitNewContent(self, string):
|
---|
555 | self.EmitLineWithDiff(None, string)
|
---|
556 |
|
---|
557 | def EmitAsmReplaceOp(self, oldAsm, oldOp, newOp, endOfLine):
|
---|
558 | newAsm = oldAsm.replace(oldOp, newOp, 1)
|
---|
559 | self.EmitAsmWithComment(oldAsm, newAsm, endOfLine)
|
---|
560 |
|
---|
561 | hexNumRe = re.compile(r'0*((?=[\da-f])\d*(?<=\d)[\da-f]*)h', re.IGNORECASE)
|
---|
562 |
|
---|
563 | def EmitAsmWithComment(self, oldAsm, newAsm, endOfLine):
|
---|
564 | for glblRe in self.globals:
|
---|
565 | newAsm = glblRe.sub(r'ASM_PFX(\1)', newAsm)
|
---|
566 |
|
---|
567 | newAsm = self.hexNumRe.sub(r'0x\1', newAsm)
|
---|
568 |
|
---|
569 | newLine = newAsm + endOfLine
|
---|
570 | emitNewLine = ((newLine.strip() != '') or
|
---|
571 | ((oldAsm + endOfLine).strip() == ''))
|
---|
572 | if emitNewLine and newLine.strip() == '':
|
---|
573 | self.newAsmEmptyLineCount += 1
|
---|
574 | if self.newAsmEmptyLineCount > 1:
|
---|
575 | emitNewLine = False
|
---|
576 | if emitNewLine:
|
---|
577 | self.EmitLine(newLine.rstrip())
|
---|
578 | elif self.diff:
|
---|
579 | print('-%s' % self.originalLine)
|
---|
580 |
|
---|
581 | leaRe = re.compile(r'''
|
---|
582 | (lea \s+) ([\w@][\w@0-9]*) \s* , \s* (\S (?:.*\S)?)
|
---|
583 | \s* $
|
---|
584 | ''',
|
---|
585 | re.VERBOSE | re.IGNORECASE
|
---|
586 | )
|
---|
587 |
|
---|
588 | def ConvertLea(self, oldAsm):
|
---|
589 | newAsm = oldAsm
|
---|
590 | if self.MatchAndSetMo(self.leaRe, oldAsm):
|
---|
591 | lea = self.mo.group(1)
|
---|
592 | dst = self.mo.group(2)
|
---|
593 | src = self.mo.group(3)
|
---|
594 | if src.find('[') < 0:
|
---|
595 | src = '[' + src + ']'
|
---|
596 | newAsm = lea + dst + ', ' + src
|
---|
597 | newAsm = self.CommonConversions(newAsm)
|
---|
598 | return newAsm
|
---|
599 |
|
---|
600 | ptrRe = re.compile(r'''
|
---|
601 | (?<! \S )
|
---|
602 | ([dfq]?word|byte) \s+ (?: ptr ) (\s*)
|
---|
603 | (?= [[\s] )
|
---|
604 | ''',
|
---|
605 | re.VERBOSE | re.IGNORECASE
|
---|
606 | )
|
---|
607 |
|
---|
608 | def ConvertPtr(self, oldAsm):
|
---|
609 | newAsm = oldAsm
|
---|
610 | while self.SearchAndSetMo(self.ptrRe, newAsm):
|
---|
611 | ty = self.mo.group(1)
|
---|
612 | if ty.lower() == 'fword':
|
---|
613 | ty = ''
|
---|
614 | else:
|
---|
615 | ty += self.mo.group(2)
|
---|
616 | newAsm = newAsm[:self.mo.start(0)] + ty + newAsm[self.mo.end(0):]
|
---|
617 | return newAsm
|
---|
618 |
|
---|
619 | labelByteRe = re.compile(r'''
|
---|
620 | (?: \s+ label \s+ (?: [dfq]?word | byte ) )
|
---|
621 | (?! \S )
|
---|
622 | ''',
|
---|
623 | re.VERBOSE | re.IGNORECASE
|
---|
624 | )
|
---|
625 |
|
---|
626 | def ConvertLabelByte(self, oldAsm):
|
---|
627 | newAsm = oldAsm
|
---|
628 | if self.SearchAndSetMo(self.labelByteRe, newAsm):
|
---|
629 | newAsm = newAsm[:self.mo.start(0)] + ':' + newAsm[self.mo.end(0):]
|
---|
630 | return newAsm
|
---|
631 |
|
---|
632 | unaryBitwiseOpRe = re.compile(r'''
|
---|
633 | ( NOT )
|
---|
634 | (?= \s+ \S )
|
---|
635 | ''',
|
---|
636 | re.VERBOSE | re.IGNORECASE
|
---|
637 | )
|
---|
638 | binaryBitwiseOpRe = re.compile(r'''
|
---|
639 | ( \S \s+ )
|
---|
640 | ( AND | OR | SHL | SHR )
|
---|
641 | (?= \s+ \S )
|
---|
642 | ''',
|
---|
643 | re.VERBOSE | re.IGNORECASE
|
---|
644 | )
|
---|
645 | bitwiseOpReplacements = {
|
---|
646 | 'not': '~',
|
---|
647 | 'and': '&',
|
---|
648 | 'shl': '<<',
|
---|
649 | 'shr': '>>',
|
---|
650 | 'or': '|',
|
---|
651 | }
|
---|
652 |
|
---|
653 | def ConvertBitwiseOp(self, oldAsm):
|
---|
654 | newAsm = oldAsm
|
---|
655 | while self.SearchAndSetMo(self.binaryBitwiseOpRe, newAsm):
|
---|
656 | prefix = self.mo.group(1)
|
---|
657 | op = self.bitwiseOpReplacements[self.mo.group(2).lower()]
|
---|
658 | newAsm = newAsm[:self.mo.start(0)] + prefix + op + \
|
---|
659 | newAsm[self.mo.end(0):]
|
---|
660 | while self.SearchAndSetMo(self.unaryBitwiseOpRe, newAsm):
|
---|
661 | op = self.bitwiseOpReplacements[self.mo.group(1).lower()]
|
---|
662 | newAsm = newAsm[:self.mo.start(0)] + op + newAsm[self.mo.end(0):]
|
---|
663 | return newAsm
|
---|
664 |
|
---|
665 | sectionRe = re.compile(r'''
|
---|
666 | \. ( code |
|
---|
667 | data
|
---|
668 | )
|
---|
669 | (?: \s+ .* )?
|
---|
670 | \s* $
|
---|
671 | ''',
|
---|
672 | re.VERBOSE | re.IGNORECASE
|
---|
673 | )
|
---|
674 |
|
---|
675 | segmentRe = re.compile(r'''
|
---|
676 | ( code |
|
---|
677 | data )
|
---|
678 | (?: \s+ SEGMENT )
|
---|
679 | (?: \s+ .* )?
|
---|
680 | \s* $
|
---|
681 | ''',
|
---|
682 | re.VERBOSE | re.IGNORECASE
|
---|
683 | )
|
---|
684 |
|
---|
685 | def ConvertSection(self, oldAsm):
|
---|
686 | newAsm = oldAsm
|
---|
687 | if self.MatchAndSetMo(self.sectionRe, newAsm) or \
|
---|
688 | self.MatchAndSetMo(self.segmentRe, newAsm):
|
---|
689 | name = self.mo.group(1).lower()
|
---|
690 | if name == 'code':
|
---|
691 | if self.x64:
|
---|
692 | self.EmitLine('DEFAULT REL')
|
---|
693 | name = 'text'
|
---|
694 | newAsm = 'SECTION .' + name
|
---|
695 | return newAsm
|
---|
696 |
|
---|
697 | fwordRe = re.compile(r'''
|
---|
698 | (?<! \S )
|
---|
699 | fword
|
---|
700 | (?! \S )
|
---|
701 | ''',
|
---|
702 | re.VERBOSE | re.IGNORECASE
|
---|
703 | )
|
---|
704 |
|
---|
705 | def FwordUnsupportedCheck(self, oldAsm):
|
---|
706 | newAsm = oldAsm
|
---|
707 | if self.SearchAndSetMo(self.fwordRe, newAsm):
|
---|
708 | newAsm = self.Unsupported(newAsm, 'fword used')
|
---|
709 | return newAsm
|
---|
710 |
|
---|
711 | __common_conversion_routines__ = (
|
---|
712 | ConvertAnonymousLabels,
|
---|
713 | ConvertPtr,
|
---|
714 | FwordUnsupportedCheck,
|
---|
715 | ConvertBitwiseOp,
|
---|
716 | ConvertLabelByte,
|
---|
717 | ConvertSection,
|
---|
718 | )
|
---|
719 |
|
---|
720 | def CommonConversions(self, oldAsm):
|
---|
721 | newAsm = oldAsm
|
---|
722 | for conv in self.__common_conversion_routines__:
|
---|
723 | newAsm = conv(self, newAsm)
|
---|
724 | return newAsm
|
---|
725 |
|
---|
726 | def Unsupported(self, asm, message=None):
|
---|
727 | if not self.force:
|
---|
728 | raise UnsupportedConversion
|
---|
729 |
|
---|
730 | self.unsupportedSyntaxSeen = True
|
---|
731 | newAsm = '%error conversion unsupported'
|
---|
732 | if message:
|
---|
733 | newAsm += '; ' + message
|
---|
734 | newAsm += ': ' + asm
|
---|
735 | return newAsm
|
---|
736 |
|
---|
737 |
|
---|
738 | class ConvertInfFile(CommonUtils):
|
---|
739 |
|
---|
740 | def __init__(self, inf, clone):
|
---|
741 | CommonUtils.__init__(self, clone)
|
---|
742 | self.inf = inf
|
---|
743 | self.ScanInfAsmFiles()
|
---|
744 | if self.infmode:
|
---|
745 | self.ConvertInfAsmFiles()
|
---|
746 |
|
---|
747 | infSrcRe = re.compile(r'''
|
---|
748 | \s*
|
---|
749 | ( [\w@][\w@0-9/]* \.(asm|s) )
|
---|
750 | \s* (?: \| [^#]* )?
|
---|
751 | \s* (?: \# .* )?
|
---|
752 | $
|
---|
753 | ''',
|
---|
754 | re.VERBOSE | re.IGNORECASE
|
---|
755 | )
|
---|
756 |
|
---|
757 | def GetInfAsmFileMapping(self):
|
---|
758 | srcToDst = {'order': []}
|
---|
759 | for line in self.lines:
|
---|
760 | line = line.rstrip()
|
---|
761 | if self.MatchAndSetMo(self.infSrcRe, line):
|
---|
762 | src = self.mo.group(1)
|
---|
763 | srcExt = self.mo.group(2)
|
---|
764 | dst = os.path.splitext(src)[0] + '.nasm'
|
---|
765 | fullDst = os.path.join(self.dir, dst)
|
---|
766 | if src not in srcToDst and not os.path.exists(fullDst):
|
---|
767 | srcToDst[src] = dst
|
---|
768 | srcToDst['order'].append(src)
|
---|
769 | return srcToDst
|
---|
770 |
|
---|
771 | def ScanInfAsmFiles(self):
|
---|
772 | src = self.inf
|
---|
773 | assert os.path.isfile(src)
|
---|
774 | f = io.open(src, 'rt')
|
---|
775 | self.lines = f.readlines()
|
---|
776 | f.close()
|
---|
777 |
|
---|
778 | path = os.path.realpath(self.inf)
|
---|
779 | (self.dir, inf) = os.path.split(path)
|
---|
780 | parent = os.path.normpath(self.dir)
|
---|
781 | (lastpath, self.moduleName) = os.path.split(parent)
|
---|
782 | self.packageName = None
|
---|
783 | while True:
|
---|
784 | lastpath = os.path.normpath(lastpath)
|
---|
785 | (parent, basename) = os.path.split(lastpath)
|
---|
786 | if parent == lastpath:
|
---|
787 | break
|
---|
788 | if basename.endswith('Pkg'):
|
---|
789 | self.packageName = basename
|
---|
790 | break
|
---|
791 | lastpath = parent
|
---|
792 |
|
---|
793 | self.srcToDst = self.GetInfAsmFileMapping()
|
---|
794 |
|
---|
795 | self.dstToSrc = {'order': []}
|
---|
796 | for src in self.srcToDst['order']:
|
---|
797 | srcExt = os.path.splitext(src)[1]
|
---|
798 | dst = self.srcToDst[src]
|
---|
799 | if dst not in self.dstToSrc:
|
---|
800 | self.dstToSrc[dst] = [src]
|
---|
801 | self.dstToSrc['order'].append(dst)
|
---|
802 | else:
|
---|
803 | self.dstToSrc[dst].append(src)
|
---|
804 |
|
---|
805 | def __len__(self):
|
---|
806 | return len(self.dstToSrc['order'])
|
---|
807 |
|
---|
808 | def __iter__(self):
|
---|
809 | return iter(self.dstToSrc['order'])
|
---|
810 |
|
---|
811 | def ConvertInfAsmFiles(self):
|
---|
812 | notConverted = []
|
---|
813 | unsupportedArchCount = 0
|
---|
814 | for dst in self:
|
---|
815 | didSomething = False
|
---|
816 | try:
|
---|
817 | self.UpdateInfAsmFile(dst)
|
---|
818 | didSomething = True
|
---|
819 | except UnsupportedConversion:
|
---|
820 | if not self.args.quiet:
|
---|
821 | print('MASM=>NASM conversion unsupported for', dst)
|
---|
822 | notConverted.append(dst)
|
---|
823 | except NoSourceFile:
|
---|
824 | if not self.args.quiet:
|
---|
825 | print('Source file missing for', reldst)
|
---|
826 | notConverted.append(dst)
|
---|
827 | except UnsupportedArch:
|
---|
828 | unsupportedArchCount += 1
|
---|
829 | else:
|
---|
830 | if didSomething:
|
---|
831 | self.ConversionFinished(dst)
|
---|
832 | if len(notConverted) > 0 and not self.args.quiet:
|
---|
833 | for dst in notConverted:
|
---|
834 | reldst = self.RootRelative(dst)
|
---|
835 | print('Unabled to convert', reldst)
|
---|
836 | if unsupportedArchCount > 0 and not self.args.quiet:
|
---|
837 | print('Skipped', unsupportedArchCount, 'files based on architecture')
|
---|
838 |
|
---|
839 | def UpdateInfAsmFile(self, dst, IgnoreMissingAsm=False):
|
---|
840 | infPath = os.path.split(os.path.realpath(self.inf))[0]
|
---|
841 | asmSrc = os.path.splitext(dst)[0] + '.asm'
|
---|
842 | fullSrc = os.path.join(infPath, asmSrc)
|
---|
843 | fullDst = os.path.join(infPath, dst)
|
---|
844 | srcParentDir = os.path.basename(os.path.split(fullSrc)[0])
|
---|
845 | if srcParentDir.lower() in UnsupportedArch.unsupported:
|
---|
846 | raise UnsupportedArch
|
---|
847 | elif not os.path.exists(fullSrc):
|
---|
848 | if not IgnoreMissingAsm:
|
---|
849 | raise NoSourceFile
|
---|
850 | else: # not os.path.exists(fullDst):
|
---|
851 | conv = ConvertAsmFile(fullSrc, fullDst, self)
|
---|
852 | self.unsupportedSyntaxSeen = conv.unsupportedSyntaxSeen
|
---|
853 |
|
---|
854 | fileChanged = False
|
---|
855 | recentSources = list()
|
---|
856 | i = 0
|
---|
857 | while i < len(self.lines):
|
---|
858 | line = self.lines[i].rstrip()
|
---|
859 | updatedLine = line
|
---|
860 | lineChanged = False
|
---|
861 | preserveOldSource = False
|
---|
862 | for src in self.dstToSrc[dst]:
|
---|
863 | assert self.srcToDst[src] == dst
|
---|
864 | updatedLine = self.ReplacePreserveSpacing(
|
---|
865 | updatedLine, src, dst)
|
---|
866 | lineChanged = updatedLine != line
|
---|
867 | if lineChanged:
|
---|
868 | preserveOldSource = self.ShouldKeepFile(src)
|
---|
869 | break
|
---|
870 |
|
---|
871 | if lineChanged:
|
---|
872 | if preserveOldSource:
|
---|
873 | if updatedLine.strip() not in recentSources:
|
---|
874 | self.lines.insert(i, updatedLine + '\n')
|
---|
875 | recentSources.append(updatedLine.strip())
|
---|
876 | i += 1
|
---|
877 | if self.diff:
|
---|
878 | print('+%s' % updatedLine)
|
---|
879 | if self.diff:
|
---|
880 | print('', line)
|
---|
881 | else:
|
---|
882 | if self.diff:
|
---|
883 | print('-%s' % line)
|
---|
884 | if updatedLine.strip() in recentSources:
|
---|
885 | self.lines[i] = None
|
---|
886 | else:
|
---|
887 | self.lines[i] = updatedLine + '\n'
|
---|
888 | recentSources.append(updatedLine.strip())
|
---|
889 | if self.diff:
|
---|
890 | print('+%s' % updatedLine)
|
---|
891 | else:
|
---|
892 | if len(recentSources) > 0:
|
---|
893 | recentSources = list()
|
---|
894 | if self.diff:
|
---|
895 | print('', line)
|
---|
896 |
|
---|
897 | fileChanged |= lineChanged
|
---|
898 | i += 1
|
---|
899 |
|
---|
900 | if fileChanged:
|
---|
901 | self.lines = list(filter(lambda l: l is not None, self.lines))
|
---|
902 |
|
---|
903 | for src in self.dstToSrc[dst]:
|
---|
904 | if not src.endswith('.asm'):
|
---|
905 | fullSrc = os.path.join(infPath, src)
|
---|
906 | if os.path.exists(fullSrc):
|
---|
907 | self.RemoveFile(fullSrc)
|
---|
908 |
|
---|
909 | if fileChanged:
|
---|
910 | f = io.open(self.inf, 'w', newline='\r\n')
|
---|
911 | f.writelines(self.lines)
|
---|
912 | f.close()
|
---|
913 | self.FileUpdated(self.inf)
|
---|
914 |
|
---|
915 | def ConversionFinished(self, dst):
|
---|
916 | asmSrc = os.path.splitext(dst)[0] + '.asm'
|
---|
917 | self.FileConversionFinished(
|
---|
918 | self.packageName, self.moduleName, asmSrc, dst)
|
---|
919 |
|
---|
920 |
|
---|
921 | class ConvertInfFiles(CommonUtils):
|
---|
922 |
|
---|
923 | def __init__(self, infs, clone):
|
---|
924 | CommonUtils.__init__(self, clone)
|
---|
925 | infs = map(lambda i: ConvertInfFile(i, self), infs)
|
---|
926 | infs = filter(lambda i: len(i) > 0, infs)
|
---|
927 | dstToInfs = {'order': []}
|
---|
928 | for inf in infs:
|
---|
929 | for dst in inf:
|
---|
930 | fulldst = os.path.realpath(os.path.join(inf.dir, dst))
|
---|
931 | pair = (inf, dst)
|
---|
932 | if fulldst in dstToInfs:
|
---|
933 | dstToInfs[fulldst].append(pair)
|
---|
934 | else:
|
---|
935 | dstToInfs['order'].append(fulldst)
|
---|
936 | dstToInfs[fulldst] = [pair]
|
---|
937 |
|
---|
938 | notConverted = []
|
---|
939 | unsupportedArchCount = 0
|
---|
940 | for dst in dstToInfs['order']:
|
---|
941 | didSomething = False
|
---|
942 | try:
|
---|
943 | for inf, reldst in dstToInfs[dst]:
|
---|
944 | inf.UpdateInfAsmFile(reldst, IgnoreMissingAsm=didSomething)
|
---|
945 | didSomething = True
|
---|
946 | except UnsupportedConversion:
|
---|
947 | if not self.args.quiet:
|
---|
948 | print('MASM=>NASM conversion unsupported for', reldst)
|
---|
949 | notConverted.append(dst)
|
---|
950 | except NoSourceFile:
|
---|
951 | if not self.args.quiet:
|
---|
952 | print('Source file missing for', reldst)
|
---|
953 | notConverted.append(dst)
|
---|
954 | except UnsupportedArch:
|
---|
955 | unsupportedArchCount += 1
|
---|
956 | else:
|
---|
957 | if didSomething:
|
---|
958 | inf.ConversionFinished(reldst)
|
---|
959 | if len(notConverted) > 0 and not self.args.quiet:
|
---|
960 | for dst in notConverted:
|
---|
961 | reldst = self.RootRelative(dst)
|
---|
962 | print('Unabled to convert', reldst)
|
---|
963 | if unsupportedArchCount > 0 and not self.args.quiet:
|
---|
964 | print('Skipped', unsupportedArchCount, 'files based on architecture')
|
---|
965 |
|
---|
966 |
|
---|
967 | class ConvertDirectories(CommonUtils):
|
---|
968 |
|
---|
969 | def __init__(self, paths, clone):
|
---|
970 | CommonUtils.__init__(self, clone)
|
---|
971 | self.paths = paths
|
---|
972 | self.ConvertInfAndAsmFiles()
|
---|
973 |
|
---|
974 | def ConvertInfAndAsmFiles(self):
|
---|
975 | infs = list()
|
---|
976 | for path in self.paths:
|
---|
977 | assert(os.path.exists(path))
|
---|
978 | for path in self.paths:
|
---|
979 | for root, dirs, files in os.walk(path):
|
---|
980 | for d in ('.svn', '.git'):
|
---|
981 | if d in dirs:
|
---|
982 | dirs.remove(d)
|
---|
983 | for f in files:
|
---|
984 | if f.lower().endswith('.inf'):
|
---|
985 | inf = os.path.realpath(os.path.join(root, f))
|
---|
986 | infs.append(inf)
|
---|
987 |
|
---|
988 | ConvertInfFiles(infs, self)
|
---|
989 |
|
---|
990 |
|
---|
991 | class ConvertAsmApp(CommonUtils):
|
---|
992 |
|
---|
993 | def __init__(self):
|
---|
994 | CommonUtils.__init__(self)
|
---|
995 |
|
---|
996 | src = self.args.source
|
---|
997 | dst = self.args.dest
|
---|
998 | if self.infmode:
|
---|
999 | ConvertInfFiles((src,), self)
|
---|
1000 | elif self.dirmode:
|
---|
1001 | ConvertDirectories((src,), self)
|
---|
1002 | elif not self.dirmode:
|
---|
1003 | ConvertAsmFile(src, dst, self)
|
---|
1004 |
|
---|
1005 | ConvertAsmApp()
|
---|