add pdf generation
This commit is contained in:
parent
7b622c2577
commit
abfb65c7d4
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/latex
|
||||
/build
|
||||
/pdf
|
||||
.obsidian
|
||||
.trash
|
||||
9
converters/bookletify.latex
Normal file
9
converters/bookletify.latex
Normal file
@ -0,0 +1,9 @@
|
||||
\documentclass[a4paper]{article}
|
||||
|
||||
\usepackage{pdfpages}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\includepdf[pages=-, nup=2x1, frame, signature*=4, landscape, angle=180]{?pdf?}
|
||||
|
||||
\end{document}
|
||||
644
converters/diagrams.lua
Normal file
644
converters/diagrams.lua
Normal file
@ -0,0 +1,644 @@
|
||||
--[[
|
||||
diagram – create images and figures from code blocks.
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright © 2019-2023 Albert Krewinkel
|
||||
Copyright © 2019 Thorsten Sommer
|
||||
Copyright © 2018 Florian Schätzig
|
||||
Copyright © 2018 John MacFarlane
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
]]
|
||||
-- The filter uses the Figure AST element, which was added in pandoc 3.
|
||||
PANDOC_VERSION:must_be_at_least '3.0'
|
||||
|
||||
local version = pandoc.types.Version '1.2.0'
|
||||
|
||||
-- Report Lua warnings to stderr if the `warn` function is not plugged into
|
||||
-- pandoc's logging system.
|
||||
if not warn then
|
||||
-- fallback
|
||||
warn = function(...) io.stderr:write(table.concat({ ... })) end
|
||||
elseif PANDOC_VERSION < '3.1.4' then
|
||||
-- starting with pandoc 3.1.4, warnings are reported to pandoc's logging
|
||||
-- system, so no need to print warnings to stderr.
|
||||
warn '@on'
|
||||
end
|
||||
|
||||
local io = require 'io'
|
||||
local pandoc = require 'pandoc'
|
||||
local system = require 'pandoc.system'
|
||||
local utils = require 'pandoc.utils'
|
||||
local List = require 'pandoc.List'
|
||||
local stringify = utils.stringify
|
||||
local with_temporary_directory = system.with_temporary_directory
|
||||
local with_working_directory = system.with_working_directory
|
||||
|
||||
--- Returns a filter-specific directory in which cache files can be
|
||||
--- stored, or nil if no such directory is available.
|
||||
local function cachedir ()
|
||||
local cache_home = os.getenv 'XDG_CACHE_HOME'
|
||||
if not cache_home or cache_home == '' then
|
||||
local user_home = system.os == 'windows'
|
||||
and os.getenv 'USERPROFILE'
|
||||
or os.getenv 'HOME'
|
||||
|
||||
if not user_home or user_home == '' then
|
||||
return nil
|
||||
end
|
||||
cache_home = pandoc.path.join{user_home, '.cache'} or nil
|
||||
end
|
||||
|
||||
-- Create filter cache directory
|
||||
return pandoc.path.join{cache_home, 'pandoc-diagram-filter'}
|
||||
end
|
||||
|
||||
--- Path holding the image cache, or `nil` if the cache is not used.
|
||||
local image_cache = nil
|
||||
|
||||
local mimetype_for_extension = {
|
||||
jpeg = 'image/jpeg',
|
||||
jpg = 'image/jpeg',
|
||||
pdf = 'application/pdf',
|
||||
png = 'image/png',
|
||||
svg = 'image/svg+xml',
|
||||
}
|
||||
|
||||
local extension_for_mimetype = {
|
||||
['application/pdf'] = 'pdf',
|
||||
['image/jpeg'] = 'jpg',
|
||||
['image/png'] = 'png',
|
||||
['image/svg+xml'] = 'svg',
|
||||
}
|
||||
|
||||
--- Converts a list of format specifiers to a set of MIME types.
|
||||
local function mime_types_set (tbl)
|
||||
local set = {}
|
||||
local mime_type
|
||||
for _, image_format_spec in ipairs(tbl) do
|
||||
mime_type = mimetype_for_extension[image_format_spec] or image_format_spec
|
||||
set[mime_type] = true
|
||||
end
|
||||
return set
|
||||
end
|
||||
|
||||
--- Reads the contents of a file.
|
||||
local function read_file (filepath)
|
||||
local fh = io.open(filepath, 'rb')
|
||||
local contents = fh:read('a')
|
||||
fh:close()
|
||||
return contents
|
||||
end
|
||||
|
||||
--- Writes the contents into a file at the given path.
|
||||
local function write_file (filepath, content)
|
||||
local fh = io.open(filepath, 'wb')
|
||||
fh:write(content)
|
||||
fh:close()
|
||||
end
|
||||
|
||||
--- Like `pandoc.pipe`, but allows "multi word" paths:
|
||||
-- Supplying a list as the first argument will use the first element as
|
||||
-- the executable path and prepend the remaining elements to the list of
|
||||
-- arguments.
|
||||
local function pipe (command, args, input)
|
||||
local cmd
|
||||
if pandoc.utils.type(command) == 'List' then
|
||||
command = command:map(stringify)
|
||||
cmd = command:remove(1)
|
||||
args = command .. args
|
||||
else
|
||||
cmd = stringify(command)
|
||||
end
|
||||
return pandoc.pipe(cmd, args, input)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Diagram Engines
|
||||
--
|
||||
|
||||
-- PlantUML engine; assumes that there's a `plantuml` binary.
|
||||
local plantuml = {
|
||||
line_comment_start = [[']],
|
||||
mime_types = mime_types_set{'pdf', 'png', 'svg'},
|
||||
compile = function (self, puml)
|
||||
local mime_type = self.mime_type or 'image/svg+xml'
|
||||
-- PlantUML format identifiers correspond to common file extensions.
|
||||
local format = extension_for_mimetype[mime_type]
|
||||
if not format then
|
||||
format, mime_type = 'svg', 'image/svg+xml'
|
||||
end
|
||||
local args = {'-t' .. format, "-pipe", "-charset", "UTF8"}
|
||||
return pipe(self.execpath or 'plantuml', args, puml), mime_type
|
||||
end,
|
||||
}
|
||||
|
||||
--- GraphViz engine for the dot language
|
||||
local graphviz = {
|
||||
line_comment_start = '//',
|
||||
mime_types = mime_types_set{'jpg', 'pdf', 'png', 'svg'},
|
||||
mime_type = 'image/svg+xml',
|
||||
compile = function (self, code)
|
||||
local mime_type = self.mime_type
|
||||
-- GraphViz format identifiers correspond to common file extensions.
|
||||
local format = extension_for_mimetype[mime_type]
|
||||
if not format then
|
||||
format, mime_type = 'svg', 'image/svg+xml'
|
||||
end
|
||||
return pipe(self.execpath or 'dot', {"-T"..format}, code), mime_type
|
||||
end,
|
||||
}
|
||||
|
||||
--- Mermaid engine
|
||||
local mermaid = {
|
||||
line_comment_start = '%%',
|
||||
mime_types = mime_types_set{'pdf', 'png', 'svg'},
|
||||
compile = function (self, code)
|
||||
local mime_type = self.mime_type or 'image/svg+xml'
|
||||
local file_extension = extension_for_mimetype[mime_type]
|
||||
return with_temporary_directory("diagram", function (tmpdir)
|
||||
return with_working_directory(tmpdir, function ()
|
||||
local infile = 'diagram.mmd'
|
||||
local outfile = 'diagram.' .. file_extension
|
||||
write_file(infile, code)
|
||||
pipe(
|
||||
self.execpath or 'mmdc',
|
||||
{"--pdfFit", "--input", infile, "--output", outfile},
|
||||
''
|
||||
)
|
||||
return read_file(outfile), mime_type
|
||||
end)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
--- TikZ
|
||||
--
|
||||
|
||||
--- LaTeX template used to compile TikZ images.
|
||||
local tikz_template = pandoc.template.compile [[
|
||||
\documentclass{standalone}
|
||||
\usepackage{tikz}
|
||||
$for(header-includes)$
|
||||
$it$
|
||||
$endfor$
|
||||
$additional-packages$
|
||||
\begin{document}
|
||||
$body$
|
||||
\end{document}
|
||||
]]
|
||||
|
||||
--- The TikZ engine uses pdflatex to compile TikZ code to an image
|
||||
local tikz = {
|
||||
line_comment_start = '%%',
|
||||
|
||||
mime_types = {
|
||||
['application/pdf'] = true,
|
||||
},
|
||||
|
||||
--- Compile LaTeX with TikZ code to an image
|
||||
compile = function (self, src, user_opts)
|
||||
return with_temporary_directory("tikz", function (tmpdir)
|
||||
return with_working_directory(tmpdir, function ()
|
||||
-- Define file names:
|
||||
local file_template = "%s/tikz-image.%s"
|
||||
local tikz_file = file_template:format(tmpdir, "tex")
|
||||
local pdf_file = file_template:format(tmpdir, "pdf")
|
||||
|
||||
-- Treat string values as raw LaTeX
|
||||
local meta = {
|
||||
['header-includes'] = user_opts['header-includes'],
|
||||
['additional-packages'] = {pandoc.RawInline(
|
||||
'latex',
|
||||
stringify(user_opts['additional-packages'] or '')
|
||||
)},
|
||||
}
|
||||
local tex_code = pandoc.write(
|
||||
pandoc.Pandoc({pandoc.RawBlock('latex', src)}, meta),
|
||||
'latex',
|
||||
{template = tikz_template}
|
||||
)
|
||||
write_file(tikz_file, tex_code)
|
||||
|
||||
-- Execute the LaTeX compiler:
|
||||
local success, result = pcall(
|
||||
pipe,
|
||||
self.execpath or 'pdflatex',
|
||||
{ '-interaction=nonstopmode', '-output-directory', tmpdir, tikz_file },
|
||||
''
|
||||
)
|
||||
if not success then
|
||||
warn(string.format(
|
||||
"The call\n%s\nfailed with error code %s. Output:\n%s",
|
||||
result.command,
|
||||
result.error_code,
|
||||
result.output
|
||||
))
|
||||
end
|
||||
return read_file(pdf_file), 'application/pdf'
|
||||
end)
|
||||
end)
|
||||
end
|
||||
}
|
||||
|
||||
--- Asymptote diagram engine
|
||||
local asymptote = {
|
||||
line_comment_start = '%%',
|
||||
mime_types = {
|
||||
['application/pdf'] = true,
|
||||
},
|
||||
compile = function (self, code)
|
||||
return with_temporary_directory("asymptote", function(tmpdir)
|
||||
return with_working_directory(tmpdir, function ()
|
||||
local pdf_file = "pandoc_diagram.pdf"
|
||||
local args = {'-tex', 'pdflatex', "-o", "pandoc_diagram", '-'}
|
||||
pipe(self.execpath or 'asy', args, code)
|
||||
return read_file(pdf_file), 'application/pdf'
|
||||
end)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
--- Cetz diagram engine
|
||||
local cetz = {
|
||||
line_comment_start = '%%',
|
||||
mime_types = mime_types_set{'jpg', 'pdf', 'png', 'svg'},
|
||||
mime_type = 'image/svg+xml',
|
||||
compile = function (self, code)
|
||||
local mime_type = self.mime_type
|
||||
local format = extension_for_mimetype[mime_type]
|
||||
if not format then
|
||||
format, mime_type = 'svg', 'image/svg+xml'
|
||||
end
|
||||
local preamble = [[
|
||||
#import "@preview/cetz:0.3.4"
|
||||
#set page(width: auto, height: auto, margin: .5cm)
|
||||
]]
|
||||
|
||||
local typst_code = preamble .. code
|
||||
|
||||
return with_temporary_directory("diagram", function (tmpdir)
|
||||
return with_working_directory(tmpdir, function ()
|
||||
local outfile = 'diagram.' .. format
|
||||
local execpath = self.execpath
|
||||
if not execpath and quarto and quarto.version >= '1.4' then
|
||||
-- fall back to the Typst exec shipped with Quarto.
|
||||
execpath = List{'quarto', 'typst'}
|
||||
end
|
||||
pipe(
|
||||
execpath or 'typst',
|
||||
{"compile", "-f", format, "-", outfile},
|
||||
typst_code
|
||||
)
|
||||
return read_file(outfile), mime_type
|
||||
end)
|
||||
end)
|
||||
end,
|
||||
}
|
||||
|
||||
local default_engines = {
|
||||
asymptote = asymptote,
|
||||
dot = graphviz,
|
||||
mermaid = mermaid,
|
||||
plantuml = plantuml,
|
||||
tikz = tikz,
|
||||
cetz = cetz,
|
||||
}
|
||||
|
||||
--
|
||||
-- Configuration
|
||||
--
|
||||
|
||||
--- Options for the output format of the given name.
|
||||
local function format_options (name)
|
||||
local pdf2svg = name ~= 'latex' and name ~= 'context'
|
||||
local is_office_format = name == 'docx' or name == 'odt'
|
||||
-- Office formats seem to work better with PNG than with SVG.
|
||||
local preferred_mime_types = is_office_format
|
||||
and pandoc.List{'image/png', 'application/pdf'}
|
||||
or pandoc.List{'application/pdf', 'image/png'}
|
||||
-- Prefer SVG for non-PDF output formats, except for Office formats
|
||||
if is_office_format then
|
||||
preferred_mime_types:insert('image/svg+xml')
|
||||
elseif pdf2svg then
|
||||
preferred_mime_types:insert(1, 'image/svg+xml')
|
||||
end
|
||||
return {
|
||||
name = name,
|
||||
pdf2svg = pdf2svg,
|
||||
preferred_mime_types = preferred_mime_types,
|
||||
best_mime_type = function (self, supported_mime_types, requested)
|
||||
return self.preferred_mime_types:find_if(function (preferred)
|
||||
return supported_mime_types[preferred] and
|
||||
(not requested or
|
||||
(pandoc.utils.type(requested) == 'List' and
|
||||
requested:includes(preferred)) or
|
||||
(pandoc.utils.type(requested) == 'table' and
|
||||
requested[preferred]) or
|
||||
|
||||
-- Assume string, Inlines, and Blocks values specify the only
|
||||
-- acceptable MIME type.
|
||||
stringify(requested) == preferred)
|
||||
end)
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
--- Returns a configured diagram engine.
|
||||
local function get_engine (name, engopts, format)
|
||||
local engine = default_engines[name] or
|
||||
select(2, pcall(require, stringify(engopts.package)))
|
||||
|
||||
-- Sanity check
|
||||
if not engine then
|
||||
warn(PANDOC_SCRIPT_FILE, ": No such engine '", name, "'.")
|
||||
return nil
|
||||
elseif engopts == false then
|
||||
-- engine is disabled
|
||||
return nil
|
||||
elseif engopts == true then
|
||||
-- use default options
|
||||
return engine
|
||||
end
|
||||
|
||||
local execpath = engopts.execpath or os.getenv(name:upper() .. '_BIN')
|
||||
|
||||
local mime_type = format:best_mime_type(
|
||||
engine.mime_types,
|
||||
engopts['mime-type'] or engopts['mime-types']
|
||||
)
|
||||
if not mime_type then
|
||||
warn(PANDOC_SCRIPT_FILE, ": Cannot use ", name, " with ", format.name)
|
||||
return nil
|
||||
end
|
||||
|
||||
return {
|
||||
execpath = execpath,
|
||||
compile = engine.compile,
|
||||
line_comment_start = engine.line_comment_start,
|
||||
mime_type = mime_type,
|
||||
opt = engopts or {},
|
||||
}
|
||||
end
|
||||
|
||||
--- Returns the diagram engine configs.
|
||||
local function configure (meta, format_name)
|
||||
local conf = meta.diagram or {}
|
||||
local format = format_options(format_name)
|
||||
meta.diagram = nil
|
||||
|
||||
-- cache for image files
|
||||
if conf.cache then
|
||||
image_cache = conf['cache-dir']
|
||||
and stringify(conf['cache-dir'])
|
||||
or cachedir()
|
||||
pandoc.system.make_directory(image_cache, true)
|
||||
end
|
||||
|
||||
-- engine configs
|
||||
local engine = {}
|
||||
for name, engopts in pairs(conf.engine or default_engines) do
|
||||
engine[name] = get_engine(name, engopts, format)
|
||||
end
|
||||
|
||||
return {
|
||||
engine = engine,
|
||||
format = format,
|
||||
cache = image_cache and true,
|
||||
image_cache = image_cache,
|
||||
}
|
||||
end
|
||||
|
||||
--
|
||||
-- Format conversion
|
||||
--
|
||||
|
||||
--- Converts a PDF to SVG.
|
||||
local pdf2svg = function (imgdata)
|
||||
-- Using `os.tmpname()` instead of a hash would be slightly cleaner, but the
|
||||
-- function causes problems on Windows (and wasm). See, e.g.,
|
||||
-- https://github.com/pandoc-ext/diagram/issues/49
|
||||
local pdf_file = 'diagram-' .. pandoc.utils.sha1(imgdata) .. '.pdf'
|
||||
write_file(pdf_file, imgdata)
|
||||
local args = {
|
||||
'--export-type=svg',
|
||||
'--export-plain-svg',
|
||||
'--export-filename=-',
|
||||
pdf_file
|
||||
}
|
||||
return pandoc.pipe('inkscape', args, ''), os.remove(pdf_file)
|
||||
end
|
||||
|
||||
local function properties_from_code (code, comment_start)
|
||||
local props = {}
|
||||
local pattern = comment_start:gsub('%p', '%%%1') .. '| ' ..
|
||||
'([-_%w]+): ([^\n]*)\n'
|
||||
for key, value in code:gmatch(pattern) do
|
||||
if key == 'fig-cap' then
|
||||
props['caption'] = value
|
||||
else
|
||||
props[key] = value
|
||||
end
|
||||
end
|
||||
return props
|
||||
end
|
||||
|
||||
local function diagram_options (cb, comment_start)
|
||||
local attribs = comment_start
|
||||
and properties_from_code(cb.text, comment_start)
|
||||
or {}
|
||||
for key, value in pairs(cb.attributes) do
|
||||
attribs[key] = value
|
||||
end
|
||||
|
||||
local alt
|
||||
local caption
|
||||
local fig_attr = {id = cb.identifier}
|
||||
local filename
|
||||
local image_attr = {}
|
||||
local user_opt = {}
|
||||
|
||||
for attr_name, value in pairs(attribs) do
|
||||
if attr_name == 'alt' then
|
||||
alt = value
|
||||
elseif attr_name == 'caption' then
|
||||
-- Read caption attribute as Markdown
|
||||
caption = attribs.caption
|
||||
and pandoc.read(attribs.caption).blocks
|
||||
or nil
|
||||
elseif attr_name == 'filename' then
|
||||
filename = value
|
||||
elseif attr_name == 'label' then
|
||||
fig_attr.id = value
|
||||
elseif attr_name == 'name' then
|
||||
fig_attr.name = value
|
||||
else
|
||||
-- Check for prefixed attributes
|
||||
local prefix, key = attr_name:match '^(%a+)%-(%a[-%w]*)$'
|
||||
if prefix == 'fig' then
|
||||
fig_attr[key] = value
|
||||
elseif prefix == 'image' or prefix == 'img' then
|
||||
image_attr[key] = value
|
||||
elseif prefix == 'opt' then
|
||||
user_opt[key] = value
|
||||
else
|
||||
-- Use as image attribute
|
||||
image_attr[attr_name] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
['alt'] = alt or
|
||||
(caption and pandoc.utils.blocks_to_inlines(caption)) or
|
||||
{},
|
||||
['caption'] = caption,
|
||||
['fig-attr'] = fig_attr,
|
||||
['filename'] = filename,
|
||||
['image-attr'] = image_attr,
|
||||
['opt'] = user_opt,
|
||||
}
|
||||
end
|
||||
|
||||
local function get_cached_image (hash, mime_type)
|
||||
if not image_cache then
|
||||
return nil
|
||||
end
|
||||
local filename = hash .. '.' .. extension_for_mimetype[mime_type]
|
||||
local imgpath = pandoc.path.join{image_cache, filename}
|
||||
local success, imgdata = pcall(read_file, imgpath)
|
||||
if success then
|
||||
return imgdata, mime_type
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function cache_image (codeblock, imgdata, mimetype)
|
||||
-- do nothing if caching is disabled or not possible.
|
||||
if not image_cache then
|
||||
return
|
||||
end
|
||||
local ext = extension_for_mimetype[mimetype]
|
||||
local filename = pandoc.sha1(codeblock.text) .. '.' .. ext
|
||||
local imgpath = pandoc.path.join{image_cache, filename}
|
||||
write_file(imgpath, imgdata)
|
||||
end
|
||||
|
||||
-- Executes each document's code block to find matching code blocks:
|
||||
local function code_to_figure (conf)
|
||||
return function (block)
|
||||
-- Check if a converter exists for this block. If not, return the block
|
||||
-- unchanged.
|
||||
local diagram_type = block.classes[1]
|
||||
if not diagram_type then
|
||||
return nil
|
||||
end
|
||||
|
||||
local engine = conf.engine[diagram_type]
|
||||
if not engine then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Unified properties.
|
||||
local dgr_opt = diagram_options(block, engine.line_comment_start)
|
||||
for optname, value in pairs(engine.opt or {}) do
|
||||
dgr_opt.opt[optname] = dgr_opt.opt[optname] or value
|
||||
end
|
||||
|
||||
local run_pdf2svg = engine.mime_type == 'application/pdf'
|
||||
and conf.format.pdf2svg
|
||||
|
||||
-- Try to retrieve the image data from the cache.
|
||||
local imgdata, imgtype
|
||||
if conf.cache then
|
||||
imgdata, imgtype = get_cached_image(
|
||||
pandoc.sha1(block.text),
|
||||
run_pdf2svg and 'image/svg+xml' or engine.mime_type
|
||||
)
|
||||
end
|
||||
|
||||
if not imgdata or not imgtype then
|
||||
-- No cached image; call the converter
|
||||
local success
|
||||
success, imgdata, imgtype =
|
||||
pcall(engine.compile, engine, block.text, dgr_opt.opt)
|
||||
|
||||
-- Bail if an error occurred; imgdata contains the error message
|
||||
-- when that happens.
|
||||
if not success then
|
||||
warn(PANDOC_SCRIPT_FILE, ': ', tostring(imgdata))
|
||||
return nil
|
||||
elseif not imgdata then
|
||||
warn(PANDOC_SCRIPT_FILE, ': Diagram engine returned no image data.')
|
||||
return nil
|
||||
elseif not imgtype then
|
||||
warn(PANDOC_SCRIPT_FILE, ': Diagram engine did not return a MIME type.')
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Convert SVG if necessary.
|
||||
if imgtype == 'application/pdf' and conf.format.pdf2svg then
|
||||
imgdata, imgtype = pdf2svg(imgdata), 'image/svg+xml'
|
||||
end
|
||||
|
||||
-- If we got here, then the transformation went ok and `img` contains
|
||||
-- the image data.
|
||||
cache_image(block, imgdata, imgtype)
|
||||
end
|
||||
|
||||
-- Use the block's filename attribute or create a new name by hashing the
|
||||
-- image content.
|
||||
local basename, _extension = pandoc.path.split_extension(
|
||||
dgr_opt.filename or pandoc.sha1(imgdata)
|
||||
)
|
||||
local fname = basename .. '.' .. extension_for_mimetype[imgtype]
|
||||
|
||||
-- Store the data in the media bag:
|
||||
pandoc.mediabag.insert(fname, imgtype, imgdata)
|
||||
|
||||
-- Create the image object.
|
||||
local image = pandoc.Image(dgr_opt.alt, fname, "", dgr_opt['image-attr'])
|
||||
|
||||
-- Create a figure if the diagram has a caption; otherwise return
|
||||
-- just the image.
|
||||
return dgr_opt.caption and
|
||||
pandoc.Figure(
|
||||
pandoc.Plain{image},
|
||||
dgr_opt.caption,
|
||||
dgr_opt['fig-attr']
|
||||
) or
|
||||
pandoc.Plain{image}
|
||||
end
|
||||
end
|
||||
|
||||
return setmetatable(
|
||||
{{
|
||||
Pandoc = function (doc)
|
||||
local conf = configure(doc.meta, FORMAT)
|
||||
return doc:walk {
|
||||
CodeBlock = code_to_figure(conf),
|
||||
}
|
||||
end
|
||||
}},
|
||||
{
|
||||
version = version,
|
||||
}
|
||||
)
|
||||
127
converters/include-files.lua
Normal file
127
converters/include-files.lua
Normal file
@ -0,0 +1,127 @@
|
||||
--- include-files.lua – filter to include Markdown files
|
||||
---
|
||||
--- Copyright: © 2019–2021 Albert Krewinkel
|
||||
--- License: MIT – see LICENSE file for details
|
||||
|
||||
-- Module pandoc.path is required and was added in version 2.12
|
||||
PANDOC_VERSION:must_be_at_least '2.12'
|
||||
|
||||
local List = require 'pandoc.List'
|
||||
local path = require 'pandoc.path'
|
||||
local system = require 'pandoc.system'
|
||||
|
||||
--- Get include auto mode
|
||||
local include_auto = false
|
||||
function get_vars (meta)
|
||||
if meta['include-auto'] then
|
||||
include_auto = true
|
||||
end
|
||||
end
|
||||
|
||||
--- Keep last heading level found
|
||||
local last_heading_level = 0
|
||||
function update_last_level(header)
|
||||
last_heading_level = header.level
|
||||
end
|
||||
|
||||
--- Update contents of included file
|
||||
local function update_contents(blocks, shift_by, include_path)
|
||||
local update_contents_filter = {
|
||||
-- Shift headings in block list by given number
|
||||
Header = function (header)
|
||||
if shift_by then
|
||||
header.level = header.level + shift_by
|
||||
end
|
||||
return header
|
||||
end,
|
||||
-- If link paths are relative then prepend include file path
|
||||
Link = function (link)
|
||||
if path.is_relative(link.target) and string.sub(path.filename(link.target), 1, 1) ~= '#' then
|
||||
link.target = path.normalize(path.join({include_path, link.target}))
|
||||
end
|
||||
return link
|
||||
end,
|
||||
-- If image paths are relative then prepend include file path
|
||||
Image = function (image)
|
||||
if path.is_relative(image.src) then
|
||||
image.src = path.normalize(path.join({include_path, image.src}))
|
||||
end
|
||||
return image
|
||||
end,
|
||||
-- Update path for include-code-files.lua filter style CodeBlocks
|
||||
CodeBlock = function (cb)
|
||||
if cb.attributes.include and path.is_relative(cb.attributes.include) then
|
||||
cb.attributes.include =
|
||||
path.normalize(path.join({include_path, cb.attributes.include}))
|
||||
end
|
||||
return cb
|
||||
end
|
||||
}
|
||||
|
||||
return pandoc.walk_block(pandoc.Div(blocks), update_contents_filter).content
|
||||
end
|
||||
|
||||
--- Filter function for code blocks
|
||||
local transclude
|
||||
function transclude (cb)
|
||||
-- ignore code blocks which are not of class "include".
|
||||
if not cb.classes:includes 'include' then
|
||||
return
|
||||
end
|
||||
|
||||
-- Markdown is used if this is nil.
|
||||
local format = cb.attributes['format']
|
||||
|
||||
-- Attributes shift headings
|
||||
local shift_heading_level_by = 0
|
||||
local shift_input = cb.attributes['shift-heading-level-by']
|
||||
if shift_input then
|
||||
shift_heading_level_by = tonumber(shift_input)
|
||||
else
|
||||
if include_auto then
|
||||
-- Auto shift headings
|
||||
shift_heading_level_by = last_heading_level
|
||||
end
|
||||
end
|
||||
|
||||
--- keep track of level before recusion
|
||||
local buffer_last_heading_level = last_heading_level
|
||||
|
||||
local blocks = List:new()
|
||||
for line in cb.text:gmatch('[^\n]+') do
|
||||
if line:sub(1,2) ~= '//' then
|
||||
local fh = io.open(line)
|
||||
if not fh then
|
||||
io.stderr:write("Cannot open file " .. line .. " | Skipping includes\n")
|
||||
else
|
||||
-- read file as the given format with global reader options
|
||||
local contents = pandoc.read(
|
||||
fh:read '*a',
|
||||
format,
|
||||
PANDOC_READER_OPTIONS
|
||||
).blocks
|
||||
last_heading_level = 0
|
||||
-- recursive transclusion
|
||||
contents = system.with_working_directory(
|
||||
path.directory(line),
|
||||
function ()
|
||||
return pandoc.walk_block(
|
||||
pandoc.Div(contents),
|
||||
{ Header = update_last_level, CodeBlock = transclude }
|
||||
)
|
||||
end).content
|
||||
--- reset to level before recursion
|
||||
last_heading_level = buffer_last_heading_level
|
||||
blocks:extend(update_contents(contents, shift_heading_level_by,
|
||||
path.directory(line)))
|
||||
fh:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
return blocks
|
||||
end
|
||||
|
||||
return {
|
||||
{ Meta = get_vars },
|
||||
{ Header = update_last_level, CodeBlock = transclude }
|
||||
}
|
||||
85
converters/mdToLatex.sh
Normal file
85
converters/mdToLatex.sh
Normal file
@ -0,0 +1,85 @@
|
||||
MD_FILE="$1"
|
||||
|
||||
BASE_DIR="$(pwd)"
|
||||
TEX_FILE="${BASE_DIR}/latex/$(basename "$MD_FILE" | sed -e 's/\.md$/.latex/')"
|
||||
BUILD_DIR="${BASE_DIR}/build/$(basename "$MD_FILE" | sed -e 's/\.md$//')"
|
||||
TEMP_MD_FILE="$BUILD_DIR/$(basename "$MD_FILE")"
|
||||
TEMP_TEX_FILE="$BUILD_DIR/$(basename "$MD_FILE" | sed -e 's|md$|latex|')"
|
||||
mkdir -p "$(dirname "$TEMP_MD_FILE")"
|
||||
|
||||
cp "$MD_FILE" "$TEMP_MD_FILE"
|
||||
|
||||
function download_images() {
|
||||
echo "download images for $1"
|
||||
for line in $(grep '!\[.*\](https://.*\.png)' "$1" | sed -e 's/ /%20;/g')
|
||||
do
|
||||
src=$(echo "$line" | sed -e 's/^.*(//' -e 's/).*$//' -e 's/%20;/ /g')
|
||||
echo "remote image found: $src"
|
||||
|
||||
mkdir -p "${BASE_DIR}/latex/images"
|
||||
name=$(echo "$src" | sed -e 's|^.*/\([^/]*\)$|\1|')
|
||||
curl "$src" > "${BASE_DIR}/latex/images/$name"
|
||||
done
|
||||
echo "download done"
|
||||
}
|
||||
|
||||
for line in $(grep '^!\[.*\](.*\.md)$' "$TEMP_MD_FILE" | sed -e 's/ /%20;/g')
|
||||
do
|
||||
md_src=$(echo "$line" | sed -e 's/^.*(//' -e 's/).*$//' -e 's/%20;/ /g')
|
||||
echo "include found: $md_src"
|
||||
|
||||
download_images "$(pwd)$md_src"
|
||||
|
||||
cp "$(pwd)$md_src" "$BUILD_DIR/$(basename "$md_src")"
|
||||
sed -i "$BUILD_DIR/$(basename "$md_src")" \
|
||||
-e 's|\[toc\]||' \
|
||||
-e 's|^\[parent\].*$||' \
|
||||
-e 's|^# |\\newpage\n# |' \
|
||||
-e 's|^## |\\newpage\n## |' \
|
||||
-e 's|\[\([^]]*\)\](#\([^)]*\))|[\1](#\L\2)|' \
|
||||
-e "s|https://live.kladjes.nl/uploads|${BASE_DIR}/latex/images|" \
|
||||
-e "s|\`\`\`mermaid|\`\`\`{.mermaid loc=${BASE_DIR}/latex/images/$(basename "$md_src")}|"
|
||||
|
||||
sed -i "$TEMP_MD_FILE" \
|
||||
-e "s|^\!\[.*\]($md_src)\$|\`\`\`\\{.include\\}\n$(basename "$md_src")\n\`\`\`|"
|
||||
|
||||
done
|
||||
|
||||
download_images "$TEMP_MD_FILE"
|
||||
|
||||
title="$(grep '^# ' "$MD_FILE" | head -n 1 | sed 's|^# ||')"
|
||||
|
||||
sed -i "$TEMP_MD_FILE" \
|
||||
-e 's|\[toc\]|\\tableofcontents|' \
|
||||
-e 's|^\[parent\].*$||' \
|
||||
-e 's|^# .*$||' \
|
||||
-e 's|^#||' \
|
||||
-e 's|^# |\\newpage\n# |' \
|
||||
-e 's|\[\([^]]*\)\](#\([^)]*\))|[\1](#\L\2)|' \
|
||||
-e "s|https://live.kladjes.nl/uploads|${BASE_DIR}/latex/images|" \
|
||||
-e "s|\`\`\`mermaid|\`\`\`{.mermaid loc=${BASE_DIR}/latex/images/$(basename "$MD_FILE")}|"
|
||||
|
||||
# -e 's|```\([^ \t]\)=|```\1 {linenumbers}|'
|
||||
|
||||
mkdir -p ${BASE_DIR}/latex/images/$(basename "$MD_FILE")
|
||||
cd "$BUILD_DIR"
|
||||
pandoc --lua-filter=../../converters/include-files.lua \
|
||||
--to=latex \
|
||||
--from=markdown+abbreviations \
|
||||
--template "${BASE_DIR}/converters/template.latex" \
|
||||
-o "$TEX_FILE" \
|
||||
--dpi 300 \
|
||||
"$(basename "$TEMP_MD_FILE")"
|
||||
cd "$BASE_DIR"
|
||||
|
||||
# for line in $(grep '^!\[.*\](.*\.md)$' "$TEMP_MD_FILE" | sed 's/ /%20;/g')
|
||||
# do
|
||||
# src=$(echo "$line" | sed -e 's/^.*(//' -e 's/).*$//' -e 's/%20;/ /g')
|
||||
|
||||
# sed -i "$TEMP_MD_FILE" \
|
||||
# -e "s/^!\[.*\]($src)\$/\\include{$src}/"
|
||||
# done
|
||||
|
||||
sed --in-place \
|
||||
-e "s|?title?|$title|" \
|
||||
"$TEX_FILE"
|
||||
142
converters/template.latex
Normal file
142
converters/template.latex
Normal file
@ -0,0 +1,142 @@
|
||||
\documentclass[11pt]{article}
|
||||
\usepackage[a4paper, portrait, includehead, includefoot, margin=1.5cm]{geometry}
|
||||
|
||||
\usepackage[english]{babel}
|
||||
|
||||
\usepackage{pdfpages}
|
||||
|
||||
\usepackage{xcolor}
|
||||
\usepackage{makecell}
|
||||
\usepackage{tabularx}
|
||||
\usepackage{adjustbox}
|
||||
|
||||
\usepackage{framed}
|
||||
|
||||
\usepackage{longtable}
|
||||
\providecommand{\tightlist}{\setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
|
||||
\usepackage{booktabs}
|
||||
|
||||
\usepackage{fontspec}
|
||||
\usepackage{xunicode}
|
||||
\usepackage{xltxtra}
|
||||
|
||||
\newfontfamily\fontRoboto[]{Roboto}
|
||||
\newfontfamily\fontUbuntu[]{Ubuntu}
|
||||
\setmainfont{Roboto}
|
||||
|
||||
% \usepackage[style=ieee]{biblatex}
|
||||
% \usepackage{csquotes}
|
||||
% \addbibresource{bibliography.bib}
|
||||
|
||||
% header and footer
|
||||
\usepackage{fancyhdr}
|
||||
\renewcommand{\headrule}{}
|
||||
|
||||
\usepackage[nodayofweek]{datetime}
|
||||
|
||||
\definecolor{darkishyellow}{rgb}{177, 179, 173}
|
||||
|
||||
% for images
|
||||
\usepackage{graphbox}
|
||||
\usepackage{sectsty}
|
||||
\sectionfont{\clearpage}
|
||||
|
||||
\setkeys{Gin}{width=.99\linewidth}
|
||||
|
||||
% add bookmarks with \hypertarget
|
||||
\usepackage{bookmark}
|
||||
\usepackage{hyperref}
|
||||
|
||||
% heading numberging
|
||||
\setcounter{secnumdepth}{3}
|
||||
\renewcommand\thesection{{\fontUbuntu\arabic{section}}}
|
||||
\renewcommand\thesubsection{{\fontUbuntu\arabic{section}.\arabic{subsection}}}
|
||||
\renewcommand\thesubsubsection{{\fontUbuntu\arabic{section}.\arabic{subsection}.\arabic{subsubsection}}}
|
||||
\usepackage{sectsty}
|
||||
\allsectionsfont{\fontUbuntu}
|
||||
\setlength{\headheight}{14pt}
|
||||
|
||||
% no indent at paragraphs
|
||||
\usepackage{parskip}
|
||||
\usepackage{setspace}
|
||||
\setstretch{1.1}
|
||||
\let\tmpitem\itemize
|
||||
\let\tmpenditem\enditemize
|
||||
\renewenvironment{itemize}{\tmpitem\setlength\itemsep{-.4em}}{\tmpenditem}
|
||||
|
||||
$if(highlighting-macros)$
|
||||
$highlighting-macros$
|
||||
$endif$
|
||||
|
||||
\begin{document}
|
||||
\raggedright
|
||||
\pagecolor{darkishyellow}
|
||||
|
||||
\begin{titlepage}
|
||||
.
|
||||
\vskip 10em
|
||||
\begin{center}
|
||||
{\Huge\fontUbuntu ?title? \par}
|
||||
\vskip 3em
|
||||
{\huge\fontUbuntu $sub_title$ \par}
|
||||
\end{center}
|
||||
\null\vfill
|
||||
{
|
||||
\large
|
||||
\lineskip .75em
|
||||
\begin{tabular}{r l}
|
||||
Auther: $for(auther)$& $auther.name$ <$auther.email$> \\
|
||||
$endfor$\\
|
||||
Class code: & ELERTS10 \\\\
|
||||
Exported on: &\today
|
||||
|
||||
\end{tabular}
|
||||
}
|
||||
\end{titlepage}
|
||||
|
||||
\pagestyle{fancy}
|
||||
\fancyhead{} % clear all header fields
|
||||
\fancyhead[LO]{\color{gray}\fontUbuntu ?title?}
|
||||
\fancyhead[RO]{\color{gray}\fontUbuntu $sub_title$}
|
||||
\fancyfoot{} % clear all footer fields
|
||||
\fancyfoot[LO]{\color{gray}\fontUbuntu $for(auther)$$auther.name_short$${sep}, $endfor$}
|
||||
\fancyfoot[CO]{\color{gray}\fontUbuntu }
|
||||
\fancyfoot[RO]{\color{gray}\fontUbuntu \thepage}
|
||||
|
||||
|
||||
$if(lof)$
|
||||
\listoffigures
|
||||
$endif$
|
||||
$if(lot)$
|
||||
\listoftables
|
||||
$endif$
|
||||
$if(linestretch)$
|
||||
\setstretch{$linestretch$}
|
||||
$endif$
|
||||
|
||||
|
||||
$body$
|
||||
|
||||
|
||||
$if(nocite-ids)$
|
||||
\nocite{$for(nocite-ids)$$it$$sep$, $endfor$}
|
||||
$endif$
|
||||
$if(natbib)$
|
||||
$if(bibliography)$
|
||||
$if(biblio-title)$
|
||||
$if(has-chapters)$
|
||||
\renewcommand\bibname{$biblio-title$}
|
||||
$else$
|
||||
\renewcommand\refname{$biblio-title$}
|
||||
$endif$
|
||||
$endif$
|
||||
\bibliography{$for(bibliography)$$bibliography$$sep$,$endfor$}
|
||||
|
||||
$endif$
|
||||
$endif$
|
||||
$if(biblatex)$
|
||||
\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$
|
||||
|
||||
$endif$
|
||||
|
||||
\end{document}
|
||||
99
makefile
Normal file
99
makefile
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
all: all_booklets all_docduments
|
||||
|
||||
all_docduments: prepare pdf/assambly_report.pdf pdf/c_report.pdf
|
||||
all_booklets: prepare pdf/assambly_report.booklet.pdf pdf/c_report.booklet.pdf
|
||||
prepare:
|
||||
mkdir -p latex pdf
|
||||
|
||||
clean:
|
||||
rm -r build latex
|
||||
|
||||
clean_all:
|
||||
rm -r build latex pdf
|
||||
|
||||
install_arch:
|
||||
mkdir -p build/install
|
||||
pacman -Sy --noconfirm --needed curl unzip texlive-basic texlive-langeuropean pandoc
|
||||
|
||||
test -e build/install/ubuntu.zip || curl https://assets.ubuntu.com/v1/0cef8205-ubuntu-font-family-0.83.zip -o build/install/ubuntu.zip
|
||||
test -d build/install/ubuntu && rm -r build/install/ubuntu || echo
|
||||
mkdir build/install/ubuntu
|
||||
unzip build/install/ubuntu.zip -d build/install/ubuntu
|
||||
mkdir -p /usr/share/fonts/ubuntu
|
||||
cp build/install/ubuntu/ubuntu-font-family-0.83/*.ttf /usr/share/fonts/ubuntu/
|
||||
chmod 0775 /usr/share/fonts/ubuntu
|
||||
chmod 0664 /usr/share/fonts/ubuntu/*
|
||||
|
||||
test -e build/install/roboto.zip || curl https://dl.dafont.com/dl/?f=roboto -o build/install/roboto.zip
|
||||
test -d build/install/roboto && rm -r build/install/roboto || echo
|
||||
mkdir build/install/roboto
|
||||
unzip build/install/roboto.zip -d build/install/roboto
|
||||
mkdir -p /usr/share/fonts/roboto
|
||||
cp build/install/roboto/*.ttf /usr/share/fonts/roboto/
|
||||
chmod 0775 /usr/share/fonts/roboto
|
||||
chmod 0664 /usr/share/fonts/roboto/*
|
||||
|
||||
install_ubuntu:
|
||||
mkdir -p build/install
|
||||
apt-get update
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
curl unzip texlive texlive-lang-european texlive-lang-greek texlive-xetex pandoc
|
||||
|
||||
test -e build/install/ubuntu.zip || curl https://assets.ubuntu.com/v1/0cef8205-ubuntu-font-family-0.83.zip -o build/install/ubuntu.zip
|
||||
test -d build/install/ubuntu && rm -r build/install/ubuntu || echo
|
||||
mkdir build/install/ubuntu
|
||||
unzip build/install/ubuntu.zip -d build/install/ubuntu
|
||||
mkdir -p /usr/share/fonts/ubuntu
|
||||
cp build/install/ubuntu/ubuntu-font-family-0.83/*.ttf /usr/share/fonts/ubuntu/
|
||||
chmod 0775 /usr/share/fonts/ubuntu
|
||||
chmod 0664 /usr/share/fonts/ubuntu/*
|
||||
|
||||
test -e build/install/roboto.zip || curl https://dl.dafont.com/dl/?f=roboto -o build/install/roboto.zip
|
||||
test -d build/install/roboto && rm -r build/install/roboto || echo
|
||||
mkdir build/install/roboto
|
||||
unzip build/install/roboto.zip -d build/install/roboto
|
||||
mkdir -p /usr/share/fonts/roboto
|
||||
cp build/install/roboto/*.ttf /usr/share/fonts/roboto/
|
||||
chmod 0775 /usr/share/fonts/roboto
|
||||
chmod 0664 /usr/share/fonts/roboto/*
|
||||
|
||||
# =======================================
|
||||
# === latex generation ==================
|
||||
# =======================================
|
||||
|
||||
latex/assambly_report.latex: converters/mdToLatex.sh converters/template.latex report-1/*.md
|
||||
mkdir -p build/assambly_report
|
||||
bash converters/mdToLatex.sh report-1/assambly_report.md latex/assambly_report.latex
|
||||
|
||||
latex/c_report.latex: converters/mdToLatex.sh converters/template.latex report-1/*.md
|
||||
mkdir -p build/c_report
|
||||
bash converters/mdToLatex.sh report-1/c_report.md latex/c_report.latex
|
||||
|
||||
# =======================================
|
||||
# === pdf generation ====================
|
||||
# =======================================
|
||||
|
||||
pdf/assambly_report.pdf: latex/assambly_report.latex
|
||||
cd build/assambly_report && xelatex ../../latex/assambly_report.latex
|
||||
cd build/assambly_report && xelatex ../../latex/assambly_report.latex
|
||||
cd build/assambly_report && xelatex ../../latex/assambly_report.latex
|
||||
mv build/assambly_report/assambly_report.pdf pdf/assambly_report.pdf
|
||||
|
||||
pdf/assambly_report.booklet.pdf: converters/bookletify.latex pdf/assambly_report.pdf
|
||||
mkdir -p build/assambly_report.booklet
|
||||
sed -e 's|?pdf?|../../pdf/assambly_report.pdf|' converters/bookletify.latex >build/assambly_report.booklet/bookletify.latex
|
||||
pdflatex -interaction=nonstopmode -output-directory="build/assambly_report.booklet" "build/assambly_report.booklet/bookletify.latex"
|
||||
mv build/assambly_report.booklet/bookletify.pdf pdf/assambly_report.booklet.pdf
|
||||
|
||||
pdf/c_report.pdf: latex/c_report.latex
|
||||
cd build/c_report && xelatex ../../latex/c_report.latex
|
||||
cd build/c_report && xelatex ../../latex/c_report.latex
|
||||
cd build/c_report && xelatex ../../latex/c_report.latex
|
||||
mv build/c_report/c_report.pdf pdf/c_report.pdf
|
||||
|
||||
pdf/c_report.booklet.pdf: converters/bookletify.latex pdf/c_report.pdf
|
||||
mkdir -p build/c_report.booklet
|
||||
sed -e 's|?pdf?|../../pdf/c_report.pdf|' converters/bookletify.latex >build/c_report.booklet/bookletify.latex
|
||||
pdflatex -interaction=nonstopmode -output-directory="build/c_report.booklet" "build/c_report.booklet/bookletify.latex"
|
||||
mv build/c_report.booklet/bookletify.pdf pdf/c_report.booklet.pdf
|
||||
@ -1,12 +1,11 @@
|
||||
---
|
||||
path: /elektro/hr/rts10/
|
||||
tags: kladjes, elektro, elektro/hr, elektro/hr/rts10
|
||||
auther:
|
||||
- Finley van Reenen (0964590@hr.nl)
|
||||
auther_short: "E.L.F. van Reenen"
|
||||
---
|
||||
|
||||
# Assembly Assignments
|
||||
[parent](/lLnsoW2yQlWpblaVBRFsYw)
|
||||
|
||||
# Assembly Assignment
|
||||
|
||||
This is the first report for _realtime systems 10_. I needed to do the following assignments:
|
||||
|
||||
@ -38,7 +37,7 @@ I applied the same fix as last year. In the debug config, replace the `\` with a
|
||||
|
||||
The algorithm in question is given in C code.
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int multiply(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int m = 0;
|
||||
@ -52,7 +51,7 @@ unsigned int multiply(unsigned int a , unsigned int b)
|
||||
|
||||
This code can be simplified without changing the algorithm by replacing the variable `i` with `b`. This will result in the following code.
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int multiply(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int m = 0;
|
||||
@ -66,7 +65,7 @@ unsigned int multiply ( unsigned int a , unsigned int b)
|
||||
|
||||
This is also the code I have implemented. The compiler puts _a_ in `R0` and _b_ in `R1`, I accepted them in place and used `R2` for _m_. At the end _m_ (`R2`) is moved to `R0` to set it as the return value.
|
||||
|
||||
```ass=
|
||||
```asm {.numberLines}
|
||||
.cpu cortex-m4
|
||||
.thumb
|
||||
.syntax unified
|
||||
@ -88,7 +87,7 @@ mul_exit:
|
||||
|
||||
a better representation of the essembly code in C would be:
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int multiply(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int m = 0;
|
||||
@ -98,7 +97,7 @@ unsigned int multiply ( unsigned int a , unsigned int b)
|
||||
|
||||
do
|
||||
{
|
||||
m = m + b;
|
||||
m = m + a;
|
||||
b --;
|
||||
} while (b > 0)
|
||||
|
||||
@ -117,7 +116,7 @@ It does not take the branch at line 10 and at line 14 it takes the branch 65535
|
||||
|
||||
Now a smarter version.
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int multiply(unsigned int a , unsigned int b)
|
||||
{
|
||||
unsigned int m = 0;
|
||||
@ -134,7 +133,7 @@ unsigned int multiply(unsigned int a , unsigned int b)
|
||||
}
|
||||
```
|
||||
|
||||
```asm=
|
||||
```asm {.numberLines}
|
||||
.cpu cortex-m4
|
||||
.thumb
|
||||
.syntax unified
|
||||
@ -162,7 +161,7 @@ bmul_exit:
|
||||
|
||||
a better representation of the essembly code in C would be:
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int multiply(unsigned int a, unsigned int b)
|
||||
{
|
||||
unsigned int m = 0;
|
||||
@ -192,7 +191,7 @@ There are 7 instructions in the loop where one only runs every `1` bit in `b`. T
|
||||
|
||||
## Assignment 10: Using your multiply function to calculate the dot product of two vectors
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int dotProduct(unsigned int a[], unsigned int b[], size_t n)
|
||||
{
|
||||
unsigned int p = 0;
|
||||
@ -206,7 +205,7 @@ unsigned int dotProduct(unsigned int a[], unsigned int b[], size_t n)
|
||||
|
||||
This function needs to call another and remember 5 variables (`*a`, `*b`, `n`, `p` and `i`). `R0` through `R3` are expected to change with a function call. There are only `R4` through `R7` left, only four spots. To solve this problem, I reversed the for loop by using n and decrementing it. This will not change the result since addition is not order sensitive. The code I implemented is the following.
|
||||
|
||||
```c-like=
|
||||
```c {.numberLines}
|
||||
unsigned int dotProduct(unsigned int a[] , unsigned int b[], size_t n)
|
||||
{
|
||||
unsigned int p = 0;
|
||||
@ -225,7 +224,7 @@ unsigned int dotProduct(unsigned int a[] , unsigned int b[], size_t n)
|
||||
|
||||
My assembly code:
|
||||
|
||||
```asm=
|
||||
```asm {.numberLines}
|
||||
.cpu cortex-m4
|
||||
.thumb
|
||||
.syntax unified
|
||||
@ -252,5 +251,4 @@ dotp_loop:
|
||||
dotp_exit:
|
||||
MOVS.N R0, R7 // move m to R0
|
||||
POP.N {R4, R5, R6, R7, PC}
|
||||
BX.N LR
|
||||
```
|
||||
|
||||
16
report-1/assambly_report.md
Normal file
16
report-1/assambly_report.md
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
sub_title: "Real Time Systems 10"
|
||||
auther:
|
||||
- name: "Finley van Reenen (0964590)"
|
||||
email: "mail@lailatheelf.nl"
|
||||
name_short: "E.L.F. van Reenen"
|
||||
---
|
||||
|
||||
# Assambly Report
|
||||
|
||||
[toc]
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
@ -146,7 +146,9 @@ while ((FLASH->ACR & /* ... */ ) == 0);
|
||||
Finaly we configur the PLL itself.
|
||||
|
||||
$$
|
||||
f_{(VCO\ clock)} = f_{(PLL\ clock\ input)} \cdot (\frac{PLLN}{PLLM}) \\
|
||||
f_{(VCO\ clock)} = f_{(PLL\ clock\ input)} \cdot (\frac{PLLN}{PLLM})
|
||||
$$
|
||||
$$
|
||||
f_{(PLL\ general\ clock\ output)} = \frac{f_{(VCO\ clock)}}{PLLP}
|
||||
$$
|
||||
|
||||
|
||||
13
report-2/c_report.md
Normal file
13
report-2/c_report.md
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
sub_title: "Real Time Systems 10"
|
||||
auther:
|
||||
- name: "Finley van Reenen (0964590)"
|
||||
email: "mail@lailatheelf.nl"
|
||||
name_short: "E.L.F. van Reenen"
|
||||
---
|
||||
|
||||
# C Report
|
||||
|
||||
[toc]
|
||||
|
||||

|
||||
Loading…
x
Reference in New Issue
Block a user