1.\" Copyright (c) 2013-2018 Devin Teske <dteske@FreeBSD.org> 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions and the following disclaimer. 9.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" notice, this list of conditions and the following disclaimer in the 11.\" documentation and/or other materials provided with the distribution. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" SUCH DAMAGE. 24.\" 25.\" $FreeBSD$ 26.\" 27.Dd March 13, 2018 28.Dt FIGPAR 3 29.Os 30.Sh NAME 31.Nm figpar , 32.Nm parse_config , 33.Nm get_config_option 34.Nd configuration file parsing library 35.Sh LIBRARY 36.Lb libfigpar 37.Sh SYNOPSIS 38.In figpar.h 39.Ft int 40.Fo parse_config 41.Fa "struct figpar_config options[]" 42.Fa "const char *path" 43.Fa "int \*[lp]*unknown\*[rp]\*[lp]struct figpar_config *option" 44.Fa "uint32_t line" 45.Fa "char *directive" 46.Fa "char *value\*[rp]" 47.Fa "uint8_t processing_options" 48.Fc 49.Ft "struct figpar_config *" 50.Fo get_config_option 51.Fa "struct figpar_config options[]" 52.Fa "const char *directive" 53.Fc 54.In string_m.h 55.Ft int 56.Fo replaceall 57.Fa "char *source" 58.Fa "const char *find" 59.Fa "const char *replace" 60.Fc 61.Ft unsigned int 62.Fo strcount 63.Fa "const char *source" 64.Fa "const char *find" 65.Fc 66.Ft void 67.Fo strexpand 68.Fa "char *source" 69.Fc 70.Ft void 71.Fo strexpandnl 72.Fa "char *source" 73.Fc 74.Ft void 75.Fo strtolower 76.Fa "char *source" 77.Fc 78.Sh DESCRIPTION 79The 80.Nm 81library provides a light-weight, 82portable framework for parsing configuration 83files. 84The library uses 85.Xr open 2 , 86.Xr read 2 , 87and 88.Xr lseek 2 89within the file pointed to by 90.Fa path 91to find directives and values which are then made available to the application. 92.Pp 93Due to the fact that configuration files may have basic syntax differences, 94the library does not attempt to impose any structure on the data but instead 95provides raw data to a set of callback functions. 96These callback functions can in-turn initiate abort through their return value, 97allowing custom syntax validation during parsing. 98.Pp 99Configuration directives, 100types, 101and callback functions are provided through data structures defined in 102.In figpar.h : 103.Bd -literal -offset indent 104struct figpar_config { 105 enum figpar_cfgtype type; /* value type */ 106 const char *directive; /* keyword */ 107 union figpar_cfgvalue value; /* value */ 108 109 /* Pointer to function used when directive is found */ 110 int (*action)(struct figpar_config *option, uint32_t line, 111 char *directive, char *value); 112}; 113 114enum figpar_cfgtype { 115 FIGPAR_TYPE_NONE = 0x0000, /* directives with no value */ 116 FIGPAR_TYPE_BOOL = 0x0001, /* boolean */ 117 FIGPAR_TYPE_INT = 0x0002, /* signed 32 bit integer */ 118 FIGPAR_TYPE_UINT = 0x0004, /* unsigned 32 bit integer */ 119 FIGPAR_TYPE_STR = 0x0008, /* string pointer */ 120 FIGPAR_TYPE_STRARRAY = 0x0010, /* string array pointer */ 121 FIGPAR_TYPE_DATA1 = 0x0020, /* void data type-1 (open) */ 122 FIGPAR_TYPE_DATA2 = 0x0040, /* void data type-2 (open) */ 123 FIGPAR_TYPE_DATA3 = 0x0080, /* void data type-3 (open) */ 124 FIGPAR_TYPE_RESERVED1 = 0x0100, /* reserved data type-1 */ 125 FIGPAR_TYPE_RESERVED2 = 0x0200, /* reserved data type-2 */ 126 FIGPAR_TYPE_RESERVED3 = 0x0400, /* reserved data type-3 */ 127}; 128 129union figpar_cfgvalue { 130 void *data; /* Pointer to NUL-terminated string */ 131 char *str; /* Pointer to NUL-terminated string */ 132 char **strarray; /* Pointer to an array of strings */ 133 int32_t num; /* Signed 32-bit integer value */ 134 uint32_t u_num; /* Unsigned 32-bit integer value */ 135 uint32_t boolean:1; /* Boolean integer value (0 or 1) */ 136}; 137.Ed 138.Pp 139The 140.Fa processing_options 141argument to 142.Fn parse_config 143is a mask of bit fields which indicate various 144processing options. 145The possible flags are: 146.Bl -tag -width FIGPAR_BREAK_ON_SEMICOLON 147.It Dv FIGPAR_BREAK_ON_EQUALS 148An equals sign 149.Pq Ql Li = 150is normally considered part of the directive. 151This flag enables terminating the directive at the equals sign. 152Also makes equals sign optional and transient. 153.It Dv FIGPAR_BREAK_ON_SEMICOLON 154A semicolon 155.Pq Ql Li \; 156is normally considered part of the value. 157This flag enables terminating the value at the semicolon. 158Also allows multiple statements on a single line separated by semicolon. 159.It Dv FIGPAR_CASE_SENSITIVE 160Normally directives are matched case insensitively using 161.Xr fnmatch 3 . 162This flag enables directive matching to be case sensitive. 163.It Dv FIGPAR_REQUIRE_EQUALS 164If a directive is not followed by an equals, 165processing is aborted. 166.It Dv FIGPAR_STRICT_EQUALS 167Equals must be part of the directive to be considered a delimiter between 168directive and value. 169.El 170.Pp 171The 172.Fa options 173struct array pointer can be NULL and every directive will run the 174.Fn unknown 175function argument. 176.Pp 177The directive for each figpar_config item in the 178.Fn parse_config 179options argument is matched against each parsed directive using 180.Xr fnmatch 3 181until a match is found. 182If a match is found, 183the 184.Fn action 185function for that figpar_config directive is run with the line number, 186directive, 187and value. 188Otherwise if no match, 189the 190.Fn unknown 191function is run 192.Pq with the same arguments . 193.Pp 194If either 195.Fa action 196or 197.Fa unknown 198return non-zero, 199.Fn parse_config 200aborts reading the file and returns the error value to its caller. 201.Pp 202.Fn get_config_option 203traverses the options-array and returns the option that matches via 204.Xr strcmp 3 , 205or if no match a pointer to a static dummy struct is returned 206.Pq whose values are all zero or NULL . 207.Pp 208The use of 209.Fa "struct figpar_config" 210is entirely optional as-is the use of 211.Fa "enum figpar_cfgtype" 212or 213.Fa "union figpar_cfgvalue" . 214For example, 215a NULL pointer can be passed to 216.Fn parse_config 217for the first argument while providing a simple 218.Fa unknown 219function based on 220.Xr queue 3 221that populates a singly-linked list of a struct containing the 222.Fa directive 223and 224.Fa value . 225.Pp 226In addition, 227miscellaneous string manipulation routines are provided by 228.In string_m.h : 229.Bl -tag -width strexpandnl() 230.It Fn replaceall 231Replace all occurrences of 232.Fa find 233in 234.Fa source 235with 236.Fa replace . 237.It Fn strcount 238Count the number of occurrences of one string that appear in the 239.Fa source 240string. 241Return value is the total count. 242An example use would be to show how large a block of memory needs to be for a 243.Fn replaceall 244series. 245.It Fn strexpand 246Expand escape sequences in a buffer pointed to by 247.Fa source . 248.It Fn strexpandnl 249Expand only the escaped newlines in a buffer pointed to by 250.Fa source . 251.It Fn strtolower 252Convert a string to lower case. 253.El 254.Sh SEE ALSO 255.Xr queue 3 256.Sh HISTORY 257The 258.Nm 259library first appeared in 260.Fx 10.2 . 261.Sh AUTHORS 262.An Devin Teske Aq dteske@FreeBSD.org 263.Sh BUGS 264This is the first implementation of the library, 265and the interface may be subject to refinement. 266