xref: /AOO41X/main/toolkit/src2xml/source/srclexer.py (revision 9f22d7c2b35e9612da695275f00a04cc0e734348)
1*9f22d7c2SAndrew Rist# *************************************************************
2*9f22d7c2SAndrew Rist#
3*9f22d7c2SAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
4*9f22d7c2SAndrew Rist#  or more contributor license agreements.  See the NOTICE file
5*9f22d7c2SAndrew Rist#  distributed with this work for additional information
6*9f22d7c2SAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
7*9f22d7c2SAndrew Rist#  to you under the Apache License, Version 2.0 (the
8*9f22d7c2SAndrew Rist#  "License"); you may not use this file except in compliance
9*9f22d7c2SAndrew Rist#  with the License.  You may obtain a copy of the License at
10*9f22d7c2SAndrew Rist#
11*9f22d7c2SAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
12*9f22d7c2SAndrew Rist#
13*9f22d7c2SAndrew Rist#  Unless required by applicable law or agreed to in writing,
14*9f22d7c2SAndrew Rist#  software distributed under the License is distributed on an
15*9f22d7c2SAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f22d7c2SAndrew Rist#  KIND, either express or implied.  See the License for the
17*9f22d7c2SAndrew Rist#  specific language governing permissions and limitations
18*9f22d7c2SAndrew Rist#  under the License.
19*9f22d7c2SAndrew Rist#
20*9f22d7c2SAndrew Rist# *************************************************************
21*9f22d7c2SAndrew Rist
22cdf0e10cSrcweirimport sys, os.path
23cdf0e10cSrcweirfrom globals import *
24cdf0e10cSrcweirimport macroparser
25cdf0e10cSrcweir
26cdf0e10cSrcweirclass EOF(Exception):
27cdf0e10cSrcweir    def __init__ (self):
28cdf0e10cSrcweir        pass
29cdf0e10cSrcweir
30cdf0e10cSrcweir    def str (self):
31cdf0e10cSrcweir        return "end of file"
32cdf0e10cSrcweir
33cdf0e10cSrcweirclass BOF(Exception):
34cdf0e10cSrcweir    def __init__ (self):
35cdf0e10cSrcweir        pass
36cdf0e10cSrcweir
37cdf0e10cSrcweir    def str (self):
38cdf0e10cSrcweir        return "beginning of file"
39cdf0e10cSrcweir
40cdf0e10cSrcweir
41cdf0e10cSrcweirdef removeHeaderQuotes (orig):
42cdf0e10cSrcweir    if len(orig) <= 2:
43cdf0e10cSrcweir        return orig
44cdf0e10cSrcweir    elif orig[0] == orig[-1] == '"':
45cdf0e10cSrcweir        return orig[1:-1]
46cdf0e10cSrcweir    elif orig[0] == '<' and orig[-1] == '>':
47cdf0e10cSrcweir        return orig[1:-1]
48cdf0e10cSrcweir
49cdf0e10cSrcweir    return orig
50cdf0e10cSrcweir
51cdf0e10cSrcweir
52cdf0e10cSrcweirdef dumpTokens (tokens, toError=False):
53cdf0e10cSrcweir
54cdf0e10cSrcweir    scope = 0
55cdf0e10cSrcweir    indent = "    "
56cdf0e10cSrcweir    line = ''
57cdf0e10cSrcweir    chars = ''
58cdf0e10cSrcweir
59cdf0e10cSrcweir    for token in tokens:
60cdf0e10cSrcweir        if token in '{<':
61cdf0e10cSrcweir            if len(line) > 0:
62cdf0e10cSrcweir                chars += indent*scope + line + "\n"
63cdf0e10cSrcweir                line = ''
64cdf0e10cSrcweir            chars += indent*scope + token + "\n"
65cdf0e10cSrcweir            scope += 1
66cdf0e10cSrcweir
67cdf0e10cSrcweir        elif token in '}>':
68cdf0e10cSrcweir            if len(line) > 0:
69cdf0e10cSrcweir                chars += indent*scope + line + "\n"
70cdf0e10cSrcweir                line = ''
71cdf0e10cSrcweir            scope -= 1
72cdf0e10cSrcweir            chars += indent*scope + token
73cdf0e10cSrcweir
74cdf0e10cSrcweir        elif token == ';':
75cdf0e10cSrcweir            if len(line) > 0:
76cdf0e10cSrcweir                chars += indent*scope + line + ";\n"
77cdf0e10cSrcweir                line = ''
78cdf0e10cSrcweir            else:
79cdf0e10cSrcweir                chars += ";\n"
80cdf0e10cSrcweir        elif len(token) > 0:
81cdf0e10cSrcweir            line += token + ' '
82cdf0e10cSrcweir
83cdf0e10cSrcweir    if len(line) > 0:
84cdf0e10cSrcweir        chars += line
85cdf0e10cSrcweir    chars += "\n"
86cdf0e10cSrcweir    if toError:
87cdf0e10cSrcweir        sys.stderr.write(chars)
88cdf0e10cSrcweir    else:
89cdf0e10cSrcweir        sys.stdout.write(chars)
90cdf0e10cSrcweir
91cdf0e10cSrcweir
92cdf0e10cSrcweirclass HeaderData(object):
93cdf0e10cSrcweir    def __init__ (self):
94cdf0e10cSrcweir        self.defines = {}
95cdf0e10cSrcweir        self.tokens = []
96cdf0e10cSrcweir
97cdf0e10cSrcweir
98cdf0e10cSrcweirclass SrcLexer(object):
99cdf0e10cSrcweir    """Lexicographical analyzer for .src format.
100cdf0e10cSrcweir
101cdf0e10cSrcweirThe role of a lexer is to parse the source file and break it into
102cdf0e10cSrcweirappropriate tokens.  Such tokens are later passed to a parser to
103cdf0e10cSrcweirbuild the syntax tree.
104cdf0e10cSrcweir"""
105cdf0e10cSrcweir    headerCache = {}
106cdf0e10cSrcweir
107cdf0e10cSrcweir    VISIBLE = 0
108cdf0e10cSrcweir    INVISIBLE_PRE = 1
109cdf0e10cSrcweir    INVISIBLE_POST = 2
110cdf0e10cSrcweir
111cdf0e10cSrcweir    def __init__ (self, chars, filepath = None):
112cdf0e10cSrcweir        self.filepath = filepath
113cdf0e10cSrcweir        self.parentLexer = None
114cdf0e10cSrcweir        self.chars = chars
115cdf0e10cSrcweir        self.bufsize = len(self.chars)
116cdf0e10cSrcweir
117cdf0e10cSrcweir        # TODO: use parameters for this
118cdf0e10cSrcweir        # Properties that can be copied.
119cdf0e10cSrcweir        self.headerDict = dict ()
120cdf0e10cSrcweir        self.debug = False
121cdf0e10cSrcweir        self.debugMacro = False
122cdf0e10cSrcweir        self.includeDirs = list ()
123cdf0e10cSrcweir        self.expandHeaders = True
124cdf0e10cSrcweir        self.inMacroDefine = False
125cdf0e10cSrcweir        self.stopOnHeader = False
126cdf0e10cSrcweir
127cdf0e10cSrcweir    def copyProperties (self, other):
128cdf0e10cSrcweir        """Copy properties from another instance of SrcLexer."""
129cdf0e10cSrcweir
130cdf0e10cSrcweir        # TODO: use parameters for this
131cdf0e10cSrcweir        self.headerDict = other.headerDict
132cdf0e10cSrcweir        self.debug = other.debug
133cdf0e10cSrcweir        self.debugMacro = other.debugMacro
134cdf0e10cSrcweir        self.includeDirs = other.includeDirs[:]
135cdf0e10cSrcweir        self.expandHeaders = other.expandHeaders
136cdf0e10cSrcweir        self.inMacroDefine = other.inMacroDefine
137cdf0e10cSrcweir        self.stopOnHeader = other.stopOnHeader
138cdf0e10cSrcweir
139cdf0e10cSrcweir    def init (self):
140cdf0e10cSrcweir        self.firstNonBlank = ''
141cdf0e10cSrcweir        self.token = ''
142cdf0e10cSrcweir        self.tokens = []
143cdf0e10cSrcweir        self.defines = {}
144cdf0e10cSrcweir        self.visibilityStack = []
145cdf0e10cSrcweir
146cdf0e10cSrcweir    def getTokens (self):
147cdf0e10cSrcweir        return self.tokens
148cdf0e10cSrcweir
149cdf0e10cSrcweir    def getDefines (self):
150cdf0e10cSrcweir        return self.defines
151cdf0e10cSrcweir
152cdf0e10cSrcweir    def nextPos (self, i):
153cdf0e10cSrcweir        while True:
154cdf0e10cSrcweir            i += 1
155cdf0e10cSrcweir            try:
156cdf0e10cSrcweir                c = self.chars[i]
157cdf0e10cSrcweir            except IndexError:
158cdf0e10cSrcweir                raise EOF
159cdf0e10cSrcweir
160cdf0e10cSrcweir            if ord(c) in [0x0D]:
161cdf0e10cSrcweir                continue
162cdf0e10cSrcweir            break
163cdf0e10cSrcweir        return i
164cdf0e10cSrcweir
165cdf0e10cSrcweir    def prevPos (self, i):
166cdf0e10cSrcweir        while True:
167cdf0e10cSrcweir            i -= 1
168cdf0e10cSrcweir            try:
169cdf0e10cSrcweir                c = self.chars[i]
170cdf0e10cSrcweir            except IndexError:
171cdf0e10cSrcweir                raise BOF
172cdf0e10cSrcweir
173cdf0e10cSrcweir            if ord(c) in [0x0D]:
174cdf0e10cSrcweir                continue
175cdf0e10cSrcweir            break
176cdf0e10cSrcweir        return i
177cdf0e10cSrcweir
178cdf0e10cSrcweir    def isCodeVisible (self):
179cdf0e10cSrcweir        if len(self.visibilityStack) == 0:
180cdf0e10cSrcweir            return True
181cdf0e10cSrcweir        for item in self.visibilityStack:
182cdf0e10cSrcweir            if item != SrcLexer.VISIBLE:
183cdf0e10cSrcweir                return False
184cdf0e10cSrcweir        return True
185cdf0e10cSrcweir
186cdf0e10cSrcweir    def tokenize (self):
187cdf0e10cSrcweir        self.init()
188cdf0e10cSrcweir
189cdf0e10cSrcweir        i = 0
190cdf0e10cSrcweir        while True:
191cdf0e10cSrcweir            c = self.chars[i]
192cdf0e10cSrcweir
193cdf0e10cSrcweir            if self.firstNonBlank == '' and not c in [' ', "\n", "\t"]:
194cdf0e10cSrcweir                # Store the first non-blank in a line.
195cdf0e10cSrcweir                self.firstNonBlank = c
196cdf0e10cSrcweir            elif c == "\n":
197cdf0e10cSrcweir                self.firstNonBlank = ''
198cdf0e10cSrcweir
199cdf0e10cSrcweir            if c == '#':
200cdf0e10cSrcweir                i = self.pound(i)
201cdf0e10cSrcweir            elif c == '/':
202cdf0e10cSrcweir                i = self.slash(i)
203cdf0e10cSrcweir            elif c == "\n":
204cdf0e10cSrcweir                i = self.lineBreak(i)
205cdf0e10cSrcweir            elif c == '"':
206cdf0e10cSrcweir                i = self.doubleQuote(i)
207cdf0e10cSrcweir            elif c in [' ', "\t"]:
208cdf0e10cSrcweir                i = self.blank(i)
209cdf0e10cSrcweir            elif c in ";()[]{}<>,=+-*":
210cdf0e10cSrcweir                # Any outstanding single-character token.
211cdf0e10cSrcweir                i = self.anyToken(i, c)
212cdf0e10cSrcweir            elif self.isCodeVisible():
213cdf0e10cSrcweir                self.token += c
214cdf0e10cSrcweir
215cdf0e10cSrcweir            try:
216cdf0e10cSrcweir                i = self.nextPos(i)
217cdf0e10cSrcweir            except EOF:
218cdf0e10cSrcweir                break
219cdf0e10cSrcweir
220cdf0e10cSrcweir        if len(self.token):
221cdf0e10cSrcweir            self.tokens.append(self.token)
222cdf0e10cSrcweir
223cdf0e10cSrcweir        if not self.parentLexer and self.debug:
224cdf0e10cSrcweir            progress ("-"*68 + "\n")
225cdf0e10cSrcweir            progress ("All defines found in this translation unit:\n")
226cdf0e10cSrcweir            keys = self.defines.keys()
227cdf0e10cSrcweir            keys.sort()
228cdf0e10cSrcweir            for key in keys:
229cdf0e10cSrcweir                progress ("@ %s\n"%key)
230cdf0e10cSrcweir
231cdf0e10cSrcweir    def dumpTokens (self, toError=False):
232cdf0e10cSrcweir        dumpTokens(self.tokens, toError)
233cdf0e10cSrcweir
234cdf0e10cSrcweir
235cdf0e10cSrcweir    def maybeAddToken (self):
236cdf0e10cSrcweir        if len(self.token) > 0:
237cdf0e10cSrcweir            self.tokens.append(self.token)
238cdf0e10cSrcweir            self.token = ''
239cdf0e10cSrcweir
240cdf0e10cSrcweir
241cdf0e10cSrcweir    #--------------------------------------------------------------------
242cdf0e10cSrcweir    # character handlers
243cdf0e10cSrcweir
244cdf0e10cSrcweir    def blank (self, i):
245cdf0e10cSrcweir        if not self.isCodeVisible():
246cdf0e10cSrcweir            return i
247cdf0e10cSrcweir
248cdf0e10cSrcweir        self.maybeAddToken()
249cdf0e10cSrcweir        return i
250cdf0e10cSrcweir
251cdf0e10cSrcweir
252cdf0e10cSrcweir    def pound (self, i):
253cdf0e10cSrcweir
254cdf0e10cSrcweir        if self.inMacroDefine:
255cdf0e10cSrcweir            return i
256cdf0e10cSrcweir
257cdf0e10cSrcweir        if not self.firstNonBlank == '#':
258cdf0e10cSrcweir            return i
259cdf0e10cSrcweir
260cdf0e10cSrcweir        self.maybeAddToken()
261cdf0e10cSrcweir        # We are in preprocessing mode.
262cdf0e10cSrcweir
263cdf0e10cSrcweir        # Get the macro command name '#<command> .....'
264cdf0e10cSrcweir
265cdf0e10cSrcweir        command, define, buf = '', '', ''
266cdf0e10cSrcweir        firstNonBlank = False
267cdf0e10cSrcweir        while True:
268cdf0e10cSrcweir            try:
269cdf0e10cSrcweir                i = self.nextPos(i)
270cdf0e10cSrcweir                c = self.chars[i]
271cdf0e10cSrcweir                if c == '\\' and self.chars[self.nextPos(i)] == "\n":
272cdf0e10cSrcweir                    i = self.nextPos(i)
273cdf0e10cSrcweir                    continue
274cdf0e10cSrcweir            except EOF:
275cdf0e10cSrcweir                break
276cdf0e10cSrcweir
277cdf0e10cSrcweir            if c == "\n":
278cdf0e10cSrcweir                if len(buf) > 0 and len(command) == 0:
279cdf0e10cSrcweir                    command = buf
280cdf0e10cSrcweir                i = self.prevPos(i)
281cdf0e10cSrcweir                break
282cdf0e10cSrcweir            elif c in [' ', "\t"]:
283cdf0e10cSrcweir                if not firstNonBlank:
284cdf0e10cSrcweir                    # Ignore any leading blanks after the '#'.
285cdf0e10cSrcweir                    continue
286cdf0e10cSrcweir
287cdf0e10cSrcweir                if len(command) == 0:
288cdf0e10cSrcweir                    command = buf
289cdf0e10cSrcweir                    buf = ''
290cdf0e10cSrcweir                else:
291cdf0e10cSrcweir                    buf += ' '
292cdf0e10cSrcweir            elif c == '(':
293cdf0e10cSrcweir                if len(buf) > 0 and len(command) == 0:
294cdf0e10cSrcweir                    command = buf
295cdf0e10cSrcweir                buf += c
296cdf0e10cSrcweir            else:
297cdf0e10cSrcweir                if not firstNonBlank:
298cdf0e10cSrcweir                    firstNonBlank = True
299cdf0e10cSrcweir                buf += c
300cdf0e10cSrcweir
301cdf0e10cSrcweir        if command == 'define':
302cdf0e10cSrcweir            self.handleMacroDefine(buf)
303cdf0e10cSrcweir        elif command == 'include':
304cdf0e10cSrcweir            self.handleMacroInclude(buf)
305cdf0e10cSrcweir        elif command == 'ifdef':
306cdf0e10cSrcweir            defineName = buf.strip()
307cdf0e10cSrcweir            if self.defines.has_key(defineName):
308cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.VISIBLE)
309cdf0e10cSrcweir            else:
310cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.INVISIBLE_PRE)
311cdf0e10cSrcweir
312cdf0e10cSrcweir        elif command == 'ifndef':
313cdf0e10cSrcweir            defineName = buf.strip()
314cdf0e10cSrcweir            if self.defines.has_key(defineName):
315cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.INVISIBLE_PRE)
316cdf0e10cSrcweir            else:
317cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.VISIBLE)
318cdf0e10cSrcweir
319cdf0e10cSrcweir        elif command == 'if':
320cdf0e10cSrcweir            if self.evalCodeVisibility(buf):
321cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.VISIBLE)
322cdf0e10cSrcweir            else:
323cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.INVISIBLE_PRE)
324cdf0e10cSrcweir
325cdf0e10cSrcweir        elif command == 'elif':
326cdf0e10cSrcweir            if len(self.visibilityStack) == 0:
327cdf0e10cSrcweir                raise ParseError ('')
328cdf0e10cSrcweir
329cdf0e10cSrcweir            if self.visibilityStack[-1] == SrcLexer.VISIBLE:
330cdf0e10cSrcweir                self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST
331cdf0e10cSrcweir            elif self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE:
332cdf0e10cSrcweir                # Evaluate only if the current visibility is false.
333cdf0e10cSrcweir                if self.evalCodeVisibility(buf):
334cdf0e10cSrcweir                    self.visibilityStack[-1] = SrcLexer.VISIBLE
335cdf0e10cSrcweir
336cdf0e10cSrcweir        elif command == 'else':
337cdf0e10cSrcweir            if len(self.visibilityStack) == 0:
338cdf0e10cSrcweir                raise ParseError ('')
339cdf0e10cSrcweir
340cdf0e10cSrcweir            if self.visibilityStack[-1] == SrcLexer.VISIBLE:
341cdf0e10cSrcweir                self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST
342cdf0e10cSrcweir            if self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE:
343cdf0e10cSrcweir                self.visibilityStack[-1] = SrcLexer.VISIBLE
344cdf0e10cSrcweir
345cdf0e10cSrcweir        elif command == 'endif':
346cdf0e10cSrcweir            if len(self.visibilityStack) == 0:
347cdf0e10cSrcweir                raise ParseError ('')
348cdf0e10cSrcweir            self.visibilityStack.pop()
349cdf0e10cSrcweir
350cdf0e10cSrcweir        elif command == 'undef':
351cdf0e10cSrcweir            pass
352cdf0e10cSrcweir        elif command in ['error', 'pragma']:
353cdf0e10cSrcweir            pass
354cdf0e10cSrcweir        else:
355cdf0e10cSrcweir            print "'%s' '%s'"%(command, buf)
356cdf0e10cSrcweir            print self.filepath
357cdf0e10cSrcweir            sys.exit(0)
358cdf0e10cSrcweir
359cdf0e10cSrcweir        return i
360cdf0e10cSrcweir
361cdf0e10cSrcweir
362cdf0e10cSrcweir    def evalCodeVisibility (self, buf):
363cdf0e10cSrcweir        try:
364cdf0e10cSrcweir            return eval(buf)
365cdf0e10cSrcweir        except:
366cdf0e10cSrcweir            return True
367cdf0e10cSrcweir
368cdf0e10cSrcweir    def handleMacroDefine (self, buf):
369cdf0e10cSrcweir
370cdf0e10cSrcweir        mparser = macroparser.MacroParser(buf)
371cdf0e10cSrcweir        mparser.debug = self.debugMacro
372cdf0e10cSrcweir        mparser.parse()
373cdf0e10cSrcweir        macro = mparser.getMacro()
374cdf0e10cSrcweir        if macro:
375cdf0e10cSrcweir            self.defines[macro.name] = macro
376cdf0e10cSrcweir
377cdf0e10cSrcweir    def handleMacroInclude (self, buf):
378cdf0e10cSrcweir
379cdf0e10cSrcweir        # Strip excess string if any.
380cdf0e10cSrcweir        pos = buf.find(' ')
381cdf0e10cSrcweir        if pos >= 0:
382cdf0e10cSrcweir            buf = buf[:pos]
383cdf0e10cSrcweir        headerSub = removeHeaderQuotes(buf)
384cdf0e10cSrcweir
385cdf0e10cSrcweir        if not self.expandHeaders:
386cdf0e10cSrcweir            # We don't want to expand headers.  Bail out.
387cdf0e10cSrcweir            if self.debug:
388cdf0e10cSrcweir                progress ("%s ignored\n"%headerSub)
389cdf0e10cSrcweir            return
390cdf0e10cSrcweir
391cdf0e10cSrcweir        defines = {}
392cdf0e10cSrcweir        headerPath = None
393cdf0e10cSrcweir        for includeDir in self.includeDirs:
394cdf0e10cSrcweir            hpath = includeDir + '/' + headerSub
395cdf0e10cSrcweir            if os.path.isfile(hpath) and hpath != self.filepath:
396cdf0e10cSrcweir                headerPath = hpath
397cdf0e10cSrcweir                break
398cdf0e10cSrcweir
399cdf0e10cSrcweir        if not headerPath:
400cdf0e10cSrcweir            error("included header file " + headerSub + " not found\n", self.stopOnHeader)
401cdf0e10cSrcweir            return
402cdf0e10cSrcweir
403cdf0e10cSrcweir        if self.debug:
404cdf0e10cSrcweir            progress ("%s found\n"%headerPath)
405cdf0e10cSrcweir
406cdf0e10cSrcweir        if headerPath in self.headerDict:
407cdf0e10cSrcweir            if self.debug:
408cdf0e10cSrcweir                progress ("%s already included\n"%headerPath)
409cdf0e10cSrcweir            return
410cdf0e10cSrcweir
411cdf0e10cSrcweir        if SrcLexer.headerCache.has_key(headerPath):
412cdf0e10cSrcweir            if self.debug:
413cdf0e10cSrcweir                progress ("%s in cache\n"%headerPath)
414cdf0e10cSrcweir            for key in SrcLexer.headerCache[headerPath].defines.keys():
415cdf0e10cSrcweir                self.defines[key] = SrcLexer.headerCache[headerPath].defines[key]
416cdf0e10cSrcweir            return
417cdf0e10cSrcweir
418cdf0e10cSrcweir        chars = open(headerPath, 'r').read()
419cdf0e10cSrcweir        mclexer = SrcLexer(chars, headerPath)
420cdf0e10cSrcweir        mclexer.copyProperties(self)
421cdf0e10cSrcweir        mclexer.parentLexer = self
422cdf0e10cSrcweir        mclexer.tokenize()
423cdf0e10cSrcweir        hdrData = HeaderData()
424cdf0e10cSrcweir        hdrData.tokens = mclexer.getTokens()
425cdf0e10cSrcweir        headerDefines = mclexer.getDefines()
426cdf0e10cSrcweir        for key in headerDefines.keys():
427cdf0e10cSrcweir            defines[key] = headerDefines[key]
428cdf0e10cSrcweir            hdrData.defines[key] = headerDefines[key]
429cdf0e10cSrcweir
430cdf0e10cSrcweir        self.headerDict[headerPath] = True
431cdf0e10cSrcweir        SrcLexer.headerCache[headerPath] = hdrData
432cdf0e10cSrcweir
433cdf0e10cSrcweir        # Update the list of headers that have already been expaneded.
434cdf0e10cSrcweir        for key in mclexer.headerDict.keys():
435cdf0e10cSrcweir            self.headerDict[key] = True
436cdf0e10cSrcweir
437cdf0e10cSrcweir        if self.debug:
438cdf0e10cSrcweir            progress ("defines found in header %s:\n"%headerSub)
439cdf0e10cSrcweir            for key in defines.keys():
440cdf0e10cSrcweir                progress ("  '%s'\n"%key)
441cdf0e10cSrcweir
442cdf0e10cSrcweir        for key in defines.keys():
443cdf0e10cSrcweir            self.defines[key] = defines[key]
444cdf0e10cSrcweir
445cdf0e10cSrcweir
446cdf0e10cSrcweir    def slash (self, i):
447cdf0e10cSrcweir        if not self.isCodeVisible():
448cdf0e10cSrcweir            return i
449cdf0e10cSrcweir
450cdf0e10cSrcweir        if i < self.bufsize - 1 and self.chars[i+1] == '/':
451cdf0e10cSrcweir            # Parse line comment.
452cdf0e10cSrcweir            line = ''
453cdf0e10cSrcweir            i += 2
454cdf0e10cSrcweir            while i < self.bufsize:
455cdf0e10cSrcweir                c = self.chars[i]
456cdf0e10cSrcweir                if ord(c) in [0x0A, 0x0D]:
457cdf0e10cSrcweir                    return i - 1
458cdf0e10cSrcweir                line += c
459cdf0e10cSrcweir                i += 1
460cdf0e10cSrcweir            self.token = ''
461cdf0e10cSrcweir        elif i < self.bufsize - 1 and self.chars[i+1] == '*':
462cdf0e10cSrcweir            comment = ''
463cdf0e10cSrcweir            i += 2
464cdf0e10cSrcweir            while i < self.bufsize:
465cdf0e10cSrcweir                c = self.chars[i]
466cdf0e10cSrcweir                if c == '/' and self.chars[i-1] == '*':
467cdf0e10cSrcweir                    return i
468cdf0e10cSrcweir                comment += c
469cdf0e10cSrcweir                i += 1
470cdf0e10cSrcweir        else:
471cdf0e10cSrcweir            return self.anyToken(i, '/')
472cdf0e10cSrcweir
473cdf0e10cSrcweir        return i
474cdf0e10cSrcweir
475cdf0e10cSrcweir
476cdf0e10cSrcweir    def lineBreak (self, i):
477cdf0e10cSrcweir        if not self.isCodeVisible():
478cdf0e10cSrcweir            return i
479cdf0e10cSrcweir
480cdf0e10cSrcweir        self.maybeAddToken()
481cdf0e10cSrcweir
482cdf0e10cSrcweir        return i
483cdf0e10cSrcweir
484cdf0e10cSrcweir
485cdf0e10cSrcweir    def doubleQuote (self, i):
486cdf0e10cSrcweir        if not self.isCodeVisible():
487cdf0e10cSrcweir            return i
488cdf0e10cSrcweir
489cdf0e10cSrcweir        literal = ''
490cdf0e10cSrcweir        i += 1
491cdf0e10cSrcweir        while i < self.bufsize:
492cdf0e10cSrcweir            c = self.chars[i]
493cdf0e10cSrcweir            if c == '"':
494cdf0e10cSrcweir                self.tokens.append('"'+literal+'"')
495cdf0e10cSrcweir                break
496cdf0e10cSrcweir            literal += c
497cdf0e10cSrcweir            i += 1
498cdf0e10cSrcweir
499cdf0e10cSrcweir        return i
500cdf0e10cSrcweir
501cdf0e10cSrcweir
502cdf0e10cSrcweir    def anyToken (self, i, token):
503cdf0e10cSrcweir        if not self.isCodeVisible():
504cdf0e10cSrcweir            return i
505cdf0e10cSrcweir
506cdf0e10cSrcweir        self.maybeAddToken()
507cdf0e10cSrcweir        self.token = token
508cdf0e10cSrcweir        self.maybeAddToken()
509cdf0e10cSrcweir        return i
510