Careful not to lose bits parameter add expression
[iverilog.git] / vpi / sys_fileio.c
blobd5fd8604314160561da3dbde817a60645bd6dcf8
1 /*
2 * Copyright (c) 2003 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_fileio.c,v 1.10 2007/03/14 04:05:51 steve Exp $"
21 #endif
23 # include "vpi_user.h"
24 # include "sys_priv.h"
25 # include <assert.h>
26 # include <string.h>
27 # include <stdio.h>
28 # include <stdlib.h>
30 #define IS_MCD(mcd) !((mcd)>>31&1)
34 * Implement the $fopen system function.
36 static PLI_INT32 sys_fopen_compiletf(PLI_BYTE8*name)
38 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
39 vpiHandle argv = vpi_iterate(vpiArgument, sys);
40 vpiHandle item;
42 if (argv == 0) {
43 vpi_printf("%s: file name argument missing.\n", name);
44 vpi_sim_control(vpiFinish, -1);
45 return -1;
48 item = vpi_scan(argv);
49 if (item == 0) {
50 vpi_printf("%s: file name argument missing.\n", name);
51 vpi_sim_control(vpiFinish, -1);
52 return -1;
55 item = vpi_scan(argv);
56 if (item == 0) {
57 /* The mode argument is optional. It is OK for it
58 to be missing. In this case, there are no more
59 arguments, and we're done. */
60 return 0;
63 if (! is_constant(item)) {
64 vpi_printf("ERROR: %s mode argument must be a constant\n", name);
65 vpi_sim_control(vpiFinish, -1);
68 if (vpi_get(vpiConstType, item) != vpiStringConst) {
69 vpi_printf("ERROR: %s mode argument must be a string.\n", name);
70 vpi_sim_control(vpiFinish, -1);
73 item = vpi_scan(argv);
74 if (item == 0) {
75 /* There should be no more arguments. */
76 return 0;
79 vpi_free_object(argv);
80 vpi_printf("%s: Too many arguments to system function.\n", name);
81 return 0;
84 static PLI_INT32 sys_fopen_calltf(PLI_BYTE8*name)
86 s_vpi_value value;
87 char *mode_string = 0;
89 vpiHandle call_handle = vpi_handle(vpiSysTfCall, 0);
90 vpiHandle argv = vpi_iterate(vpiArgument, call_handle);
91 vpiHandle item = vpi_scan(argv);
92 vpiHandle mode = vpi_scan(argv);
94 assert(item);
96 if (mode) {
97 value.format = vpiStringVal;
98 vpi_get_value(mode, &value);
99 mode_string = strdup(value.value.str);
101 vpi_free_object(argv);
104 /* Get the string form of the file name from the file name
105 argument. */
106 value.format = vpiStringVal;
107 vpi_get_value(item, &value);
109 if ((value.format != vpiStringVal) || !value.value.str) {
110 vpi_printf("ERROR: %s: File name argument (type=%d)"
111 " does not have a string value\n",
112 name, vpi_get(vpiType, item));
113 if (mode) free(mode_string);
114 return 0;
117 value.format = vpiIntVal;
118 if (mode) {
119 value.value.integer = vpi_fopen(value.value.str, mode_string);
120 free(mode_string);
121 } else
122 value.value.integer = vpi_mcd_open(value.value.str);
124 vpi_put_value(call_handle, &value, 0, vpiNoDelay);
126 return 0;
129 static PLI_INT32 sys_fopen_sizetf(PLI_BYTE8*x)
131 return 32;
135 * Implement $fclose system function
137 static PLI_INT32 sys_fclose_calltf(PLI_BYTE8*name)
139 unsigned int mcd;
140 int type;
141 s_vpi_value value;
143 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
144 vpiHandle argv = vpi_iterate(vpiArgument, sys);
145 vpiHandle item = vpi_scan(argv);
147 if (item == 0) {
148 vpi_printf("%s: mcd parameter missing.\n", name);
149 return 0;
151 type = vpi_get(vpiType, item);
152 switch (type) {
153 case vpiReg:
154 case vpiRealVal:
155 case vpiIntegerVar:
156 break;
157 default:
158 vpi_printf("ERROR: %s mcd parameter must be of integral type",
159 name);
160 vpi_printf(", got vpiType=%d\n", type);
161 vpi_free_object(argv);
162 return 0;
165 value.format = vpiIntVal;
166 vpi_get_value(item, &value);
167 mcd = value.value.integer;
169 vpi_mcd_close(mcd);
170 return 0;
173 static PLI_INT32 sys_fflush_calltf(PLI_BYTE8*name)
175 fflush(0);
176 return 0;
180 static PLI_INT32 sys_fputc_calltf(PLI_BYTE8*name)
182 unsigned int mcd;
183 int type;
184 unsigned char x;
185 s_vpi_value value, xvalue;
186 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
187 vpiHandle argv = vpi_iterate(vpiArgument, sys);
188 vpiHandle item = vpi_scan(argv);
189 FILE *fp;
191 if (item == 0) {
192 vpi_printf("%s: mcd parameter missing.\n", name);
193 return 0;
196 type = vpi_get(vpiType, item);
197 switch (type) {
198 case vpiReg:
199 case vpiRealVal:
200 case vpiIntegerVar:
201 break;
202 default:
203 vpi_printf("ERROR: %s mcd parameter must be of integral", name);
204 vpi_printf(", got vpiType=%d\n", type);
205 vpi_free_object(argv);
206 return 0;
209 value.format = vpiIntVal;
210 vpi_get_value(item, &value);
211 mcd = value.value.integer;
213 if (IS_MCD(mcd)) return EOF;
215 item = vpi_scan(argv);
217 xvalue.format = vpiIntVal;
218 vpi_get_value(item, &xvalue);
219 x = xvalue.value.integer;
221 fp = vpi_get_file(mcd);
222 if (!fp) return EOF;
224 return fputc(x, fp);
227 static PLI_INT32 sys_fgetc_calltf(PLI_BYTE8*name)
229 unsigned int mcd;
230 int type;
231 s_vpi_value value, rval;
232 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
233 vpiHandle argv = vpi_iterate(vpiArgument, sys);
234 vpiHandle item = vpi_scan(argv);
235 FILE *fp;
237 if (item == 0) {
238 vpi_printf("%s: mcd parameter missing.\n", name);
239 return 0;
242 type = vpi_get(vpiType, item);
243 switch (type) {
244 case vpiReg:
245 case vpiRealVal:
246 case vpiIntegerVar:
247 break;
248 default:
249 vpi_printf("ERROR: %s mcd parameter must be of integral", name);
250 vpi_printf(", got vpiType=%d\n", type);
251 vpi_free_object(argv);
252 return 0;
255 value.format = vpiIntVal;
256 vpi_get_value(item, &value);
257 mcd = value.value.integer;
259 rval.format = vpiIntVal;
261 fp = vpi_get_file(mcd);
262 if (!fp || IS_MCD(mcd))
263 rval.value.integer = EOF;
264 else
265 rval.value.integer = fgetc(fp);
267 vpi_put_value(sys, &rval, 0, vpiNoDelay);
269 return 0;
272 static PLI_INT32 sys_fgetc_sizetf(PLI_BYTE8*x)
274 return 32;
277 static PLI_INT32 sys_fgets_compiletf(PLI_BYTE8*name)
279 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
280 vpiHandle argv = vpi_iterate(vpiArgument, sys);
281 vpiHandle item = vpi_scan(argv);
282 int type;
284 if (item == 0) {
285 vpi_printf("%s: string parameter missing.\n", name);
286 return 0;
289 type = vpi_get(vpiType, item);
291 if (type != vpiReg) {
292 vpi_printf("%s: string parameter must be a reg.\n", name);
293 vpi_free_object(argv);
294 return 0;
297 item = vpi_scan(argv);
298 if (item == 0) {
299 vpi_printf("%s: mcd parameter missing.\n", name);
300 return 0;
303 /* That should be all the arguments. */
304 item = vpi_scan(argv);
305 assert(item == 0);
307 return 0;
310 static PLI_INT32 sys_fgets_calltf(PLI_BYTE8*name)
312 unsigned int mcd;
313 FILE*fd;
314 s_vpi_value value, rval;
316 char*txt;
317 unsigned txt_len;
319 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
320 vpiHandle argv = vpi_iterate(vpiArgument, sys);
321 vpiHandle str = vpi_scan(argv);
322 vpiHandle mch = vpi_scan(argv);
324 value.format = vpiIntVal;
325 vpi_get_value(mch, &value);
326 mcd = value.value.integer;
328 fd = vpi_get_file(mcd);
329 if (!fd || IS_MCD(mcd)) {
330 rval.format = vpiIntVal;
331 rval.value.integer = 0;
332 vpi_put_value(sys, &rval, 0, vpiNoDelay);
333 return 0;
336 txt_len = vpi_get(vpiSize, str) / 8;
337 txt = malloc(txt_len + 1);
339 if (fgets(txt, txt_len+1, fd) == 0) {
340 rval.format = vpiIntVal;
341 rval.value.integer = 0;
342 vpi_put_value(sys, &rval, 0, vpiNoDelay);
343 free(txt);
344 return 0;
347 rval.format = vpiIntVal;
348 rval.value.integer = strlen(txt);
349 vpi_put_value(sys, &rval, 0, vpiNoDelay);
351 value.format = vpiStringVal;
352 value.value.str = txt;
353 vpi_put_value(str, &value, 0, vpiNoDelay);
355 free(txt);
357 return 0;
360 static PLI_INT32 sys_ungetc_compiletf(PLI_BYTE8*name)
362 int type;
363 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
364 vpiHandle argv = vpi_iterate(vpiArgument, sys);
365 vpiHandle item = vpi_scan(argv);
367 if (item == 0) {
368 vpi_printf("%s: mcd parameter missing.\n", name);
369 return 0;
372 type = vpi_get(vpiType, item);
373 switch (type) {
374 case vpiReg:
375 case vpiRealVal:
376 case vpiIntegerVar:
377 break;
378 default:
379 vpi_printf("ERROR: %s mcd parameter must be of integral", name);
380 vpi_printf(", got vpiType=%d\n", type);
381 vpi_free_object(argv);
382 return 0;
385 return 0;
388 static PLI_INT32 sys_ungetc_calltf(PLI_BYTE8*name)
390 unsigned int mcd;
391 unsigned char x;
392 s_vpi_value value, xvalue, rval;
393 vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
394 vpiHandle argv = vpi_iterate(vpiArgument, sys);
395 vpiHandle item = vpi_scan(argv);
396 FILE *fp;
398 rval.format = vpiIntVal;
400 assert(item);
402 value.format = vpiIntVal;
403 vpi_get_value(item, &value);
404 mcd = value.value.integer;
406 if (IS_MCD(mcd)) {
407 rval.value.integer = EOF;
408 vpi_put_value(sys, &rval, 0, vpiNoDelay);
409 return 0;
412 item = vpi_scan(argv);
414 xvalue.format = vpiIntVal;
415 vpi_get_value(item, &xvalue);
416 x = xvalue.value.integer;
418 fp = vpi_get_file(mcd);
419 if ( !fp ) {
420 rval.value.integer = EOF;
421 vpi_put_value(sys, &rval, 0, vpiNoDelay);
422 return 0;
425 ungetc(x, fp);
427 rval.value.integer = 0;
428 vpi_put_value(sys, &rval, 0, vpiNoDelay);
429 return 0;
432 static PLI_INT32 sys_ungetc_sizetf(PLI_BYTE8*x)
434 return 32;
439 void sys_fileio_register()
441 s_vpi_systf_data tf_data;
443 //============================== fopen
444 tf_data.type = vpiSysFunc;
445 tf_data.tfname = "$fopen";
446 tf_data.calltf = sys_fopen_calltf;
447 tf_data.compiletf = sys_fopen_compiletf;
448 tf_data.sizetf = sys_fopen_sizetf;
449 tf_data.user_data = "$fopen";
450 vpi_register_systf(&tf_data);
452 //============================== fclose
453 tf_data.type = vpiSysTask;
454 tf_data.tfname = "$fclose";
455 tf_data.calltf = sys_fclose_calltf;
456 tf_data.compiletf = 0;
457 tf_data.sizetf = 0;
458 tf_data.user_data = "$fclose";
459 vpi_register_systf(&tf_data);
461 //============================== fflush
462 tf_data.type = vpiSysTask;
463 tf_data.tfname = "$fflush";
464 tf_data.calltf = sys_fflush_calltf;
465 tf_data.compiletf = 0;
466 tf_data.sizetf = 0;
467 tf_data.user_data = "$fflush";
468 vpi_register_systf(&tf_data);
470 //============================== fputc
471 tf_data.type = vpiSysTask;
472 tf_data.tfname = "$fputc";
473 tf_data.calltf = sys_fputc_calltf;
474 tf_data.compiletf = 0;
475 tf_data.sizetf = 0;
476 tf_data.user_data = "$fputc";
477 vpi_register_systf(&tf_data);
479 //============================== fgetc
480 tf_data.type = vpiSysFunc;
481 tf_data.sysfunctype = vpiSysFuncInt;
482 tf_data.tfname = "$fgetc";
483 tf_data.calltf = sys_fgetc_calltf;
484 tf_data.compiletf = 0;
485 tf_data.sizetf = sys_fgetc_sizetf;
486 tf_data.user_data = "$fgetc";
487 vpi_register_systf(&tf_data);
489 //============================== fgets
490 tf_data.type = vpiSysFunc;
491 tf_data.sysfunctype = vpiSysFuncInt;
492 tf_data.tfname = "$fgets";
493 tf_data.calltf = sys_fgets_calltf;
494 tf_data.compiletf = sys_fgets_compiletf;
495 tf_data.sizetf = 0;
496 tf_data.user_data = "$fgets";
497 vpi_register_systf(&tf_data);
499 //============================== ungetc
500 tf_data.type = vpiSysFunc;
501 tf_data.sysfunctype = vpiSysFuncInt;
502 tf_data.tfname = "$ungetc";
503 tf_data.calltf = sys_ungetc_calltf;
504 tf_data.compiletf = sys_ungetc_compiletf;
505 tf_data.sizetf = sys_ungetc_sizetf;
506 tf_data.user_data = "$ungetc";
507 vpi_register_systf(&tf_data);
512 * $Log: sys_fileio.c,v $
513 * Revision 1.10 2007/03/14 04:05:51 steve
514 * VPI tasks take PLI_BYTE* by the standard.
516 * Revision 1.9 2006/10/30 22:45:37 steve
517 * Updates for Cygwin portability (pr1585922)
519 * Revision 1.8 2006/08/03 05:02:46 steve
520 * Use compiletf to check arguments.
522 * Revision 1.7 2005/09/20 18:34:01 steve
523 * Clean up compiler warnings.
525 * Revision 1.6 2005/01/09 20:12:22 steve
526 * Merge $fopen robustness fix from 0.8
528 * Revision 1.5.2.1 2005/01/01 20:07:41 steve
529 * More robust handling of file name argument to $fopen.
531 * Revision 1.5 2004/08/24 16:16:23 steve
532 * Fix read count passed to fgets.
534 * Revision 1.4 2004/02/20 03:20:04 steve
535 * unused variable warning.
537 * Revision 1.3 2004/02/19 21:33:13 steve
538 * Add the $fgets function.
540 * Revision 1.2 2003/11/07 19:40:05 steve
541 * Implement basic fflush.
543 * Revision 1.1 2003/10/30 03:43:20 steve
544 * Rearrange fileio functions, and add ungetc.