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