52a0e16176c69899138147bccc1608c9c42f9772
[strongswan.git] / src / libstrongswan / utils / lexparser.c
1 /**
2 * @file lexparser.c
3 *
4 * @brief lexical parser for text-based configuration files
5 *
6 */
7
8 /*
9 * Copyright (C) 2001-2006 Andreas Steffen, Zuercher Hochschule Winterthur
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
20 *
21 * RCSID $Id$
22 */
23
24 #include <string.h>
25
26 #include "lexparser.h"
27
28
29 /**
30 * eat whitespace
31 */
32 bool eat_whitespace(chunk_t *src)
33 {
34 while (src->len > 0 && (*src->ptr == ' ' || *src->ptr == '\t'))
35 {
36 src->ptr++; src->len--;
37 }
38 return src->len > 0 && *src->ptr != '#';
39 }
40
41 /**
42 * compare string with chunk
43 */
44 bool match(const char *pattern, const chunk_t *ch)
45 {
46 return ch->len == strlen(pattern) && strncmp(pattern, ch->ptr, ch->len) == 0;
47 }
48
49 /**
50 * extracts a token ending with the first occurrence of a given termination symbol
51 */
52 bool extract_token(chunk_t *token, const char termination, chunk_t *src)
53 {
54 u_char *eot = memchr(src->ptr, termination, src->len);
55
56 /* initialize empty token */
57 *token = chunk_empty;
58
59 if (eot == NULL) /* termination symbol not found */
60 {
61 return FALSE;
62 }
63
64 /* extract token */
65 token->ptr = src->ptr;
66 token->len = (u_int)(eot - src->ptr);
67
68 /* advance src pointer after termination symbol */
69 src->ptr = eot + 1;
70 src->len -= (token->len + 1);
71
72 return TRUE;
73 }
74
75 /**
76 * extracts a token ending with the last occurrence of a given termination symbol
77 */
78 bool extract_last_token(chunk_t *token, const char termination, chunk_t *src)
79 {
80 u_char *eot = memrchr(src->ptr, termination, src->len);
81
82 /* initialize empty token */
83 *token = chunk_empty;
84
85 if (eot == NULL) /* termination symbol not found */
86 {
87 return FALSE;
88 }
89
90 /* extract token */
91 token->ptr = src->ptr;
92 token->len = (u_int)(eot - src->ptr);
93
94 /* advance src pointer after termination symbol */
95 src->ptr = eot + 1;
96 src->len -= (token->len + 1);
97
98 return TRUE;
99 }
100
101 /**
102 * fetches a new line terminated by \n or \r\n
103 */
104 bool fetchline(chunk_t *src, chunk_t *line)
105 {
106 if (src->len == 0) /* end of src reached */
107 return FALSE;
108
109 if (extract_token(line, '\n', src))
110 {
111 if (line->len > 0 && *(line->ptr + line->len -1) == '\r')
112 line->len--; /* remove optional \r */
113 }
114 else /*last line ends without newline */
115 {
116 *line = *src;
117 src->ptr += src->len;
118 src->len = 0;
119 }
120 return TRUE;
121 }
122
123 err_t extract_value(chunk_t *value, chunk_t *line)
124 {
125 char delimiter = ' ';
126
127 if (!eat_whitespace(line))
128 {
129 *value = chunk_empty;
130 return NULL;
131 }
132 if (*line->ptr == '\'' || *line->ptr == '"')
133 {
134 delimiter = *line->ptr;
135 line->ptr++; line->len--;
136 }
137 if (!extract_token(value, delimiter, line))
138 {
139 if (delimiter == ' ')
140 {
141 *value = *line;
142 line->len = 0;
143 }
144 else
145 {
146 return "missing second delimiter";
147 }
148 }
149 return NULL;
150 }
151
152 /**
153 * extracts a parameter: value pair
154 */
155 err_t extract_parameter_value(chunk_t *name, chunk_t *value, chunk_t *line)
156 {
157 /* extract name */
158 if (!extract_token(name,':', line))
159 {
160 return "missing ':'";
161 }
162
163 /* extract value */
164 return extract_value(value, line);
165 }