xref: /trunk/main/toolkit/src2xml/source/srclexer.py (revision 7d9fa7c3)
19f22d7c2SAndrew Rist# *************************************************************
29f22d7c2SAndrew Rist#
39f22d7c2SAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
49f22d7c2SAndrew Rist#  or more contributor license agreements.  See the NOTICE file
59f22d7c2SAndrew Rist#  distributed with this work for additional information
69f22d7c2SAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
79f22d7c2SAndrew Rist#  to you under the Apache License, Version 2.0 (the
89f22d7c2SAndrew Rist#  "License"); you may not use this file except in compliance
99f22d7c2SAndrew Rist#  with the License.  You may obtain a copy of the License at
109f22d7c2SAndrew Rist#
119f22d7c2SAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
129f22d7c2SAndrew Rist#
139f22d7c2SAndrew Rist#  Unless required by applicable law or agreed to in writing,
149f22d7c2SAndrew Rist#  software distributed under the License is distributed on an
159f22d7c2SAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f22d7c2SAndrew Rist#  KIND, either express or implied.  See the License for the
179f22d7c2SAndrew Rist#  specific language governing permissions and limitations
189f22d7c2SAndrew Rist#  under the License.
199f22d7c2SAndrew Rist#
209f22d7c2SAndrew Rist# *************************************************************
219f22d7c2SAndrew 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 = ''
58ae54856bSPedro Giffuni
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
101ae54856bSPedro GiffuniThe 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
185ae54856bSPedro Giffuni
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")
22677de67d5SPedro Giffuni            keys = sorted(self.defines.keys())
227cdf0e10cSrcweir            for key in keys:
228cdf0e10cSrcweir                progress ("@ %s\n"%key)
229cdf0e10cSrcweir
230cdf0e10cSrcweir    def dumpTokens (self, toError=False):
231cdf0e10cSrcweir        dumpTokens(self.tokens, toError)
232cdf0e10cSrcweir
233cdf0e10cSrcweir
234cdf0e10cSrcweir    def maybeAddToken (self):
235cdf0e10cSrcweir        if len(self.token) > 0:
236cdf0e10cSrcweir            self.tokens.append(self.token)
237cdf0e10cSrcweir            self.token = ''
238cdf0e10cSrcweir
239cdf0e10cSrcweir
240cdf0e10cSrcweir    #--------------------------------------------------------------------
241cdf0e10cSrcweir    # character handlers
242cdf0e10cSrcweir
243cdf0e10cSrcweir    def blank (self, i):
244cdf0e10cSrcweir        if not self.isCodeVisible():
245cdf0e10cSrcweir            return i
246cdf0e10cSrcweir
247cdf0e10cSrcweir        self.maybeAddToken()
248cdf0e10cSrcweir        return i
249cdf0e10cSrcweir
250cdf0e10cSrcweir
251cdf0e10cSrcweir    def pound (self, i):
252cdf0e10cSrcweir
253cdf0e10cSrcweir        if self.inMacroDefine:
254cdf0e10cSrcweir            return i
255cdf0e10cSrcweir
256cdf0e10cSrcweir        if not self.firstNonBlank == '#':
257cdf0e10cSrcweir            return i
258cdf0e10cSrcweir
259cdf0e10cSrcweir        self.maybeAddToken()
260cdf0e10cSrcweir        # We are in preprocessing mode.
261cdf0e10cSrcweir
262cdf0e10cSrcweir        # Get the macro command name '#<command> .....'
263cdf0e10cSrcweir
264cdf0e10cSrcweir        command, define, buf = '', '', ''
265cdf0e10cSrcweir        firstNonBlank = False
266cdf0e10cSrcweir        while True:
267cdf0e10cSrcweir            try:
268cdf0e10cSrcweir                i = self.nextPos(i)
269cdf0e10cSrcweir                c = self.chars[i]
270cdf0e10cSrcweir                if c == '\\' and self.chars[self.nextPos(i)] == "\n":
271cdf0e10cSrcweir                    i = self.nextPos(i)
272cdf0e10cSrcweir                    continue
273cdf0e10cSrcweir            except EOF:
274cdf0e10cSrcweir                break
275cdf0e10cSrcweir
276cdf0e10cSrcweir            if c == "\n":
277cdf0e10cSrcweir                if len(buf) > 0 and len(command) == 0:
278cdf0e10cSrcweir                    command = buf
279cdf0e10cSrcweir                i = self.prevPos(i)
280cdf0e10cSrcweir                break
281cdf0e10cSrcweir            elif c in [' ', "\t"]:
282cdf0e10cSrcweir                if not firstNonBlank:
283cdf0e10cSrcweir                    # Ignore any leading blanks after the '#'.
284cdf0e10cSrcweir                    continue
285cdf0e10cSrcweir
286cdf0e10cSrcweir                if len(command) == 0:
287cdf0e10cSrcweir                    command = buf
288cdf0e10cSrcweir                    buf = ''
289cdf0e10cSrcweir                else:
290cdf0e10cSrcweir                    buf += ' '
291cdf0e10cSrcweir            elif c == '(':
292cdf0e10cSrcweir                if len(buf) > 0 and len(command) == 0:
293cdf0e10cSrcweir                    command = buf
294cdf0e10cSrcweir                buf += c
295cdf0e10cSrcweir            else:
296cdf0e10cSrcweir                if not firstNonBlank:
297cdf0e10cSrcweir                    firstNonBlank = True
298cdf0e10cSrcweir                buf += c
299cdf0e10cSrcweir
300cdf0e10cSrcweir        if command == 'define':
301cdf0e10cSrcweir            self.handleMacroDefine(buf)
302cdf0e10cSrcweir        elif command == 'include':
303cdf0e10cSrcweir            self.handleMacroInclude(buf)
304cdf0e10cSrcweir        elif command == 'ifdef':
305cdf0e10cSrcweir            defineName = buf.strip()
306*7d9fa7c3SPedro Giffuni            if defineName in self.defines:
307cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.VISIBLE)
308cdf0e10cSrcweir            else:
309cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.INVISIBLE_PRE)
310cdf0e10cSrcweir
311cdf0e10cSrcweir        elif command == 'ifndef':
312cdf0e10cSrcweir            defineName = buf.strip()
313*7d9fa7c3SPedro Giffuni            if defineName in self.defines:
314cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.INVISIBLE_PRE)
315cdf0e10cSrcweir            else:
316cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.VISIBLE)
317cdf0e10cSrcweir
318cdf0e10cSrcweir        elif command == 'if':
319cdf0e10cSrcweir            if self.evalCodeVisibility(buf):
320cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.VISIBLE)
321cdf0e10cSrcweir            else:
322cdf0e10cSrcweir                self.visibilityStack.append(SrcLexer.INVISIBLE_PRE)
323cdf0e10cSrcweir
324cdf0e10cSrcweir        elif command == 'elif':
325cdf0e10cSrcweir            if len(self.visibilityStack) == 0:
326cdf0e10cSrcweir                raise ParseError ('')
327cdf0e10cSrcweir
328cdf0e10cSrcweir            if self.visibilityStack[-1] == SrcLexer.VISIBLE:
329cdf0e10cSrcweir                self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST
330cdf0e10cSrcweir            elif self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE:
331cdf0e10cSrcweir                # Evaluate only if the current visibility is false.
332cdf0e10cSrcweir                if self.evalCodeVisibility(buf):
333cdf0e10cSrcweir                    self.visibilityStack[-1] = SrcLexer.VISIBLE
334cdf0e10cSrcweir
335cdf0e10cSrcweir        elif command == 'else':
336cdf0e10cSrcweir            if len(self.visibilityStack) == 0:
337cdf0e10cSrcweir                raise ParseError ('')
338cdf0e10cSrcweir
339cdf0e10cSrcweir            if self.visibilityStack[-1] == SrcLexer.VISIBLE:
340cdf0e10cSrcweir                self.visibilityStack[-1] = SrcLexer.INVISIBLE_POST
341cdf0e10cSrcweir            if self.visibilityStack[-1] == SrcLexer.INVISIBLE_PRE:
342cdf0e10cSrcweir                self.visibilityStack[-1] = SrcLexer.VISIBLE
343cdf0e10cSrcweir
344cdf0e10cSrcweir        elif command == 'endif':
345cdf0e10cSrcweir            if len(self.visibilityStack) == 0:
346cdf0e10cSrcweir                raise ParseError ('')
347cdf0e10cSrcweir            self.visibilityStack.pop()
348cdf0e10cSrcweir
349cdf0e10cSrcweir        elif command == 'undef':
350cdf0e10cSrcweir            pass
351cdf0e10cSrcweir        elif command in ['error', 'pragma']:
352cdf0e10cSrcweir            pass
353cdf0e10cSrcweir        else:
354*7d9fa7c3SPedro Giffuni            print("'%s' '%s'"%(command, buf))
355*7d9fa7c3SPedro Giffuni            print(self.filepath)
356cdf0e10cSrcweir            sys.exit(0)
357cdf0e10cSrcweir
358cdf0e10cSrcweir        return i
359cdf0e10cSrcweir
360cdf0e10cSrcweir
361cdf0e10cSrcweir    def evalCodeVisibility (self, buf):
362cdf0e10cSrcweir        try:
363cdf0e10cSrcweir            return eval(buf)
364cdf0e10cSrcweir        except:
365cdf0e10cSrcweir            return True
366ae54856bSPedro Giffuni
367cdf0e10cSrcweir    def handleMacroDefine (self, buf):
368cdf0e10cSrcweir
369cdf0e10cSrcweir        mparser = macroparser.MacroParser(buf)
370cdf0e10cSrcweir        mparser.debug = self.debugMacro
371cdf0e10cSrcweir        mparser.parse()
372cdf0e10cSrcweir        macro = mparser.getMacro()
373cdf0e10cSrcweir        if macro:
374cdf0e10cSrcweir            self.defines[macro.name] = macro
375cdf0e10cSrcweir
376cdf0e10cSrcweir    def handleMacroInclude (self, buf):
377cdf0e10cSrcweir
378cdf0e10cSrcweir        # Strip excess string if any.
379cdf0e10cSrcweir        pos = buf.find(' ')
380cdf0e10cSrcweir        if pos >= 0:
381cdf0e10cSrcweir            buf = buf[:pos]
382cdf0e10cSrcweir        headerSub = removeHeaderQuotes(buf)
383cdf0e10cSrcweir
384cdf0e10cSrcweir        if not self.expandHeaders:
385cdf0e10cSrcweir            # We don't want to expand headers.  Bail out.
386cdf0e10cSrcweir            if self.debug:
387cdf0e10cSrcweir                progress ("%s ignored\n"%headerSub)
388cdf0e10cSrcweir            return
389cdf0e10cSrcweir
390cdf0e10cSrcweir        defines = {}
391cdf0e10cSrcweir        headerPath = None
392cdf0e10cSrcweir        for includeDir in self.includeDirs:
393cdf0e10cSrcweir            hpath = includeDir + '/' + headerSub
394cdf0e10cSrcweir            if os.path.isfile(hpath) and hpath != self.filepath:
395cdf0e10cSrcweir                headerPath = hpath
396cdf0e10cSrcweir                break
397cdf0e10cSrcweir
398cdf0e10cSrcweir        if not headerPath:
399cdf0e10cSrcweir            error("included header file " + headerSub + " not found\n", self.stopOnHeader)
400cdf0e10cSrcweir            return
401ae54856bSPedro Giffuni
402cdf0e10cSrcweir        if self.debug:
403cdf0e10cSrcweir            progress ("%s found\n"%headerPath)
404cdf0e10cSrcweir
405cdf0e10cSrcweir        if headerPath in self.headerDict:
406cdf0e10cSrcweir            if self.debug:
407cdf0e10cSrcweir                progress ("%s already included\n"%headerPath)
408cdf0e10cSrcweir            return
409cdf0e10cSrcweir
410*7d9fa7c3SPedro Giffuni        if headerPath in SrcLexer.headerCache:
411cdf0e10cSrcweir            if self.debug:
412cdf0e10cSrcweir                progress ("%s in cache\n"%headerPath)
413*7d9fa7c3SPedro Giffuni            for key in list(SrcLexer.headerCache[headerPath].defines.keys()):
414cdf0e10cSrcweir                self.defines[key] = SrcLexer.headerCache[headerPath].defines[key]
415cdf0e10cSrcweir            return
416cdf0e10cSrcweir
417cdf0e10cSrcweir        chars = open(headerPath, 'r').read()
418cdf0e10cSrcweir        mclexer = SrcLexer(chars, headerPath)
419cdf0e10cSrcweir        mclexer.copyProperties(self)
420cdf0e10cSrcweir        mclexer.parentLexer = self
421cdf0e10cSrcweir        mclexer.tokenize()
422cdf0e10cSrcweir        hdrData = HeaderData()
423cdf0e10cSrcweir        hdrData.tokens = mclexer.getTokens()
424cdf0e10cSrcweir        headerDefines = mclexer.getDefines()
425*7d9fa7c3SPedro Giffuni        for key in list(headerDefines.keys()):
426cdf0e10cSrcweir            defines[key] = headerDefines[key]
427cdf0e10cSrcweir            hdrData.defines[key] = headerDefines[key]
428cdf0e10cSrcweir
429cdf0e10cSrcweir        self.headerDict[headerPath] = True
430cdf0e10cSrcweir        SrcLexer.headerCache[headerPath] = hdrData
431cdf0e10cSrcweir
432cdf0e10cSrcweir        # Update the list of headers that have already been expaneded.
433*7d9fa7c3SPedro Giffuni        for key in list(mclexer.headerDict.keys()):
434cdf0e10cSrcweir            self.headerDict[key] = True
435cdf0e10cSrcweir
436cdf0e10cSrcweir        if self.debug:
437cdf0e10cSrcweir            progress ("defines found in header %s:\n"%headerSub)
438*7d9fa7c3SPedro Giffuni            for key in list(defines.keys()):
439cdf0e10cSrcweir                progress ("  '%s'\n"%key)
440cdf0e10cSrcweir
441*7d9fa7c3SPedro Giffuni        for key in list(defines.keys()):
442cdf0e10cSrcweir            self.defines[key] = defines[key]
443cdf0e10cSrcweir
444cdf0e10cSrcweir
445cdf0e10cSrcweir    def slash (self, i):
446cdf0e10cSrcweir        if not self.isCodeVisible():
447cdf0e10cSrcweir            return i
448cdf0e10cSrcweir
449cdf0e10cSrcweir        if i < self.bufsize - 1 and self.chars[i+1] == '/':
450cdf0e10cSrcweir            # Parse line comment.
451cdf0e10cSrcweir            line = ''
452cdf0e10cSrcweir            i += 2
453cdf0e10cSrcweir            while i < self.bufsize:
454cdf0e10cSrcweir                c = self.chars[i]
455cdf0e10cSrcweir                if ord(c) in [0x0A, 0x0D]:
456cdf0e10cSrcweir                    return i - 1
457cdf0e10cSrcweir                line += c
458cdf0e10cSrcweir                i += 1
459cdf0e10cSrcweir            self.token = ''
460cdf0e10cSrcweir        elif i < self.bufsize - 1 and self.chars[i+1] == '*':
461cdf0e10cSrcweir            comment = ''
462cdf0e10cSrcweir            i += 2
463cdf0e10cSrcweir            while i < self.bufsize:
464cdf0e10cSrcweir                c = self.chars[i]
465cdf0e10cSrcweir                if c == '/' and self.chars[i-1] == '*':
466cdf0e10cSrcweir                    return i
467cdf0e10cSrcweir                comment += c
468cdf0e10cSrcweir                i += 1
469cdf0e10cSrcweir        else:
470cdf0e10cSrcweir            return self.anyToken(i, '/')
471cdf0e10cSrcweir
472cdf0e10cSrcweir        return i
473cdf0e10cSrcweir
474cdf0e10cSrcweir
475cdf0e10cSrcweir    def lineBreak (self, i):
476cdf0e10cSrcweir        if not self.isCodeVisible():
477cdf0e10cSrcweir            return i
478cdf0e10cSrcweir
479cdf0e10cSrcweir        self.maybeAddToken()
480cdf0e10cSrcweir
481cdf0e10cSrcweir        return i
482cdf0e10cSrcweir
483cdf0e10cSrcweir
484cdf0e10cSrcweir    def doubleQuote (self, i):
485cdf0e10cSrcweir        if not self.isCodeVisible():
486cdf0e10cSrcweir            return i
487cdf0e10cSrcweir
488cdf0e10cSrcweir        literal = ''
489cdf0e10cSrcweir        i += 1
490cdf0e10cSrcweir        while i < self.bufsize:
491cdf0e10cSrcweir            c = self.chars[i]
492cdf0e10cSrcweir            if c == '"':
493cdf0e10cSrcweir                self.tokens.append('"'+literal+'"')
494cdf0e10cSrcweir                break
495cdf0e10cSrcweir            literal += c
496cdf0e10cSrcweir            i += 1
497cdf0e10cSrcweir
498cdf0e10cSrcweir        return i
499cdf0e10cSrcweir
500cdf0e10cSrcweir
501cdf0e10cSrcweir    def anyToken (self, i, token):
502cdf0e10cSrcweir        if not self.isCodeVisible():
503cdf0e10cSrcweir            return i
504cdf0e10cSrcweir
505cdf0e10cSrcweir        self.maybeAddToken()
506cdf0e10cSrcweir        self.token = token
507cdf0e10cSrcweir        self.maybeAddToken()
508cdf0e10cSrcweir        return i
509