17db96d56Sopenharmony_ciimport os.path
27db96d56Sopenharmony_ciimport re
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_cifrom . import common as _common
57db96d56Sopenharmony_ci
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ciTOOL = 'gcc'
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci# https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
107db96d56Sopenharmony_ciLINE_MARKER_RE = re.compile(r'^# (\d+) "([^"]+)"(?: [1234])*$')
117db96d56Sopenharmony_ciPREPROC_DIRECTIVE_RE = re.compile(r'^\s*#\s*(\w+)\b.*')
127db96d56Sopenharmony_ciCOMPILER_DIRECTIVE_RE = re.compile(r'''
137db96d56Sopenharmony_ci    ^
147db96d56Sopenharmony_ci    (.*?)  # <before>
157db96d56Sopenharmony_ci    (__\w+__)  # <directive>
167db96d56Sopenharmony_ci    \s*
177db96d56Sopenharmony_ci    [(] [(]
187db96d56Sopenharmony_ci    (
197db96d56Sopenharmony_ci        [^()]*
207db96d56Sopenharmony_ci        (?:
217db96d56Sopenharmony_ci            [(]
227db96d56Sopenharmony_ci            [^()]*
237db96d56Sopenharmony_ci            [)]
247db96d56Sopenharmony_ci            [^()]*
257db96d56Sopenharmony_ci         )*
267db96d56Sopenharmony_ci     )  # <args>
277db96d56Sopenharmony_ci    ( [)] [)] )?  # <closed>
287db96d56Sopenharmony_ci''', re.VERBOSE)
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ciPOST_ARGS = (
317db96d56Sopenharmony_ci    '-pthread',
327db96d56Sopenharmony_ci    '-std=c99',
337db96d56Sopenharmony_ci    #'-g',
347db96d56Sopenharmony_ci    #'-Og',
357db96d56Sopenharmony_ci    #'-Wno-unused-result',
367db96d56Sopenharmony_ci    #'-Wsign-compare',
377db96d56Sopenharmony_ci    #'-Wall',
387db96d56Sopenharmony_ci    #'-Wextra',
397db96d56Sopenharmony_ci    '-E',
407db96d56Sopenharmony_ci)
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_cidef preprocess(filename, incldirs=None, macros=None, samefiles=None):
447db96d56Sopenharmony_ci    text = _common.preprocess(
457db96d56Sopenharmony_ci        TOOL,
467db96d56Sopenharmony_ci        filename,
477db96d56Sopenharmony_ci        incldirs=incldirs,
487db96d56Sopenharmony_ci        macros=macros,
497db96d56Sopenharmony_ci        #preargs=PRE_ARGS,
507db96d56Sopenharmony_ci        postargs=POST_ARGS,
517db96d56Sopenharmony_ci        executable=['gcc'],
527db96d56Sopenharmony_ci        compiler='unix',
537db96d56Sopenharmony_ci    )
547db96d56Sopenharmony_ci    return _iter_lines(text, filename, samefiles)
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ci
577db96d56Sopenharmony_cidef _iter_lines(text, filename, samefiles, *, raw=False):
587db96d56Sopenharmony_ci    lines = iter(text.splitlines())
597db96d56Sopenharmony_ci
607db96d56Sopenharmony_ci    # Build the lines and filter out directives.
617db96d56Sopenharmony_ci    partial = 0  # depth
627db96d56Sopenharmony_ci    origfile = None
637db96d56Sopenharmony_ci    for line in lines:
647db96d56Sopenharmony_ci        m = LINE_MARKER_RE.match(line)
657db96d56Sopenharmony_ci        if m:
667db96d56Sopenharmony_ci            lno, origfile = m.groups()
677db96d56Sopenharmony_ci            lno = int(lno)
687db96d56Sopenharmony_ci        elif _filter_orig_file(origfile, filename, samefiles):
697db96d56Sopenharmony_ci            if (m := PREPROC_DIRECTIVE_RE.match(line)):
707db96d56Sopenharmony_ci                name, = m.groups()
717db96d56Sopenharmony_ci                if name != 'pragma':
727db96d56Sopenharmony_ci                    raise Exception(line)
737db96d56Sopenharmony_ci            else:
747db96d56Sopenharmony_ci                if not raw:
757db96d56Sopenharmony_ci                    line, partial = _strip_directives(line, partial=partial)
767db96d56Sopenharmony_ci                yield _common.SourceLine(
777db96d56Sopenharmony_ci                    _common.FileInfo(filename, lno),
787db96d56Sopenharmony_ci                    'source',
797db96d56Sopenharmony_ci                    line or '',
807db96d56Sopenharmony_ci                    None,
817db96d56Sopenharmony_ci                )
827db96d56Sopenharmony_ci            lno += 1
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_cidef _strip_directives(line, partial=0):
867db96d56Sopenharmony_ci    # We assume there are no string literals with parens in directive bodies.
877db96d56Sopenharmony_ci    while partial > 0:
887db96d56Sopenharmony_ci        if not (m := re.match(r'[^{}]*([()])', line)):
897db96d56Sopenharmony_ci            return None, partial
907db96d56Sopenharmony_ci        delim, = m.groups()
917db96d56Sopenharmony_ci        partial += 1 if delim == '(' else -1  # opened/closed
927db96d56Sopenharmony_ci        line = line[m.end():]
937db96d56Sopenharmony_ci
947db96d56Sopenharmony_ci    line = re.sub(r'__extension__', '', line)
957db96d56Sopenharmony_ci
967db96d56Sopenharmony_ci    while (m := COMPILER_DIRECTIVE_RE.match(line)):
977db96d56Sopenharmony_ci        before, _, _, closed = m.groups()
987db96d56Sopenharmony_ci        if closed:
997db96d56Sopenharmony_ci            line = f'{before} {line[m.end():]}'
1007db96d56Sopenharmony_ci        else:
1017db96d56Sopenharmony_ci            after, partial = _strip_directives(line[m.end():], 2)
1027db96d56Sopenharmony_ci            line = f'{before} {after or ""}'
1037db96d56Sopenharmony_ci            if partial:
1047db96d56Sopenharmony_ci                break
1057db96d56Sopenharmony_ci
1067db96d56Sopenharmony_ci    return line, partial
1077db96d56Sopenharmony_ci
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_cidef _filter_orig_file(origfile, current, samefiles):
1107db96d56Sopenharmony_ci    if origfile == current:
1117db96d56Sopenharmony_ci        return True
1127db96d56Sopenharmony_ci    if origfile == '<stdin>':
1137db96d56Sopenharmony_ci        return True
1147db96d56Sopenharmony_ci    if os.path.isabs(origfile):
1157db96d56Sopenharmony_ci        return False
1167db96d56Sopenharmony_ci
1177db96d56Sopenharmony_ci    for filename in samefiles or ():
1187db96d56Sopenharmony_ci        if filename.endswith(os.path.sep):
1197db96d56Sopenharmony_ci            filename += os.path.basename(current)
1207db96d56Sopenharmony_ci        if origfile == filename:
1217db96d56Sopenharmony_ci            return True
1227db96d56Sopenharmony_ci
1237db96d56Sopenharmony_ci    return False
124