Fix for assertion error when expanding macro.
[iverilog.git] / vpi / sys_plusargs.c
blob9847f036ae0c4b918683b3530ef1472b7cfd8746
1 /*
2 * Copyright (c) 2002 Stephen Williams (steve@icarus.com)
4 * This source code is free software; you can redistribute it
5 * and/or modify it in source code form under the terms of the GNU
6 * General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option)
8 * any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 #ifdef HAVE_CVS_IDENT
20 #ident "$Id: sys_plusargs.c,v 1.7 2007/03/14 04:05:51 steve Exp $"
21 #endif
23 # include <vpi_user.h>
24 # include <string.h>
25 # include <stdlib.h>
26 # include <assert.h>
28 static PLI_INT32 sys_plusargs_sizetf(PLI_BYTE8*x)
30 return 32;
34 * The compiletf for $test$plusargs checks that there is one argument
35 * to the function call, and that argument is a constant string.
37 static PLI_INT32 sys_test_plusargs_compiletf(PLI_BYTE8*xx)
39 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
40 vpiHandle argv = vpi_iterate(vpiArgument, sys);
41 vpiHandle arg;
43 if (argv == 0) {
44 vpi_printf("ERROR: $test$plusargs requires one argument\n");
45 vpi_control(vpiFinish, 1);
46 return 0;
49 arg = vpi_scan(argv);
50 assert(arg != 0);
52 switch (vpi_get(vpiType, arg)) {
53 case vpiConstant:
54 if (vpi_get(vpiConstType, arg) != vpiStringConst) {
55 vpi_printf("ERROR: Argument of $test$plusargs "
56 " must be a constant string.\n");
57 vpi_control(vpiFinish, 1);
58 return 0;
60 break;
62 default:
63 vpi_printf("ERROR: Argument of $test$plusargs "
64 " must be a constant string.\n");
65 vpi_control(vpiFinish, 1);
66 return 0;
70 arg = vpi_scan(argv);
71 if (arg != 0) {
72 vpi_printf("ERROR: too many arguments to $test$plusargs\n");
73 vpi_control(vpiFinish, 1);
76 return 0;
80 * Compare the +arguments passed to the simulator with the argument
81 * passed to the $test$plusargs. If there is a simulator argument that
82 * is like this argument, then return true. Otherwise return false.
84 static PLI_INT32 sys_test_plusargs_calltf(PLI_BYTE8*xx)
86 int idx;
87 int flag = 0;
88 size_t slen, len;
89 s_vpi_vlog_info info;
90 s_vpi_value value;
91 s_vpi_value result;
93 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
94 vpiHandle argv = vpi_iterate(vpiArgument, sys);
95 vpiHandle arg = vpi_scan(argv);
97 value.format = vpiStringVal;
98 vpi_get_value(arg, &value);
99 slen = strlen(value.value.str);
101 vpi_get_vlog_info(&info);
103 /* Look for a +arg that matches the prefix supplied. */
104 for (idx = 0 ; idx < info.argc ; idx += 1) {
106 /* Skip arguments that are not +args. */
107 if (info.argv[idx][0] != '+')
108 continue;
110 len = strlen(info.argv[idx]+1);
111 if (len < slen)
112 continue;
114 if (strncmp(value.value.str, info.argv[idx]+1, slen) != 0)
115 continue;
117 flag = 1;
118 break;
121 result.format = vpiIntVal;
122 result.value.integer = flag;
123 vpi_put_value(sys, &result, 0, vpiNoDelay);
125 return 0;
128 static PLI_INT32 sys_value_plusargs_compiletf(PLI_BYTE8*xx)
130 s_vpi_value value;
131 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
132 vpiHandle argv = vpi_iterate(vpiArgument, sys);
133 vpiHandle arg;
135 if (argv == 0) {
136 vpi_printf("ERROR: $value$plusargs requires two arguments\n");
137 vpi_control(vpiFinish, 1);
138 return 0;
141 arg = vpi_scan(argv);
142 assert(arg != 0);
144 switch (vpi_get(vpiType, arg)) {
145 case vpiConstant:
146 if (vpi_get(vpiConstType, arg) != vpiStringConst) {
147 vpi_printf("ERROR: First argument of $value$plusargs "
148 " must be a constant string.\n");
149 vpi_control(vpiFinish, 1);
150 return 0;
152 break;
154 default:
155 vpi_printf("ERROR: First argument of $value$plusargs "
156 " must be a constant string.\n");
157 vpi_control(vpiFinish, 1);
158 return 0;
159 break;
162 /* Check that the format string has a reasonable format. */
163 value.format = vpiStringVal;
164 vpi_get_value(arg, &value);
165 { char*fmt = value.value.str;
166 char*cp = strchr(fmt, '%');
168 if (cp == 0) {
169 vpi_printf("ERROR: Invalid argument format string"
170 ": %s\n", fmt);
171 vpi_control(vpiFinish, 1);
172 return 0;
175 cp += 1;
176 if (*cp == '0')
177 cp += 1;
179 switch (*cp) {
180 case 'd':
181 case 'o':
182 case 'b':
183 case 'h':
184 case 's':
185 cp += 1;
186 break;
187 default:
188 vpi_printf("ERROR: Invalid argument format string"
189 ": %s\n", fmt);
190 vpi_control(vpiFinish, 1);
191 return 0;
194 if (*cp != 0) {
195 vpi_printf("ERROR: Trailing junk after value format"
196 ": %s\n", fmt);
197 vpi_control(vpiFinish, 1);
198 return 0;
202 arg = vpi_scan(argv);
203 if (argv == 0) {
204 vpi_printf("ERROR: $value$plusargs requires two arguments\n");
205 vpi_control(vpiFinish, 1);
206 return 0;
209 switch (vpi_get(vpiType, arg)) {
211 case vpiReg:
212 case vpiIntegerVar:
213 break;
215 default:
216 vpi_printf("ERROR: value field doesn\'t match format: %s\n",
217 value.value.str);
218 vpi_control(vpiFinish, 1);
219 return 0;
222 arg = vpi_scan(argv);
223 if (arg != 0) {
224 vpi_printf("ERROR: too many arguments to $value$plusargs\n");
225 vpi_control(vpiFinish, 1);
226 return 0;
229 return 0;
232 static PLI_INT32 sys_value_plusargs_calltf(PLI_BYTE8*xx)
234 char*cp;
235 int idx;
236 int flag = 0;
237 size_t slen, len;
238 s_vpi_vlog_info info;
239 s_vpi_value format;
240 s_vpi_value result;
242 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
243 vpiHandle argv = vpi_iterate(vpiArgument, sys);
244 vpiHandle arg1 = vpi_scan(argv);
245 vpiHandle arg2 = vpi_scan(argv);
247 format.format = vpiStringVal;
248 vpi_get_value(arg1, &format);
250 vpi_get_vlog_info(&info);
252 cp = strchr(format.value.str, '%');
253 assert(cp);
254 slen = cp - format.value.str;
256 cp += 1;
257 if (*cp == '0')
258 cp += 1;
260 for (idx = 0 ; idx < info.argc ; idx += 1) {
262 if (info.argv[idx][0] != '+')
263 continue;
265 len = strlen(info.argv[idx]+1);
266 if (len < slen)
267 continue;
269 if (strncmp(format.value.str, info.argv[idx]+1, slen) != 0)
270 continue;
272 switch (*cp) {
273 case 'd':
274 result.format = vpiIntVal;
275 result.value.integer = strtoul(info.argv[idx]+1+slen,0,10);
276 break;
277 case 'o':
278 result.format = vpiIntVal;
279 result.value.integer = strtoul(info.argv[idx]+1+slen,0,8);
280 break;
281 case 'h':
282 result.format = vpiIntVal;
283 result.value.integer = strtoul(info.argv[idx]+1+slen,0,16);
284 break;
285 case 'b':
286 result.format = vpiIntVal;
287 result.value.integer = strtoul(info.argv[idx]+1+slen,0,12);
288 break;
289 case 's':
290 result.format = vpiStringVal;
291 result.value.str = info.argv[idx]+1+slen;
292 break;
293 default:
294 assert(0);
297 vpi_put_value(arg2, &result, 0, vpiNoDelay);
298 flag = 1;
299 break;
302 result.format = vpiIntVal;
303 result.value.integer = flag;
304 vpi_put_value(sys, &result, 0, vpiNoDelay);
306 return 0;
309 void sys_plusargs_register()
311 s_vpi_systf_data tf_data;
314 tf_data.type = vpiSysFunc;
315 tf_data.tfname = "$test$plusargs";
316 tf_data.calltf = sys_test_plusargs_calltf;
317 tf_data.compiletf = sys_test_plusargs_compiletf;
318 tf_data.sizetf = sys_plusargs_sizetf;
319 vpi_register_systf(&tf_data);
321 tf_data.type = vpiSysFunc;
322 tf_data.tfname = "$value$plusargs";
323 tf_data.calltf = sys_value_plusargs_calltf;
324 tf_data.compiletf = sys_value_plusargs_compiletf;
325 tf_data.sizetf = sys_plusargs_sizetf;
326 vpi_register_systf(&tf_data);
331 * $Log: sys_plusargs.c,v $
332 * Revision 1.7 2007/03/14 04:05:51 steve
333 * VPI tasks take PLI_BYTE* by the standard.
335 * Revision 1.6 2006/10/30 22:45:37 steve
336 * Updates for Cygwin portability (pr1585922)
338 * Revision 1.5 2004/10/04 01:10:58 steve
339 * Clean up spurious trailing white space.
341 * Revision 1.4 2002/08/12 01:35:05 steve
342 * conditional ident string using autoconfig.
344 * Revision 1.3 2002/08/11 23:47:04 steve
345 * Add missing Log and Ident strings.
347 * Revision 1.2 2002/08/10 17:00:31 steve
348 * Allow vpiIntegerVar as parameter to $value$plusarg
350 * Revision 1.1 2002/04/07 04:37:53 steve
351 * Add $plusargs system functions.