Deprecated Output
I have turned off the Lua filter discussed in this post. It was running everytime I rendered/published the blog. I have copy-pasted the original output for reference.
In Executable Rust Code in Quarto I made a rough implementation of having Rust code compiled and its output rendered.
With some small adjustments we can do the same for other languages, including C.
Here is the Lua filter:
local io = require("io")
local os = require("os")
local tempfile = require("os").tmpname
local log_file
-- Function to initialize the log file
local function init_log()
log_file = io.open("c_executor_debug.log", "w")
end
-- Function to log messages to file and stderr
local function log(...)
local args = {...}
for i = 1, #args do
args[i] = tostring(args[i])
end
local message = table.concat(args, " ")
if log_file then
log_file:write(message .. "\n")
log_file:flush()
end
io.stderr:write(message .. "\n")
io.stderr:flush()
end
-- Helper function to execute C code and return the output
local function execute_c_code(code)
local temp_file = tempfile() .. ".c"
("Temporary C file:", temp_file)
loglocal source_file, err = io.open(temp_file, "w")
if not source_file then
("Failed to create source file:", err)
logerror("Failed to create source file: " .. err)
end
source_file:write(code)
source_file:close()
local temp_bin = tempfile()
("Temporary binary file:", temp_bin)
log
local compile_command = "gcc " .. temp_file .. " -o " .. temp_bin .. " 2>&1"
("Compile Command:", compile_command)
loglocal compile_pipe = io.popen(compile_command)
local compile_output = compile_pipe:read("*a")
local compile_result = compile_pipe:close()
if compile_result ~= true then
os.remove(temp_file)
("C compilation failed. Output:", compile_output)
logerror("C compilation failed. Output: " .. compile_output)
end
local exec_command = temp_bin .. " 2>&1"
("Exec Command:", exec_command)
loglocal exec_pipe = io.popen(exec_command)
local output = exec_pipe:read("*a")
exec_pipe:close()
local ok, rm_err = pcall(function()
os.remove(temp_file)
os.remove(temp_bin)
end)
if not ok then
("Failed to clean up temporary files:", rm_err)
logerror("Failed to clean up temporary files: " .. rm_err)
end
("Output:", output)
logreturn output
end
local echo_global = true
function Meta(meta)
if meta.echo ~= nil then
echo_global = pandoc.utils.stringify(meta.echo) == "true"
end
end
-- Lua filter function
function CodeBlock(elem)
if not log_file then
()
init_logend
local is_c_code = elem.attr.classes:includes("{c}")
if is_c_code then
("Processing C code block")
loglocal output = execute_c_code(elem.text)
output = output:gsub("%s+$", "")
local blocks = {}
if echo_global then
-- Render C code as a formatted block
table.insert(blocks, pandoc.CodeBlock(elem.text, {class="c"}))
end
-- Always return the output
table.insert(blocks, pandoc.Para(pandoc.Str(output)))
return blocks
else
("Skipping non-C code block")
logend
end
-- Ensure log file is closed properly at the end
function Pandoc(doc)
if log_file then
log_file:close()
end
return doc
end
Here is a “Hello, World” example.
#include <stdio.h>
int main() {
("Hello, World!\n");
printfreturn 0;
}
Hello, World!
Similar to the lessons learned from the Rust implementation, there is plausibly a better implementation with an entirely different starting point.