kgdb: Add TUI mode as an option
[dragonfly.git] / usr.bin / dfregress / parser.c
1 /*
2  * Copyright (c) 2009-2011 Alex Hornung <alex@alexhornung.com>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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.
15  *
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.
28  */
29
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"
38
39 #define _iswhitespace(X)        ((((X) == ' ') || ((X) == '\t'))?1:0)
40
41
42 static int line_no = 1;
43
44 static int iswhitespace(char c)
45 {
46         return _iswhitespace(c);
47 }
48
49 static int iscomma(char c)
50 {
51         return (c == ',');
52 }
53
54 void
55 syntax_error(const char *fmt, ...)
56 {
57         char buf[1024];
58         va_list ap;
59
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);
64 }
65
66
67 int
68 entry_check_num_args(char **tokens, int num)
69 {
70         int i;
71
72         for (i = 0; tokens[i] != NULL; i++)
73                 ;
74
75         if (i < num) {
76                 syntax_error("at least %d tokens were expected but only %d "
77                     "were found", num, i);
78                 return 1;
79         }
80         return 0;
81 }
82
83 static int
84 line_tokenize(char *buffer, int (*is_sep)(char), char comment_char, char **tokens)
85 {
86         int c, n, i;
87         int quote = 0;
88
89         i = strlen(buffer) + 1;
90         c = 0;
91
92         /* Skip leading white-space */
93         while ((_iswhitespace(buffer[c])) && (c < i)) c++;
94
95         /*
96          * If this line effectively (after indentation) begins with the comment
97          * character, we ignore the rest of the line.
98          */
99         if (buffer[c] == comment_char)
100                 return 0;
101
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];
115                                 }
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';
125                                 }
126                         }
127                 }
128
129                 if (quote) {
130                         continue;
131                 }
132
133                 if (is_sep(buffer[c])) {
134                         buffer[c++] = '\0';
135                         while ((_iswhitespace(buffer[c])) && (c < i)) c++;
136                         tokens[n++] = &buffer[c--];
137                 }
138         }
139         tokens[n] = NULL;
140
141         if (quote) {
142                 tokens[0] = NULL;
143                 return 0;
144         }
145
146         return n;
147 }
148
149 static int
150 process_line(FILE* fd, parser_t parser, void *arg)
151 {
152         char buffer[4096];
153         char *tokens[256];
154         int c, n, i = 0;
155         int ret = 0;
156
157         while (((c = fgetc(fd)) != EOF) && (c != '\n')) {
158                 buffer[i++] = (char)c;
159                 if (i == (sizeof(buffer) -1))
160                         break;
161         }
162         buffer[i] = '\0';
163
164         if (feof(fd) || ferror(fd))
165                 ret = 1;
166
167
168         n = line_tokenize(buffer, &iswhitespace, '#', tokens);
169
170         /*
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.
174          */
175         if ((n < 1) || (tokens[0][0] == '\0'))
176                 return ret;
177
178         parser(arg, tokens);
179
180         return ret;
181 }
182
183 int
184 parse_options(char *str, char **options)
185 {
186         int i;
187
188         i = line_tokenize(str, &iscomma, '#', options);
189         if (i == 0)
190                 syntax_error("Invalid expression in options token");
191                 /* NOTREACHED */
192
193         return i;
194 }
195
196 int
197 process_file(const char *file, parser_t parser, void *arg, int *nlines)
198 {
199         FILE *fd;
200
201         line_no = 0;
202
203         fd = fopen(file, "r");
204         if (fd == NULL)
205                 err(1, "fopen");
206                 /* NOTREACHED */
207
208         while (process_line(fd, parser, arg) == 0)
209                 ++line_no;
210
211         fclose(fd);
212
213         if (nlines != NULL)
214                 *nlines = line_no;
215
216         return 0;
217 }
218