* nss/nss_files/files-parse.c (parse_list): Set EOL from LINE if it
[glibc.git] / nss / nss_files / files-parse.c
blob1f3b13886d7ef2d8c18b9c807266485cb66a2c59
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.
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.
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.
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. */
20 #include <ctype.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdlib.h>
26 #define CONCAT(a,b) CONCAT1(a,b)
27 #define CONCAT1(a,b) a##b
29 #ifndef STRUCTURE
30 #define STRUCTURE ENTNAME
31 #endif
34 struct parser_data
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];
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
56 #ifdef EXTERN_PARSER
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);
62 #define LINE_PARSER(EOLSET, BODY) /* Do nothing */
64 #else
66 /* Define a line parsing function. */
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; \
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)); \
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; \
110 #define ISCOLON(c) ((c) == ':')
113 #ifndef TRAILING_LIST_MEMBER
114 #define TRAILING_LIST_PARSER /* Nothing to do. */
115 #else
117 #define TRAILING_LIST_PARSER \
119 char **list = parse_list (line, data, datalen); \
120 if (list) \
121 result->TRAILING_LIST_MEMBER = list; \
122 else \
123 return 0; \
126 static inline char **
127 parse_list (char *line, struct parser_data *data, int datalen)
129 char *eol, **list, **p;
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;
146 p = list;
147 while (1)
149 char *elt;
151 if ((char *) &p[1] - (char *) data > datalen)
153 /* We cannot fit another pointer in the buffer. */
154 errno = ERANGE;
155 return NULL;
157 if (*line == '\0')
158 break;
160 elt = line;
161 while (1)
163 if (TRAILING_LIST_SEPARATOR_P (*line))
165 *p++ = elt;
166 *line = '\0';
168 ++line;
169 while (TRAILING_LIST_SEPARATOR_P (*line));
170 elt = line;
172 else if (*line == '\0' || *line == '\n')
174 /* End of the line. */
175 if (line > elt)
176 /* Last element. */
177 *p++ = elt;
178 *line = '\0';
179 break;
181 else
182 ++line;
185 *p = NULL;
187 return list;
190 #endif /* EXTERN_PARSER */
193 #define LOOKUP_NAME(nameelt, aliaselt) \
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; \
205 #endif
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