Skip to content

Commit f2ea896

Browse files
committed
Added detection of runtime macros
Added logger Switched to C++20 Fixes #6
1 parent 5005623 commit f2ea896

File tree

7 files changed

+122
-10
lines changed

7 files changed

+122
-10
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ message("COMPILER USED: '${CMAKE_CXX_COMPILER_ID}'")
1717

1818
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/release")
1919

20-
set(CMAKE_CXX_STANDARD 17)
20+
set(CMAKE_CXX_STANDARD 20)
2121
set(CMAKE_CXX_STANDARD_REQUIRED ON)
2222
set(CMAKE_CXX_EXTENSIONS OFF)
2323

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ Create `sqfc.json` in current working directory
2929
"workerThreads": 8,
3030
"rootPathMappings": [
3131
["T:/", "\\"]
32-
]
32+
],
33+
"logging": {
34+
"verbose": false
35+
}
3336
}
3437
```

src/logger.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "logger.hpp"
2+
#include <mutex>
3+
#include <iostream>
4+
5+
6+
std::mutex loggerMutex;
7+
8+
void LoggerBogger::Log(LogLevel level, const std::string& msg)
9+
{
10+
if (level == LogLevel::Verbose && !m_EnableVerbose)
11+
return;
12+
13+
std::lock_guard m(loggerMutex);
14+
15+
std::cout << msg.c_str() << "\n";
16+
}

src/logger.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
#include <string>
3+
4+
enum class LogLevel
5+
{
6+
Normal,
7+
Verbose
8+
};
9+
10+
class LoggerBogger // Weird name because SQF-VM also has class Logger, without namespace (most of its stuff is in namespace, just not that)
11+
{
12+
public:
13+
//#TODO in-place formatting, vsnprintf
14+
//#TODO multithreading queue instead of locking
15+
16+
//! This function might be hit by multiple threads
17+
void Log(LogLevel level, const std::string& msg);
18+
19+
bool m_EnableVerbose = false;
20+
};
21+
22+
inline LoggerBogger GLogger;

src/main.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <json.hpp>
2020
#include "luaHandler.hpp"
21+
#include "logger.hpp"
2122

2223
std::queue<std::filesystem::path> tasks;
2324
std::mutex taskMutex;
@@ -149,8 +150,6 @@ int main(int argc, char* argv[]) {
149150
return 0; //#TODO return real error state if any script failed
150151
}
151152

152-
153-
154153
if (!std::filesystem::exists("sqfc.json")) {
155154
std::cout << "Missing sqfc.json in current working directory" << "\n";
156155
return 1;
@@ -205,6 +204,15 @@ int main(int argc, char* argv[]) {
205204
}
206205
}
207206

207+
// Logging
208+
209+
210+
if (auto loggingConfig = json["logging"]; !loggingConfig.is_null())
211+
{
212+
if (auto verboseCfg = loggingConfig["verbose"]; verboseCfg.is_boolean())
213+
GLogger.m_EnableVerbose = verboseCfg;
214+
}
215+
208216

209217

210218
// Setup workers

src/scriptCompiler.cpp

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
#include <iostream>
77
#include <mutex>
8+
#include <format>
9+
#include "logger.hpp"
810
#include "optimizer/optimizerModuleBase.hpp"
911
#include "optimizer/optimizer.h"
1012
#include "scriptSerializer.hpp"
@@ -15,6 +17,7 @@
1517
#include "parser/preprocessor/default.h"
1618
#include "parser/sqf/parser.tab.hh"
1719
#include "runtime/d_string.h"
20+
#include "runtime/logging.h"
1821

1922
std::once_flag commandMapInitFlag;
2023

@@ -61,10 +64,70 @@ void ScriptCompiler::init()
6164
const ::sqf::runtime::diagnostics::diag_info dinf,
6265
const ::sqf::runtime::fileio::pathinfo location,
6366
const std::string& data) -> std::string
64-
{
65-
ignoreCurrentFile = true;
66-
return {}; // string return type is wrong, isn't used for anything
67-
} });
67+
{
68+
if (ignoreCurrentFile)
69+
return {};
70+
71+
GLogger.Log(LogLevel::Verbose, std::format("File '{}' skipped because it uses pragma ASC_ignoreFile", location.virtual_));
72+
73+
ignoreCurrentFile = true;
74+
return {}; // string return type is wrong, isn't used for anything
75+
} });
76+
77+
// Handle macros that must be resolved at game start time and cannot be precompiled
78+
auto runtimeMacroCallback = [this](const sqf::runtime::parser::macro& m,
79+
const ::sqf::runtime::diagnostics::diag_info dinf,
80+
const ::sqf::runtime::fileio::pathinfo location,
81+
const std::vector<std::string>& params,
82+
::sqf::runtime::runtime& runtime) -> std::string
83+
{
84+
if (ignoreCurrentFile)
85+
return {};
86+
87+
GLogger.Log(LogLevel::Verbose, std::format("File '{}' skipped because it uses runtime-only macro '{}'", location.virtual_, m.name()));
88+
89+
ignoreCurrentFile = true;
90+
return {};
91+
};
92+
93+
// https://community.bistudio.com/wiki/PreProcessor_Commands#has_include
94+
for (auto& it : {
95+
"__has_include",
96+
"__DATE_ARR__",
97+
"__DATE_STR__",
98+
"__DATE_STR_ISO8601__",
99+
"__TIME__",
100+
"__TIME_UTC__",
101+
"__DAY__",
102+
"__MONTH__",
103+
"__YEAR__",
104+
"__TIMESTAMP_UTC__",
105+
106+
// We could support these, shouldn't make a different, random number is random
107+
"__RAND_INT8__",
108+
"__RAND_INT16__",
109+
"__RAND_INT32__",
110+
"__RAND_INT64__",
111+
"__RAND_UINT8__",
112+
"__RAND_UINT16__",
113+
"__RAND_UINT32__",
114+
"__RAND_UINT64__"
115+
// SQF-VM supports these, but it sets wrong values. We want runtime ones.
116+
"__GAME_VER__",
117+
"__GAME_VER_MAJ__",
118+
"__GAME_VER_MIN__",
119+
"__GAME_BUILD__",
120+
121+
"__A3_DIAG__",
122+
"__A3_DEBUG__",
123+
"__A3_EXPERIMENTAL__",
124+
"__A3_PROFILING__"
125+
})
126+
addMacro({ it, runtimeMacroCallback });
127+
128+
addMacro({ "__ARMA__", "1" }); // Only A3 has bytecode
129+
addMacro({ "__ARMA3__", "1" }); // Only A3 has bytecode
130+
68131
}
69132

70133
ScriptCompiler::ScriptCompiler(const std::vector<std::filesystem::path>& includePaths) {
@@ -116,7 +179,6 @@ CompiledCodeData ScriptCompiler::compileScript(std::filesystem::path physicalPat
116179

117180
if (ignoreCurrentFile)
118181
{
119-
std::cout << "File " << physicalPath.generic_string() << " skipped due to ASC_ignoreFile pragma\n";
120182
ignoreCurrentFile = false;
121183
return CompiledCodeData();
122184
}

src/scriptSerializer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,10 @@ void ScriptSerializer::compiledToBinaryCompressed(const CompiledCodeData& code,
278278

279279
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
280280
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT> {
281+
using base = std::basic_streambuf<CharT, TraitsT>;
281282
public:
282283
vectorwrapbuf(std::vector<CharT>& vec) {
283-
setg(vec.data(), vec.data(), vec.data() + vec.size());
284+
base::setg(vec.data(), vec.data(), vec.data() + vec.size());
284285
}
285286
};
286287

0 commit comments

Comments
 (0)