kernel - Fix callout_stop/callout_reset rearm race
[dragonfly.git] / usr.bin / dfregress / parser.c
bloba42a2c6abdc8ca1e0e63ee51921683a6ef92a6d4
1 /*
2 * Copyright (c) 2009-2011 Alex Hornung <alex@alexhornung.com>.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <err.h>
37 #include "parser.h"
39 #define _iswhitespace(X) ((((X) == ' ') || ((X) == '\t'))?1:0)
42 static int line_no = 1;
44 static int iswhitespace(char c)
46 return _iswhitespace(c);
49 static int iscomma(char c)
51 return (c == ',');
54 void
55 syntax_error(const char *fmt, ...)
57 char buf[1024];
58 va_list ap;
60 va_start(ap, fmt);
61 vsnprintf(buf, sizeof(buf), fmt, ap);
62 va_end(ap);
63 errx(1, "syntax error on line %d: %s\n", line_no, buf);
67 int
68 entry_check_num_args(char **tokens, int num)
70 int i;
72 for (i = 0; tokens[i] != NULL; i++)
75 if (i < num) {
76 syntax_error("at least %d tokens were expected but only %d "
77 "were found", num, i);
78 return 1;
80 return 0;
83 static int
84 line_tokenize(char *buffer, int (*is_sep)(char), char comment_char, char **tokens)
86 int c, n, i;
87 int quote = 0;
89 i = strlen(buffer) + 1;
90 c = 0;
92 /* Skip leading white-space */
93 while ((_iswhitespace(buffer[c])) && (c < i)) c++;
96 * If this line effectively (after indentation) begins with the comment
97 * character, we ignore the rest of the line.
99 if (buffer[c] == comment_char)
100 return 0;
102 tokens[0] = &buffer[c];
103 for (n = 1; c < i; c++) {
104 if (buffer[c] == '"') {
105 quote = !quote;
106 if (quote) {
107 if ((c >= 1) && (&buffer[c] != tokens[n-1])) {
108 #if 0
109 syntax_error("stray opening quote not "
110 "at beginning of token");
111 /* NOTREACHED */
112 #endif
113 } else {
114 tokens[n-1] = &buffer[c+1];
116 } else {
117 if ((c < i-1) && (!is_sep(buffer[c+1]))) {
118 #if 0
119 syntax_error("stray closing quote not "
120 "at end of token");
121 /* NOTREACHED */
122 #endif
123 } else {
124 buffer[c] = '\0';
129 if (quote) {
130 continue;
133 if (is_sep(buffer[c])) {
134 buffer[c++] = '\0';
135 while ((_iswhitespace(buffer[c])) && (c < i)) c++;
136 tokens[n++] = &buffer[c--];
139 tokens[n] = NULL;
141 if (quote) {
142 tokens[0] = NULL;
143 return 0;
146 return n;
149 static int
150 process_line(FILE* fd, parser_t parser, void *arg)
152 char buffer[4096];
153 char *tokens[256];
154 int c, n, i = 0;
155 int ret = 0;
157 while (((c = fgetc(fd)) != EOF) && (c != '\n')) {
158 buffer[i++] = (char)c;
159 if (i == (sizeof(buffer) -1))
160 break;
162 buffer[i] = '\0';
164 if (feof(fd) || ferror(fd))
165 ret = 1;
168 n = line_tokenize(buffer, &iswhitespace, '#', tokens);
171 * If there are not enough arguments for any function or it is
172 * a line full of whitespaces, we just return here. Or if a
173 * quote wasn't closed.
175 if ((n < 1) || (tokens[0][0] == '\0'))
176 return ret;
178 parser(arg, tokens);
180 return ret;
184 parse_options(char *str, char **options)
186 int i;
188 i = line_tokenize(str, &iscomma, '#', options);
189 if (i == 0)
190 syntax_error("Invalid expression in options token");
191 /* NOTREACHED */
193 return i;
197 process_file(const char *file, parser_t parser, void *arg, int *nlines)
199 FILE *fd;
201 line_no = 0;
203 fd = fopen(file, "r");
204 if (fd == NULL)
205 err(1, "fopen");
206 /* NOTREACHED */
208 while (process_line(fd, parser, arg) == 0)
209 ++line_no;
211 fclose(fd);
213 if (nlines != NULL)
214 *nlines = line_no;
216 return 0;