From 5cda848f9419c77782008dabe6dc7cba9dc34396 Mon Sep 17 00:00:00 2001 From: Přemysl Eric Janouch
Date: Mon, 12 Sep 2022 21:19:55 +0200
Subject: Don't depend on a standalone C preprocessor
And get rid of the sed insanity.
---
CMakeLists.txt | 32 ++++++++--------
nncmpp.actions | 6 +--
nncmpp.actions.awk | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++
nncmpp.c | 5 +--
4 files changed, 127 insertions(+), 22 deletions(-)
create mode 100644 nncmpp.actions.awk
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 451e76b..543e0c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,14 @@ endif ()
# For custom modules
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/liberty/cmake)
+# Collect important build toggles for our simple preprocessor
+# (cpp(1) isn't part of POSIX, otherwise we could reuse config.h)
+set (options)
+macro (add_option variable help value)
+ option (${ARGV})
+ list (APPEND options "${variable}=$
+# SPDX-License-Identifier: 0BSD
+#
+# Usage: env LC_ALL=C A=0 B=1 awk -f nncmpp.actions.awk \
+# nncmpp.actions > nncmpp-actions.h
+
+# --- Preprocessor -------------------------------------------------------------
+
+function fatal(message) {
+ print "// " FILENAME ":" FNR ": fatal error: " message
+ print FILENAME ":" FNR ": fatal error: " message > "/dev/stderr"
+ exit 1
+}
+
+function condition(pass, passing, a, i) {
+ split(substr($0, RSTART + RLENGTH), a, /[[:space:]]+/)
+ if (!(1 in a))
+ fatal("missing condition")
+
+ passing = 0
+ for (i in a)
+ if (a[i] && !pass == !ENVIRON[a[i]])
+ passing = 1
+
+ while (getline > 0) {
+ if (match($0, /^[[:space:]]*[.]endif[[:space:]]*$/))
+ return 1
+
+ if (match($0, /^[[:space:]]*[.]else[[:space:]]*$/))
+ passing = !passing
+ else if (!directive() && passing)
+ process()
+ }
+
+ fatal("unterminated condition body")
+}
+
+# Multiple arguments mean logical OR, multiple directives mean logical AND.
+# Similar syntax is also used by Exim, BSD make, or various assemblers.
+#
+# Looking at what others have picked for their preprocessor syntax:
+# {OpenGL, FreeBASIC} reuse #ifdef, which would be confusing with C code around,
+# {Mental Ray, RapidQ and UniVerse BASIC} use $ifdef, NSIS has !ifdef,
+# and Verilog went for `ifdef. Not much more can be easily found.
+function directive() {
+ sub(/#.*/, "")
+ if (match($0, /^[[:space:]]*[.]ifdef[[:space:]]+/))
+ return condition(1)
+ if (match($0, /^[[:space:]]*[.]ifndef[[:space:]]+/))
+ return condition(0)
+ if (/^[[:space:]]*[.]/)
+ fatal("unexpected or unsupported directive")
+ return 0
+}
+
+!directive() {
+ process()
+}
+
+# --- Postprocessor ------------------------------------------------------------
+
+function strip(string) {
+ gsub(/^[[:space:]]*|[[:space:]]*$/, "", string)
+ return string
+}
+
+function process( constant, name, description) {
+ if (match($0, /,/)) {
+ constant = name = strip(substr($0, 1, RSTART - 1))
+ description = strip(substr($0, RSTART + RLENGTH))
+ gsub(/_/, "-", name)
+
+ N++
+ Constants[N] = constant
+ Names[N] = tolower(name)
+ Descriptions[N] = description
+ } else if (/[^[:space:]]/) {
+ fatal("invalid action definition syntax")
+ }
+}
+
+function tocstring(string) {
+ gsub(/\\/, "\\\\", string)
+ gsub(/"/, "\\\"", string)
+ return "\"" string "\""
+}
+
+END {
+ print "enum action {"
+ for (i in Constants)
+ print "\t" "ACTION_" Constants[i] ","
+ print "\t" "ACTION_COUNT"
+ print "};"
+ print ""
+ print "static const char *g_action_names[] = {"
+ for (i in Names)
+ print "\t" tocstring(Names[i]) ","
+ print "};"
+ print ""
+ print "static const char *g_action_descriptions[] = {"
+ for (i in Descriptions)
+ print "\t" tocstring(Descriptions[i]) ","
+ print "};"
+}
diff --git a/nncmpp.c b/nncmpp.c
index b96191b..74f0a51 100644
--- a/nncmpp.c
+++ b/nncmpp.c
@@ -4168,9 +4168,8 @@ help_tab_on_action (enum action action)
if (action == ACTION_DESCRIBE)
{
- char *name = xstrdup (g_action_names[a]);
- cstr_transform (name, tolower_ascii);
- app_show_message (xstrdup ("Configuration name: "), name);
+ app_show_message (xstrdup ("Configuration name: "),
+ xstrdup (g_action_names[a]));
return true;
}
if (action != ACTION_CHOOSE || a == ACTION_CHOOSE /* avoid recursion */)
--
cgit v1.2.3-70-g09d2