1*eee6300fSDevin Teske.\" Copyright (c) 2013-2018 Devin Teske <dteske@FreeBSD.org> 2041394f3SDevin Teske.\" All rights reserved. 3041394f3SDevin Teske.\" 4041394f3SDevin Teske.\" Redistribution and use in source and binary forms, with or without 5041394f3SDevin Teske.\" modification, are permitted provided that the following conditions 6041394f3SDevin Teske.\" are met: 7041394f3SDevin Teske.\" 1. Redistributions of source code must retain the above copyright 8041394f3SDevin Teske.\" notice, this list of conditions and the following disclaimer. 9041394f3SDevin Teske.\" 2. Redistributions in binary form must reproduce the above copyright 10041394f3SDevin Teske.\" notice, this list of conditions and the following disclaimer in the 11041394f3SDevin Teske.\" documentation and/or other materials provided with the distribution. 12041394f3SDevin Teske.\" 13041394f3SDevin Teske.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14041394f3SDevin Teske.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15041394f3SDevin Teske.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16041394f3SDevin Teske.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17041394f3SDevin Teske.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18041394f3SDevin Teske.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19041394f3SDevin Teske.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20041394f3SDevin Teske.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21041394f3SDevin Teske.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22041394f3SDevin Teske.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23041394f3SDevin Teske.\" SUCH DAMAGE. 24041394f3SDevin Teske.\" 255d8a5640SDevin Teske.Dd March 13, 2018 26041394f3SDevin Teske.Dt FIGPAR 3 27041394f3SDevin Teske.Os 28041394f3SDevin Teske.Sh NAME 29041394f3SDevin Teske.Nm figpar , 30041394f3SDevin Teske.Nm parse_config , 31041394f3SDevin Teske.Nm get_config_option 32041394f3SDevin Teske.Nd configuration file parsing library 33041394f3SDevin Teske.Sh LIBRARY 34041394f3SDevin Teske.Lb libfigpar 35041394f3SDevin Teske.Sh SYNOPSIS 36041394f3SDevin Teske.In figpar.h 37041394f3SDevin Teske.Ft int 38041394f3SDevin Teske.Fo parse_config 397d57771bSDevin Teske.Fa "struct figpar_config options[]" 407d57771bSDevin Teske.Fa "const char *path" 417d57771bSDevin Teske.Fa "int \*[lp]*unknown\*[rp]\*[lp]struct figpar_config *option" 427d57771bSDevin Teske.Fa "uint32_t line" 437d57771bSDevin Teske.Fa "char *directive" 447d57771bSDevin Teske.Fa "char *value\*[rp]" 457d57771bSDevin Teske.Fa "uint8_t processing_options" 46041394f3SDevin Teske.Fc 479d9cc246SDevin Teske.Ft "struct figpar_config *" 48041394f3SDevin Teske.Fo get_config_option 497d57771bSDevin Teske.Fa "struct figpar_config options[]" 507d57771bSDevin Teske.Fa "const char *directive" 51041394f3SDevin Teske.Fc 52041394f3SDevin Teske.In string_m.h 53041394f3SDevin Teske.Ft int 54041394f3SDevin Teske.Fo replaceall 557d57771bSDevin Teske.Fa "char *source" 567d57771bSDevin Teske.Fa "const char *find" 577d57771bSDevin Teske.Fa "const char *replace" 58041394f3SDevin Teske.Fc 59041394f3SDevin Teske.Ft unsigned int 60041394f3SDevin Teske.Fo strcount 617d57771bSDevin Teske.Fa "const char *source" 627d57771bSDevin Teske.Fa "const char *find" 63041394f3SDevin Teske.Fc 64041394f3SDevin Teske.Ft void 65041394f3SDevin Teske.Fo strexpand 66041394f3SDevin Teske.Fa "char *source" 67041394f3SDevin Teske.Fc 68041394f3SDevin Teske.Ft void 69041394f3SDevin Teske.Fo strexpandnl 70041394f3SDevin Teske.Fa "char *source" 71041394f3SDevin Teske.Fc 72041394f3SDevin Teske.Ft void 73041394f3SDevin Teske.Fo strtolower 74041394f3SDevin Teske.Fa "char *source" 75041394f3SDevin Teske.Fc 76041394f3SDevin Teske.Sh DESCRIPTION 77041394f3SDevin TeskeThe 78041394f3SDevin Teske.Nm 797d57771bSDevin Teskelibrary provides a light-weight, 807d57771bSDevin Teskeportable framework for parsing configuration 81041394f3SDevin Teskefiles. 82041394f3SDevin TeskeThe library uses 83041394f3SDevin Teske.Xr open 2 , 84041394f3SDevin Teske.Xr read 2 , 85041394f3SDevin Teskeand 86041394f3SDevin Teske.Xr lseek 2 87041394f3SDevin Teskewithin the file pointed to by 88041394f3SDevin Teske.Fa path 89041394f3SDevin Tesketo find directives and values which are then made available to the application. 90041394f3SDevin Teske.Pp 91041394f3SDevin TeskeDue to the fact that configuration files may have basic syntax differences, 92041394f3SDevin Teskethe library does not attempt to impose any structure on the data but instead 93041394f3SDevin Teskeprovides raw data to a set of callback functions. 94041394f3SDevin TeskeThese callback functions can in-turn initiate abort through their return value, 95041394f3SDevin Teskeallowing custom syntax validation during parsing. 96041394f3SDevin Teske.Pp 977d57771bSDevin TeskeConfiguration directives, 987d57771bSDevin Tesketypes, 997d57771bSDevin Teskeand callback functions are provided through data structures defined in 100041394f3SDevin Teske.In figpar.h : 101041394f3SDevin Teske.Bd -literal -offset indent 1029d9cc246SDevin Teskestruct figpar_config { 1039d9cc246SDevin Teske enum figpar_cfgtype type; /* value type */ 104041394f3SDevin Teske const char *directive; /* keyword */ 1059d9cc246SDevin Teske union figpar_cfgvalue value; /* value */ 106041394f3SDevin Teske 107041394f3SDevin Teske /* Pointer to function used when directive is found */ 1089d9cc246SDevin Teske int (*action)(struct figpar_config *option, uint32_t line, 109041394f3SDevin Teske char *directive, char *value); 110041394f3SDevin Teske}; 111041394f3SDevin Teske 1129d9cc246SDevin Teskeenum figpar_cfgtype { 1139d9cc246SDevin Teske FIGPAR_TYPE_NONE = 0x0000, /* directives with no value */ 1149d9cc246SDevin Teske FIGPAR_TYPE_BOOL = 0x0001, /* boolean */ 1159d9cc246SDevin Teske FIGPAR_TYPE_INT = 0x0002, /* signed 32 bit integer */ 1169d9cc246SDevin Teske FIGPAR_TYPE_UINT = 0x0004, /* unsigned 32 bit integer */ 1179d9cc246SDevin Teske FIGPAR_TYPE_STR = 0x0008, /* string pointer */ 1189d9cc246SDevin Teske FIGPAR_TYPE_STRARRAY = 0x0010, /* string array pointer */ 1199d9cc246SDevin Teske FIGPAR_TYPE_DATA1 = 0x0020, /* void data type-1 (open) */ 1209d9cc246SDevin Teske FIGPAR_TYPE_DATA2 = 0x0040, /* void data type-2 (open) */ 1219d9cc246SDevin Teske FIGPAR_TYPE_DATA3 = 0x0080, /* void data type-3 (open) */ 1229d9cc246SDevin Teske FIGPAR_TYPE_RESERVED1 = 0x0100, /* reserved data type-1 */ 1239d9cc246SDevin Teske FIGPAR_TYPE_RESERVED2 = 0x0200, /* reserved data type-2 */ 1249d9cc246SDevin Teske FIGPAR_TYPE_RESERVED3 = 0x0400, /* reserved data type-3 */ 125041394f3SDevin Teske}; 126041394f3SDevin Teske 1279d9cc246SDevin Teskeunion figpar_cfgvalue { 128041394f3SDevin Teske void *data; /* Pointer to NUL-terminated string */ 129041394f3SDevin Teske char *str; /* Pointer to NUL-terminated string */ 130041394f3SDevin Teske char **strarray; /* Pointer to an array of strings */ 131041394f3SDevin Teske int32_t num; /* Signed 32-bit integer value */ 132041394f3SDevin Teske uint32_t u_num; /* Unsigned 32-bit integer value */ 133041394f3SDevin Teske uint32_t boolean:1; /* Boolean integer value (0 or 1) */ 134041394f3SDevin Teske}; 135041394f3SDevin Teske.Ed 136041394f3SDevin Teske.Pp 137041394f3SDevin TeskeThe 138041394f3SDevin Teske.Fa processing_options 139041394f3SDevin Teskeargument to 140041394f3SDevin Teske.Fn parse_config 141041394f3SDevin Teskeis a mask of bit fields which indicate various 142041394f3SDevin Teskeprocessing options. 1437d57771bSDevin TeskeThe possible flags are: 1449d9cc246SDevin Teske.Bl -tag -width FIGPAR_BREAK_ON_SEMICOLON 1459d9cc246SDevin Teske.It Dv FIGPAR_BREAK_ON_EQUALS 146041394f3SDevin TeskeAn equals sign 147041394f3SDevin Teske.Pq Ql Li = 148041394f3SDevin Teskeis normally considered part of the directive. 149041394f3SDevin TeskeThis flag enables terminating the directive at the equals sign. 150041394f3SDevin TeskeAlso makes equals sign optional and transient. 1519d9cc246SDevin Teske.It Dv FIGPAR_BREAK_ON_SEMICOLON 152041394f3SDevin TeskeA semicolon 153041394f3SDevin Teske.Pq Ql Li \; 154041394f3SDevin Teskeis normally considered part of the value. 155041394f3SDevin TeskeThis flag enables terminating the value at the semicolon. 156041394f3SDevin TeskeAlso allows multiple statements on a single line separated by semicolon. 1579d9cc246SDevin Teske.It Dv FIGPAR_CASE_SENSITIVE 158041394f3SDevin TeskeNormally directives are matched case insensitively using 159041394f3SDevin Teske.Xr fnmatch 3 . 160041394f3SDevin TeskeThis flag enables directive matching to be case sensitive. 1619d9cc246SDevin Teske.It Dv FIGPAR_REQUIRE_EQUALS 1627d57771bSDevin TeskeIf a directive is not followed by an equals, 1637d57771bSDevin Teskeprocessing is aborted. 1649d9cc246SDevin Teske.It Dv FIGPAR_STRICT_EQUALS 165041394f3SDevin TeskeEquals must be part of the directive to be considered a delimiter between 166041394f3SDevin Teskedirective and value. 167041394f3SDevin Teske.El 168041394f3SDevin Teske.Pp 169041394f3SDevin TeskeThe 170041394f3SDevin Teske.Fa options 1717d57771bSDevin Teskestruct array pointer can be NULL and every directive will run the 172041394f3SDevin Teske.Fn unknown 173041394f3SDevin Teskefunction argument. 174041394f3SDevin Teske.Pp 1759d9cc246SDevin TeskeThe directive for each figpar_config item in the 176041394f3SDevin Teske.Fn parse_config 177041394f3SDevin Teskeoptions argument is matched against each parsed directive using 178041394f3SDevin Teske.Xr fnmatch 3 179041394f3SDevin Teskeuntil a match is found. 1807d57771bSDevin TeskeIf a match is found, 1817d57771bSDevin Teskethe 182041394f3SDevin Teske.Fn action 1837d57771bSDevin Teskefunction for that figpar_config directive is run with the line number, 1847d57771bSDevin Teskedirective, 1857d57771bSDevin Teskeand value. 1867d57771bSDevin TeskeOtherwise if no match, 1877d57771bSDevin Teskethe 188041394f3SDevin Teske.Fn unknown 1897d57771bSDevin Teskefunction is run 190041394f3SDevin Teske.Pq with the same arguments . 191041394f3SDevin Teske.Pp 192041394f3SDevin TeskeIf either 193041394f3SDevin Teske.Fa action 194041394f3SDevin Teskeor 195041394f3SDevin Teske.Fa unknown 196041394f3SDevin Teskereturn non-zero, 197041394f3SDevin Teske.Fn parse_config 198041394f3SDevin Teskeaborts reading the file and returns the error value to its caller. 199041394f3SDevin Teske.Pp 200041394f3SDevin Teske.Fn get_config_option 201041394f3SDevin Tesketraverses the options-array and returns the option that matches via 202041394f3SDevin Teske.Xr strcmp 3 , 203041394f3SDevin Teskeor if no match a pointer to a static dummy struct is returned 204041394f3SDevin Teske.Pq whose values are all zero or NULL . 205041394f3SDevin Teske.Pp 206041394f3SDevin TeskeThe use of 2079d9cc246SDevin Teske.Fa "struct figpar_config" 208041394f3SDevin Teskeis entirely optional as-is the use of 2099d9cc246SDevin Teske.Fa "enum figpar_cfgtype" 210041394f3SDevin Teskeor 2119d9cc246SDevin Teske.Fa "union figpar_cfgvalue" . 2127d57771bSDevin TeskeFor example, 2137d57771bSDevin Teskea NULL pointer can be passed to 214041394f3SDevin Teske.Fn parse_config 2157d57771bSDevin Teskefor the first argument while providing a simple 216041394f3SDevin Teske.Fa unknown 217041394f3SDevin Teskefunction based on 218041394f3SDevin Teske.Xr queue 3 2197d57771bSDevin Teskethat populates a singly-linked list of a struct containing the 220041394f3SDevin Teske.Fa directive 221041394f3SDevin Teskeand 222041394f3SDevin Teske.Fa value . 223041394f3SDevin Teske.Pp 2247d57771bSDevin TeskeIn addition, 2257d57771bSDevin Teskemiscellaneous string manipulation routines are provided by 226041394f3SDevin Teske.In string_m.h : 227041394f3SDevin Teske.Bl -tag -width strexpandnl() 228041394f3SDevin Teske.It Fn replaceall 229041394f3SDevin TeskeReplace all occurrences of 230041394f3SDevin Teske.Fa find 231041394f3SDevin Teskein 232041394f3SDevin Teske.Fa source 233041394f3SDevin Teskewith 234041394f3SDevin Teske.Fa replace . 235041394f3SDevin Teske.It Fn strcount 236041394f3SDevin TeskeCount the number of occurrences of one string that appear in the 237041394f3SDevin Teske.Fa source 238041394f3SDevin Teskestring. 239041394f3SDevin TeskeReturn value is the total count. 2407d57771bSDevin TeskeAn example use would be to show how large a block of memory needs to be for a 241041394f3SDevin Teske.Fn replaceall 242041394f3SDevin Teskeseries. 243041394f3SDevin Teske.It Fn strexpand 244041394f3SDevin TeskeExpand escape sequences in a buffer pointed to by 245041394f3SDevin Teske.Fa source . 246041394f3SDevin Teske.It Fn strexpandnl 247041394f3SDevin TeskeExpand only the escaped newlines in a buffer pointed to by 248041394f3SDevin Teske.Fa source . 249041394f3SDevin Teske.It Fn strtolower 250041394f3SDevin TeskeConvert a string to lower case. 251041394f3SDevin Teske.El 252041394f3SDevin Teske.Sh SEE ALSO 253041394f3SDevin Teske.Xr queue 3 254041394f3SDevin Teske.Sh HISTORY 255041394f3SDevin TeskeThe 256041394f3SDevin Teske.Nm 257041394f3SDevin Teskelibrary first appeared in 2581f35b247SDevin Teske.Fx 10.2 . 259041394f3SDevin Teske.Sh AUTHORS 260041394f3SDevin Teske.An Devin Teske Aq dteske@FreeBSD.org 261041394f3SDevin Teske.Sh BUGS 262041394f3SDevin TeskeThis is the first implementation of the library, 263041394f3SDevin Teskeand the interface may be subject to refinement. 264