]> git.ipfire.org Git - thirdparty/glibc.git/blob - nss/nss_files/files-parse.c
* nss/nss_files/files-parse.c (parse_list): Set EOL from LINE if it
[thirdparty/glibc.git] / nss / nss_files / files-parse.c
1 /* Common code for file-based database parsers in nss_files module.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
19
20 #include <ctype.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25
26 #define CONCAT(a,b) CONCAT1(a,b)
27 #define CONCAT1(a,b) a##b
28
29 #ifndef STRUCTURE
30 #define STRUCTURE ENTNAME
31 #endif
32
33
34 struct parser_data
35 {
36 #ifdef ENTDATA
37 struct ENTDATA entdata;
38 #define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata;
39 #else
40 #define ENTDATA_DECL(data)
41 #endif
42 char linebuffer[0];
43 };
44
45 #ifdef ENTDATA
46 /* The function can't be exported, because the entdata structure
47 is defined only in files-foo.c. */
48 #define parser_stclass static inline
49 #else
50 /* Export the line parser function so it can be used in nss_db. */
51 #define parser_stclass /* Global */
52 #define parse_line CONCAT(_nss_files_parse_,ENTNAME)
53 #endif
54
55
56 #ifdef EXTERN_PARSER
57
58 /* The parser is defined in a different module. */
59 extern int parse_line (char *line, struct STRUCTURE *result,
60 struct parser_data *data, int datalen);
61
62 #define LINE_PARSER(EOLSET, BODY) /* Do nothing */
63
64 #else
65
66 /* Define a line parsing function. */
67
68 #define LINE_PARSER(EOLSET, BODY) \
69 parser_stclass int \
70 parse_line (char *line, struct STRUCTURE *result, \
71 struct parser_data *data, int datalen) \
72 { \
73 ENTDATA_DECL (data) \
74 char *p = strpbrk (line, EOLSET "\n"); \
75 if (p) \
76 *p = '\0'; \
77 BODY; \
78 TRAILING_LIST_PARSER; \
79 return 1; \
80 }
81
82
83 #define STRING_FIELD(variable, terminator_p, swallow) \
84 { \
85 variable = line; \
86 while (!terminator_p (*line)) \
87 if (*++line == '\0') \
88 return 0; \
89 *line = '\0'; \
90 do \
91 ++line; \
92 while (swallow && terminator_p (*line)); \
93 }
94
95 #define INT_FIELD(variable, terminator_p, swallow, base, convert) \
96 { \
97 char *endp; \
98 variable = convert (strtol (line, &endp, base)); \
99 if (endp == line) \
100 return 0; \
101 else if (terminator_p (*endp)) \
102 do \
103 ++endp; \
104 while (swallow && terminator_p (*endp)); \
105 else if (*endp != '\0') \
106 return 0; \
107 line = endp; \
108 }
109
110 #define ISCOLON(c) ((c) == ':')
111
112
113 #ifndef TRAILING_LIST_MEMBER
114 #define TRAILING_LIST_PARSER /* Nothing to do. */
115 #else
116
117 #define TRAILING_LIST_PARSER \
118 { \
119 char **list = parse_list (line, data, datalen); \
120 if (list) \
121 result->TRAILING_LIST_MEMBER = list; \
122 else \
123 return 0; \
124 }
125
126 static inline char **
127 parse_list (char *line, struct parser_data *data, int datalen)
128 {
129 char *eol, **list, **p;
130
131 if (line >= data->linebuffer && line < (char *) data + datalen)
132 /* Find the end of the line buffer, we will use the space in DATA after
133 it for storing the vector of pointers. */
134 eol = strchr (line, '\0') + 1;
135 else
136 /* LINE does not point within DATA->linebuffer, so that space is
137 not being used for scratch space right now. We can use all of
138 it for the pointer vector storage. */
139 eol = data->linebuffer;
140 /* Adjust the pointer so it is aligned for storing pointers. */
141 eol += __alignof__ (char *) - 1;
142 eol -= (eol - (char *) 0) % __alignof__ (char *);
143 /* We will start the storage here for the vector of pointers. */
144 list = (char **) eol;
145
146 p = list;
147 while (1)
148 {
149 char *elt;
150
151 if ((char *) &p[1] - (char *) data > datalen)
152 {
153 /* We cannot fit another pointer in the buffer. */
154 errno = ERANGE;
155 return NULL;
156 }
157 if (*line == '\0')
158 break;
159
160 elt = line;
161 while (1)
162 {
163 if (TRAILING_LIST_SEPARATOR_P (*line))
164 {
165 *p++ = elt;
166 *line = '\0';
167 do
168 ++line;
169 while (TRAILING_LIST_SEPARATOR_P (*line));
170 elt = line;
171 }
172 else if (*line == '\0' || *line == '\n')
173 {
174 /* End of the line. */
175 if (line > elt)
176 /* Last element. */
177 *p++ = elt;
178 *line = '\0';
179 break;
180 }
181 else
182 ++line;
183 }
184 }
185 *p = NULL;
186
187 return list;
188 }
189
190 #endif /* EXTERN_PARSER */
191
192
193 #define LOOKUP_NAME(nameelt, aliaselt) \
194 { \
195 char **ap; \
196 if (! strcmp (name, result->nameelt)) \
197 break; \
198 for (ap = result->aliaselt; *ap; ++ap) \
199 if (! strcmp (name, *ap)) \
200 break; \
201 if (*ap) \
202 break; \
203 }
204
205 #endif
206
207 /* This is defined by db-*.c to include "../nss_db/db-XXX.c" instead. */
208 #ifndef GENERIC
209 #define GENERIC "files-XXX.c"
210 #endif