dwm-libconfig 6.8
Runtime configuration parsing for dwm using libconfig.
Loading...
Searching...
No Matches
parser.c File Reference
#include <errno.h>
#include <libconfig.h>
#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

Detailed Description

Runtime configuration parser using libconfig.

This file replaces the need to edit config.h or config.def.h and recompile to make changes to dwm's configuration by parsing a configuration file (see example dwm.conf) at runtime. That configuration file contains all the configuration values traditionally found in config.h or config.def.h, and can be edited at any time without the need to change dwm's source code, allowing you to install dwm once and configure it any time you wish without the source code. For more information, please see the patch's GitHub page: https://github.com/JeffofBread/dwm-libconfig.

Authors
JeffOfBread jeffo.nosp@m.fbre.nosp@m.adcod.nosp@m.ing@.nosp@m.gmail.nosp@m..com
Yuxuan Shui - yshui.nosp@m.v7@g.nosp@m.mail..nosp@m.com, author of picom, which I (JeffOfBread) copied code from. Code from picom is credited as such.
Mihir Lad - mihir.nosp@m.lad5.nosp@m.5@gma.nosp@m.il.c.nosp@m.om, author of dwm-ipc, which I (JeffOfBread) copied code from. Code from dwm-ipc is credited as such.
See also
https://github.com/hyperrealm/libconfig
https://github.com/JeffofBread/dwm-libconfig
https://github.com/yshui/picom
https://github.com/mihirlad55/dwm-ipc
Warning
This file must be included in dwm.c after these:
  1. The inclusion of config.h
  2. The structs Arg, Rule, Button, Key
  3. The enums for clicks and color schemes
Note
I (JeffOfBread) did not write all the code present in this file. Though I have made minor changes, it's still not fair to say I wrote the code. I have listed them above as authors, and all code I used from them (many of the public utility functions) has been credited accordingly.
Todo

Finish documentation. Make sure function arguments are noted for being dynamically allocated in that function or its sub functions.

Overhaul printing / logging to match the new error handling.

Try and reduce the number of unique string literals throughout the parser. Tons are used for logging, inflating binary size by 8kb.

Data Structures

struct  Button_Alias_Map_t
 Struct to map a string alias to a matching X11 button. More...
struct  Click_Alias_Map_t
 Struct to map a string alias to a matching click enum. More...
struct  Errors_t
 Struct containing a count of accumulated Error_t. More...
struct  Function_Alias_Map_t
 Struct to map a string alias to a matching function pointer, its argument data type, and that argument's acceptable range. More...
struct  Modifier_Alias_Map_t
 Struct to map a string alias to a matching X11 modifier. More...
struct  Setting_Alias_Map_t
 Struct to map a string alias to a matching setting pointer, its optional status, argument data type, and that argument's acceptable range. More...
struct  Theme_Alias_Map_t
 Struct to map a string alias to a matching color string pointer. More...

Macros

#define _LOG(LEVEL, ...)
 Log a categorized message.
#define LOG_TRACE(...)
 Log a trace message.
#define LOG_DEBUG(...)
 Log a debug message.
#define LOG_INFO(...)
 Log an informational message.
#define LOG_WARN(...)
 Log a warning message.
#define LOG_ERROR(...)
 Log an error message.
#define LOG_FATAL(...)
 Log a fatal issue message.
#define RETURN_ERRORS_IF_NULL(check, errors, ...)
 Return function with Errors_t struct if variable is NULL.
#define RETURN_VALUE_IF_NULL(check, value, ...)
 Return function with a given value if variable is NULL.
#define RETURN_IF_NULL(check, ...)
 Return function if variable is NULL.
#define SET_STATUS_TEXT(...)
 Macro to easily set status text before first bar draw.

Typedefs

typedef Errors_t(* Array_Element_Parser_Function_t) (config_setting_t *element_setting, unsigned int element_index, void *parsed_element)
 Typedef used to abstract config array parsing functions. Allows for more generic parsing of multiple types.

Enumerations

enum  Data_Type_t {
  TYPE_NONE , TYPE_BOOLEAN , TYPE_INT , TYPE_UINT ,
  TYPE_FLOAT , TYPE_STRING
}
 Enum used to keep track of what kind of data is to be stored in an Arg struct. More...
enum  Error_t {
  ERROR_NONE , ERROR_NOT_FOUND , ERROR_TYPE , ERROR_RANGE ,
  ERROR_NULL_VALUE , ERROR_ALLOCATION , ERROR_IO , ERROR_ENUM_LENGTH
}
 Enum to categorize the types of errors that can occur during parsing. More...

Functions

void config_cleanup (void)
 Frees dynamically allocated parser data.
Errors_t parse_config (void)
 Parse program configuration from a configuration file.
void add_error (Errors_t *errors, const Error_t error)
 Adds an error to an Errors_t struct.
void copy_errors (Errors_t *destination, const Errors_t source)
 Copy errors from source to destination.
int errors_failure_count (const Errors_t *errors)
 Counts the number of failure errors present in an Errors_t struct.
char * estrdup (const char *string)
 Simple wrapper around strdup() to provide error logging.
void extend_string (char **source_string, const char *addition)
 Extend one string with another.
const Layout * get_layout (void(*arrange)(Monitor *))
 Find and return a layout that uses a specific arrange function.
char * get_xdg_config_home (void)
 Get the user's XDG configuration directory path.
char * get_xdg_data_home (void)
 Get the user's XDG data directory path.
char * join_strings (const char *string_1, const char *string_2)
 Join two strings into one.
int make_directory_path (const char *path)
 Creates all directories in a given path if they don't exist.
int normalize_path (const char *original_path, char **normalized_path)
 Normalize a file or folder path to remove repeat forward slash characters.
void setlayout_floating (const Arg *arg)
 Set current layout to floating.
void setlayout_monocle (const Arg *arg)
 Set current layout to monocle.
void setlayout_tiled (const Arg *arg)
 Set current layout to tile.
void spawn_string (const Arg *arg)
 Wrapper around spawn() for simpler program spawning.
static Error_t _parser_backup_config (config_t *config)
 Backs up a libconfig configuration to disk.
static Error_t _parse_bind_argument (config_setting_t *setting, const Data_Type_t argument_type, const long double range_min, const long double range_max, Arg *argument)
 TODO.
static Errors_t _parse_bind_core (config_setting_t *setting, const unsigned int bind_index, unsigned int *modifier, void(**function)(const Arg *), Arg *argument)
 TODO.
static Error_t _parse_bind_function (config_setting_t *setting, void(**function)(const Arg *), Data_Type_t *argument_type, long double *range_min, long double *range_max)
 TODO.
static Error_t _parse_bind_modifier (config_setting_t *setting, unsigned int *modifier)
 TODO.
static Errors_t _parse_buttonbind (config_setting_t *setting, const unsigned int index, Button *buttonbind)
 TODO.
static Errors_t _parse_buttonbind_adapter (config_setting_t *setting, const unsigned int index, void *buttonbind)
 Thin adapter function to allow for buttonbind parsing inside a generic array parsing function.
static Error_t _parse_buttonbind_button (config_setting_t *setting, unsigned int *button)
 TODO.
static Error_t _parse_buttonbind_click (config_setting_t *setting, unsigned int *click)
 TODO.
static Errors_t _parse_buttonbinds_config (const config_t *config, Button **array, unsigned int *count, bool *malloced)
 Parse a list of buttonbinds from a libconfig configuration into a list of Button structs.
static Errors_t _parse_font (config_setting_t *setting, const unsigned int index, const char **font)
 TODO.
static Errors_t _parse_font_adapter (config_setting_t *setting, const unsigned int index, void *font)
 Thin adapter function to allow for font parsing inside a generic array parsing function.
static Errors_t _parse_generic_settings (const config_t *config)
 Parse generic configuration settings from a libconfig configuration.
static Errors_t _parse_keybind (config_setting_t *setting, const unsigned int index, Key *keybind)
 TODO.
static Errors_t _parse_keybind_adapter (config_setting_t *setting, const unsigned int index, void *keybind)
 Thin adapter function to allow for keybind parsing inside a generic array parsing function.
static Error_t _parse_keybind_keysym (config_setting_t *setting, KeySym *keysym)
 TODO.
static Errors_t _parse_keybinds_config (const config_t *config, Key **array, unsigned int *count, bool *malloced)
 Parse a list of keybinds from a libconfig configuration into a list of Key structs.
static Errors_t _parser_open_config_file (config_t *config, const char *custom_config_filepath, char **found_config_filepath, bool *fallback_config_loaded)
 Attempts to find, open, and store a valid libconfig configuration file.
static Errors_t _parse_rule (config_setting_t *setting, const unsigned int index, Rule *rule)
 Parse a rule from a libconfig configuration setting.
static Errors_t _parse_rule_adapter (config_setting_t *setting, const unsigned int index, void *rule)
 Thin adapter function to allow for rule parsing inside a generic array parsing function.
static Errors_t _parse_rules_config (const config_t *config, Rule **array, unsigned int *count, bool *malloced)
 Parse a list of rules from a libconfig configuration into a list of Rule structs.
static Errors_t _parse_setting_array (const config_setting_t *setting, const size_t element_size, const Array_Element_Parser_Function_t array_element_parser_function, bool *malloced, void **parsed_config, unsigned int *parsed_config_length)
 TODO.
static Errors_t _parse_tag (config_setting_t *setting, const unsigned int index)
 TODO.
static Errors_t _parse_tags_adapter (config_setting_t *setting, const unsigned int index, void *unused)
 Thin adapter function to allow for tag parsing inside a generic array parsing function.
static Errors_t _parse_tags_config (const config_t *config)
 Parse a list of tags from a libconfig configuration.
static Errors_t _parse_theme (config_setting_t *setting, const unsigned int index)
 Parse a theme from a libconfig configuration setting.
static Errors_t _parse_theme_adapter (config_setting_t *setting, const unsigned int index, void *unused)
 Thin adapter function to allow for theme parsing inside a generic array parsing function.
static Errors_t _parse_theme_config (const config_t *config)
 Parse a list of themes from a libconfig configuration.
static Error_t _libconfig_generic_lookup (config_setting_t *parent_setting, const char *path, const int expected_type, void *parsed_value)
 TODO.
static Error_t _libconfig_get_setting_name (const config_setting_t *setting, const char **found_name)
 Returns the name of a given setting, or its nearest named parent setting.
static Error_t _libconfig_lookup_float (config_setting_t *parent_setting, const char *path, const float range_min, const float range_max, float *parsed_value)
 Look up a float value in a libconfig setting.
static Error_t _libconfig_lookup_int (config_setting_t *parent_setting, const char *path, const int range_min, const int range_max, int *parsed_value)
 Look up an integer value in a libconfig setting.
static Error_t _libconfig_lookup_string (config_setting_t *parent_setting, const char *path, const char **parsed_value)
 Look up a string value in a libconfig setting.
static Error_t _libconfig_lookup_uint (config_setting_t *parent_setting, const char *path, const unsigned int range_min, const unsigned int range_max, unsigned int *parsed_value)
 Look up an unsigned integer value in a libconfig setting.

Variables

config_t libconfig_config
 Master libconfig configuration context used for parsing.
char * config_filepath
 Path to the currently loaded configuration's file.
Key * keys
 Array of current keybinds.
Button * buttons
 Array of current buttons.
Rule * rules
 Array of current rules.
const char ** fonts
 Array of current fonts.
unsigned int keys_count
 Number of elements in keys.
unsigned int buttons_count
 Number of elements in buttons.
unsigned int rules_count
 Number of elements in rules.
unsigned int fonts_count
 Number of elements in fonts_count.
bool keys_malloced
 Boolean tracking whether keys has been dynamically allocated.
bool buttons_malloced
 Boolean tracking whether buttons has been dynamically allocated.
bool rules_malloced
 Boolean tracking whether rules has been dynamically allocated.
bool fonts_malloced
 Boolean tracking whether fonts has been dynamically allocated.
static const char * _parser_filepath
 Parser filepath string.
const char * ERROR_ENUM_STRINGS []
 String name pairs to Error_t.
const char * FAILED_ALLOC_PRINT_STRING
 Common string used for logging memory allocation issues.
const char * POINTER_NULL_PRINT_STRING
 Common string used for logging NULL pointers.
static const Click_Alias_Map_t CLICK_ALIAS_MAP []
 Default alias map for dwm's click enum.
static const Button_Alias_Map_t BUTTON_ALIAS_MAP []
 Default alias map for common X11 buttons.
static const Function_Alias_Map_t FUNCTION_ALIAS_MAP []
 Default alias map for dwm's arg functions.
static const Modifier_Alias_Map_t MODIFIER_ALIAS_MAP []
 Default alias map for common X11 modifiers.
static const Setting_Alias_Map_t SETTING_ALIAS_MAP []
 Default alias map for dwm's global config settings.
static const Theme_Alias_Map_t THEME_ALIAS_MAP []
 Default alias map for dwm's scheme indexes.

Macro Definition Documentation

◆ _LOG

#define _LOG ( LEVEL,
... )

Log a categorized message.

Logging is more or less intended to be enabled/disabled by uncommenting/commenting individual logging level's macro bodies. I would prefer a proper logging system, but that seems out the scope of this patch, and this works good enough for the patch's needs.

Also, if you would like to include function names in the log, you can use __func__:

fprintf( stdout, LEVEL " [%s::%s::%d]: ", _parser_filepath, __func__, __LINE__ );
static const char * _parser_filepath
Parser filepath string.
Definition parser.c:253
Parameters
[in]LEVELLog level string literal.
68#define _LOG( LEVEL, ... )\
69 do {\
70 fprintf( stdout, LEVEL " [%s::%d]: ", _parser_filepath, __LINE__ );\
71 fprintf( stdout, "" __VA_ARGS__ );\
72 } while ( false )

◆ RETURN_ERRORS_IF_NULL

#define RETURN_ERRORS_IF_NULL ( check,
errors,
... )

Return function with Errors_t struct if variable is NULL.

Parameters
[in]checkVariable to be checked for NULL.
[in,out]errorsErrors_t struct to be returned with an ERROR_NULL_VALUE error if check is NULL.
[in]...Format and message to be given to LOG_ERROR() to be logged.
100#define RETURN_ERRORS_IF_NULL( check, errors, ... )\
101 if( check == NULL ){\
102 LOG_ERROR( __VA_ARGS__ );\
103 add_error( &errors, ERROR_NULL_VALUE );\
104 return errors;\
105 }

Referenced by _parse_bind_core(), _parse_buttonbind(), _parse_buttonbinds_config(), _parse_font(), _parse_generic_settings(), _parse_keybind(), _parse_keybinds_config(), _parse_rule(), _parse_rules_config(), _parse_setting_array(), _parse_tag(), _parse_tags_config(), _parse_theme(), _parse_theme_config(), and _parser_open_config_file().

◆ RETURN_IF_NULL

#define RETURN_IF_NULL ( check,
... )

Return function if variable is NULL.

Parameters
[in]checkVariable to be checked for NULL.
[in]...Format and message to be given to LOG_ERROR() to be logged.
126#define RETURN_IF_NULL( check, ... )\
127 if( check == NULL ){\
128 LOG_ERROR( __VA_ARGS__ );\
129 return;\
130 }

Referenced by add_error(), copy_errors(), extend_string(), setlayout_floating(), setlayout_monocle(), setlayout_tiled(), and spawn_string().

◆ RETURN_VALUE_IF_NULL

#define RETURN_VALUE_IF_NULL ( check,
value,
... )

Return function with a given value if variable is NULL.

Parameters
[in]checkVariable to be checked for NULL.
[in]valueValue to be returned if check is NULL.
[in]...Format and message to be given to LOG_ERROR() to be logged.
114#define RETURN_VALUE_IF_NULL( check, value, ... )\
115 if( check == NULL ){\
116 LOG_ERROR( __VA_ARGS__ );\
117 return value;\
118 }

Referenced by _parse_bind_argument(), _parse_bind_function(), _parse_bind_modifier(), _parse_buttonbind_button(), _parse_buttonbind_click(), _parse_keybind_keysym(), _parser_backup_config(), errors_failure_count(), estrdup(), get_xdg_config_home(), get_xdg_data_home(), join_strings(), make_directory_path(), and normalize_path().

◆ SET_STATUS_TEXT

#define SET_STATUS_TEXT ( ...)

Macro to easily set status text before first bar draw.

Parameters
[in]...Format and variables to be printed to the status text.
136#define SET_STATUS_TEXT( ... )\
137 do{\
138 snprintf( stext, sizeof( stext ), "" __VA_ARGS__ );\
139 XStoreName(dpy, root, stext);\
140 XSync(dpy, False);\
141 } while ( false )

Referenced by parse_config().

Enumeration Type Documentation

◆ Data_Type_t

Enum used to keep track of what kind of data is to be stored in an Arg struct.

Enumerator
TYPE_NONE 

No data stored/required.

TYPE_BOOLEAN 

Boolean data.

TYPE_INT 

Integer data.

TYPE_UINT 

Unsigned Integer data.

TYPE_FLOAT 

Float data.

TYPE_STRING 

String data.

160 {
161 TYPE_NONE = 0,
163 TYPE_INT,
164 TYPE_UINT,
165 TYPE_FLOAT,
Data_Type_t
Enum used to keep track of what kind of data is to be stored in an Arg struct.
Definition parser.c:160
@ TYPE_NONE
No data stored/required.
Definition parser.c:161
@ TYPE_FLOAT
Float data.
Definition parser.c:165
@ TYPE_INT
Integer data.
Definition parser.c:163
@ TYPE_BOOLEAN
Boolean data.
Definition parser.c:162
@ TYPE_UINT
Unsigned Integer data.
Definition parser.c:164
@ TYPE_STRING
String data.
Definition parser.c:166

◆ Error_t

enum Error_t

Enum to categorize the types of errors that can occur during parsing.

Todo
Maybe look at adding ERROR_ARGUMENT, as we check function arguments a ton.
Enumerator
ERROR_NONE 

No issue. Always must be first.

ERROR_NOT_FOUND 

Value was unable to be acquired.

ERROR_TYPE 

Value was not of required type.

ERROR_RANGE 

Value evaluated out of required range.

ERROR_NULL_VALUE 

Value evaluated NULL.

ERROR_ALLOCATION 

Failed to dynamically allocating memory.

ERROR_IO 

Failure processing or collecting input/output.

ERROR_ENUM_LENGTH 

Count of possible enum values. Always must be last.

173 {
174 ERROR_NONE = 0,
176 ERROR_TYPE,
180 ERROR_IO,
182} Error_t;
Error_t
Enum to categorize the types of errors that can occur during parsing.
Definition parser.c:173
@ ERROR_ALLOCATION
Failed to dynamically allocating memory.
Definition parser.c:179
@ ERROR_ENUM_LENGTH
Count of possible enum values. Always must be last.
Definition parser.c:181
@ ERROR_RANGE
Value evaluated out of required range.
Definition parser.c:177
@ ERROR_IO
Failure processing or collecting input/output.
Definition parser.c:180
@ ERROR_TYPE
Value was not of required type.
Definition parser.c:176
@ ERROR_NOT_FOUND
Value was unable to be acquired.
Definition parser.c:175
@ ERROR_NONE
No issue. Always must be first.
Definition parser.c:174
@ ERROR_NULL_VALUE
Value evaluated NULL.
Definition parser.c:178

Function Documentation

◆ _libconfig_generic_lookup()

Error_t _libconfig_generic_lookup ( config_setting_t * parent_setting,
const char * path,
const int expected_type,
void * parsed_value )
static

TODO.

TODO

Parameters
[in]parent_settingTODO
[in]pathTODO
[in]expected_typeTODO
[out]parsed_valueTODO
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_NOT_FOUND if lookup failed.
ERROR_TYPE if type found at path does not match expected_type or if there is an unexpected type in the switch case.
2222 {
2223
2224 if ( parent_setting == NULL || path == NULL || parsed_value == NULL ) return ERROR_NULL_VALUE;
2225
2226 config_setting_t *child_setting = config_setting_lookup( parent_setting, path );
2227
2228 if ( child_setting == NULL ) return ERROR_NOT_FOUND;
2229
2230 if ( config_setting_type( child_setting ) != expected_type ) return ERROR_TYPE;
2231
2232 switch ( expected_type ) {
2233 case CONFIG_TYPE_STRING:
2234 *(const char **) parsed_value = config_setting_get_string( child_setting );
2235 break;
2236
2237 case CONFIG_TYPE_INT:
2238 *(int *) parsed_value = config_setting_get_int( child_setting );
2239 break;
2240
2241 case CONFIG_TYPE_INT64:
2242 *(long long *) parsed_value = config_setting_get_int64( child_setting );
2243 break;
2244
2245 case CONFIG_TYPE_FLOAT:
2246 *(float *) parsed_value = config_setting_get_float( child_setting );
2247 break;
2248
2249 case CONFIG_TYPE_BOOL:
2250 *(bool *) parsed_value = config_setting_get_bool( child_setting );
2251 break;
2252
2253 case CONFIG_TYPE_GROUP:
2254 case CONFIG_TYPE_ARRAY:
2255 case CONFIG_TYPE_LIST:
2256 *(config_setting_t **) parsed_value = child_setting;
2257 break;
2258
2259 default:
2260 return ERROR_TYPE;
2261 }
2262
2263 return ERROR_NONE;
2264}

References ERROR_NONE, ERROR_NOT_FOUND, ERROR_NULL_VALUE, and ERROR_TYPE.

Referenced by _libconfig_lookup_float(), _libconfig_lookup_int(), _libconfig_lookup_string(), _libconfig_lookup_uint(), _parse_bind_argument(), _parse_buttonbinds_config(), _parse_generic_settings(), _parse_keybinds_config(), _parse_rules_config(), _parse_tags_config(), _parse_theme(), and _parse_theme_config().

◆ _libconfig_get_setting_name()

Error_t _libconfig_get_setting_name ( const config_setting_t * setting,
const char ** found_name )
static

Returns the name of a given setting, or its nearest named parent setting.

TODO

Parameters
[in]settingTODO
[out]found_nameTODO
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_NOT_FOUND if no named parent settings are found.
2278 {
2279
2280 if ( setting == NULL || found_name == NULL ) return ERROR_NULL_VALUE;
2281
2282 while ( setting != NULL ) {
2283 const char *tmp_string = config_setting_name( setting );
2284
2285 if ( tmp_string != NULL ) {
2286 *found_name = tmp_string;
2287 return ERROR_NONE;
2288 }
2289
2290 setting = config_setting_parent( setting );
2291 }
2292
2293 return ERROR_NOT_FOUND;
2294}

References ERROR_NONE, ERROR_NOT_FOUND, and ERROR_NULL_VALUE.

Referenced by _parse_bind_core(), and _parse_setting_array().

◆ _libconfig_lookup_float()

Error_t _libconfig_lookup_float ( config_setting_t * parent_setting,
const char * path,
const float range_min,
const float range_max,
float * parsed_value )
static

Look up a float value in a libconfig setting.

TODO

Parameters
[in]parent_settingPointer to the libconfig setting to perform the lookup in.
[in]pathPath expression to search within parent_setting.
[in]range_minMinimum value that can be saved to parsed_value.
[in]range_maxMaximum value that can be saved to parsed_value.
[out]parsed_valuePointer to where the parsed value will be stored on success.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_RANGE if range_min exceeds range_max or if the parsed value at path is outside the provided range.
Any error returned from _libconfig_generic_lookup().
2313 {
2314
2315 if ( parent_setting == NULL || path == NULL || parsed_value == NULL ) return ERROR_NULL_VALUE;
2316 if ( range_min > range_max ) return ERROR_RANGE;
2317
2318 float tmp_float = 0;
2319 const Error_t lookup_error = _libconfig_generic_lookup( parent_setting, path, CONFIG_TYPE_FLOAT, &tmp_float );
2320 if ( lookup_error != ERROR_NONE ) return lookup_error;
2321
2322 if ( tmp_float < range_min || tmp_float > range_max ) return ERROR_RANGE;
2323
2324 *parsed_value = tmp_float;
2325
2326 return ERROR_NONE;
2327}
static Error_t _libconfig_generic_lookup(config_setting_t *parent_setting, const char *path, int expected_type, void *parsed_value)
TODO.
Definition parser.c:2222

References _libconfig_generic_lookup(), ERROR_NONE, ERROR_NULL_VALUE, and ERROR_RANGE.

Referenced by _parse_bind_argument(), and _parse_generic_settings().

◆ _libconfig_lookup_int()

Error_t _libconfig_lookup_int ( config_setting_t * parent_setting,
const char * path,
const int range_min,
const int range_max,
int * parsed_value )
static

Look up an integer value in a libconfig setting.

TODO

Parameters
[in]parent_settingPointer to the libconfig setting to perform the lookup in.
[in]pathPath expression to search within parent_setting.
[in]range_minMinimum value that can be saved to parsed_value.
[in]range_maxMaximum value that can be saved to parsed_value.
[out]parsed_valuePointer to where the parsed value will be stored on success.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_RANGE if range_min exceeds range_max or if the parsed value at path is outside the provided range.
Any error returned from _libconfig_generic_lookup().
2346 {
2347
2348 if ( parent_setting == NULL || path == NULL || parsed_value == NULL ) return ERROR_NULL_VALUE;
2349 if ( range_min > range_max ) return ERROR_RANGE;
2350
2351 int tmp_int = 0;
2352 const Error_t lookup_error = _libconfig_generic_lookup( parent_setting, path, CONFIG_TYPE_INT, &tmp_int );
2353 if ( lookup_error != ERROR_NONE ) return lookup_error;
2354
2355 if ( tmp_int < range_min || tmp_int > range_max ) return ERROR_RANGE;
2356
2357 *parsed_value = tmp_int;
2358
2359 return ERROR_NONE;
2360}

References _libconfig_generic_lookup(), ERROR_NONE, ERROR_NULL_VALUE, and ERROR_RANGE.

Referenced by _parse_bind_argument(), _parse_generic_settings(), and _parse_rule().

◆ _libconfig_lookup_string()

Error_t _libconfig_lookup_string ( config_setting_t * parent_setting,
const char * path,
const char ** parsed_value )
static

Look up a string value in a libconfig setting.

TODO

Parameters
[in]parent_settingPointer to the libconfig setting to perform the lookup in.
[in]pathPath expression to search within parent_setting.
[out]parsed_valuePointer to where the parsed value will be stored on success.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
Any error returned from _libconfig_generic_lookup().
2375 {
2376
2377 if ( parent_setting == NULL || path == NULL || parsed_value == NULL ) return ERROR_NULL_VALUE;
2378
2379 const Error_t lookup_error = _libconfig_generic_lookup( parent_setting, path, CONFIG_TYPE_STRING, parsed_value );
2380 if ( lookup_error != ERROR_NONE ) return lookup_error;
2381
2382 if ( *parsed_value && strcasecmp( *parsed_value, "NULL" ) == 0 ) {
2383 *parsed_value = NULL;
2384 }
2385
2386 return ERROR_NONE;
2387}

References _libconfig_generic_lookup(), ERROR_NONE, and ERROR_NULL_VALUE.

Referenced by _parse_bind_argument(), _parse_bind_function(), _parse_bind_modifier(), _parse_buttonbind_button(), _parse_buttonbind_click(), _parse_generic_settings(), _parse_keybind_keysym(), _parse_rule(), and _parse_theme().

◆ _libconfig_lookup_uint()

Error_t _libconfig_lookup_uint ( config_setting_t * parent_setting,
const char * path,
const unsigned int range_min,
const unsigned int range_max,
unsigned int * parsed_value )
static

Look up an unsigned integer value in a libconfig setting.

TODO

Parameters
[in]parent_settingPointer to the libconfig setting to perform the lookup in.
[in]pathPath expression to search within parent_setting.
[in]range_minMinimum value that can be saved to parsed_value.
[in]range_maxMaximum value that can be saved to parsed_value.
[out]parsed_valuePointer to where the parsed value will be stored on success.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_RANGE if range_min exceeds range_max or if the parsed value at path is less than zero or outside the provided range.
Any error returned from _libconfig_generic_lookup().
2406 {
2407
2408 if ( parent_setting == NULL || path == NULL || parsed_value == NULL ) return ERROR_NULL_VALUE;
2409 if ( range_min > range_max ) return ERROR_RANGE;
2410
2411 int tmp_int = 0;
2412 const Error_t lookup_error = _libconfig_generic_lookup( parent_setting, path, CONFIG_TYPE_INT, &tmp_int );
2413 if ( lookup_error != ERROR_NONE ) return lookup_error;
2414
2415 if ( tmp_int < 0 ) return ERROR_RANGE;
2416
2417 const unsigned int tmp_uint = (unsigned int) tmp_int;
2418
2419 if ( tmp_uint < range_min || tmp_uint > range_max ) return ERROR_RANGE;
2420
2421 *parsed_value = tmp_uint;
2422
2423 return ERROR_NONE;
2424}

References _libconfig_generic_lookup(), ERROR_NONE, ERROR_NULL_VALUE, and ERROR_RANGE.

Referenced by _parse_bind_argument(), _parse_generic_settings(), and _parse_rule().

◆ _parse_bind_argument()

Error_t _parse_bind_argument ( config_setting_t * setting,
const Data_Type_t argument_type,
const long double range_min,
const long double range_max,
Arg * argument )
static

TODO.

TODO

Parameters
[in]settingTODO
[in]argument_typeEnum describing the type of data stored in parsed_argument.
[in]range_minMinimum value parsed_argument can have. Only applies to numerical types.
[in]range_maxMaximum value parsed_argument can have. Only applies to numerical types.
[out]argumentPointer to an Arg struct where the parsed value of type argument_type in range range_min to range_max will be stored.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_TYPE if argument_type does not match any case in the switch statement.
Any error returned from any of the _libconfig_setting_lookup_TYPE() functions.
1128 {
1129
1130 RETURN_VALUE_IF_NULL( setting, ERROR_NULL_VALUE, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1131 RETURN_VALUE_IF_NULL( argument, ERROR_NULL_VALUE, "%s:\"argument\"\n", POINTER_NULL_PRINT_STRING );
1132
1133 const char *argument_path = "argument";
1134 Error_t lookup_error = ERROR_NONE;
1135 switch ( argument_type ) {
1136 case TYPE_NONE: {
1137 return ERROR_NONE;
1138 }
1139
1140 case TYPE_BOOLEAN: {
1141 lookup_error = _libconfig_generic_lookup( setting, argument_path, CONFIG_TYPE_BOOL, (bool *) &argument->ui );
1142 break;
1143 }
1144
1145 case TYPE_INT: {
1146 lookup_error = _libconfig_lookup_int( setting, argument_path, range_min, range_max, &argument->i );
1147 break;
1148 }
1149
1150 case TYPE_UINT: {
1151 lookup_error = _libconfig_lookup_uint( setting, argument_path, range_min, range_max, &argument->ui );
1152 break;
1153 }
1154
1155 case TYPE_FLOAT: {
1156 lookup_error = _libconfig_lookup_float( setting, argument_path, range_min, range_max, &argument->f );
1157 break;
1158 }
1159
1160 case TYPE_STRING: {
1161 lookup_error = _libconfig_lookup_string( setting, argument_path, (const char **) &argument->v );
1162 break;
1163 }
1164
1165 default: {
1166 LOG_WARN( "Unknown argument type during bind parsing: %d. Please reprogram to a valid type\n", argument_type );
1167 return ERROR_TYPE;
1168 }
1169 }
1170
1171 return lookup_error;
1172}
#define RETURN_VALUE_IF_NULL(check, value,...)
Return function with a given value if variable is NULL.
Definition parser.c:114
static Error_t _libconfig_lookup_float(config_setting_t *parent_setting, const char *path, float range_min, float range_max, float *parsed_value)
Look up a float value in a libconfig setting.
Definition parser.c:2313
static Error_t _libconfig_lookup_uint(config_setting_t *parent_setting, const char *path, unsigned int range_min, unsigned int range_max, unsigned int *parsed_value)
Look up an unsigned integer value in a libconfig setting.
Definition parser.c:2406
const char * POINTER_NULL_PRINT_STRING
Common string used for logging NULL pointers.
Definition parser.c:262
static Error_t _libconfig_lookup_int(config_setting_t *parent_setting, const char *path, int range_min, int range_max, int *parsed_value)
Look up an integer value in a libconfig setting.
Definition parser.c:2346
static Error_t _libconfig_lookup_string(config_setting_t *parent_setting, const char *path, const char **parsed_value)
Look up a string value in a libconfig setting.
Definition parser.c:2375
#define LOG_WARN(...)
Log a warning message.
Definition parser.c:84

References _libconfig_generic_lookup(), _libconfig_lookup_float(), _libconfig_lookup_int(), _libconfig_lookup_string(), _libconfig_lookup_uint(), ERROR_NONE, ERROR_NULL_VALUE, ERROR_TYPE, LOG_WARN, POINTER_NULL_PRINT_STRING, RETURN_VALUE_IF_NULL, TYPE_BOOLEAN, TYPE_FLOAT, TYPE_INT, TYPE_NONE, TYPE_STRING, and TYPE_UINT.

Referenced by _parse_bind_core().

◆ _parse_bind_core()

Errors_t _parse_bind_core ( config_setting_t * setting,
const unsigned int bind_index,
unsigned int * modifier,
void(** function )(const Arg *),
Arg * argument )
static

TODO.

TODO

Parameters
[in]settingTODO
[in]bind_indexTODO
[out]modifierTODO
[out]functionTODO
[out]argumentTODO
Returns
TODO
1187 {
1188
1189 Errors_t returned_errors = { 0 };
1190
1191 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1192 RETURN_ERRORS_IF_NULL( modifier, returned_errors, "%s:\"modifier\"\n", POINTER_NULL_PRINT_STRING );
1193 RETURN_ERRORS_IF_NULL( function, returned_errors, "%s:\"function\"\n", POINTER_NULL_PRINT_STRING );
1194 RETURN_ERRORS_IF_NULL( argument, returned_errors, "%s:\"argument\"\n", POINTER_NULL_PRINT_STRING );
1195
1196 const char *setting_name = NULL;
1197 const Error_t setting_name_error = _libconfig_get_setting_name( setting, &setting_name );
1198 add_error( &returned_errors, setting_name_error );
1199
1200 if ( setting_name_error != ERROR_NONE ) {
1201 LOG_WARN( "Unable to acquire setting name, logs in this function may not print correctly: %s\n", ERROR_ENUM_STRINGS[ setting_name_error ] );
1202 }
1203
1204 const Error_t modifier_error = _parse_bind_modifier( setting, modifier );
1205 add_error( &returned_errors, modifier_error );
1206
1207 if ( modifier_error != ERROR_NONE ) {
1208 LOG_WARN( "\"%s\" index %d invalid, unable to parse the bind's modifier: %s\n", setting_name, bind_index + 1, ERROR_ENUM_STRINGS[ modifier_error ] );
1209 return returned_errors;
1210 }
1211
1212 Data_Type_t argument_type = TYPE_NONE;
1213 long double range_min = 0, range_max = 0;
1214 const Error_t bind_error = _parse_bind_function( setting, function, &argument_type, &range_min, &range_max );
1215 add_error( &returned_errors, bind_error );
1216
1217 if ( bind_error != ERROR_NONE ) {
1218 LOG_WARN( "\"%s\" index %d invalid, unable to parse the bind's function: %s\n", setting_name, bind_index + 1, ERROR_ENUM_STRINGS[ bind_error ] );
1219 return returned_errors;
1220 }
1221
1222 const Error_t argument_error = _parse_bind_argument( setting, argument_type, range_min, range_max, argument );
1223 add_error( &returned_errors, argument_error );
1224
1225 if ( argument_error != ERROR_NONE ) {
1226 LOG_WARN( "\"%s\" index %d invalid, unable to parse the bind's arguments: %s\n", setting_name, bind_index + 1, ERROR_ENUM_STRINGS[ argument_error ] );
1227 return returned_errors;
1228 }
1229
1230 return returned_errors;
1231}
static Error_t _parse_bind_argument(config_setting_t *setting, Data_Type_t argument_type, long double range_min, long double range_max, Arg *argument)
TODO.
Definition parser.c:1128
static Error_t _parse_bind_function(config_setting_t *setting, void(**function)(const Arg *), Data_Type_t *argument_type, long double *range_min, long double *range_max)
TODO.
Definition parser.c:1249
const char * ERROR_ENUM_STRINGS[]
String name pairs to Error_t.
Definition parser.c:256
#define RETURN_ERRORS_IF_NULL(check, errors,...)
Return function with Errors_t struct if variable is NULL.
Definition parser.c:100
static Error_t _libconfig_get_setting_name(const config_setting_t *setting, const char **found_name)
Returns the name of a given setting, or its nearest named parent setting.
Definition parser.c:2278
static Error_t _parse_bind_modifier(config_setting_t *setting, unsigned int *modifier)
TODO.
Definition parser.c:1292
void add_error(Errors_t *errors, Error_t error)
Adds an error to an Errors_t struct.
Definition parser.c:543
Struct containing a count of accumulated Error_t.
Definition parser.c:185

References _libconfig_get_setting_name(), _parse_bind_argument(), _parse_bind_function(), _parse_bind_modifier(), add_error(), ERROR_ENUM_STRINGS, ERROR_NONE, LOG_WARN, POINTER_NULL_PRINT_STRING, RETURN_ERRORS_IF_NULL, and TYPE_NONE.

Referenced by _parse_buttonbind(), and _parse_keybind().

◆ _parse_bind_function()

Error_t _parse_bind_function ( config_setting_t * setting,
void(** function )(const Arg *),
Data_Type_t * argument_type,
long double * range_min,
long double * range_max )
static

TODO.

TODO

Parameters
[in]settingTODO
[out]functionTODO
[out]argument_typePointer to where to store the data type of the Arg that can be passed to function.
[out]range_minPointer to where to store the minimum value of the Arg that can be passed to function.
[out]range_maxPointer to where to store the maximum value of the Arg that can be passed to function.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_NOT_FOUND if parsed intermediate function string does not match any alias found in FUNCTION_ALIAS_MAP.
Any error returned from _libconfig_setting_lookup_string().
1249 {
1250
1251 RETURN_VALUE_IF_NULL( setting, ERROR_NULL_VALUE, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1252 RETURN_VALUE_IF_NULL( function, ERROR_NULL_VALUE, "%s:\"function\"\n", POINTER_NULL_PRINT_STRING );
1253 RETURN_VALUE_IF_NULL( argument_type, ERROR_NULL_VALUE, "%s:\"argument_type\"\n", POINTER_NULL_PRINT_STRING );
1254 RETURN_VALUE_IF_NULL( range_min, ERROR_NULL_VALUE, "%s:\"range_min\"\n", POINTER_NULL_PRINT_STRING );
1255 RETURN_VALUE_IF_NULL( range_max, ERROR_NULL_VALUE, "%s:\"range_max\"\n", POINTER_NULL_PRINT_STRING );
1256
1257 const char *function_string = NULL;
1258 const Error_t lookup_error = _libconfig_lookup_string( setting, "function", &function_string );
1259
1260 if ( lookup_error != ERROR_NONE ) return lookup_error;
1261
1262 for ( unsigned int i = 0; i < LENGTH( FUNCTION_ALIAS_MAP ); i++ ) {
1263 if ( strcasecmp( function_string, FUNCTION_ALIAS_MAP[ i ].alias ) == 0 ) {
1264 *function = FUNCTION_ALIAS_MAP[ i ].function;
1265 *argument_type = FUNCTION_ALIAS_MAP[ i ].argument_type;
1266 *range_min = FUNCTION_ALIAS_MAP[ i ].range_min;
1267 *range_max = FUNCTION_ALIAS_MAP[ i ].range_max;
1268 return ERROR_NONE;
1269 }
1270 }
1271
1272 return ERROR_NOT_FOUND;
1273}
static const Function_Alias_Map_t FUNCTION_ALIAS_MAP[]
Default alias map for dwm's arg functions.
Definition parser.c:365

References _libconfig_lookup_string(), ERROR_NONE, ERROR_NOT_FOUND, ERROR_NULL_VALUE, FUNCTION_ALIAS_MAP, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_bind_core().

◆ _parse_bind_modifier()

Error_t _parse_bind_modifier ( config_setting_t * setting,
unsigned int * modifier )
static

TODO.

TODO

Parameters
[in]settingTODO
[out]modifierTODO
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_ALLOCATION if estrdup() fails to allocate memory.
ERROR_NOT_FOUND if parsed intermediate modifier string does not match any alias found in MODIFIER_ALIAS_MAP.
Any error returned from _libconfig_setting_lookup_string().
See also
https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/X.h
1292 {
1293
1294 RETURN_VALUE_IF_NULL( setting, ERROR_NULL_VALUE, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1295 RETURN_VALUE_IF_NULL( modifier, ERROR_NULL_VALUE, "%s:\"modifier\"\n", POINTER_NULL_PRINT_STRING );
1296
1297 const char *modifier_string = NULL;
1298 const Error_t lookup_error = _libconfig_lookup_string( setting, "modifier", &modifier_string );
1299
1300 if ( lookup_error != ERROR_NONE ) return lookup_error;
1301
1302 char *buffer = estrdup( modifier_string );
1303
1304 if ( buffer == NULL ) return ERROR_ALLOCATION;
1305
1306 char *modifier_token = strtok( buffer, "+" );
1307 while ( modifier_token != NULL ) {
1308
1309 while ( *modifier_token == ' ' || *modifier_token == '\t' ) modifier_token++;
1310
1311 char *end = modifier_token + strlen( modifier_token ) - 1;
1312 while ( end > modifier_token && ( *end == ' ' || *end == '\t' ) ) {
1313 *end = '\0';
1314 end--;
1315 }
1316
1317 bool found = false;
1318 for ( unsigned int i = 0; i < LENGTH( MODIFIER_ALIAS_MAP ); i++ ) {
1319 if ( strcasecmp( modifier_token, MODIFIER_ALIAS_MAP[ i ].alias ) == 0 ) {
1320 *modifier |= MODIFIER_ALIAS_MAP[ i ].modifier;
1321 found = true;
1322 break;
1323 }
1324 }
1325
1326 if ( found == false ) {
1327 LOG_WARN( "Invalid modifier: \"%s\"\n", modifier_token );
1328 free( buffer );
1329 return ERROR_NOT_FOUND;
1330 }
1331
1332 modifier_token = strtok( NULL, "+" );
1333 }
1334
1335 free( buffer );
1336
1337 return ERROR_NONE;
1338}
static const Modifier_Alias_Map_t MODIFIER_ALIAS_MAP[]
Default alias map for common X11 modifiers.
Definition parser.c:390
char * estrdup(const char *string)
Simple wrapper around strdup() to provide error logging.
Definition parser.c:610

References _libconfig_lookup_string(), ERROR_ALLOCATION, ERROR_NONE, ERROR_NOT_FOUND, ERROR_NULL_VALUE, estrdup(), LOG_WARN, MODIFIER_ALIAS_MAP, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_bind_core().

◆ _parse_buttonbind()

Errors_t _parse_buttonbind ( config_setting_t * setting,
const unsigned int index,
Button * buttonbind )
static

TODO.

TODO

Parameters
[in]settingTODO
[in]indexTODO
[out]buttonbindTODO
Returns
TODO
1351 {
1352
1353 Errors_t returned_errors = { 0 };
1354
1355 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
1356 RETURN_ERRORS_IF_NULL( buttonbind, returned_errors, "%s:\"buttonbind\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
1357
1358 copy_errors( &returned_errors, _parse_bind_core( setting, index, &buttonbind->mask, &buttonbind->func, &buttonbind->arg ) );
1359
1360 const Error_t button_error = _parse_buttonbind_button( setting, &buttonbind->button );
1361 add_error( &returned_errors, button_error );
1362
1363 if ( button_error != ERROR_NONE ) {
1364 LOG_WARN( "Buttonbind %d invalid, unable to parse the bind's button: %s\n", index + 1, ERROR_ENUM_STRINGS[ button_error ] );
1365 return returned_errors;
1366 }
1367
1368 const Error_t click_error = _parse_buttonbind_click( setting, &buttonbind->click );
1369 add_error( &returned_errors, click_error );
1370
1371 if ( click_error != ERROR_NONE ) {
1372 LOG_WARN( "Buttonbind %d invalid, unable to parse the bind's click: %s\n", index + 1, ERROR_ENUM_STRINGS[ click_error ] );
1373 }
1374
1375 // Ensure button is zeroed and doesn't accidentally have any
1376 // data left over from parsing that could cause unusual behavior
1377 if ( errors_failure_count( &returned_errors ) != 0 ) {
1378 buttonbind->click = 0;
1379 buttonbind->mask = 0;
1380 buttonbind->button = 0;
1381 buttonbind->func = NULL;
1382 buttonbind->arg.i = 0;
1383 }
1384
1385 return returned_errors;
1386}
int errors_failure_count(const Errors_t *errors)
Counts the number of failure errors present in an Errors_t struct.
Definition parser.c:583
void copy_errors(Errors_t *destination, Errors_t source)
Copy errors from source to destination.
Definition parser.c:563
static Error_t _parse_buttonbind_click(config_setting_t *setting, unsigned int *click)
TODO.
Definition parser.c:1458
static Errors_t _parse_bind_core(config_setting_t *setting, unsigned int bind_index, unsigned int *modifier, void(**function)(const Arg *), Arg *argument)
TODO.
Definition parser.c:1187
static Error_t _parse_buttonbind_button(config_setting_t *setting, unsigned int *button)
TODO.
Definition parser.c:1413

References _parse_bind_core(), _parse_buttonbind_button(), _parse_buttonbind_click(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, errors_failure_count(), LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by _parse_buttonbind_adapter().

◆ _parse_buttonbind_adapter()

Errors_t _parse_buttonbind_adapter ( config_setting_t * setting,
const unsigned int index,
void * buttonbind )
static

Thin adapter function to allow for buttonbind parsing inside a generic array parsing function.

See _parse_buttonbind() for function documentation.

1393 {
1394 return _parse_buttonbind( setting, index, (Button *) buttonbind );
1395}
static Errors_t _parse_buttonbind(config_setting_t *setting, unsigned int index, Button *buttonbind)
TODO.
Definition parser.c:1351

References _parse_buttonbind().

Referenced by _parse_buttonbinds_config().

◆ _parse_buttonbind_button()

Error_t _parse_buttonbind_button ( config_setting_t * setting,
unsigned int * button )
static

TODO.

TODO

Parameters
[in]settingTODO
[out]buttonTODO
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided or if strtoul() failed to properly convert parsed intermediate button string to a number.
ERROR_RANGE If parsed button value exceeds 8 bit mask value limit (255, 8 bit maximum value minus 1) or is 0, an empty/no button.
See also
https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/blob/master/include/X11/X.h
1413 {
1414
1415 RETURN_VALUE_IF_NULL( setting, ERROR_NULL_VALUE, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1417
1418 const char *button_string = NULL;
1419 const Error_t lookup_error = _libconfig_lookup_string( setting, "button", &button_string );
1420
1421 if ( lookup_error != ERROR_NONE ) return lookup_error;
1422
1423 for ( unsigned int i = 0; i < LENGTH( BUTTON_ALIAS_MAP ); i++ ) {
1424 if ( strcasecmp( button_string, BUTTON_ALIAS_MAP[ i ].alias ) == 0 ) {
1425 *button = BUTTON_ALIAS_MAP[ i ].button;
1426 return ERROR_NONE;
1427 }
1428 }
1429
1430 errno = 0;
1431 char *end_pointer = NULL;
1432 const unsigned long parsed_value = strtoul( button_string, &end_pointer, 10 );
1433
1434 if ( errno != 0 || end_pointer == button_string || *end_pointer != '\0' ) return ERROR_NULL_VALUE;
1435
1436 // X11 button mask is only 8 bits, ensure it fits
1437 if ( parsed_value == 0 || parsed_value >= Button1Mask ) return ERROR_RANGE;
1438
1439 *button = (unsigned int) parsed_value;
1440
1441 return ERROR_NONE;
1442}
static const Button_Alias_Map_t BUTTON_ALIAS_MAP[]
Default alias map for common X11 buttons.
Definition parser.c:351

References _libconfig_lookup_string(), BUTTON_ALIAS_MAP, ERROR_NONE, ERROR_NULL_VALUE, ERROR_RANGE, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_buttonbind().

◆ _parse_buttonbind_click()

Error_t _parse_buttonbind_click ( config_setting_t * setting,
unsigned int * click )
static

TODO.

TODO

Parameters
[in]settingTODO
[out]clickTODO
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_NOT_FOUND if parsed intermediate click string does not match any alias found in CLICK_ALIAS_MAP.
Any error returned from _libconfig_setting_lookup_string().
1458 {
1459
1460 RETURN_VALUE_IF_NULL( setting, ERROR_NULL_VALUE, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1462
1463 const char *click_string = NULL;
1464 const Error_t lookup_error = _libconfig_lookup_string( setting, "click", &click_string );
1465
1466 if ( lookup_error != ERROR_NONE ) return lookup_error;
1467
1468 for ( unsigned int i = 0; i < LENGTH( CLICK_ALIAS_MAP ); i++ ) {
1469 if ( strcasecmp( click_string, CLICK_ALIAS_MAP[ i ].alias ) == 0 ) {
1470 *click = CLICK_ALIAS_MAP[ i ].click;
1471 return ERROR_NONE;
1472 }
1473 }
1474
1475 return ERROR_NOT_FOUND;
1476}
static const Click_Alias_Map_t CLICK_ALIAS_MAP[]
Default alias map for dwm's click enum.
Definition parser.c:341

References _libconfig_lookup_string(), CLICK_ALIAS_MAP, ERROR_NONE, ERROR_NOT_FOUND, ERROR_NULL_VALUE, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_buttonbind().

◆ _parse_buttonbinds_config()

Errors_t _parse_buttonbinds_config ( const config_t * config,
Button ** array,
unsigned int * count,
bool * malloced )
static

Parse a list of buttonbinds from a libconfig configuration into a list of Button structs.

TODO

Parameters
[in]configPointer to the libconfig configuration containing the buttonbinds to be parsed into array.
[out]arrayPointer to where to dynamically allocate and store all the parsed buttonbinds.
[out]countPointer to where to store the number of buttonbinds to be parsed. This value does not take into account any failures during parsing the buttonbinds.
[out]mallocedBoolean to track if array has been dynamically allocated yet or not, analogous to if the default buttonbinds are being used or not. Value is set to false after allocation.
Returns
TODO
Note
TODO Maybe mention dynamic allocation in _parse_binds_config()?
1494 {
1495
1496 Errors_t returned_errors = { 0 };
1497 const char *lookup_path = "buttonbinds";
1498
1499 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
1500
1501 config_setting_t *array_setting = NULL;
1502 const Error_t lookup_error = _libconfig_generic_lookup( config_root_setting( config ), lookup_path, CONFIG_TYPE_LIST, &array_setting );
1503 add_error( &returned_errors, lookup_error );
1504
1505 if ( lookup_error != ERROR_NONE ) {
1506 LOG_ERROR( "Lookup of \"%s\" failed: %s\n", lookup_path, ERROR_ENUM_STRINGS[ lookup_error ] );
1507 return returned_errors;
1508 }
1509
1510 const Errors_t array_errors = _parse_setting_array( array_setting, sizeof( Button ), _parse_buttonbind_adapter, malloced, (void **) array, count );
1511 copy_errors( &returned_errors, array_errors );
1512
1513 return returned_errors;
1514}
static Errors_t _parse_setting_array(const config_setting_t *setting, size_t element_size, Array_Element_Parser_Function_t array_element_parser_function, bool *malloced, void **parsed_config, unsigned int *parsed_config_length)
TODO.
Definition parser.c:1950
static Errors_t _parse_buttonbind_adapter(config_setting_t *setting, unsigned int index, void *buttonbind)
Thin adapter function to allow for buttonbind parsing inside a generic array parsing function.
Definition parser.c:1393
#define LOG_ERROR(...)
Log an error message.
Definition parser.c:87

References _libconfig_generic_lookup(), _parse_buttonbind_adapter(), _parse_setting_array(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, LOG_ERROR, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by parse_config().

◆ _parse_font()

Errors_t _parse_font ( config_setting_t * setting,
const unsigned int index,
const char ** font )
static

TODO.

TODO

Parameters
[in]settingTODO
[in]indexTODO
[out]fontTODO
Returns
TODO
1527 {
1528
1529 Errors_t returned_errors = { 0 };
1530
1531 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
1532
1533 if ( config_setting_type( setting ) != CONFIG_TYPE_STRING ) {
1534 LOG_WARN( "Font element at index %u is not a string\n", index );
1535 add_error( &returned_errors, ERROR_TYPE );
1536 return returned_errors;
1537 }
1538
1539 *font = config_setting_get_string( setting );
1540
1541 if ( *font == NULL ) {
1542 LOG_WARN( "Failed to parse theme font at index %u for unknown an reason\n", index );
1543 add_error( &returned_errors, ERROR_NULL_VALUE );
1544 return returned_errors;
1545 }
1546
1547 return returned_errors;
1548}

References add_error(), ERROR_NULL_VALUE, ERROR_TYPE, LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by _parse_font_adapter().

◆ _parse_font_adapter()

Errors_t _parse_font_adapter ( config_setting_t * setting,
const unsigned int index,
void * font )
static

Thin adapter function to allow for font parsing inside a generic array parsing function.

See _parse_font() for function documentation.

1555 {
1556 return _parse_font( setting, index, (const char **) font );
1557}
static Errors_t _parse_font(config_setting_t *setting, unsigned int index, const char **font)
TODO.
Definition parser.c:1527

References _parse_font().

Referenced by _parse_theme().

◆ _parse_generic_settings()

Errors_t _parse_generic_settings ( const config_t * config)
static

Parse generic configuration settings from a libconfig configuration.

TODO

Parameters
[in]configPointer to the libconfig configuration containing the generic settings to be parsed.
Returns
TODO
1568 {
1569
1570 Errors_t returned_errors = { 0 };
1571
1572 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
1573
1574 for ( unsigned int i = 0; i < LENGTH( SETTING_ALIAS_MAP ); ++i ) {
1575 Error_t returned_error = ERROR_NONE;
1576
1577 switch ( SETTING_ALIAS_MAP[ i ].type ) {
1578 case TYPE_BOOLEAN:
1579 returned_error = _libconfig_generic_lookup( config_root_setting( config ), SETTING_ALIAS_MAP[ i ].alias, CONFIG_TYPE_BOOL, SETTING_ALIAS_MAP[ i ].setting );
1580 break;
1581
1582 case TYPE_INT:
1583 returned_error = _libconfig_lookup_int( config_root_setting( config ), SETTING_ALIAS_MAP[ i ].alias, (int) SETTING_ALIAS_MAP[ i ].range_min,
1584 (int) SETTING_ALIAS_MAP[ i ].range_max, SETTING_ALIAS_MAP[ i ].setting );
1585 break;
1586
1587 case TYPE_UINT:
1588 returned_error = _libconfig_lookup_uint( config_root_setting( config ), SETTING_ALIAS_MAP[ i ].alias, (unsigned int) SETTING_ALIAS_MAP[ i ].range_min,
1589 (unsigned int) SETTING_ALIAS_MAP[ i ].range_max, SETTING_ALIAS_MAP[ i ].setting );
1590 break;
1591
1592 case TYPE_FLOAT:
1593 returned_error = _libconfig_lookup_float( config_root_setting( config ), SETTING_ALIAS_MAP[ i ].alias, (float) SETTING_ALIAS_MAP[ i ].range_min,
1594 (float) SETTING_ALIAS_MAP[ i ].range_max, SETTING_ALIAS_MAP[ i ].setting );
1595 break;
1596
1597 case TYPE_STRING:
1598 returned_error = _libconfig_lookup_string( config_root_setting( config ), SETTING_ALIAS_MAP[ i ].alias, SETTING_ALIAS_MAP[ i ].setting );
1599 break;
1600
1601 default:
1602 returned_error = ERROR_TYPE;
1603 LOG_WARN( "Setting \"%s\" is programmed with an invalid type\n", SETTING_ALIAS_MAP[ i ].alias );
1604 break;
1605 }
1606
1607 if ( returned_error != ERROR_NONE ) {
1608 if ( returned_error == ERROR_NOT_FOUND && SETTING_ALIAS_MAP[ i ].optional ) {
1609 LOG_DEBUG( "\"%s\" was not found but is flagged as optional, continuing", SETTING_ALIAS_MAP[ i ].alias );
1610 } else {
1611 add_error( &returned_errors, returned_error );
1612 LOG_WARN( "Issue while parsing \"%s\": %s\n", SETTING_ALIAS_MAP[ i ].alias, ERROR_ENUM_STRINGS[ returned_error ] );
1613 }
1614 }
1615 }
1616
1617 return returned_errors;
1618}
#define LOG_DEBUG(...)
Log a debug message.
Definition parser.c:78
static const Setting_Alias_Map_t SETTING_ALIAS_MAP[]
Default alias map for dwm's global config settings.
Definition parser.c:406

References _libconfig_generic_lookup(), _libconfig_lookup_float(), _libconfig_lookup_int(), _libconfig_lookup_string(), _libconfig_lookup_uint(), add_error(), ERROR_ENUM_STRINGS, ERROR_NONE, ERROR_NOT_FOUND, ERROR_TYPE, LOG_DEBUG, LOG_WARN, POINTER_NULL_PRINT_STRING, RETURN_ERRORS_IF_NULL, SETTING_ALIAS_MAP, TYPE_BOOLEAN, TYPE_FLOAT, TYPE_INT, TYPE_STRING, and TYPE_UINT.

Referenced by parse_config().

◆ _parse_keybind()

Errors_t _parse_keybind ( config_setting_t * setting,
const unsigned int index,
Key * keybind )
static

TODO.

TODO

Parameters
[in]settingTODO
[in]indexTODO
[out]keybindTODO
Returns
TODO
1631 {
1632
1633 Errors_t returned_errors = { 0 };
1634
1635 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1636 RETURN_ERRORS_IF_NULL( keybind, returned_errors, "%s:\"keybind\"\n", POINTER_NULL_PRINT_STRING );
1637
1638 const Errors_t bind_core_errors = _parse_bind_core( setting, index, &keybind->mod, &keybind->func, &keybind->arg );
1639 copy_errors( &returned_errors, bind_core_errors );
1640
1641 const Error_t keysym_error = _parse_keybind_keysym( setting, &keybind->keysym );
1642 add_error( &returned_errors, keysym_error );
1643
1644 if ( keysym_error != ERROR_NONE ) {
1645 LOG_WARN( "Keybind %d invalid, unable to parse the bind's key: %s\n", index + 1, ERROR_ENUM_STRINGS[ keysym_error ] );
1646 }
1647
1648 // Ensure key is zeroed and doesn't accidentally have any
1649 // data left over from parsing that could cause unusual behavior
1650 if ( errors_failure_count( &returned_errors ) != 0 ) {
1651 keybind->mod = 0;
1652 keybind->keysym = NoSymbol;
1653 keybind->func = NULL;
1654 keybind->arg.i = 0;
1655 }
1656
1657 return returned_errors;
1658}
static Error_t _parse_keybind_keysym(config_setting_t *setting, KeySym *keysym)
TODO.
Definition parser.c:1688

References _parse_bind_core(), _parse_keybind_keysym(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, errors_failure_count(), LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by _parse_keybind_adapter().

◆ _parse_keybind_adapter()

Errors_t _parse_keybind_adapter ( config_setting_t * setting,
const unsigned int index,
void * keybind )
static

Thin adapter function to allow for keybind parsing inside a generic array parsing function.

See _parse_keybind() for function documentation.

1665 {
1666 return _parse_keybind( setting, index, (Key *) keybind );
1667}
static Errors_t _parse_keybind(config_setting_t *setting, unsigned int index, Key *keybind)
TODO.
Definition parser.c:1631

References _parse_keybind().

Referenced by _parse_keybinds_config().

◆ _parse_keybind_keysym()

Error_t _parse_keybind_keysym ( config_setting_t * setting,
KeySym * keysym )
static

TODO.

TODO

Parameters
[in]settingTODO
[out]keysymPointer to where to store the parsed keysym value.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_NOT_FOUND if unable to convert parsed string to keysym.
Any error returned from _libconfig_setting_lookup_string().
Note
xev is likely your best bet at finding the keysym values that will work with XStringToKeysym(). If someone knows a better way, please reach out and let me know.
See also
https://gitlab.freedesktop.org/xorg/app/xev
https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/master/src/StrKeysym.c?ref_type=heads#L74
1688 {
1689
1690 RETURN_VALUE_IF_NULL( setting, ERROR_NULL_VALUE, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1692
1693 const char *keybind_string = NULL;
1694 const Error_t lookup_error = _libconfig_lookup_string( setting, "key", &keybind_string );
1695
1696 if ( lookup_error != ERROR_NONE ) return lookup_error;
1697
1698 *keysym = XStringToKeysym( keybind_string );
1699
1700 if ( *keysym == NoSymbol ) {
1701 LOG_WARN( "Failed to convert string (\"%s\") to keysym\n", keybind_string );
1702 return ERROR_NOT_FOUND;
1703 }
1704
1705 // The upper case return of XConvertCase(), which we don't use.
1706 KeySym unused = 0;
1707 XConvertCase( *keysym, keysym, &unused );
1708
1709 return ERROR_NONE;
1710}

References _libconfig_lookup_string(), ERROR_NONE, ERROR_NOT_FOUND, ERROR_NULL_VALUE, LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_keybind().

◆ _parse_keybinds_config()

Errors_t _parse_keybinds_config ( const config_t * config,
Key ** array,
unsigned int * count,
bool * malloced )
static

Parse a list of keybinds from a libconfig configuration into a list of Key structs.

TODO

Parameters
[in]configPointer to the libconfig configuration containing the keybinds to be parsed into array.
[out]arrayPointer to where to dynamically allocate memory and store all the parsed keybinds.
[out]countPointer to where to store the number of keybinds to be parsed. This value does not take into account any failures during parsing the keybinds.
[out]mallocedBoolean to track if array has been dynamically allocated yet or not, analogous to if the default keybinds are being used or not. Value is set to false after allocation.
Returns
TODO
Note
TODO Maybe mention dynamic allocation in _parse_binds_config()?
1729 {
1730
1731 Errors_t returned_errors = { 0 };
1732 const char *lookup_path = "keybinds";
1733
1734 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
1735
1736 config_setting_t *array_setting = NULL;
1737 const Error_t lookup_error = _libconfig_generic_lookup( config_root_setting( config ), lookup_path, CONFIG_TYPE_LIST, &array_setting );
1738 add_error( &returned_errors, lookup_error );
1739
1740 if ( lookup_error != ERROR_NONE ) {
1741 LOG_ERROR( "Lookup of \"%s\" failed: %s\n", lookup_path, ERROR_ENUM_STRINGS[ lookup_error ] );
1742 return returned_errors;
1743 }
1744
1745 const Errors_t array_errors = _parse_setting_array( array_setting, sizeof( Key ), _parse_keybind_adapter, malloced, (void **) array, count );
1746 copy_errors( &returned_errors, array_errors );
1747
1748 return returned_errors;
1749}
static Errors_t _parse_keybind_adapter(config_setting_t *setting, unsigned int index, void *keybind)
Thin adapter function to allow for keybind parsing inside a generic array parsing function.
Definition parser.c:1665

References _libconfig_generic_lookup(), _parse_keybind_adapter(), _parse_setting_array(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, LOG_ERROR, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by parse_config().

◆ _parse_rule()

Errors_t _parse_rule ( config_setting_t * setting,
const unsigned int index,
Rule * rule )
static

Parse a rule from a libconfig configuration setting.

TODO

Parameters
[in]settingPointer to the libconfig setting containing the rule to be parsed into rule.
[in]indexIndex of the current rule in the larger array. Used purely for debug printing.
[out]rulePointer to the Rule struct where the values parsed from setting are stored.
Returns
TODO
1849 {
1850
1851 Errors_t returned_errors = { 0 };
1852
1853 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"config\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
1854 RETURN_ERRORS_IF_NULL( rule, returned_errors, "%s:\"rule\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
1855
1856 add_error( &returned_errors, _libconfig_lookup_string( setting, "class", &rule->class ) );
1857 add_error( &returned_errors, _libconfig_lookup_string( setting, "instance", &rule->instance ) );
1858 add_error( &returned_errors, _libconfig_lookup_string( setting, "title", &rule->title ) );
1859 add_error( &returned_errors, _libconfig_lookup_uint( setting, "tag-mask", 0, TAGMASK, &rule->tags ) );
1860 add_error( &returned_errors, _libconfig_lookup_int( setting, "monitor", -1, 99, &rule->monitor ) );
1861
1862 // This logically should be a boolean value, but I didn't want to
1863 // deviate from the coded type, so I kept it an int and range check it.
1864 add_error( &returned_errors, _libconfig_lookup_int( setting, "floating", 0, 1, &rule->isfloating ) );
1865
1866 // Ensure rule is zeroed and doesn't accidentally have any
1867 // data left over from parsing that could cause unusual behavior
1868 if ( errors_failure_count( &returned_errors ) != 0 ) {
1869 rule->class = NULL;
1870 rule->instance = NULL;
1871 rule->title = NULL;
1872 rule->tags = 0;
1873 rule->isfloating = 0;
1874 rule->monitor = 0;
1875 }
1876
1877 LOG_DEBUG( "Rule %d: class: \"%s\", instance: \"%s\", title: \"%s\", tag-mask: %d, monitor: %d, floating: %d\n", rule_index, parsed_rule->class, parsed_rule->instance, parsed_rule->title,
1878 parsed_rule->tags, parsed_rule->monitor, parsed_rule->isfloating );
1879
1880 return returned_errors;
1881}

References _libconfig_lookup_int(), _libconfig_lookup_string(), _libconfig_lookup_uint(), add_error(), errors_failure_count(), LOG_DEBUG, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by _parse_rule_adapter().

◆ _parse_rule_adapter()

Errors_t _parse_rule_adapter ( config_setting_t * setting,
const unsigned int index,
void * rule )
static

Thin adapter function to allow for rule parsing inside a generic array parsing function.

See _parse_rule() for function documentation.

1888 {
1889 return _parse_rule( setting, index, (Rule *) rule );
1890}
static Errors_t _parse_rule(config_setting_t *setting, unsigned int index, Rule *rule)
Parse a rule from a libconfig configuration setting.
Definition parser.c:1849

References _parse_rule().

Referenced by _parse_rules_config().

◆ _parse_rules_config()

Errors_t _parse_rules_config ( const config_t * config,
Rule ** array,
unsigned int * count,
bool * malloced )
static

Parse a list of rules from a libconfig configuration into a list of Rule structs.

TODO

Parameters
[in]configPointer to the libconfig configuration containing the rules to be parsed into array.
[out]arrayPointer to where to dynamically allocate memory and store all the parsed rules.
[out]countPointer to where to store the number of rules to be parsed. This value does not take into account any failures during parsing the rules.
[out]mallocedBoolean to track if array has been dynamically allocated yet or not, analogous to if the default rules are being used or not. Value is set to false after allocation.
Returns
TODO
Todo
Check for NULL pointers from function arguments. Possible able to use lookup_path in logs instead of repeating message
1908 {
1909
1910 Errors_t returned_errors = { 0 };
1911 const char *lookup_path = "rules";
1912
1913 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
1914
1915 config_setting_t *array_setting = NULL;
1916 const Error_t lookup_error = _libconfig_generic_lookup( config_root_setting( config ), lookup_path, CONFIG_TYPE_LIST, &array_setting );
1917 add_error( &returned_errors, lookup_error );
1918
1919 if ( lookup_error != ERROR_NONE ) {
1920 LOG_ERROR( "Lookup of \"%s\" failed: %s\n", lookup_path, ERROR_ENUM_STRINGS[ lookup_error ] );
1921 return returned_errors;
1922 }
1923
1924 const Errors_t array_errors = _parse_setting_array( array_setting, sizeof( Rule ), _parse_rule_adapter, malloced, (void **) array, count );
1925 copy_errors( &returned_errors, array_errors );
1926
1927 return returned_errors;
1928}
static Errors_t _parse_rule_adapter(config_setting_t *setting, unsigned int index, void *rule)
Thin adapter function to allow for rule parsing inside a generic array parsing function.
Definition parser.c:1888

References _libconfig_generic_lookup(), _parse_rule_adapter(), _parse_setting_array(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, LOG_ERROR, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by parse_config().

◆ _parse_setting_array()

Errors_t _parse_setting_array ( const config_setting_t * setting,
const size_t element_size,
const Array_Element_Parser_Function_t array_element_parser_function,
bool * malloced,
void ** parsed_config,
unsigned int * parsed_config_length )
static

TODO.

TODO

Parameters
[in]settingTODO
[in]element_sizeTODO
[in]array_element_parser_functionTODO
[in,out]mallocedTODO
[in,out]parsed_configTODO
[out]parsed_config_lengthTODO
Returns
TODO
Todo
It may be worth trying to add some kind of safeguard to fall back on default config if enough elements fail to be parsed. For example, if the keybinds all (or many) fail, it could soft-lock the user in the program. Not sure best way to do that, or if it is even the best idea to add.
Todo
The logic around malloced and null checking parsed_config before allocation is brittle, needs work.
1951 {
1952
1953 Errors_t returned_errors = { 0 };
1954
1955 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\"\n", POINTER_NULL_PRINT_STRING );
1956 RETURN_ERRORS_IF_NULL( parsed_config_length, returned_errors, "%s:\"parsed_config_length\"\n", POINTER_NULL_PRINT_STRING );
1957
1958 const char *setting_name = NULL;
1959 const Error_t setting_name_error = _libconfig_get_setting_name( setting, &setting_name );
1960
1961 if ( setting_name_error != ERROR_NONE ) {
1962 LOG_WARN( "Unable to acquire setting name, logs in this function may not print correctly: %s\n", ERROR_ENUM_STRINGS[ setting_name_error ] );
1963 }
1964
1965 *parsed_config_length = config_setting_length( setting );
1966 if ( *parsed_config_length == 0 ) {
1967 LOG_ERROR( "No %s listed. Default values will be used\n", setting_name );
1968 add_error( &returned_errors, ERROR_NOT_FOUND );
1969 return returned_errors;
1970 }
1971
1972 LOG_DEBUG( "%u elements detected in \"%s\"\n", *parsed_config_length, setting_name );
1973
1974 // malloced is also used to determine if we should dynamically
1975 // allocate the array or if it is already allocated some other
1976 // way, usually on the stack, as well as report that it has
1977 // been dynamically allocated here.
1978 if ( malloced != NULL && parsed_config != NULL ) {
1979
1980 if ( element_size == 0 ) {
1981 LOG_ERROR( "Cannot allocate memory correctly if element size to allocate is 0\n" );
1982 add_error( &returned_errors, ERROR_RANGE );
1983 return returned_errors;
1984 }
1985
1986 LOG_DEBUG( "Dynamically allocating %lu bytes of memory for \"%s\"\n", *parsed_config_length * element_size, setting_name );
1987
1988 errno = 0;
1989 void *calloced_memory = calloc( *parsed_config_length, element_size );
1990
1991 if ( calloced_memory == NULL ) {
1992 LOG_ERROR( "Failed to allocate %lu bytes for \"%s\": %s\n", *parsed_config_length * element_size, setting_name, strerror(errno) );
1993 add_error( &returned_errors, ERROR_ALLOCATION );
1994 return returned_errors;
1995 }
1996
1997 *parsed_config = calloced_memory;
1998 *malloced = true;
1999 }
2000
2001 for ( unsigned int i = 0; i < *parsed_config_length; i++ ) {
2002
2003 config_setting_t *child_setting = config_setting_get_elem( setting, i );
2004
2005 RETURN_ERRORS_IF_NULL( child_setting, returned_errors, "Element index %u in \"%s\" returned NULL\n", i, setting_name );
2006
2007 // Yes, parsed_config can be NULL, that is intended. It is used by things like
2008 // theme or tag parsing that rely on global values.
2009 void *element = parsed_config ? (char *) ( *parsed_config ) + ( i * element_size ) : NULL;
2010
2011 const Errors_t parsing_error = array_element_parser_function( child_setting, i, element );
2012
2013 if ( errors_failure_count( &parsing_error ) ) {
2014 LOG_WARN( "\"%s\" element number %d failed to be parsed. It had %d errors\n", setting_name, i + 1, errors_failure_count( &parsing_error ) );
2015 copy_errors( &returned_errors, parsing_error );
2016 continue;
2017 }
2018 }
2019
2020 return returned_errors;
2021}

References _libconfig_get_setting_name(), add_error(), copy_errors(), ERROR_ALLOCATION, ERROR_ENUM_STRINGS, ERROR_NONE, ERROR_NOT_FOUND, ERROR_RANGE, errors_failure_count(), LOG_DEBUG, LOG_ERROR, LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by _parse_buttonbinds_config(), _parse_keybinds_config(), _parse_rules_config(), _parse_tags_config(), _parse_theme(), and _parse_theme_config().

◆ _parse_tag()

Errors_t _parse_tag ( config_setting_t * setting,
const unsigned int index )
static

TODO.

TODO

Parameters
[in]settingTODO
[out]indexTODO
Returns
TODO
2033 {
2034
2035 Errors_t returned_errors = { 0 };
2036
2037 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
2038
2039 if ( index >= LENGTH( tags ) ) {
2040 LOG_WARN( "Parsed tag's index exceeds limits of the tags array\n" );
2041 add_error( &returned_errors, ERROR_RANGE );
2042 return returned_errors;
2043 }
2044
2045 const char *original_tag_name = tags[ index ];
2046
2047 if ( config_setting_type( setting ) != CONFIG_TYPE_STRING ) {
2048 LOG_WARN( "Tag element at index %u is not a string\n", index );
2049 add_error( &returned_errors, ERROR_TYPE );
2050 return returned_errors;
2051 }
2052
2053 tags[ index ] = config_setting_get_string( setting );
2054
2055 if ( tags[ index ] == NULL ) {
2056 tags[ index ] = original_tag_name;
2057 LOG_WARN( "Failed to parse tag at index %u for unknown an reason\n", index );
2058 add_error( &returned_errors, ERROR_NULL_VALUE );
2059 return returned_errors;
2060 }
2061
2062 return returned_errors;
2063}

References add_error(), ERROR_NULL_VALUE, ERROR_RANGE, ERROR_TYPE, LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by _parse_tags_adapter().

◆ _parse_tags_adapter()

Errors_t _parse_tags_adapter ( config_setting_t * setting,
const unsigned int index,
void * unused )
static

Thin adapter function to allow for tag parsing inside a generic array parsing function.

See _parse_tag() for function documentation.

2070 {
2071 return _parse_tag( setting, index );
2072}
static Errors_t _parse_tag(config_setting_t *setting, unsigned int index)
TODO.
Definition parser.c:2033

References _parse_tag().

Referenced by _parse_tags_config().

◆ _parse_tags_config()

Errors_t _parse_tags_config ( const config_t * config)
static

Parse a list of tags from a libconfig configuration.

TODO

Parameters
[in]configPointer to the libconfig configuration containing the tags to be parsed.
Returns
TODO
2083 {
2084
2085 const char *lookup_path = "tags";
2086 unsigned int tags_count = 0;
2087 Errors_t returned_errors = { 0 };
2088
2089 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
2090
2091 config_setting_t *array_setting = NULL;
2092 const Error_t lookup_error = _libconfig_generic_lookup( config_root_setting( config ), lookup_path, CONFIG_TYPE_LIST, &array_setting );
2093 add_error( &returned_errors, lookup_error );
2094
2095 if ( lookup_error != ERROR_NONE ) {
2096 LOG_ERROR( "Lookup of \"%s\" failed: %s\n", lookup_path, ERROR_ENUM_STRINGS[ lookup_error ] );
2097 return returned_errors;
2098 }
2099
2100 const Errors_t array_errors = _parse_setting_array( array_setting, 0, _parse_tags_adapter, NULL, NULL, &tags_count );
2101 copy_errors( &returned_errors, array_errors );
2102
2103 if ( tags_count > LENGTH( tags ) ) {
2104 LOG_WARN( "More than %lu tag names detected (%d were detected) while parsing config, only the first %lu will be used\n", LENGTH( tags ), tags_count, LENGTH( tags ) );
2105 } else if ( tags_count < LENGTH( tags ) ) {
2106 LOG_WARN( "Less than %lu tag names detected while parsing config, default tags will be used for the remainder\n", LENGTH( tags ) );
2107 }
2108
2109 return returned_errors;
2110}
static Errors_t _parse_tags_adapter(config_setting_t *setting, unsigned int index, void *unused)
Thin adapter function to allow for tag parsing inside a generic array parsing function.
Definition parser.c:2070

References _libconfig_generic_lookup(), _parse_setting_array(), _parse_tags_adapter(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, LOG_ERROR, LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by parse_config().

◆ _parse_theme()

Errors_t _parse_theme ( config_setting_t * setting,
const unsigned int index )
static

Parse a theme from a libconfig configuration setting.

TODO

Parameters
[in]settingPointer to the libconfig setting containing the theme to be parsed.
[in]indexIndex of the current theme being parsed.
Returns
TODO
2122 {
2123
2124 Errors_t returned_errors = { 0 };
2125
2126 RETURN_ERRORS_IF_NULL( setting, returned_errors, "%s:\"setting\" at index %d\n", POINTER_NULL_PRINT_STRING, index );
2127
2128 // dwm does not support more than 1 theme
2129 if ( index > 0 ) {
2130 LOG_WARN( "%d themes detected. dwm can only supports using 1 theme\n", index + 1 );
2131 add_error( &returned_errors, ERROR_RANGE );
2132 return returned_errors;
2133 }
2134
2135 const char *fonts_lookup_path = "fonts";
2136 config_setting_t *array_setting = NULL;
2137 const Error_t lookup_error = _libconfig_generic_lookup( setting, fonts_lookup_path, CONFIG_TYPE_LIST, &array_setting );
2138 add_error( &returned_errors, lookup_error );
2139
2140 if ( lookup_error != ERROR_NONE ) {
2141 LOG_ERROR( "Lookup of \"%s\" failed: %s\n", fonts_lookup_path, ERROR_ENUM_STRINGS[ lookup_error ] );
2142 return returned_errors;
2143 }
2144
2145 const Errors_t font_errors = _parse_setting_array( array_setting, sizeof( char * ), _parse_font_adapter, &fonts_malloced, (void **) &fonts, &fonts_count );
2146 copy_errors( &returned_errors, font_errors );
2147
2148 for ( unsigned int i = 0; i < LENGTH( THEME_ALIAS_MAP ); i++ ) {
2149 const Error_t error = _libconfig_lookup_string( setting, THEME_ALIAS_MAP[ i ].alias, THEME_ALIAS_MAP[ i ].color );
2150 add_error( &returned_errors, error );
2151 if ( error != ERROR_NONE ) {
2152 LOG_WARN( "Failed to parse theme %d's element \"%s\": %s\n", index, THEME_ALIAS_MAP[ i ].alias, ERROR_ENUM_STRINGS[ error ] );
2153 }
2154 }
2155
2156 return returned_errors;
2157}
bool fonts_malloced
Boolean tracking whether fonts has been dynamically allocated.
Definition parser.c:244
const char ** fonts
Array of current fonts.
Definition parser.c:234
unsigned int fonts_count
Number of elements in fonts_count.
Definition parser.c:239
static Errors_t _parse_font_adapter(config_setting_t *setting, unsigned int index, void *font)
Thin adapter function to allow for font parsing inside a generic array parsing function.
Definition parser.c:1555
static const Theme_Alias_Map_t THEME_ALIAS_MAP[]
Default alias map for dwm's scheme indexes.
Definition parser.c:419

References _libconfig_generic_lookup(), _libconfig_lookup_string(), _parse_font_adapter(), _parse_setting_array(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, ERROR_RANGE, fonts, fonts_count, fonts_malloced, LOG_ERROR, LOG_WARN, POINTER_NULL_PRINT_STRING, RETURN_ERRORS_IF_NULL, and THEME_ALIAS_MAP.

Referenced by _parse_theme_adapter().

◆ _parse_theme_adapter()

Errors_t _parse_theme_adapter ( config_setting_t * setting,
const unsigned int index,
void * unused )
static

Thin adapter function to allow for theme parsing inside a generic array parsing function.

See _parse_theme() for function documentation.

2164 {
2165 return _parse_theme( setting, index );
2166}
static Errors_t _parse_theme(config_setting_t *setting, unsigned int index)
Parse a theme from a libconfig configuration setting.
Definition parser.c:2122

References _parse_theme().

Referenced by _parse_theme_config().

◆ _parse_theme_config()

Errors_t _parse_theme_config ( const config_t * config)
static

Parse a list of themes from a libconfig configuration.

TODO

Parameters
[in]configPointer to the libconfig configuration containing the theme to be parsed.
Returns
TODO
Note
dwm only supports a single theme, so only the first theme in the list is parsed.
2179 {
2180
2181 Errors_t returned_errors = { 0 };
2182 const char *lookup_path = "themes";
2183
2184 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
2185
2186 config_setting_t *array_setting = NULL;
2187 const Error_t lookup_error = _libconfig_generic_lookup( config_root_setting( config ), lookup_path, CONFIG_TYPE_LIST, &array_setting );
2188 add_error( &returned_errors, lookup_error );
2189
2190 if ( lookup_error != ERROR_NONE ) {
2191 LOG_ERROR( "Lookup of \"%s\" failed: %s\n", lookup_path, ERROR_ENUM_STRINGS[ lookup_error ] );
2192 return returned_errors;
2193 }
2194
2195 unsigned int unused = 0;
2196 const Errors_t array_errors = _parse_setting_array( array_setting, 0, _parse_theme_adapter, NULL, NULL, &unused );
2197 copy_errors( &returned_errors, array_errors );
2198
2199 return returned_errors;
2200}
static Errors_t _parse_theme_adapter(config_setting_t *setting, unsigned int index, void *unused)
Thin adapter function to allow for theme parsing inside a generic array parsing function.
Definition parser.c:2164

References _libconfig_generic_lookup(), _parse_setting_array(), _parse_theme_adapter(), add_error(), copy_errors(), ERROR_ENUM_STRINGS, ERROR_NONE, LOG_ERROR, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by parse_config().

◆ _parser_backup_config()

Error_t _parser_backup_config ( config_t * config)
static

Backs up a libconfig configuration to disk.

This function backs up the given libconfig config_t, config, following the XDG specification. If the function get_xdg_data_home() fails to find the XDG data directory (which is likely), we will default to using "~/.local/share/" instead. Meaning that, in the latter case, the filepath to the backup file will be "~/.local/share/dwm/dwm_last.conf". "/dwm/dwm_last.conf" will always be appended to the end of whatever path is returned by get_xdg_data_home(). The backup file is then created and written to by libconfig's config_write_file().

Parameters
[in]configPointer to the libconfig configuration to be backed up.
Returns
ERROR_NONE on success.
ERROR_NULL_VALUE if a NULL argument is provided.
ERROR_NOT_FOUND if the call to get_xdg_data_home() failed to provide necessary directory.
ERROR_ALLOCATION if any calls to extend_string() were unable to allocate necessary memory to construct the complete backup filepath.
ERROR_IO if libconfig failed to write config to a file.
1078 {
1079
1081
1082 // Save xdg data directory to buffer (~/.local/share)
1083 char *buffer = get_xdg_data_home();
1084
1085 RETURN_VALUE_IF_NULL( buffer, ERROR_NOT_FOUND, "Failed to get parent backup directory path\n" );
1086
1087 // Append buffer (already has "~/.local/share" or other xdg data directory)
1088 // with the directory we want to backup the config to, create the directory
1089 // if it doesn't exist, and then extend with the filename we want to backup
1090 // to config in.
1091 extend_string( &buffer, "/dwm/" );
1092 RETURN_VALUE_IF_NULL( buffer, ERROR_ALLOCATION, "%s for backup directory path\n", FAILED_ALLOC_PRINT_STRING );
1093
1094 if ( make_directory_path( buffer ) != 0 ) return ERROR_IO;
1095
1096 extend_string( &buffer, "dwm_last.conf" );
1097 RETURN_VALUE_IF_NULL( buffer, ERROR_ALLOCATION, "%s for backup file path\n", FAILED_ALLOC_PRINT_STRING );
1098
1099 if ( config_write_file( config, buffer ) == CONFIG_FALSE ) {
1100 LOG_ERROR( "Failed to write configuration to \"%s\"\n", buffer );
1101 free( buffer );
1102 return ERROR_IO;
1103 }
1104
1105 LOG_INFO( "Current config backed up to \"%s\"\n", buffer );
1106 free( buffer );
1107
1108 return ERROR_NONE;
1109}
const char * FAILED_ALLOC_PRINT_STRING
Common string used for logging memory allocation issues.
Definition parser.c:259
int make_directory_path(const char *path)
Creates all directories in a given path if they don't exist.
Definition parser.c:848
#define LOG_INFO(...)
Log an informational message.
Definition parser.c:81
void extend_string(char **source_string, const char *addition)
Extend one string with another.
Definition parser.c:647
char * get_xdg_data_home(void)
Get the user's XDG data directory path.
Definition parser.c:752

References ERROR_ALLOCATION, ERROR_IO, ERROR_NONE, ERROR_NOT_FOUND, ERROR_NULL_VALUE, extend_string(), FAILED_ALLOC_PRINT_STRING, get_xdg_data_home(), LOG_ERROR, LOG_INFO, make_directory_path(), POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by parse_config().

◆ _parser_open_config_file()

Errors_t _parser_open_config_file ( config_t * config,
const char * custom_config_filepath,
char ** found_config_filepath,
bool * fallback_config_loaded )
static

Attempts to find, open, and store a valid libconfig configuration file.

This function handles most of the high level logic regarding finding, opening, validating, and storing a libconfig configuration file. This function will first search for a custom configuration file, passed in using config_filepath. If that is not found, a list of default directories are searched. If still no user configuration is found, a user's last configuration backup will be attempted to be loaded. If again unsuccessful, a system default configuration file will be loaded. Finally, if all else fails, the function will return and the program will rely on the hardcoded default values loaded from config.h

Parameters
[in]configTODO
[in]custom_config_filepathTODO
[out]found_config_filepathTODO
[out]fallback_config_loadedTODO
Returns
TODO
Todo

These error returns may not be the most accurate, not sure exactly the best fits.

Should the parser even look for another config file if one is passed from the CLI? Could be deceptive behavior.

1773 {
1774
1775 Errors_t returned_errors = { 0 };
1776
1777 RETURN_ERRORS_IF_NULL( config, returned_errors, "%s:\"config\"\n", POINTER_NULL_PRINT_STRING );
1778 RETURN_ERRORS_IF_NULL( found_config_filepath, returned_errors, "%s:\"found_config_filepath\"\n", POINTER_NULL_PRINT_STRING );
1779 RETURN_ERRORS_IF_NULL( fallback_config_loaded, returned_errors, "%s:\"fallback_config_loaded\"\n", POINTER_NULL_PRINT_STRING );
1780
1781 char *xdg_config_home = get_xdg_config_home();
1782 char *xdg_data_home = get_xdg_data_home();
1783
1784 const struct Filepath {
1785 const char *filepath_1;
1786 const char *filepath_2;
1787 const bool is_fallback_config;
1788 } config_filepaths[ ] = {
1789 { custom_config_filepath, "", false },
1790 { xdg_config_home, "/dwm.conf", false },
1791 { xdg_config_home, "/dwm/dwm.conf", false },
1792 { xdg_data_home, "/dwm/dwm_last.conf", true },
1793 { "/etc/dwm.conf", "", true }
1794 };
1795
1796 for ( unsigned int i = 0; i < LENGTH( config_filepaths ); i++ ) {
1797 char constructed_path[ PATH_MAX ];
1798
1799 if ( config_filepaths[ i ].filepath_1 != NULL && config_filepaths[ i ].filepath_2 != NULL ) {
1800 snprintf( constructed_path, sizeof( constructed_path ), "%s%s", config_filepaths[ i ].filepath_1, config_filepaths[ i ].filepath_2 );
1801 } else {
1802 LOG_DEBUG( "Part of a path at index %d was NULL while trying top open a configuration file, skipping invalid path\n", i );
1803 continue;
1804 }
1805
1806 LOG_DEBUG( "Attempting to open config file \"%s\"\n", constructed_path );
1807
1808 FILE *configuration_file = fopen( constructed_path, "r" );
1809
1810 if ( configuration_file == NULL ) {
1811 LOG_DEBUG( "Unable to open config file \"%s\"\n", constructed_path );
1812 continue;
1813 }
1814
1815 if ( config_read( config, configuration_file ) == CONFIG_FALSE ) {
1816 LOG_WARN( "Problem parsing config file \"%s\", line %d: %s\n", constructed_path, config_error_line( config ), config_error_text( config ) );
1817 add_error( &returned_errors, ERROR_NULL_VALUE );
1818 fclose( configuration_file );
1819 continue;
1820 }
1821
1822 *found_config_filepath = estrdup( constructed_path );
1823 if ( *found_config_filepath == NULL ) add_error( &returned_errors, ERROR_ALLOCATION );
1824
1825 *fallback_config_loaded = config_filepaths[ i ].is_fallback_config;
1826
1827 fclose( configuration_file );
1828
1829 break;
1830 }
1831
1832 free( xdg_config_home );
1833 free( xdg_data_home );
1834
1835 return returned_errors;
1836}
char * get_xdg_config_home(void)
Get the user's XDG configuration directory path.
Definition parser.c:716

References add_error(), ERROR_ALLOCATION, ERROR_NULL_VALUE, estrdup(), get_xdg_config_home(), get_xdg_data_home(), LOG_DEBUG, LOG_WARN, POINTER_NULL_PRINT_STRING, and RETURN_ERRORS_IF_NULL.

Referenced by parse_config().

◆ add_error()

void add_error ( Errors_t * errors,
const Error_t error )

Adds an error to an Errors_t struct.

This function acts as a simple way to increment the error count of an Errors_t struct at the correct error index.

Parameters
[out]errorsPointer to an Errors_t struct to add error to.
[in]errorError to be added to the error count in errors.
543 {
544
545 RETURN_IF_NULL( errors, "%s:\"errors\"\n", POINTER_NULL_PRINT_STRING );
546
547 if ( error < ERROR_ENUM_LENGTH ) {
548 errors->errors_count[ error ]++;
549 }
550}
#define RETURN_IF_NULL(check,...)
Return function if variable is NULL.
Definition parser.c:126
unsigned int errors_count[ERROR_ENUM_LENGTH]
Array of error counts for every enum of Error_t.
Definition parser.c:186

References ERROR_ENUM_LENGTH, Errors_t::errors_count, POINTER_NULL_PRINT_STRING, and RETURN_IF_NULL.

Referenced by _parse_bind_core(), _parse_buttonbind(), _parse_buttonbinds_config(), _parse_font(), _parse_generic_settings(), _parse_keybind(), _parse_keybinds_config(), _parse_rule(), _parse_rules_config(), _parse_setting_array(), _parse_tag(), _parse_tags_config(), _parse_theme(), _parse_theme_config(), _parser_open_config_file(), and parse_config().

◆ config_cleanup()

void config_cleanup ( void )

Frees dynamically allocated parser data.

Frees all dynamically allocated data allocated during the parsing process. Intended for use before program exit and after parse_config().

439 {
440
441 if ( config_filepath != NULL ) free( config_filepath );
442
443 if ( rules_malloced == false ) free( rules );
444 if ( keys_malloced == false ) free( keys );
445 if ( buttons_malloced == false ) free( buttons );
446 if ( fonts_malloced == false ) free( fonts );
447
448 config_destroy( &libconfig_config );
449}
bool rules_malloced
Boolean tracking whether rules has been dynamically allocated.
Definition parser.c:243
bool buttons_malloced
Boolean tracking whether buttons has been dynamically allocated.
Definition parser.c:242
bool keys_malloced
Boolean tracking whether keys has been dynamically allocated.
Definition parser.c:241
Button * buttons
Array of current buttons.
Definition parser.c:232
char * config_filepath
Path to the currently loaded configuration's file.
Definition parser.c:229
config_t libconfig_config
Master libconfig configuration context used for parsing.
Definition parser.c:228
Rule * rules
Array of current rules.
Definition parser.c:233
Key * keys
Array of current keybinds.
Definition parser.c:231

References buttons, buttons_malloced, config_filepath, fonts, fonts_malloced, keys, keys_malloced, libconfig_config, rules, and rules_malloced.

◆ copy_errors()

void copy_errors ( Errors_t * destination,
const Errors_t source )

Copy errors from source to destination.

This function copies the errors in source to the Errors_t struct pointed to by destination. It does not alter the errors in source. If the pointer to destination is NULL, an error will be logged and the function will return.

Parameters
[out]destinationPointer to where to copy errors to.
[in]sourceErrors to copy.
563 {
564
565 RETURN_IF_NULL( destination, "%s:\"destination\"\n", POINTER_NULL_PRINT_STRING );
566
567 for ( unsigned int i = 0; i < ERROR_ENUM_LENGTH; i++ ) {
568 destination->errors_count[ i ] += source.errors_count[ i ];
569 }
570}

References ERROR_ENUM_LENGTH, Errors_t::errors_count, POINTER_NULL_PRINT_STRING, and RETURN_IF_NULL.

Referenced by _parse_buttonbind(), _parse_buttonbinds_config(), _parse_keybind(), _parse_keybinds_config(), _parse_rules_config(), _parse_setting_array(), _parse_tags_config(), _parse_theme(), _parse_theme_config(), and parse_config().

◆ errors_failure_count()

int errors_failure_count ( const Errors_t * errors)

Counts the number of failure errors present in an Errors_t struct.

This function acts as a simple way to count the number of failure errors present in an Errors_t struct.

Parameters
[in]errorsPointer to an Errors_t struct to count errors from.
Returns
-1 if errors is NULL, else the total of the number of failure errors present in errors.
583 {
584
585 RETURN_VALUE_IF_NULL( errors, -1, "%s:\"errors\"\n", POINTER_NULL_PRINT_STRING );
586
587 int count = 0;
588
589 for ( unsigned int i = ERROR_NONE + 1; i < ERROR_ENUM_LENGTH; i++ ) {
590 count += (int) errors->errors_count[ i ];
591 }
592
593 return count;
594}

References ERROR_ENUM_LENGTH, ERROR_NONE, Errors_t::errors_count, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_buttonbind(), _parse_keybind(), _parse_rule(), _parse_setting_array(), and parse_config().

◆ estrdup()

char * estrdup ( const char * string)

Simple wrapper around strdup() to provide error logging.

This function acts as a simple wrapper around strdup() that provides some NULL safety as well as error logging around strdup(). It can be used as a drop in replacement for strdup() safely.

Parameters
[in]stringString to be copied.
Returns
NULL if allocation failed or string was NULL, or the pointer to a dynamically allocated duplicate of string.
Note
Returned string is dynamically allocated and will need to be manually freed.
610 {
611
612 RETURN_VALUE_IF_NULL( string, NULL, "%s:\"string\"\n", POINTER_NULL_PRINT_STRING );
613
614 errno = 0;
615 char *return_string = strdup( string );
616
617 RETURN_VALUE_IF_NULL( return_string, NULL, "%s using strdup(): %s\n", FAILED_ALLOC_PRINT_STRING, strerror(errno) );
618
619 return return_string;
620}

References FAILED_ALLOC_PRINT_STRING, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parse_bind_modifier(), _parser_open_config_file(), extend_string(), get_xdg_config_home(), and get_xdg_data_home().

◆ extend_string()

void extend_string ( char ** source_string,
const char * addition )

Extend one string with another.

This function reallocates and extends the string pointed to by source_string with the string addition. If either the pointer to source_string or addition are NULL, the function will log an error and return. If the string at source_string is NULL, addition will be copied into it's place using dynamic allocation. If all succeeds, then the string pointed to by source_string will be dynamically reallocated to contain both the source string and addition, and will need to be freed manually.

Parameters
[in,out]source_stringPointer to the string to be extended with addition. Must point to a NULL or heap allocated string.
[in]additionAdditional string to be appended to the string pointed to by source_string.
Warning
String at source_string must be NULL or heap allocated. If it points to a string literal, realloc() will crash the program. See join_strings() if you wish to append a string literal.
Note
  1. source_string is or will be dynamically allocated and must be manually freed.
  2. This function is derived from picom's mstrextend(). Credit more or less goes to Yuxuan Shui, I just made some minor adjustments.
Author
Yuxuan Shui - yshui.nosp@m.v7@g.nosp@m.mail..nosp@m.com
See also
https://github.com/yshui/picom
https://github.com/yshui/picom/blob/69539edc0638019e3dd88c67007e90ce7f51174e/src/utils/str.c#L54
647 {
648
649 RETURN_IF_NULL( source_string, "%s:\"source_string\"\n", POINTER_NULL_PRINT_STRING );
650 RETURN_IF_NULL( addition, "%s:\"addition\"\n", POINTER_NULL_PRINT_STRING );
651
652 if ( *source_string == NULL ) {
653 *source_string = estrdup( addition );
654 LOG_DEBUG( "Source string was NULL, addition was copied into its place\n" );
655 return;
656 }
657
658 const size_t source_length = strlen( *source_string );
659 const size_t addition_length = strlen( addition );
660 const size_t total_length = source_length + addition_length + 1; // +1 for NULL termination
661
662 errno = 0;
663 *source_string = realloc( *source_string, total_length * sizeof( char ) );
664
665 RETURN_IF_NULL( *source_string, "%s (%lu bytes) using realloc(): %s\n", FAILED_ALLOC_PRINT_STRING, total_length * sizeof( char ), strerror(errno) );
666
667 strncpy( *source_string + source_length, addition, addition_length );
668 ( *source_string )[ total_length - 1 ] = '\0';
669}

References estrdup(), FAILED_ALLOC_PRINT_STRING, LOG_DEBUG, POINTER_NULL_PRINT_STRING, and RETURN_IF_NULL.

Referenced by _parser_backup_config().

◆ get_layout()

const Layout * get_layout ( void(* arrange )(Monitor *))

Find and return a layout that uses a specific arrange function.

This function searches the global array layouts for a layout struct that contains arrange. If it is found, a pointer to it is returned, else NULL is returned.

Parameters
[in]arrangeArrange function used by the layout to be found and returned.
Returns
Pointer to the found layout or NULL if no layout containing arrange was found.
Note
This function assumes that only one layout uses the given arrange function. If multiple layouts use the same arrange function, then this function will simply return the first one in the array using that arrange function.
686 {
687
688 for ( unsigned int i = 0; i < LENGTH( layouts ); i++ ) {
689 if ( layouts[ i ].arrange == arrange ) {
690 return &layouts[ i ];
691 }
692 }
693
694 return NULL;
695}

Referenced by setlayout_floating(), setlayout_monocle(), and setlayout_tiled().

◆ get_xdg_config_home()

char * get_xdg_config_home ( void )

Get the user's XDG configuration directory path.

TODO

Returns
Pointer of a dynamically allocated string containing the complete path to the user's XDG configuration directory, or NULL if no directory was able to be found.
Note
  1. If the function is successful, the returned string will have been dynamically allocated and will need to be manually freed.
  2. This function is derived from picom's xdg_config_home(). Credit more or less goes to Yuxuan Shui, I just made some minor adjustments.
Author
Yuxuan Shui - yshui.nosp@m.v7@g.nosp@m.mail..nosp@m.com
See also
https://github.com/yshui/picom
https://github.com/yshui/picom/blob/69539edc0638019e3dd88c67007e90ce7f51174e/src/config.c#L33
716 {
717
718 char *xdg_config_home = getenv( "XDG_CONFIG_HOME" );
719 const char *user_home = getenv( "HOME" );
720
721 LOG_DEBUG( "XDG_CONFIG_HOME: \"%s\", HOME: \"%s\"\n", xdg_config_home, user_home );
722
723 if ( xdg_config_home == NULL ) {
724 const char *default_config_directory = "/.config";
725
726 RETURN_VALUE_IF_NULL( user_home, NULL, "XDG_CONFIG_HOME and HOME are not set\n" );
727
728 xdg_config_home = join_strings( user_home, default_config_directory );
729 } else {
730 xdg_config_home = estrdup( xdg_config_home );
731 }
732
733 return xdg_config_home;
734}
char * join_strings(const char *string_1, const char *string_2)
Join two strings into one.
Definition parser.c:798

References estrdup(), join_strings(), LOG_DEBUG, and RETURN_VALUE_IF_NULL.

Referenced by _parser_open_config_file().

◆ get_xdg_data_home()

char * get_xdg_data_home ( void )

Get the user's XDG data directory path.

TODO

Returns
Pointer of a dynamically allocated string containing the complete path to the user's XDG data directory, or NULL if no directory was able to be found.
Note
This function is derived from picom's xdg_config_home(). Credit more or less goes to Yuxuan Shui, I just made some minor adjustments.
Author
Yuxuan Shui - yshui.nosp@m.v7@g.nosp@m.mail..nosp@m.com
See also
https://github.com/yshui/picom
https://github.com/yshui/picom/blob/69539edc0638019e3dd88c67007e90ce7f51174e/src/config.c#L33
752 {
753
754 char *xdg_data_home = getenv( "XDG_DATA_HOME" );
755 const char *user_home = getenv( "HOME" );
756
757 LOG_DEBUG( "XDG_DATA_HOME: \"%s\", HOME: \"%s\"\n", xdg_data_home, user_home );
758
759 if ( xdg_data_home == NULL ) {
760 const char *default_data_directory = "/.local/share";
761
762 RETURN_VALUE_IF_NULL( user_home, NULL, "XDG_DATA_HOME and HOME are not set\n" );
763
764 xdg_data_home = join_strings( user_home, default_data_directory );
765 } else {
766 xdg_data_home = estrdup( xdg_data_home );
767 }
768
769 return xdg_data_home;
770}

References estrdup(), join_strings(), LOG_DEBUG, and RETURN_VALUE_IF_NULL.

Referenced by _parser_backup_config(), and _parser_open_config_file().

◆ join_strings()

char * join_strings ( const char * string_1,
const char * string_2 )

Join two strings into one.

TODO

Parameters
[in]string_1String for string_2 to be appended to.
[in]string_2String to be appended to string_1.
Returns
Pointer of a dynamically allocated string containing the now joined strings, or NULL on failure.
Note
  1. Returned string is dynamically allocated and will need to be manually freed.
  2. This function is derived from picom's mstrjoin(). Credit more or less goes to Yuxuan Shui, I just made some minor adjustments.
  3. gcc warns about legitimate truncation worries in strncpy(). strncpy( joined_string, string_1, length_1 ) intentionally truncates the null byte from string_1, however. strncpy( joined_string + length_1, string_2, length_2 ) uses bounds depending on the source argument, but joined_string is allocated with length_1 + length_2 + 1, so this strncpy() can't overflow.
Author
Yuxuan Shui - yshui.nosp@m.v7@g.nosp@m.mail..nosp@m.com
See also
https://github.com/yshui/picom
https://github.com/yshui/picom/blob/69961987e1238f9bc3af53fa0774fc19fdec44a4/src/utils/str.c#L24
798 {
799
800 RETURN_VALUE_IF_NULL( string_1, NULL, "%s:\"string_1\"\n", POINTER_NULL_PRINT_STRING );
801 RETURN_VALUE_IF_NULL( string_2, NULL, "%s:\"string_2\"\n", POINTER_NULL_PRINT_STRING );
802
803 const size_t length_1 = strlen( string_1 );
804 const size_t length_2 = strlen( string_2 );
805 const size_t total_length = length_1 + length_2 + 1;
806
807 errno = 0;
808 char *joined_string = calloc( total_length, sizeof( char ) );
809
810 RETURN_VALUE_IF_NULL( joined_string, NULL, "%s (%lu bytes) using calloc(): %s\n", FAILED_ALLOC_PRINT_STRING, total_length * sizeof( char ), strerror(errno) )
811
812 #ifndef __clang__
813 #pragma GCC diagnostic push
814 #pragma GCC diagnostic ignored "-Wpragmas"
815 #pragma GCC diagnostic ignored "-Wstringop-truncation"
816 #pragma GCC diagnostic ignored "-Wstringop-overflow"
817 #endif
818
819 strncpy( joined_string, string_1, length_1 );
820 strncpy( joined_string + length_1, string_2, length_2 );
821
822 #ifndef __clang__
823 #pragma GCC diagnostic pop
824 #endif
825
826 joined_string[ total_length - 1 ] = '\0';
827
828 return joined_string;
829}

References FAILED_ALLOC_PRINT_STRING, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by get_xdg_config_home(), and get_xdg_data_home().

◆ make_directory_path()

int make_directory_path ( const char * path)

Creates all directories in a given path if they don't exist.

TODO

Parameters
[in]pathString containing the directory path to attempt to create.
Returns
0 on success, -1 on failure.
Note
This function is derived from dwm-ipc's mkdirp(). Credit more or less goes to Mihir Lad, I just made some minor adjustments.
Author
Mihir Lad - mihir.nosp@m.lad5.nosp@m.5@gma.nosp@m.il.c.nosp@m.om
See also
https://github.com/mihirlad55/dwm-ipc
https://github.com/mihirlad55/dwm-ipc/blob/b3eebba7c043482d454afc5c882f513fc1b157ad/util.c#L103
848 {
849
850 RETURN_VALUE_IF_NULL( path, -1, "%s:\"path\"\n", POINTER_NULL_PRINT_STRING );
851
852 char *normalized_path = NULL;
853
854 if ( normalize_path( path, &normalized_path ) != 0 ) {
855 LOG_ERROR( "Unable to make directory path because path normalization failed" );
856 return -1;
857 }
858
859 const char *walk = normalized_path;
860 const size_t normalized_path_length = strlen( normalized_path );
861
862 while ( walk < normalized_path + normalized_path_length + 1 ) {
863
864 // Get length from walk to next '/'
865 const size_t distance_to_slash = strcspn( walk, "/" );
866
867 // Skip path /
868 if ( distance_to_slash == 0 ) {
869 walk++;
870 continue;
871 }
872
873 // Length of current path segment
874 const size_t current_path_length = walk - normalized_path + distance_to_slash;
875 char current_path[ current_path_length + 1 ];
876
877 struct stat stat_variable;
878
879 // Copy path segment to stat
880 strncpy( current_path, normalized_path, current_path_length );
881 strcpy( current_path + current_path_length, "" );
882
883 errno = 0;
884 if ( stat( current_path, &stat_variable ) < 0 ) {
885 if ( errno == ENOENT ) {
886 LOG_DEBUG( "Making directory %s\n", current_path );
887 if ( mkdir( current_path, 0700 ) < 0 ) {
888 LOG_ERROR( "Failed to make directory \"%s\": %s\n", current_path, strerror( errno ) );
889 free( normalized_path );
890 return -1;
891 }
892 } else {
893 LOG_ERROR( "Error stat-ing directory \"%s\": %s\n", current_path, strerror( errno ) );
894 free( normalized_path );
895 return -1;
896 }
897 }
898
899 // Continue to next path segment
900 walk += distance_to_slash;
901 }
902
903 free( normalized_path );
904 return 0;
905}
int normalize_path(const char *original_path, char **normalized_path)
Normalize a file or folder path to remove repeat forward slash characters.
Definition parser.c:928

References LOG_DEBUG, LOG_ERROR, normalize_path(), POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by _parser_backup_config().

◆ normalize_path()

int normalize_path ( const char * original_path,
char ** normalized_path )

Normalize a file or folder path to remove repeat forward slash characters.

TODO

Parameters
[in]original_pathString containing the path to be normalized.
[out]normalized_pathPointer to where to store the normalized path. It is dynamically allocated and will need to be manually freed.
Returns
0 on success, -1 on failure.
Note
  1. normalized_path can be dynamically allocated and will need to be manually freed.
  2. This function is derived from dwm-ipc's normalizepath(). Credit more or less goes to Mihir Lad, I just made some minor adjustments.
Author
Mihir Lad - mihir.nosp@m.lad5.nosp@m.5@gma.nosp@m.il.c.nosp@m.om
See also
https://github.com/mihirlad55/dwm-ipc
https://github.com/mihirlad55/dwm-ipc/blob/b3eebba7c043482d454afc5c882f513fc1b157ad/util.c#L40
928 {
929
930 RETURN_VALUE_IF_NULL( original_path, -1, "%s:\"original_path\"\n", POINTER_NULL_PRINT_STRING );
931 RETURN_VALUE_IF_NULL( normalized_path, -1, "%s:\"normalized_path\"\n", POINTER_NULL_PRINT_STRING );
932
933 const size_t original_length = strlen( original_path );
934
935 errno = 0;
936 *normalized_path = calloc( ( original_length + 1 ), sizeof( char ) );
937
938 RETURN_VALUE_IF_NULL( *normalized_path, -1, "%s (%lu bytes) using calloc(): %s\n", FAILED_ALLOC_PRINT_STRING, ( original_length + 1 ) * sizeof( char ), strerror(errno) );
939
940 size_t new_length = 0;
941 const char *match, *walk = original_path;
942 while ( ( match = strchr( walk, '/' ) ) ) {
943
944 // Copy everything between match and walk
945 strncpy( *normalized_path + new_length, walk, match - walk );
946 new_length += match - walk;
947 walk += match - walk;
948
949 // Skip all repeating slashes
950 while ( *walk == '/' ) walk++;
951
952 // If not last character in path
953 if ( walk != original_path + original_length ) ( *normalized_path )[ new_length++ ] = '/';
954 }
955
956 ( *normalized_path )[ new_length++ ] = '\0';
957
958 // Copy remaining path
959 strcat( *normalized_path, walk );
960 new_length += strlen( walk );
961
962 errno = 0;
963 *normalized_path = realloc( *normalized_path, new_length * sizeof( char ) );
964
965 RETURN_VALUE_IF_NULL( *normalized_path, -1, "%s (%lu bytes) using realloc(): %s\n", FAILED_ALLOC_PRINT_STRING, new_length * sizeof( char ), strerror(errno) );
966
967 return 0;
968}

References FAILED_ALLOC_PRINT_STRING, POINTER_NULL_PRINT_STRING, and RETURN_VALUE_IF_NULL.

Referenced by make_directory_path().

◆ parse_config()

Errors_t parse_config ( void )

Parse program configuration from a configuration file.

This function serves as the entry point into the configuration parser of the dwm-libconfig patch. This function serves as a high level entry to the configuration parser. It largely calls helper functions to handle the actual parsing of the configuration file in various segmented and modular steps.

For more information on the specific details on what actions the parser performs, please reference the helper function related to the functionality you want to learn more about, they all have their own documentation and comments.

Returns
An Errors_t struct containing all collected errors (including ERROR_NONE) while parsing the configuration. See Error_t for a list of possible error types.
Todo

Polish the status texts a little. I like the idea but could be refined.

Backup config file logic is clumsily structured, it should be improved. It also probably should include rules_malloced

470 {
471
472 Errors_t returned_errors = { 0 };
473
474 config_init( &libconfig_config );
475
476 bool fallback_config_loaded = false;
477 const char *custom_config_filepath = config_filepath;
478 config_filepath = NULL;
479 copy_errors( &returned_errors, _parser_open_config_file( &libconfig_config, custom_config_filepath, &config_filepath, &fallback_config_loaded ) );
480
481 // Exit the parser if we haven't acquired a configuration file.
482 // Without a configuration file, there isn't a reason to continue parsing.
483 // The program will have to rely on the hardcoded default values instead.
484 if ( config_filepath == NULL ) {
485 LOG_ERROR( "Unable to load any configs. Hardcoded default config values will be used. Exiting parsing\n" );
486 SET_STATUS_TEXT( "Failed to load config file" );
487 config_destroy( &libconfig_config );
488 return returned_errors;
489 }
490
491 LOG_INFO( "Path to config file: \"%s\"\n", config_filepath );
492
493 config_set_options( &libconfig_config, CONFIG_OPTION_AUTOCONVERT | CONFIG_OPTION_SEMICOLON_SEPARATORS );
494
495 Errors_t parsing_errors = { 0 };
496
501 copy_errors( &parsing_errors, _parse_tags_config( &libconfig_config ) );
502 copy_errors( &parsing_errors, _parse_theme_config( &libconfig_config ) );
503
504 // The error requirement being 0 may be a bit strict, I am not sure. May need
505 // some relaxing or possibly come up with a better way of calculating if a config
506 // passes, or is valid enough to warrant backing up.
507 if ( errors_failure_count( &parsing_errors ) == 0 && keys_malloced && buttons_malloced && !fallback_config_loaded ) {
508 const Error_t backup_error = _parser_backup_config( &libconfig_config );
509 add_error( &parsing_errors, backup_error );
510 } else {
511 if ( keys_malloced == false || buttons_malloced == false ) {
512 LOG_WARN( "Not saving config as backup, as hardcoded default bind values were used, not the user's\n" );
513 }
514 if ( fallback_config_loaded == true ) {
515 LOG_WARN( "Not saving config as backup, as the parsed configuration file is a system fallback configuration\n" );
516 }
517 if ( errors_failure_count( &parsing_errors ) != 0 ) {
518 LOG_WARN( "Not saving config as backup, as the parsed config had too many (%d) errors\n", errors_failure_count( &parsing_errors ) );
519 }
520 }
521
522 copy_errors( &returned_errors, parsing_errors );
523 LOG_DEBUG( "Parsing errors: %d, Total errors: %d\n", errors_failure_count( &parsing_errors ), errors_failure_count( &returned_errors ) );
524
525 SET_STATUS_TEXT( "%s | Errors: %u", config_filepath, errors_failure_count( &returned_errors ) );
526
527 return returned_errors;
528}
unsigned int buttons_count
Number of elements in buttons.
Definition parser.c:237
static Errors_t _parse_tags_config(const config_t *config)
Parse a list of tags from a libconfig configuration.
Definition parser.c:2083
unsigned int rules_count
Number of elements in rules.
Definition parser.c:238
static Errors_t _parser_open_config_file(config_t *config, const char *custom_config_filepath, char **found_config_filepath, bool *fallback_config_loaded)
Attempts to find, open, and store a valid libconfig configuration file.
Definition parser.c:1773
unsigned int keys_count
Number of elements in keys.
Definition parser.c:236
static Errors_t _parse_rules_config(const config_t *config, Rule **array, unsigned int *count, bool *malloced)
Parse a list of rules from a libconfig configuration into a list of Rule structs.
Definition parser.c:1908
static Errors_t _parse_buttonbinds_config(const config_t *config, Button **array, unsigned int *count, bool *malloced)
Parse a list of buttonbinds from a libconfig configuration into a list of Button structs.
Definition parser.c:1494
static Errors_t _parse_theme_config(const config_t *config)
Parse a list of themes from a libconfig configuration.
Definition parser.c:2179
#define SET_STATUS_TEXT(...)
Macro to easily set status text before first bar draw.
Definition parser.c:136
static Error_t _parser_backup_config(config_t *config)
Backs up a libconfig configuration to disk.
Definition parser.c:1078
static Errors_t _parse_generic_settings(const config_t *config)
Parse generic configuration settings from a libconfig configuration.
Definition parser.c:1568
static Errors_t _parse_keybinds_config(const config_t *config, Key **array, unsigned int *count, bool *malloced)
Parse a list of keybinds from a libconfig configuration into a list of Key structs.
Definition parser.c:1729

References _parse_buttonbinds_config(), _parse_generic_settings(), _parse_keybinds_config(), _parse_rules_config(), _parse_tags_config(), _parse_theme_config(), _parser_backup_config(), _parser_open_config_file(), add_error(), buttons, buttons_count, buttons_malloced, config_filepath, copy_errors(), errors_failure_count(), keys, keys_count, keys_malloced, libconfig_config, LOG_DEBUG, LOG_ERROR, LOG_INFO, LOG_WARN, rules, rules_count, rules_malloced, and SET_STATUS_TEXT.

◆ setlayout_floating()

void setlayout_floating ( const Arg * arg)

Set current layout to floating.

This is a wrapper for the setlayout() function. It sets the currently focused monitor's layout to the floating layout found in the layouts array.

Parameters
argUnused.
979 {
980
981 const Layout *layout = get_layout( NULL ); // NULL is floating layout's arrange function
982
983 RETURN_IF_NULL( layout, "Failed to get floating layout" );
984
985 setlayout( &(Arg){ .v = layout } );
986}
const Layout * get_layout(void(*arrange)(Monitor *))
Find and return a layout that uses a specific arrange function.
Definition parser.c:686

References get_layout(), and RETURN_IF_NULL.

◆ setlayout_monocle()

void setlayout_monocle ( const Arg * arg)

Set current layout to monocle.

This is a wrapper for the setlayout() function. It sets the currently focused monitor's layout to the monocle layout found in the layouts array.

Parameters
argUnused.
997 {
998
999 const Layout *layout = get_layout( monocle );
1000
1001 RETURN_IF_NULL( layout, "Failed to get monocle layout" );
1002
1003 setlayout( &(Arg){ .v = layout } );
1004}

References get_layout(), and RETURN_IF_NULL.

◆ setlayout_tiled()

void setlayout_tiled ( const Arg * arg)

Set current layout to tile.

This is a wrapper for the setlayout() function. It sets the currently focused monitor's layout to the tile layout found in the layouts array.

Parameters
argUnused.
1015 {
1016
1017 const Layout *layout = get_layout( tile );
1018
1019 RETURN_IF_NULL( layout, "Failed to get tile layout" );
1020
1021 setlayout( &(Arg){ .v = layout } );
1022}

References get_layout(), and RETURN_IF_NULL.

◆ spawn_string()

void spawn_string ( const Arg * arg)

Wrapper around spawn() for simpler program spawning.

This wrapper is to simplify the parsers interaction with the spawn() function. It takes in the program name and arguments as a string from Arg, prepares them with the necessary shell executable and flag, and then passes it all to spawn().

Parameters
[in]argPointer to the Arg struct containing a null terminated string containing the name and arguments of the program to spawn.
1036 {
1037
1038 RETURN_IF_NULL( arg, "%s:\"arg\"\n", POINTER_NULL_PRINT_STRING );
1039 RETURN_IF_NULL( arg->v, "%s:\"arg->v\"\n", POINTER_NULL_PRINT_STRING );
1040
1041 const char *cmd = arg->v;
1042 char *argv[ ] = { "/bin/sh", "-c", (char *) cmd, NULL };
1043 const Arg tmp = { .v = argv };
1044
1045 LOG_DEBUG( "Attempting to spawn \"%s\"\n", (char *) cmd );
1046 spawn( &tmp );
1047}

References LOG_DEBUG, POINTER_NULL_PRINT_STRING, and RETURN_IF_NULL.

Variable Documentation

◆ _parser_filepath

const char* _parser_filepath
static

Parser filepath string.

This variable is to save on binary size. By instead referencing this string when logging, we don't add hundreds of repeat string literals to the binary, saving roughly 4kb on the final binary.

◆ BUTTON_ALIAS_MAP

const Button_Alias_Map_t BUTTON_ALIAS_MAP[]
static

Default alias map for common X11 buttons.

351 {
352 { "leftclick", Button1 },
353 { "left-click", Button1 },
354 { "middleclick", Button2 },
355 { "middle-click", Button2 },
356 { "rightclick", Button3 },
357 { "right-click", Button3 },
358 { "scrollup", Button4 },
359 { "scroll-up", Button4 },
360 { "scrolldown", Button5 },
361 { "scroll-down", Button5 },
362};

Referenced by _parse_buttonbind_button().

◆ CLICK_ALIAS_MAP

const Click_Alias_Map_t CLICK_ALIAS_MAP[]
static

Default alias map for dwm's click enum.

341 {
342 { "tag", ClkTagBar },
343 { "layout", ClkLtSymbol },
344 { "status", ClkStatusText },
345 { "title", ClkWinTitle },
346 { "client", ClkClientWin },
347 { "desktop", ClkRootWin },
348};

Referenced by _parse_buttonbind_click().

◆ ERROR_ENUM_STRINGS

const char* ERROR_ENUM_STRINGS[]

String name pairs to Error_t.

256{ "None", "Not found", "Invalid type", "Out of range", "Null value", "Failed to allocate memory", "I/O exception" };

Referenced by _parse_bind_core(), _parse_buttonbind(), _parse_buttonbinds_config(), _parse_generic_settings(), _parse_keybind(), _parse_keybinds_config(), _parse_rules_config(), _parse_setting_array(), _parse_tags_config(), _parse_theme(), and _parse_theme_config().

◆ FUNCTION_ALIAS_MAP

const Function_Alias_Map_t FUNCTION_ALIAS_MAP[]
static

Default alias map for dwm's arg functions.

365 {
366 { "focusmon", focusmon, TYPE_INT, -99, 99 },
367 { "focusstack", focusstack, TYPE_INT, -99, 99 },
368 { "incnmaster", incnmaster, TYPE_INT, -99, 99 },
369 { "killclient", killclient, TYPE_NONE },
370 { "movemouse", movemouse, TYPE_NONE },
371 { "quit", quit, TYPE_NONE },
372 { "resizemouse", resizemouse, TYPE_NONE },
373 { "setlayout-tiled", setlayout_tiled, TYPE_NONE },
374 { "setlayout-floating", setlayout_floating, TYPE_NONE },
375 { "setlayout-monocle", setlayout_monocle, TYPE_NONE },
376 { "setlayout-toggle", setlayout, TYPE_NONE },
377 { "setmfact", setmfact, TYPE_FLOAT, -0.95f, 1.95f },
378 { "spawn", spawn_string, TYPE_STRING },
379 { "tag", tag, TYPE_INT, -1, TAGMASK },
380 { "tagmon", tagmon, TYPE_INT, -99, 99 },
381 { "togglebar", togglebar, TYPE_NONE },
382 { "togglefloating", togglefloating, TYPE_NONE },
383 { "toggletag", toggletag, TYPE_INT, -1, TAGMASK },
384 { "toggleview", toggleview, TYPE_INT, -1, TAGMASK },
385 { "view", view, TYPE_INT, -1, TAGMASK },
386 { "zoom", zoom, TYPE_NONE },
387};
void setlayout_monocle(const Arg *arg)
Set current layout to monocle.
Definition parser.c:997
void setlayout_tiled(const Arg *arg)
Set current layout to tile.
Definition parser.c:1015
void spawn_string(const Arg *arg)
Wrapper around spawn() for simpler program spawning.
Definition parser.c:1036
void setlayout_floating(const Arg *arg)
Set current layout to floating.
Definition parser.c:979

Referenced by _parse_bind_function().

◆ MODIFIER_ALIAS_MAP

const Modifier_Alias_Map_t MODIFIER_ALIAS_MAP[]
static

Default alias map for common X11 modifiers.

390 {
391 { "super", Mod4Mask },
392 { "control", ControlMask },
393 { "ctrl", ControlMask },
394 { "shift", ShiftMask },
395 { "alt", Mod1Mask },
396 { "caps", LockMask },
397 { "capslock", LockMask },
398 { "mod1", Mod1Mask },
399 { "mod2", Mod2Mask },
400 { "mod3", Mod3Mask },
401 { "mod4", Mod4Mask },
402 { "mod5", Mod5Mask },
403};

Referenced by _parse_bind_modifier().

◆ SETTING_ALIAS_MAP

const Setting_Alias_Map_t SETTING_ALIAS_MAP[]
static

Default alias map for dwm's global config settings.

406 {
407 { "showbar", &showbar, TYPE_BOOLEAN, true },
408 { "topbar", &topbar, TYPE_BOOLEAN, true },
409 { "resizehints", &resizehints, TYPE_BOOLEAN, true },
410 { "lockfullscreen", &lockfullscreen, TYPE_BOOLEAN, true },
411 { "borderpx", &borderpx, TYPE_UINT, true, 0, 9999 },
412 { "snap", &snap, TYPE_UINT, true, 0, 9999 },
413 { "nmaster", &nmaster, TYPE_UINT, true, 0, 99 },
414 { "refreshrate", &refreshrate, TYPE_UINT, true, 0, 999 },
415 { "mfact", &mfact, TYPE_FLOAT, true, 0.05f, 0.95f },
416};

Referenced by _parse_generic_settings().

◆ THEME_ALIAS_MAP

const Theme_Alias_Map_t THEME_ALIAS_MAP[]
static

Default alias map for dwm's scheme indexes.

419 {
420 { "normal-foreground", &colors[ SchemeNorm ][ ColFg ] },
421 { "normal-background", &colors[ SchemeNorm ][ ColBg ] },
422 { "normal-border", &colors[ SchemeNorm ][ ColBorder ] },
423 { "selected-foreground", &colors[ SchemeSel ][ ColFg ] },
424 { "selected-background", &colors[ SchemeSel ][ ColBg ] },
425 { "selected-border", &colors[ SchemeSel ][ ColBorder ] },
426};

Referenced by _parse_theme().