# Changelog
## 1.3.1.2 — no FFS packaging in the recipe
The recipe no longer `python_requires` ffs-packaging-tools (proprietary)
and the package no longer carries `manifest.fson`: the library knows
nothing of FFS. FFS's own packaging (`ws-package.py`) builds that file
list from the Conan package when it needs it.
## 1.3.1.1 — packaging metadata stays out of plain installs
`manifest.fson` (the Conan package's signing / file-list metadata) was a
CMake `install()` file in the runtime component, so `cmake --install` and
every CPack package put it into the prefix root — the same path for each
fedem library installed into one prefix, and a file conflict between
their RPM / DEB packages. conanfile.py `package()` now copies it; the
Conan package is unchanged.
## 1.3.1 — 2026-09-26
- `mstring_generate()` works from any build, not only inside Conan's
build environment. Measured in plugin with a plain `cmake --build`:
editing a `.msg` ran mstring, which failed with "libcparse.so.1: cannot
open shared object file" — the executable had no RUNPATH and relied on
`LD_LIBRARY_PATH`. The Conan package now ships `libcparse.so*` in `lib/`
and the executable's RUNPATH is `$ORIGIN/../lib`.
- Under Conan, `mstring_generate()` takes the tool_requires' own
executable on every configure. A cached `MSTRING_EXECUTABLE` used to
survive a package update whenever the old package folder still existed,
and kept running the previous mstring.
- The generated files are touched after each run. mstring leaves an
unchanged file alone, and Make, which has no "ran but unchanged"
(Ninja's restat), then re-ran mstring on every build after a `.msg`
was merely touched.
## 1.3.0 — 2026-09-26
- `$EXPORT MACRO`: a visibility macro before every generated class and
free-function declaration (shared libraries built with hidden visibility,
DLLs).
- `$EXCEPTION OVERRIDE name`: the exception implements its base's
`virtual std::string name( ) const noexcept` instead of `What()` /
`what()` — for an exception hierarchy whose base implements `what()`.
- Motivated by plugin's dsold, whose DSOExceptions / ExceptionMessages had
been generated once by hand-edited mstring output; they are now generated
at build time.
## 1.2.0 — 2026-09-26
- `$MESSAGE Name : STRING THROW` — the artefacts of one message, without
changing the sticky settings.
- Translation checks: a warning for a message missing a language other
messages have, and for a parameter one language uses and another does not.
- `-w` silences warnings; `mstring_generate( ... OPTIONS -w )`.
- `$CHARSET` and the charset of a `[language charset]` header are
deprecated (a warning): they only ever produced a comment.
- Removed the never-reachable parameter default value code.
- String, syslog and exception `What()` build their text directly into a
`std::string` instead of through a `std::ostringstream` — same text,
including the locale's number formatting. Per call (gcc 11, -O2, the
`bench/` messages): a two-parameter string 418 → 94 ns, a constant text
337 → 40 ns; the object file is smaller too.
- `$MODULE name INLINE`: a header-only module (all definitions `inline`,
helpers in a guarded shared namespace); `mstring_generate( ... INLINE )`.
`NOSOURCE` alone (declarations without definitions) is deprecated.
- `bench/` (`-DBENCH=ON`).
## 1.1.0 — 2026-09-26
The message-file parser is rewritten on cparse; the flex / bison front end
and the build dependency on them are gone. The input language is the same,
with the gaps below closed. Generated code now compiles as C++17 and C++20.
### Parser
- Diagnostics carry `file:line:column`; a message without text is warned
about; a duplicate message or parameter, a parameter after the texts and
a reserved parameter name are errors.
- `$CHARSET UTF-8`, `$LANGUAGE tr_TR.UTF-8` — names with `-`, `.` or `@`
were rejected.
- A `[language]` header without a charset resets the charset to `$CHARSET`
(it kept the previous header's).
- `MEMBER OF` accepts a qualified class name; `CONST` / `NONCONST` are
optional (the default is `CONST`), as documented.
- `$SYSLOG FACILITY AUTH` means `LOG_AUTH` (it gave `LOG_AUTHPRIV`).
- A `#` comment after a text line or a directive no longer swallows the
line end; CRLF files and a missing final newline are accepted.
- Macros: nested braces, `\;` / `\}` anywhere in the expression; `\{`
writes a literal `{`. `\\` is one backslash (it became an escape of the
next character in the generated literal). Octal and hex escapes are
handled explicitly.
- `$IMPORT`: searched next to the importing file first; the name may be
quoted and trailing blanks are ignored; recursive imports are reported;
an imported file no longer continues the importer's message.
- Directive and option names are case-insensitive; several options may
share a line.
- `-I a:b` split the list wrongly (it dropped characters); `-I` may be
repeated; `-` reads standard input; `-v` prints the version.
### Generated code
- No dynamic exception specifications (`throw ( )` is ill-formed in C++20).
- The locale parameters are `std::locale const &` (a temporary locale could
not be passed).
- Language selection matches locale names by prefix (`[tr]` matches
`tr_TR.UTF-8`), most specific first; it used to require the exact name.
The generator no longer constructs the locales itself, which aborted when
a language was not installed on the build machine.
- Formats (`{$x;std::setw(4);precision(2)}`) restore the whole stream
format afterwards, not only the flags; `std::setw(4)` is a manipulator,
not a member call.
- Non-ASCII bytes are written as octal escapes without leaving `std::oct`
set on the output.
- `MEMBER AS` functions are declared in the streamable class (they did not
compile), `$SYSLOG MEMBER OF` is a member (it was a free function with
no declaration), the exception's locale constructor exists whenever
`$THROW` needs it.
- Classes store parameters by value (`std::decay_t`), so an exception
built from `std::string const &` does not dangle; exceptions implement
`what()`; `$THROW` functions are `[[noreturn]]`; `$USING` is in the
header, inside the namespace; the default base-class access is `public`.
- `NOHEADER` puts the declarations into the source; it no longer writes an
empty file named after the module (overwriting such a file).
- A missing output folder is an error instead of silently writing nothing.
### Project
- Conan recipe (`application`, requires cparse), `mstring_generate()` CMake
module, pkg-config file with the executable path, `manifest.fson`.
- MIT license files, tests and examples.
## 1.0.0
The flex / bison implementation.