|
45 | 45 | #include <unordered_set> |
46 | 46 | #include <variant> |
47 | 47 |
|
| 48 | +#include "cxx/preprocessor_fwd.h" |
48 | 49 | #include "pp_keywords-priv.h" |
49 | 50 |
|
50 | 51 | namespace { |
@@ -1004,13 +1005,6 @@ struct Preprocessor::Private { |
1004 | 1005 | return fs::exists(file); |
1005 | 1006 | } |
1006 | 1007 |
|
1007 | | - [[nodiscard]] auto readFile(const fs::path &file) const -> std::string { |
1008 | | - std::ifstream in(file); |
1009 | | - std::ostringstream out; |
1010 | | - out << in.rdbuf(); |
1011 | | - return out.str(); |
1012 | | - } |
1013 | | - |
1014 | 1008 | [[nodiscard]] auto checkHeaderProtection(TokList *ts) const -> TokList *; |
1015 | 1009 |
|
1016 | 1010 | [[nodiscard]] auto checkPragmaOnceProtected(TokList *ts) const -> bool; |
@@ -1193,9 +1187,6 @@ struct Preprocessor::Private { |
1193 | 1187 | [[nodiscard]] auto parseIncludeDirective(TokList *directive, TokList *ts) |
1194 | 1188 | -> std::optional<ParsedIncludeDirective>; |
1195 | 1189 |
|
1196 | | - [[nodiscard]] auto findOrCreateSourceFile(const std::string &fileName) |
1197 | | - -> SourceFile *; |
1198 | | - |
1199 | 1190 | [[nodiscard]] auto parseHeaderName(TokList *ts) |
1200 | 1191 | -> std::tuple<TokList *, std::optional<Include>>; |
1201 | 1192 |
|
@@ -1313,6 +1304,110 @@ struct Preprocessor::ParseArguments { |
1313 | 1304 | } |
1314 | 1305 | }; |
1315 | 1306 |
|
| 1307 | +void PendingInclude::resolveWith( |
| 1308 | + std::optional<std::string> resolvedFileName) const { |
| 1309 | + auto d = preprocessor.d.get(); |
| 1310 | + |
| 1311 | + if (!resolvedFileName.has_value()) { |
| 1312 | + const auto &header = getHeaderName(include); |
| 1313 | + d->error(static_cast<TokList *>(loc), |
| 1314 | + std::format("file '{}' not found", header)); |
| 1315 | + return; |
| 1316 | + } |
| 1317 | + |
| 1318 | + auto fileName = resolvedFileName.value(); |
| 1319 | + |
| 1320 | + auto resume = [=, this]() -> std::optional<PreprocessingState> { |
| 1321 | + auto sourceFile = d->findSourceFile(fileName); |
| 1322 | + if (!sourceFile) { |
| 1323 | + PendingFileContent request{ |
| 1324 | + .preprocessor = preprocessor, |
| 1325 | + .fileName = fileName, |
| 1326 | + }; |
| 1327 | + return request; |
| 1328 | + } |
| 1329 | + |
| 1330 | + if (sourceFile->pragmaOnceProtected) { |
| 1331 | + // nothing to do |
| 1332 | + return std::nullopt; |
| 1333 | + } |
| 1334 | + |
| 1335 | + if (auto it = d->ifndefProtectedFiles_.find(fileName); |
| 1336 | + it != d->ifndefProtectedFiles_.end() && |
| 1337 | + d->macros_.contains(it->second)) { |
| 1338 | + return std::nullopt; |
| 1339 | + } |
| 1340 | + |
| 1341 | + auto continuation = sourceFile; |
| 1342 | + if (!continuation) return std::nullopt; |
| 1343 | + |
| 1344 | + // make the continuation the current file |
| 1345 | + auto dirpath = fs::path(continuation->fileName); |
| 1346 | + dirpath.remove_filename(); |
| 1347 | + |
| 1348 | + d->buffers_.push_back(Preprocessor::Private::Buffer{ |
| 1349 | + .source = continuation, |
| 1350 | + .currentPath = dirpath, |
| 1351 | + .ts = continuation->tokens, |
| 1352 | + .includeDepth = d->includeDepth_ + 1, |
| 1353 | + }); |
| 1354 | + |
| 1355 | + if (d->willIncludeHeader_) { |
| 1356 | + d->willIncludeHeader_(fileName, d->includeDepth_ + 1); |
| 1357 | + } |
| 1358 | + |
| 1359 | + return std::nullopt; |
| 1360 | + }; |
| 1361 | + |
| 1362 | + auto sourceFile = d->findSourceFile(fileName); |
| 1363 | + if (sourceFile) { |
| 1364 | + resume(); |
| 1365 | + return; |
| 1366 | + } |
| 1367 | + |
| 1368 | + d->continuation_ = std::move(resume); |
| 1369 | +} |
| 1370 | + |
| 1371 | +void PendingFileContent::setContent(std::optional<std::string> content) const { |
| 1372 | + auto d = preprocessor.d.get(); |
| 1373 | + |
| 1374 | + if (!content.has_value()) { |
| 1375 | + // report error |
| 1376 | + return; |
| 1377 | + } |
| 1378 | + |
| 1379 | + auto sourceFile = d->createSourceFile(fileName, std::move(*content)); |
| 1380 | + |
| 1381 | + sourceFile->pragmaOnceProtected = |
| 1382 | + d->checkPragmaOnceProtected(sourceFile->tokens); |
| 1383 | + |
| 1384 | + sourceFile->headerProtection = d->checkHeaderProtection(sourceFile->tokens); |
| 1385 | + |
| 1386 | + if (sourceFile->headerProtection) { |
| 1387 | + sourceFile->headerProtectionLevel = d->evaluating_.size(); |
| 1388 | + |
| 1389 | + d->ifndefProtectedFiles_.insert_or_assign( |
| 1390 | + sourceFile->fileName, sourceFile->headerProtection->tok->text); |
| 1391 | + } |
| 1392 | + |
| 1393 | + auto continuation = sourceFile; |
| 1394 | + |
| 1395 | + // make the continuation the current file |
| 1396 | + auto dirpath = fs::path(continuation->fileName); |
| 1397 | + dirpath.remove_filename(); |
| 1398 | + |
| 1399 | + d->buffers_.push_back(Preprocessor::Private::Buffer{ |
| 1400 | + .source = continuation, |
| 1401 | + .currentPath = dirpath, |
| 1402 | + .ts = continuation->tokens, |
| 1403 | + .includeDepth = d->includeDepth_ + 1, |
| 1404 | + }); |
| 1405 | + |
| 1406 | + if (d->willIncludeHeader_) { |
| 1407 | + d->willIncludeHeader_(fileName, d->includeDepth_ + 1); |
| 1408 | + } |
| 1409 | +} |
| 1410 | + |
1316 | 1411 | Preprocessor::Private::Private() { |
1317 | 1412 | skipping_.push_back(false); |
1318 | 1413 | evaluating_.push_back(true); |
@@ -2021,43 +2116,6 @@ auto Preprocessor::Private::parseIncludeDirective(TokList *directive, |
2021 | 2116 | return std::nullopt; |
2022 | 2117 | } |
2023 | 2118 |
|
2024 | | -auto Preprocessor::Private::findOrCreateSourceFile(const std::string &fileName) |
2025 | | - -> SourceFile * { |
2026 | | - if (auto it = ifndefProtectedFiles_.find(fileName); |
2027 | | - it != ifndefProtectedFiles_.end() && macros_.contains(it->second)) { |
2028 | | - return nullptr; |
2029 | | - } |
2030 | | - |
2031 | | - auto sourceFile = findSourceFile(fileName); |
2032 | | - |
2033 | | - if (sourceFile && sourceFile->pragmaOnceProtected) { |
2034 | | - // nothing to do |
2035 | | - return nullptr; |
2036 | | - } |
2037 | | - |
2038 | | - if (!sourceFile) { |
2039 | | - sourceFile = createSourceFile(fileName, readFile(fileName)); |
2040 | | - |
2041 | | - sourceFile->pragmaOnceProtected = |
2042 | | - checkPragmaOnceProtected(sourceFile->tokens); |
2043 | | - |
2044 | | - sourceFile->headerProtection = checkHeaderProtection(sourceFile->tokens); |
2045 | | - |
2046 | | - if (sourceFile->headerProtection) { |
2047 | | - sourceFile->headerProtectionLevel = evaluating_.size(); |
2048 | | - |
2049 | | - ifndefProtectedFiles_.insert_or_assign( |
2050 | | - sourceFile->fileName, sourceFile->headerProtection->tok->text); |
2051 | | - } |
2052 | | - } |
2053 | | - |
2054 | | - if (willIncludeHeader_) { |
2055 | | - willIncludeHeader_(fileName, includeDepth_ + 1); |
2056 | | - } |
2057 | | - |
2058 | | - return sourceFile; |
2059 | | -} |
2060 | | - |
2061 | 2119 | auto Preprocessor::Private::parseHeaderName(TokList *ts) |
2062 | 2120 | -> std::tuple<TokList *, std::optional<Include>> { |
2063 | 2121 | if (lookat(ts, TokenKind::T_STRING_LITERAL)) { |
@@ -2932,43 +2990,6 @@ void Preprocessor::preprocess(std::string source, std::string fileName, |
2932 | 2990 | endPreprocessing(tokens); |
2933 | 2991 | } |
2934 | 2992 |
|
2935 | | -void PendingInclude::resolveWith(std::optional<std::string> fileName) const { |
2936 | | - auto d = preprocessor.d.get(); |
2937 | | - |
2938 | | - if (!fileName.has_value()) { |
2939 | | - const auto &header = getHeaderName(include); |
2940 | | - d->error(static_cast<TokList *>(loc), |
2941 | | - std::format("file '{}' not found", header)); |
2942 | | - return; |
2943 | | - } |
2944 | | - |
2945 | | - auto resume = [=]() -> std::optional<PreprocessingState> { |
2946 | | - auto continuation = d->findOrCreateSourceFile(*fileName); |
2947 | | - if (!continuation) return std::nullopt; |
2948 | | - |
2949 | | - // make the continuation the current file |
2950 | | - auto dirpath = fs::path(continuation->fileName); |
2951 | | - dirpath.remove_filename(); |
2952 | | - |
2953 | | - d->buffers_.push_back(Preprocessor::Private::Buffer{ |
2954 | | - .source = continuation, |
2955 | | - .currentPath = dirpath, |
2956 | | - .ts = continuation->tokens, |
2957 | | - .includeDepth = d->includeDepth_ + 1, |
2958 | | - }); |
2959 | | - |
2960 | | - return std::nullopt; |
2961 | | - }; |
2962 | | - |
2963 | | - auto sourceFile = d->findSourceFile(*fileName); |
2964 | | - if (sourceFile) { |
2965 | | - resume(); |
2966 | | - return; |
2967 | | - } |
2968 | | - |
2969 | | - d->continuation_ = std::move(resume); |
2970 | | -} |
2971 | | - |
2972 | 2993 | void Preprocessor::beginPreprocessing(std::string source, std::string fileName, |
2973 | 2994 | std::vector<Token> &tokens) { |
2974 | 2995 | assert(!d->findSourceFile(fileName)); |
@@ -3242,4 +3263,12 @@ void DefaultPreprocessorState::operator()(const PendingHasIncludes &status) { |
3242 | 3263 | }); |
3243 | 3264 | } |
3244 | 3265 |
|
| 3266 | +void DefaultPreprocessorState::operator()(const PendingFileContent &request) { |
| 3267 | + std::ifstream in(request.fileName); |
| 3268 | + std::ostringstream out; |
| 3269 | + out << in.rdbuf(); |
| 3270 | + |
| 3271 | + request.setContent(out.str()); |
| 3272 | +} |
| 3273 | + |
3245 | 3274 | } // namespace cxx |
0 commit comments