Fix: mi: missing files on make dist
[lttng-tools.git] / src / common / config / ini.c
CommitLineData
bac6245e
JG
1/*
2 * inih -- simple .INI file parser
3 *
4 * The "inih" library is distributed under the New BSD license:
5 *
6 * Copyright (c) 2009, Brush Technology - All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Brush Technology nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BRUSH TECHNOLOGY ''AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
23 * EVENT SHALL BRUSH TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * http://code.google.com/p/inih/
32 */
33
34#include <stdio.h>
35#include <ctype.h>
36#include <string.h>
37
38#include "ini.h"
39
40#if !INI_USE_STACK
41#include <stdlib.h>
42#endif
43
44#define MAX_SECTION 50
45#define MAX_NAME 50
46
47/* Strip whitespace chars off end of given string, in place. Return s. */
48static char* rstrip(char* s)
49{
50 char* p = s + strlen(s);
51
52 while (p > s && isspace((unsigned char)(*--p)))
53 *p = '\0';
54 return s;
55}
56
57/* Return pointer to first non-whitespace char in given string. */
58static char* lskip(const char* s)
59{
60 while (*s && isspace((unsigned char)(*s)))
61 s++;
62 return (char*)s;
63}
64
65/*
66 * Return pointer to first char c or ';' comment in given string, or pointer to
67 * null at end of string if neither found. ';' must be prefixed by a whitespace
68 * character to register as a comment.
69 */
70static char* find_char_or_comment(const char* s, char c)
71{
72 int was_whitespace = 0;
73
74 while (*s && *s != c && !(was_whitespace && *s == ';')) {
75 was_whitespace = isspace((unsigned char)(*s));
76 s++;
77 }
78 return (char*)s;
79}
80
81/* Version of strncpy that ensures dest (size bytes) is null-terminated. */
82static char* strncpy0(char* dest, const char* src, size_t size)
83{
84 strncpy(dest, src, size);
85 dest[size - 1] = '\0';
86 return dest;
87}
88
89/* See documentation in header file. */
b2035012 90LTTNG_HIDDEN
bac6245e
JG
91int ini_parse_file(FILE* file, ini_entry_handler handler, void* user)
92{
93 /* Uses a fair bit of stack (use heap instead if you need to) */
94#if INI_USE_STACK
95 char line[INI_MAX_LINE];
96#else
97 char* line;
98#endif
99 char section[MAX_SECTION] = "";
100 char prev_name[MAX_NAME] = "";
101
102 char* start;
103 char* end;
104 char* name;
105 char* value;
106 int lineno = 0;
107 int error = 0;
108
109#if !INI_USE_STACK
110 line = (char*)malloc(INI_MAX_LINE);
111 if (!line) {
112 return -2;
113 }
114#endif
115
116 /* Scan through file line by line */
117 while (fgets(line, INI_MAX_LINE, file) != NULL) {
118 lineno++;
119
120 start = line;
121#if INI_ALLOW_BOM
122 if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
123 (unsigned char)start[1] == 0xBB &&
124 (unsigned char)start[2] == 0xBF) {
125 start += 3;
126 }
127#endif
128 start = lskip(rstrip(start));
129
130 if (*start == ';' || *start == '#') {
131 /*
132 * Per Python ConfigParser, allow '#' comments at
133 * start of line.
134 */
135 }
136#if INI_ALLOW_MULTILINE
137 else if (*prev_name && *start && start > line) {
138 /* Non-black line with leading whitespace, treat as
139 * continuation of previous name's value
140 * (as per Python ConfigParser).
141 */
142 if (handler(user, section, prev_name, start) < 0 &&
143 !error) {
144 error = lineno;
145 }
146 }
147#endif
148 else if (*start == '[') {
149 /* A "[section]" line */
150 end = find_char_or_comment(start + 1, ']');
151 if (*end == ']') {
152 *end = '\0';
153 strncpy0(section, start + 1, sizeof(section));
154 *prev_name = '\0';
155 }
156 else if (!error) {
157 /* No ']' found on section line */
158 error = lineno;
159 }
160 }
161 else if (*start && *start != ';') {
162 /* Not a comment, must be a name[=:]value pair */
163 end = find_char_or_comment(start, '=');
164 if (*end != '=') {
165 end = find_char_or_comment(start, ':');
166 }
167 if (*end == '=' || *end == ':') {
168 *end = '\0';
169 name = rstrip(start);
170 value = lskip(end + 1);
171 end = find_char_or_comment(value, '\0');
172 if (*end == ';') {
173 *end = '\0';
174 }
175
176 rstrip(value);
177
178 /*
179 * Valid name[=:]value pair found, call
180 * handler
181 */
182 strncpy0(prev_name, name, sizeof(prev_name));
183 if (handler(user, section, name, value) < 0 &&
184 !error) {
185 error = lineno;
186 }
187 }
188 else if (!error) {
189 /* No '=' or ':' found on name[=:]value line */
190 error = lineno;
191 }
192 }
193 }
194
195#if !INI_USE_STACK
196 free(line);
197#endif
198
199 return error;
200}
201
202/* See documentation in header file. */
b2035012 203LTTNG_HIDDEN
bac6245e
JG
204int ini_parse(const char* filename, ini_entry_handler handler, void* user)
205{
206 FILE* file;
207 int error;
208
209 file = fopen(filename, "r");
210 if (!file) {
211 return -1;
212 }
213
214 error = ini_parse_file(file, handler, user);
215 fclose(file);
216 return error;
217}
This page took 0.034387 seconds and 5 git commands to generate.