diff options
| author | Přemysl Eric Janouch <p@janouch.name> | 2022-09-12 21:19:55 +0200 | 
|---|---|---|
| committer | Přemysl Eric Janouch <p@janouch.name> | 2022-09-13 01:01:35 +0200 | 
| commit | 5cda848f9419c77782008dabe6dc7cba9dc34396 (patch) | |
| tree | 10ab6a83f92b0fb107101ce27edefdccc959b8a4 | |
| parent | a167ae40b3b0e7a5081167a87cb4621dd15e5dd7 (diff) | |
| download | nncmpp-5cda848f9419c77782008dabe6dc7cba9dc34396.tar.gz nncmpp-5cda848f9419c77782008dabe6dc7cba9dc34396.tar.xz nncmpp-5cda848f9419c77782008dabe6dc7cba9dc34396.zip | |
Don't depend on a standalone C preprocessor
And get rid of the sed insanity.
| -rw-r--r-- | CMakeLists.txt | 32 | ||||
| -rw-r--r-- | nncmpp.actions | 6 | ||||
| -rw-r--r-- | nncmpp.actions.awk | 106 | ||||
| -rw-r--r-- | nncmpp.c | 5 | 
4 files changed, 127 insertions, 22 deletions
| 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}=$<BOOL:${${variable}}>") +endmacro () +  # Dependencies  find_package (Ncursesw REQUIRED)  find_package (PkgConfig REQUIRED) @@ -19,7 +27,7 @@ pkg_check_modules (curl REQUIRED libcurl)  include (AddThreads)  find_package (Termo QUIET NO_MODULE) -option (USE_SYSTEM_TERMO +add_option (USE_SYSTEM_TERMO  	"Don't compile our own termo library, use the system one" ${Termo_FOUND})  if (USE_SYSTEM_TERMO)  	if (NOT Termo_FOUND) @@ -41,7 +49,7 @@ else ()  endif ()  pkg_check_modules (fftw fftw3 fftw3f) -option (WITH_FFTW "Use FFTW to enable spectrum visualisation" ${fftw_FOUND}) +add_option (WITH_FFTW "Use FFTW to enable spectrum visualisation" ${fftw_FOUND})  if (WITH_FFTW)  	if (NOT fftw_FOUND)  		message (FATAL_ERROR "FFTW not found") @@ -50,7 +58,8 @@ if (WITH_FFTW)  endif ()  pkg_check_modules (libpulse libpulse) -option (WITH_PULSE "Enable control of PulseAudio sink volume" ${libpulse_FOUND}) +add_option (WITH_PULSE +	"Enable PulseAudio sink volume control" ${libpulse_FOUND})  if (WITH_PULSE)  	if (NOT libpulse_FOUND)  		message (FATAL_ERROR "libpulse not found") @@ -59,7 +68,7 @@ if (WITH_PULSE)  endif ()  pkg_check_modules (x11 x11 xrender xft fontconfig) -option (WITH_X11 "Use FFTW to enable spectrum visualisation" ${x11_FOUND}) +add_option (WITH_X11 "Use FFTW to enable spectrum visualisation" ${x11_FOUND})  if (WITH_X11)  	if (NOT x11_FOUND)  		message (FATAL_ERROR "Some X11 libraries were not found") @@ -99,20 +108,13 @@ configure_file (${PROJECT_SOURCE_DIR}/config.h.in  	${PROJECT_BINARY_DIR}/config.h)  include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR}) -# Assuming a Unix-compatible system with a standalone preprocessor  set (actions_list ${PROJECT_SOURCE_DIR}/nncmpp.actions) +set (actions_awk ${PROJECT_SOURCE_DIR}/nncmpp.actions.awk)  set (actions ${PROJECT_BINARY_DIR}/nncmpp-actions.h)  add_custom_command (OUTPUT ${actions} -	COMMAND cpp -I${PROJECT_BINARY_DIR} -P ${actions_list} -		| grep . | tr [[\n]] ^ | sed -ne [[h; s/,[^^]*/,/g]] -e [[s/$/COUNT/]] -			-e [[s/[^^]*/\tACTION_&/g]] -e [[s/.*/enum action {\n&\n};\n/p]] -			-e [[g; s/,[^^]*//g; y/_/-/]] -e [[s/[^^]\{1,\}/\t"&",/g]] -			-e [[s/.*/static const char *g_action_names[] = {\n&};\n/p]] -			-e [[g; s/[^^]*, *//g;]] -e [[s/[^^]\{1,\}/\t"&",/g]] -			-e [[s/.*/static const char *g_action_descriptions[] = {\n&};/p]] -		| tr ^ [[\n]] > ${actions} -	COMMAND test -s ${actions} -	DEPENDS ${actions_list} ${PROJECT_BINARY_DIR}/config.h VERBATIM) +	COMMAND env LC_ALL=C ${options} +		awk -f ${actions_awk} ${actions_list} > ${actions} +	DEPENDS ${actions_awk} ${actions_list} VERBATIM)  # Build the main executable and link it  add_executable (${PROJECT_NAME} ${PROJECT_NAME}.c ${actions}) diff --git a/nncmpp.actions b/nncmpp.actions index 38a8f76..7d0662d 100644 --- a/nncmpp.actions +++ b/nncmpp.actions @@ -1,5 +1,3 @@ -#include "config.h" -  NONE,               Do nothing  QUIT,               Quit @@ -28,11 +26,11 @@ MPD_CONSUME,        Toggle consume  MPD_UPDATE_DB,      Update MPD database  MPD_COMMAND,        Send raw command to MPD -#ifdef WITH_PULSE +.ifdef WITH_PULSE  PULSE_VOLUME_UP,    Increase PulseAudio volume  PULSE_VOLUME_DOWN,  Decrease PulseAudio volume  PULSE_MUTE,         Toggle PulseAudio sink mute -#endif +.endif  CHOOSE,             Choose item  DELETE,             Delete item diff --git a/nncmpp.actions.awk b/nncmpp.actions.awk new file mode 100644 index 0000000..b4d7eaf --- /dev/null +++ b/nncmpp.actions.awk @@ -0,0 +1,106 @@ +# nncmpp.actions.awk: produce C code for a list of user actions +# +# Copyright (c) 2022, Přemysl Eric Janouch <p@janouch.name> +# 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 "};" +} @@ -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 */) | 
