1 /* Copyright (c) 1986-2007 Pragmatic C Software Corp. */
2
3 /*
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place, Suite 330, Boston, MA, 02111-1307.
17
18 We are selling our new Verilog compiler that compiles to X86 Linux
19 assembly language. It is at least two times faster for accurate gate
20 level designs and much faster for procedural designs. The new
21 commercial compiled Verilog product is called CVC. For more information
22 on CVC visit our website at www.pragmatic-c.com/cvc.htm or contact
23 Andrew at avanvick@pragmatic-c.com
24
25 */
26
27
28 /*
29 * miscellaneous routines
30 */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <pwd.h>
37
38 #include <sys/types.h>
39 #include <sys/timeb.h>
40 #include <sys/fcntl.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43
44 #include <time.h>
45 #include <setjmp.h>
46 #include <ctype.h>
47 #include <errno.h>
48 #include <stdarg.h>
49
50 #ifdef __DBMALLOC__
51 #include "../malloc.h"
52 #endif
53
54 /* REMOVEME - no longer supporting SunOS - maybe needed for hpux? */
55 #if defined(__sparc) && !defined(__SVR4) && !defined(__FreeBSD__)
56 extern int32 tolower(int32);
57 extern ungetc(int32 c, FILE *);
58 extern long time (long *);
59 #endif
60
61 #include "v.h"
62 #include "cvmacros.h"
63
64 /* local prototypes */
65 static char *expand_arg_macro(struct sy_t *, int32 *);
66 static void process_macdef(void);
67 static void dmp_macdef_exptab(char *, struct macexp_t *);
68 static void process_macundef(void);
69 static char *bld_macdef_arglist(int32 *);
70 static char *remchk_macdef_coms(char *);
71 static struct macexp_t *bld_mac_expandtab(char *, char *, int32);
72 static int32 find_mac_formal_arg(char *);
73 static void free_macexplst(register struct macexp_t *);
74 static void do_argmacdefine(char *, struct macexp_t *, int32);
75 static int32 cskip_ifdef_section(FILE *, int32);
76 static int32 my_getc(FILE *);
77 static int32 rd_comment(FILE *);
78 static int32 skipto_attr_end(FILE *);
79 static void rd_attribute(FILE *);
80 static int32 vgetstr(FILE *);
81 static void str_tovval(void);
82 static void unget2_vtok(int32);
83 static int32 rd_num(FILE *, int32);
84 static void rem_lead_0chars(char *);
85 static int32 voverwhite(FILE *, register int32);
86 static int32 chlen_to_bitlen(int32, int32);
87 static void chg_abwrklen(int32);
88 static void to_dec(int32 *);
89 static void wide_strtoverdec(int32);
90 static void to_bin(int32);
91 static void to_oct(int32);
92 static void to_hex(int32);
93 static int32 vnum_toowide(word32 *, int32);
94 static int32 nibblexz(word32, word32, int32);
95 static int32 octdigxz(word32 *, word32 *, int32);
96 static void widen_val(word32 *, int32, int32, word32);
97 static char *prt2_vtok(int32);
98 static int32 get_vkeywrd(register char *);
99 static int32 set_syncto_tokclass(byte);
100 static int32 set_specitem_class(void);
101 static int32 set_udpsyncto(byte);
102 static int32 get_cfgkeywrd(char *);
103 static int32 get_cmdcomment(FILE *);
104 static void one_rot(struct tnode_t *, struct tnode_t *, struct tnode_t *);
105 static void two_rot(struct tnode_t *, struct tnode_t *, struct tnode_t *);
106 static struct tnode_t *alloc_tnode(struct symtab_t *);
107 static char *__to_nppsubtyp(char *, word32);
108 static char *decompnum_to_str(char *, char *, int32, int32);
109 static char *nfbig_alloc(int32);
110 static char *tilde_expand(char *, int32 *);
111 static char *pv_stralloc2(char *);
112 static int32 try_chg_tononesc(void);
113 static int32 ch_tobits(word32 *, word32 *, int32);
114 static int32 ch_toocts(word32 *, word32 *, int32);
115 static int32 ch_tohexs(word32 *, word32 *, int32);
116
117 /* extern prototypes (maybe defined in this module) */
118 extern void __get_vtok(void);
119 extern int32 __chk_beg_line(int32);
120 extern void __collect_line(void);
121 extern void __skipover_line(void);
122 extern void __do_macdefine(char *, char *);
123 extern int32 __bqline_emptytail(register char *);
124 extern void __do_include(void);
125 extern int32 __rd_ialine(void);
126 extern int32 __get1_vtok(FILE *);
127 extern void __vstr_to_vval(word32 *, char *, int32);
128 extern struct xstk_t *__cstr_to_vval(char *);
129 extern void __unget_vtok(void);
130 extern int32 __to_base(int32);
131 extern int32 __is_vdigit(int32, int32);
132 extern void __to_dhboval(int32, int32);
133 extern char *__prt_vtok(void);
134 extern char *__to_opname(word32);
135 extern char *__get_vkeynam(char *, int32);
136 extern int32 __vskipto_modend(int32);
137 extern int32 __vskipto2_modend(int32, int32);
138 extern int32 __vskipto3_modend(int32, int32, int32);
139 extern int32 __vskipto_any(int32);
140 extern int32 __vskipto2_any(int32, int32);
141 extern int32 __vskipto3_any(int32, int32, int32);
142 extern int32 __vskipto4_any(int32, int32, int32, int32);
143 extern int32 __spec_vskipto_any(int32);
144 extern int32 __spec_vskipto2_any(int32, int32);
145 extern int32 __spec_vskipto3_any(int32, int32, int32);
146 extern int32 __udp_vskipto_any(int32);
147 extern int32 __udp_vskipto2_any(int32, int32);
148 extern int32 __udp_vskipto3_any(int32, int32, int32);
149 extern int32 __get_cmdtok(FILE *);
150 extern struct sy_t *__get_sym_env(char *);
151 extern struct sy_t *__find_sym(char *);
152 extern struct sy_t *__decl_sym(char *, struct symtab_t *);
153 extern void __add_sym(char *, struct tnode_t *);
154 extern struct sy_t *__get_sym(char *, struct symtab_t *);
155 extern struct tnode_t *__vtfind(char *, struct symtab_t *);
156 extern struct sy_t *__zget_sym(char *, struct sy_t **, word32);
157 extern struct symtab_t *__alloc_symtab(int32);
158 extern int32 __ip_indsrch(char *);
159 extern char *__to_idnam(struct expr_t *);
160 extern char *__to_mpnam(char *, char *);
161 extern int32 __fr_wtnam(int32);
162 extern char *__to_wtnam(char *, struct net_t *);
163 extern char *__to_wtnam2(char *, word32);
164 extern char *__to_ptnam(char *, word32);
165 extern char *__to_splt_nam(char *, int32);
166 extern word32 __fr_stren_nam(int32);
167 extern char *__to_stren_nam(char *, int32, int32);
168 extern char *__to_stval_nam(char *, word32);
169 extern char *__to1_stren_nam(char *, int32, int32);
170 extern int32 __is_capstren(int32);
171 extern int32 __fr_cap_size(int32);
172 extern word32 __to_cap_size(int32);
173 extern char *__to_sytyp(char *, word32);
174 extern char *__to_tsktyp(char *, word32);
175 extern char *__to_sttyp(char *, word32);
176 extern char *__to_qctyp(char *, word32);
177 extern char *__to_tetyp(char *, word32);
178 extern char *__to_npptyp(char *, struct net_pin_t *);
179 extern char *__to_deltypnam(char *, word32);
180 extern char *__to_tcnam(char *, word32);
181 extern int32 __fr_tcnam(char *);
182 extern char *__to_gonam(char *, struct gate_t *, word32);
183 extern char *__to_ginam(char *, struct gate_t *, word32, int32);
184 extern char *__to_vnam(char *, word32, word32);
185 extern char *__to_vvstnam(char *, word32);
186 extern char *__to_vvnam(char *, word32);
187 extern char *__to_uvvnam(char *, word32);
188 extern char __to_baselet(int32);
189 extern char *__to_timunitnam(char *, word32);
190 extern char *__to_edgenam(char *, word32);
191 extern char *__to_dcenam(char *, word32);
192 extern char *__pv_stralloc(char *);
193 extern char *__my_malloc(int32);
194 extern void __my_free(char *, int32);
195 extern char *__my_realloc(char *, int32, int32);
196 extern void __my_fclose(FILE *);
197 extern void __my_rewind(FILE *);
198 extern int32 __tilde_open(char *, int32);
199 extern FILE *__tilde_fopen(char *, char *);
200 extern FILE *__my_fopen(char *, char *);
201 extern int32 __tilde_creat(char *);
202 extern int32 __my_creat(char *);
203 extern char *__schop(char *, char *);
204 extern char *__bld_lineloc(char *, word32, int32);
205 extern void __init_sy(struct sy_t *);
206
207 extern void __crit_msg(char *, ...);
208 extern void __sysfatal_msg(char *, ...);
209 extern void __cv_msg(char *, ...);
210 extern void __cvsim_msg(char *, ...);
211 extern void __dbg_msg(char *, ...);
212 extern void __misc_terr(char *, int32);
213 extern void __misc_fterr(char *, int32);
214 extern void __misc_gfterr(char *, int32, word32, int32);
215 extern void __misc_sgfterr(char *, int32);
216 extern void __case_terr(char *, int32);
217 extern void __arg_terr(char *, int32);
218 extern void __pv_terr(int32, char *, ...);
219 extern void __fterr(int32, char *, ...);
220 extern void __sgfterr(int32, char *, ...);
221 extern void __gfterr(int32, word32, int32, char *, ...);
222 extern void __pv_err(int32, char *, ...);
223 extern void __pv_ferr(int32, char *, ...);
224 extern void __sgferr(int32, char *, ...);
225 extern void __gferr(int32, word32, int32, char *, ...);
226 extern void __ia_err(int32, char *, ...);
227 extern void __via_err(int32, char *, va_list, va_list);
228 extern void __pv_warn(int32, char *, ...);
229 extern void __pv_fwarn(int32, char *, ...);
230 extern void __sgfwarn(int32, char *, ...);
231 extern void __gfwarn(int32, word32, int32, char *, ...);
232 extern void __ia_warn(int32, char *, ...);
233 extern void __via_warn(int32, char *, va_list, va_list);
234 extern void __inform(int32, char *, ...);
235 extern void __finform(int32, char *, ...);
236 extern void __sgfinform(int32, char *, ...);
237 extern void __gfinform(int32, word32, int32, char *, ...);
238 extern int32 __em_suppr(int32);
239 extern void __my_fprintf(FILE *, char *, ...);
240 extern void __my_vfprintf(FILE *, char *, va_list, va_list);
241 extern void __vpi_error_trycall(void);
242 extern void __cberror_fill_einfo(int32, int32, char *, char *, int32);
243
244 extern int32 __pop_vifstk(void);
245 extern int32 __open_sfil(void);
246 extern void __push_vinfil(void);
247 extern void __grow_infils(int32);
248 extern void __grow_xstk(void);
249 extern void __chg_xstk_width(struct xstk_t *, int32);
250 extern double __my_strtod(char *, char **, int32 *);
251 extern word32 __my_strtoul(char *, char **, int *);
252 extern int32 __trim1_0val(word32 *, int32);
253 extern void __lmult(register word32 *, register word32 *, register word32 *, int32);
254 extern void __ladd(word32 *, word32 *, word32 *, int32);
255 extern void __lhsbsel(register word32 *, register int32, word32);
256 extern void __lhspsel(register word32 *, register int32, register word32 *, register int32);
257 extern void __rhspsel(register word32 *, register word32 *, register int32, register int32);
258 extern void __my_exit(int32, int32);
259 extern char *__to_timstr(char *, word64 *);
260 extern int32 __notokenize_skiplines(char *);
261 extern char *__to_dispst_str(char *, word32);
262
263
264 extern struct opinfo_t __opinfo[];
265 extern byte __stren_map_tab[];
266 extern word32 __masktab[];
267
268 /* system stuff */
269 extern int32 errno;
270
271 /* jmp buf defined in v_dbg */
272 extern jmp_buf __iact_jmpbuf;
273 extern char __pv_ctab[];
274
275 /*
276 * ROUTINES THE INTERFACE TO GET TOKEN ROUTINES
277 */
278
279 /*
280 * get a Verilog token (outer routine for macro handling)
281 *
282 * routine sets globals __toktyp and __token and may set other for numbers
283 * (modified from yylex in "The Unix Programming Environment" p. 337)
284 *
285 * BEWARE - need to be careful here because for efficiency using global
286 * strings ok to use __xs but not call prt2_vtok more than once in error
287 */
__get_vtok(void)288 extern void __get_vtok(void)
289 {
290 int32 ttyp, ifdtyp, len, savlin_cnt;
291 struct sy_t *syp, *tmpsyp;
292 char *chp;
293
294 /* assume no attribute prefix */
295 __attr_prefix = FALSE;
296 if (__lasttoktyp != UNDEF)
297 {
298 __toktyp = __lasttoktyp;
299 strcpy(__token, __lasttoken);
300 __lasttoktyp = UNDEF;
301 /* SJM 10/16/00 - must save and restore state of pending attr prefix */
302 /* seen when token is pushed back - happens for endmodule then read of */
303 /* module to check for EOF */
304 __attr_prefix = __last_attr_prefix;
305
306 /* extremely rare number push back case */
307 if (__toktyp == NUMBER)
308 {
309 word32 wlen;
310
311 __itokbase = __lastitokbase;
312 __itoksized = __lastitoksized;
313 __itoksizdflt = __lastitoksizdflt;
314 __itok_signed = __lastitok_signed;
315 __itoklen = __lastitoklen;
316
317 /* used malloc to save const value, now need to restore and free */
318 wlen = wlen_(__itoklen);
319 memcpy(__acwrk, __lastacwrk, wlen*WRDBYTES);
320 __my_free((char *) __lastacwrk, wlen*WRDBYTES);
321 memcpy(__bcwrk, __lastbcwrk, wlen*WRDBYTES);
322 __my_free((char *) __lastbcwrk, wlen*WRDBYTES);
323 __lastacwrk = __lastbcwrk = NULL;
324 }
325 else if (__toktyp == REALNUM)
326 {
327 __itokbase = __lastitokbase;
328 __itoksized = __lastitoksized;
329 __itoksizdflt = __lastitoksizdflt;
330 __itok_signed = __lastitok_signed;
331 __itoklen = __lastitoklen;
332 __itok_realval = __lastitok_realval;
333 }
334 return;
335 }
336
337 vtagain:
338 /* file will be NULL when reading from macro text */
339 switch ((byte) (ttyp = __get1_vtok(__in_s))) {
340 case TEOF:
341 /* first try to pop some sort of outer nested thing */
342 if (__pop_vifstk())
343 {
344 /* SJM 06/22/00 - for 2 stage 2 tok num - ready to read 2nd tok of num */
345 if (__macro_sep_width)
346 {
347 __maybe_2tok_sized_num = TRUE;
348 __macro_sep_width = FALSE;
349 }
350 goto vtagain;
351 }
352 /* next try to replace just finished 0th element with new input file */
353 if (__cur_infi + 1 > __last_inf || __iact_state)
354 { __toktyp = TEOF; return; }
355 __cur_infi++;
356 if (!__open_sfil()) { __toktyp = TEOF; return; }
357 /* know first token of file flag now on */
358 goto vtagain;
359 case CDIR_DEFINE:
360 /* on return - know all of line read */
361 process_macdef();
362 goto vtagain;
363 case CDIR_UNDEF:
364 process_macundef();
365 goto vtagain;
366 case CDIR_INCLUDE:
367 if (__iact_state)
368 {
369 illegal_iact_dir:
370 __ia_err(1401, "%s compiler directive illegal in interactive commands",
371 prt2_vtok(ttyp));
372 __skipover_line();
373 goto vtagain;
374 }
375 /* on return all of line read - trims tail of line for file name */
376 if (!__chk_beg_line(CDIR_INCLUDE)) goto vtagain;
377 /* collect line into mac wr kstrafter first skips white space to token */
378 __collect_line();
379 __do_include();
380 goto vtagain;
381 case CDIR_IFDEF: case CDIR_IFNDEF:
382 if (__iact_state) goto illegal_iact_dir;
383 ifdtyp = ttyp;
384 if (!__chk_beg_line(ifdtyp)) goto vtagain;
385 /* see if token `defined */
386 savlin_cnt = __lin_cnt;
387 if ((ttyp = __get1_vtok(__in_s)) != ID)
388 {
389 /* BEWARE */
390 /* must use get vkeynam for compile directive (know only 2 possible) */
391 /* because prt2_vtok uses fixed storage */
392 __pv_ferr(923, "%s not followed by text macro name - %s read",
393 __get_vkeynam(__xs, ifdtyp), prt2_vtok(ttyp));
394 goto skip_rest;
395 }
396 if (*__token == '`')
397 {
398 __pv_fwarn(570,
399 "%s text macro name %s should not begin with ` - dropped",
400 __get_vkeynam(__xs, ifdtyp), __token);
401 strcpy(__xs, __token);
402 goto skip_rest;
403 }
404 else { strcpy(&(__xs[1]), __token); __xs[0] = '`'; }
405 if (savlin_cnt != __lin_cnt)
406 {
407 __pv_ferr(921, "%s text macro name must be on same line",
408 __get_vkeynam(__xs, ifdtyp));
409 unget2_vtok(ttyp);
410 /* to get here know moved to next line */
411 goto vtagain;
412 }
413 __in_ifdef_level++;
414 /* notice for macro with args. here still just use name */
415 tmpsyp = __get_sym(__xs, __pv_defsyms);
416
417 /* undeclare when macro undefed because no way to remove from symtab */
418 if (tmpsyp != NULL && !tmpsyp->sydecl) tmpsyp = NULL;
419
420 /* `ifndef reverses sense of `ifdef - following C preprocessor */
421 if ((ifdtyp == CDIR_IFDEF && tmpsyp == NULL)
422 || (ifdtyp == CDIR_IFNDEF && tmpsyp != NULL))
423 {
424 /* case 1: `ifdef symbol not defined (i.e. if fails) */
425 if (cskip_ifdef_section(__in_s, ifdtyp) == CDIR_ENDIF)
426 {
427 /* if this is `endif just skipped `ifdef (or `ifndef) so continue */
428 /* if else enter look for else state */
429 __in_ifdef_level--;
430 }
431 /* `else or `endif read and processed when get to here */
432 /* know if end with `else, will be ready to include `else lines */
433 /* if this is `endif get an actual token */
434 goto vtagain;
435 }
436 /* case 2: symbol defined - continue getting tokens to `else or endif` */
437 skip_rest:
438 /* must always skip over rest of line */
439 __skipover_line();
440 goto vtagain;
441 case CDIR_ELSE:
442 if (__iact_state) goto illegal_iact_dir;
443 if (!__chk_beg_line(CDIR_ELSE)) goto vtagain;
444 /* know ifdef was true - this is end and need to skip */
445 if (__in_ifdef_level == 0)
446 {
447 __pv_ferr(924, "`else read but no previous matching initial `ifdef");
448 goto skip_rest;
449 }
450 /* if skip to another else, this will emit error and continue */
451 /* know can only return with `endif */
452 cskip_ifdef_section(__in_s, CDIR_ELSE);
453 __in_ifdef_level--;
454 /* this will have consumed `endif line */
455 goto vtagain;
456 case CDIR_ENDIF:
457 if (__iact_state) goto illegal_iact_dir;
458 if (!__chk_beg_line(CDIR_ENDIF)) goto vtagain;
459 __skipover_line();
460 /* think this can never happen */
461 if (__in_ifdef_level == 0)
462 {
463 __pv_ferr(925, "`endif read but no previous matching initial `ifdef");
464 goto vtagain;
465 }
466 __in_ifdef_level--;
467 /* else just up one nested ifdef level */
468 goto vtagain;
469 /* SJM 09/18/99 - these need to be supported inside modules */
470 case CDIR_ENDPROTECT:
471 case CDIR_ENDPROTECTED:
472 case CDIR_PROTECT:
473 case CDIR_PROTECTED:
474 __pv_fwarn(619, "directive %s unimplemented", prt2_vtok(ttyp));
475 __skipover_line();
476 goto vtagain;
477 /* notice time scale can only appear outside modules*/
478 case ID:
479 /* user redefinition of compiler directive overwrites keyword */
480 if (*__token == '$') goto ret_id;
481
482 if (*__token == '`')
483 {
484 if ((syp = __get_sym(__token, __pv_defsyms)) == NULL || !syp->sydecl)
485 {
486 __pv_fwarn(654,
487 "text macro %s undefined or possibly compiler directive for other tool - ignored",
488 __token);
489 goto vtagain;
490 }
491 if (!syp->sy_argsmac)
492 {
493 chp = syp->el.edfchp;
494 /* `define macros can be empty from +define+ command arg */
495 if (strcmp(chp, "") == 0) goto vtagain;
496 len = -1;
497 }
498 else
499 {
500 int32 sav_first_num_eol;
501
502 /* save first tok state, if `xx expands to compiler dir. must be 1st */
503 /* 2 stage num eol in get 1 vtok sets first of line */
504 if (__first_linetok) sav_first_num_eol = TRUE;
505 else sav_first_num_eol = FALSE;
506
507 /* expand into malloced storage setting length to len */
508 /* this may unget TEOF token */
509 chp = expand_arg_macro(syp, &len);
510 __first_num_eol = sav_first_num_eol;
511 if (chp == NULL) goto vtagain;
512 }
513 /* if currently reading file, must preserve line count */
514 if (__visp->vi_s != NULL) __visp->vilin_cnt = __lin_cnt;
515 /* push string on top of read stack */
516 __push_vinfil();
517 __visp->vichp = __visp->vichp_beg = chp;
518 __visp->vichplen = len;
519 __in_s = NULL;
520 /* DBG remove --- */
521 if (__debug_flg)
522 __dbg_msg("macro %s value [%s]\n", syp->synam, chp);
523 /* --- */
524 goto vtagain;
525 }
526 ret_id:
527 __file_just_op = FALSE;
528 __toktyp = ID;
529 break;
530 default:
531 /* if this is not directive, must indicate not at start of file */
532 if (ttyp < CDIR_TOKEN_START || ttyp > CDIR_TOKEN_END)
533 __file_just_op = FALSE;
534 __toktyp = ttyp;
535 break;
536 }
537 /* SJM 06/22/00 - using 2 state 2 token number - finished by here */
538 __maybe_2tok_sized_num = FALSE;
539 /* DBG remove --
540 if (__debug_flg)
541 {
542 if (__toktyp == ID) __dbg_msg("++ returning token %s [%d]\n", __token,
543 __toktyp);
544 else __dbg_msg("++ returning token %s [%d]\n", __prt_vtok(), __toktyp);
545 }
546 --- */
547 }
548
549 /* macro for adding char and growing mac wrk str */
550 #define addto_macwrkstr_(c) \
551 do { \
552 int32 osize; \
553 if (++len >= __macwrklen - 1) \
554 { \
555 osize = __macwrklen; \
556 __macwrklen += IDLEN; \
557 __macwrkstr = __my_realloc(__macwrkstr, osize, __macwrklen); \
558 chp = &(__macwrkstr[len - 1]); \
559 } \
560 *chp++ = (c); \
561 } while (0)
562
563 /*
564 * expand a macro with arguments
565 *
566 * collects , (...) list which may have syntax errors into mac work string
567 * list cannot cross macro or include but can contain white space
568 * build array of args that are malloced using __macwrkstr
569 * processing within argument () special char not token scanning
570 * reads ending ) then stops reading
571 *
572 * notice sections of text with unmatched ) or , are illegal since
573 * in Verilog \ escapes an identifier
574 */
expand_arg_macro(struct sy_t * syp,int32 * explen)575 static char *expand_arg_macro(struct sy_t *syp, int32 *explen)
576 {
577 register int32 c;
578 register char *chp, *chp2;
579 int32 ttyp, par_cnt, setb_cnt, setb_err, last_argno, last_i, len;
580 struct amac_t *amacp;
581 struct macexp_t *mxp;
582 struct macarg_t *macap, *macap2, *maca_hdr, *maca_end, **mactab;
583
584 *explen = -1;
585 if ((ttyp = __get1_vtok(__in_s)) != LPAR)
586 {
587 __pv_ferr(1270, "%s macro argument list ( expected - %s read",
588 syp->synam, prt2_vtok(ttyp));
589 unget2_vtok(ttyp);
590 return(NULL);
591 }
592 /* get each argument first into mac wrk str then alloc */
593 /* argument is string before next non nested , or ) */
594 macap = maca_end = maca_hdr = NULL;
595 for (c = -1, last_argno = 0;; last_argno++)
596 {
597 setb_err = FALSE;
598 par_cnt = setb_cnt = 0;
599 for (chp = __macwrkstr, len = 0;;)
600 {
601 c = my_getc(__in_s);
602 switch (c) {
603 case EOF:
604 eof_err:
605 __pv_ferr(1295,
606 "%s macro argument no. %d **EOF** read before argument ending , or )",
607 syp->synam, last_argno);
608 /* must put back eof */
609 my_ungetc_(c, __in_s);
610 /* allow memory leak on syntax eof error */
611 return(NULL);
612 case '(': par_cnt++; break;
613 case ')':
614 /* if this is extra ) must end - error if in concat */
615 if (par_cnt == 0)
616 {
617 if (setb_cnt > 0)
618 __pv_ferr(1296,
619 "%s macro argument no. %d list ending ) found but concatenate not ended",
620 syp->synam, last_argno);
621 goto arg_end;
622 }
623 par_cnt--;
624 break;
625 case '{': setb_cnt++; break;
626 case '}':
627 if (setb_cnt == 0 && !setb_err)
628 {
629 __pv_ferr(1297,
630 "%s macro argument no. %d list nested concatenate illegal - too many }s",
631 syp->synam, last_argno);
632 setb_err = TRUE;
633 }
634 else setb_cnt--;
635 break;
636 case ',':
637 if (par_cnt == 0 && setb_cnt == 0) goto arg_end;
638 break;
639 /* copy all chars in quoted string - vgetstr used later to scan */
640 case '"':
641 addto_macwrkstr_(c);
642 for (;;)
643 {
644 c = my_getc(__in_s);
645 /* must not end on escaped " */
646 if (c == '\\') { addto_macwrkstr_(c); c = my_getc(__in_s); }
647 else if (c == '"') break;
648
649 if (c == EOF) goto eof_err;
650 /* here collect embedded new line, error later */
651 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
652 addto_macwrkstr_(c);
653 }
654 break;
655 /* copy from escape through white space since maybe esc. id */
656 /* no escaping inside escaped ID */
657 case '\\':
658 addto_macwrkstr_(c);
659 for (;;)
660 {
661 c = my_getc(__in_s);
662 if (c == EOF) goto eof_err;
663 if (vis_white_(c)) break;
664 addto_macwrkstr_(c);
665 }
666 break;
667 }
668 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
669 addto_macwrkstr_(c);
670 }
671 arg_end:
672 *chp = '\0';
673 macap = (struct macarg_t *) __my_malloc(sizeof(struct macarg_t));
674 macap->macargnam = __pv_stralloc(__macwrkstr);
675 macap->macargnxt = NULL;
676 if (maca_end == NULL) maca_hdr = maca_end = macap;
677 else maca_end->macargnxt = macap;
678 maca_end = macap;
679 if (c == ')') break;
680 }
681 /* convert argument list to table for look up from sym mac exp. tab */
682 mactab = (struct macarg_t **)
683 __my_malloc((last_argno + 1)*sizeof(struct macarg_t *));
684 for (last_i = -1, macap = maca_hdr; macap != NULL; macap = macap->macargnxt)
685 mactab[++last_i] = macap;
686 /* DBG remove */
687 if (last_i != last_argno) __misc_terr(__FILE__, __LINE__);
688 /* --- */
689 amacp = syp->el.eamacp;
690 if (last_i + 1 != amacp->num_formal_args)
691 {
692 __pv_ferr(1298,
693 "%s macro requires %d formal arguments - %d present", syp->synam,
694 amacp->num_formal_args, last_i + 1);
695 chp2 = NULL;
696 goto done;
697 }
698 /* do the expansion */
699 chp = __macwrkstr;
700 for (len = 0, mxp = amacp->amxp; mxp != NULL; mxp = mxp->macexpnxt)
701 {
702 /* copy into chp the leading string */
703 for (chp2 = mxp->leading_str; *chp2 != '\0'; chp2++)
704 addto_macwrkstr_(*chp2);
705 /* copy the actual argument, -1 for none (trailing part) */
706 if (mxp->ins_argno != -1)
707 {
708 for (chp2 = mactab[mxp->ins_argno]->macargnam; *chp2 != '\0'; chp2++)
709 addto_macwrkstr_(*chp2);
710 }
711 }
712 *chp = '\0';
713 chp2 = __my_malloc(len + 1);
714 strcpy(chp2, __macwrkstr);
715 *explen = len;
716
717 /* final step - free actual arg list */
718 done:
719 for (macap = maca_hdr; macap != NULL;)
720 {
721 macap2 = macap->macargnxt;
722 __my_free((char *) macap->macargnam, strlen(macap->macargnam) + 1);
723 __my_free((char *) macap, sizeof(struct macarg_t));
724 macap = macap2;
725 }
726 maca_hdr = NULL;
727 __my_free((char *) mactab, (last_argno + 1)*sizeof(struct macarg_t *));
728 return(chp2);
729 }
730
731 /*
732 * process one `define macro define
733 * know `define read and consumes entire line
734 * notice macro name must be in symbol table with `
735 */
process_macdef(void)736 static void process_macdef(void)
737 {
738 int32 ttyp, has_err, savlin_cnt, nargs, c, space_before_lpar;
739 char *mactxt_chp, dnam[IDLEN];
740 struct macexp_t *mxp;
741
742 if (!__chk_beg_line(CDIR_DEFINE)) return;
743 savlin_cnt = __lin_cnt;
744 has_err = FALSE;
745 if ((ttyp = __get1_vtok(__in_s)) != ID)
746 {
747 __pv_ferr(922, "`define not followed by text macro identifier - %s read",
748 prt2_vtok(ttyp));
749 has_err = TRUE;
750 }
751 /* need to use get token that does not know about line breaks */
752 if (__lin_cnt != savlin_cnt)
753 {
754 __pv_ferr(929, "`define text macro identifier name must be on same line");
755 unget2_vtok(ttyp);
756 return;
757 }
758 if (!has_err && __token[0] == '`')
759 {
760 __pv_ferr(1291,
761 "`define text macro identifier name %s cannot begin with `", __token);
762 has_err = TRUE;
763 }
764 if (!has_err) { strcpy(dnam, "`"); strcat(dnam, __token); }
765 /* always collect entire line (with possible escaped nl) into mac wrk str */
766
767 c = my_getc(__in_s);
768 /* if white space collect will skip anyway - no need to unget */
769 if (vis_nonnl_white_(c)) space_before_lpar = TRUE;
770 else
771 {
772 space_before_lpar = FALSE;
773 my_ungetc_(c, __in_s);
774 }
775 __collect_line();
776
777 /* if problem with definition but saw `define return after line read */
778 if (has_err) return;
779
780 if (get_vkeywrd(dnam) != ID)
781 {
782 __pv_ferr(1293,
783 "macro name %s conflicts with predefined directive - redefinition illegal",
784 dnam);
785 return;
786 }
787
788 /* if has argument build list and return start of body in mac wrk str */
789 /* returns nil if error (it emits the message) */
790 /* SJM - 01/31/00 - now for arg macros ( must be next char (no intervening white space) */
791 /* otherwise ( treated as grouping param */
792 if (!space_before_lpar && __macwrkstr[0] == '(')
793 {
794 /* build the global formal argument list and skip over it */
795 if ((mactxt_chp = bld_macdef_arglist(&nargs)) == NULL) return;
796
797 /* remove all comments macro and replace multiple white space with 1 sp */
798 /* also remove trailing white space */
799 /* this replaces value in mac wrk str - will always be no longer */
800 if ((mactxt_chp = remchk_macdef_coms(mactxt_chp)) == NULL) return;
801
802 /* if expands to empty (could be some white space) make one space */
803 if ((mxp = bld_mac_expandtab(dnam, mactxt_chp, nargs)) == NULL)
804 { strcpy(__macwrkstr, " "); goto do_nonarg; }
805 do_argmacdefine(dnam, mxp, nargs);
806 if (__debug_flg) dmp_macdef_exptab(dnam, mxp);
807 }
808 else
809 {
810 do_nonarg:
811 /* SJM - 01/31/00 - continue to support old escaped scheme */
812 if (__macwrkstr[0] == '\\' && __macwrkstr[1] == '(')
813 mactxt_chp = &(__macwrkstr[1]);
814 else mactxt_chp = __macwrkstr;
815 if ((mactxt_chp = remchk_macdef_coms(mactxt_chp)) == NULL) return;
816 __do_macdefine(dnam, mactxt_chp);
817 if (__debug_flg)
818 __dbg_msg("+++ text macro %s defined with value [%s]\n", dnam,
819 mactxt_chp);
820 }
821 }
822
823 /*
824 * dump the arg. macro expansion table for debugging
825 */
dmp_macdef_exptab(char * dnam,struct macexp_t * mxp)826 static void dmp_macdef_exptab(char *dnam, struct macexp_t *mxp)
827 {
828 int32 argno;
829
830 __dbg_msg("+++ arg text macro %s defined - expands from:\n", dnam);
831 for (argno = 1; mxp != NULL; mxp = mxp->macexpnxt, argno++)
832 {
833 __dbg_msg(" arg. %d: prefix [%s] insert actual %d\n",
834 argno, mxp->leading_str, mxp->ins_argno);
835 }
836 __dbg_msg("+++ end of formal args +++\n");
837 }
838
839 /*
840 * undefine a macro
841 */
process_macundef(void)842 static void process_macundef(void)
843 {
844 int32 ttyp, has_err, savlin_cnt;
845 struct sy_t *syp;
846 char dnam[IDLEN];
847
848 if (!__chk_beg_line(CDIR_UNDEF)) return;
849 savlin_cnt = __lin_cnt;
850 has_err = FALSE;
851 if ((ttyp = __get1_vtok(__in_s)) != ID)
852 {
853 __pv_ferr(922, "`undef required text macro identifier missing - %s read",
854 prt2_vtok(ttyp));
855 has_err = TRUE;
856 }
857 /* need to use get token that does not know about line breaks */
858 if (__lin_cnt != savlin_cnt)
859 {
860 __pv_ferr(929, "`undef text macro identifier name must be on same line");
861 unget2_vtok(ttyp);
862 return;
863 }
864 if (!has_err && __token[0] == '`')
865 {
866 __pv_ferr(1291,
867 "`undef text macro identifier name %s cannot begin with `", __token);
868 has_err = TRUE;
869 }
870 if (!has_err) { strcpy(dnam, "`"); strcat(dnam, __token); }
871 __skipover_line();
872 if (has_err) return;
873
874 if (get_vkeywrd(dnam) != ID)
875 {
876 __pv_ferr(1293,
877 "`undef of macro name %s illegal - cannot `undef predefined directive",
878 dnam);
879 return;
880 }
881
882 if ((syp = __get_sym(dnam, __pv_defsyms)) == NULL || !syp->sydecl)
883 {
884 __pv_fwarn(655, "`undef of %s does nothing - macro not defined", dnam);
885 return;
886 }
887 if (syp->sy_argsmac)
888 {
889 free_macexplst(syp->el.eamacp->amxp);
890 __my_free((char *) syp->el.eamacp, sizeof(struct amac_t));
891 syp->sy_argsmac = FALSE;
892 }
893 else __my_free(syp->el.edfchp, strlen(syp->el.edfchp) + 1);
894 syp->el.edfchp = __pv_stralloc("");
895 syp->sydecl = FALSE;
896 }
897
898 /*
899 * return F and emit error if not at beginning of line
900 * tricky case if first token file_just_op - this is really first token
901 * in line but flag will be off - check for case and if found must turn
902 * off file just open - if this check not called will get turned off
903 * normally.
904 *
905 * problem here is caused by Verilog semantics that treat compiler directives
906 * as having \n as token but in normal code not a token
907 */
__chk_beg_line(int32 cdtyp)908 extern int32 __chk_beg_line(int32 cdtyp)
909 {
910 /* ---
911 if (__iact_state)
912 {
913 __ia_err(1401,
914 "compiler directives illegal in interactive commands - %s read",
915 __get_vkeynam(__xs, cdtyp));
916 return(FALSE);
917 }
918 --- */
919 if (!__first_linetok)
920 {
921 if (__file_just_op) { __file_just_op = FALSE; return(TRUE); }
922 else __pv_ferr(928, "compiler directive %s must be first token on line",
923 __get_vkeynam(__xs, cdtyp));
924 return(FALSE);
925 }
926 return(TRUE);
927 }
928
929 /*
930 * collect a line into mac wrk str first skip over all leading white space
931 * notice white space inside line kept and line can be arbitrarily long
932 * with possible escaped new lines
933 *
934 * this sets length of used part of macro line
935 * this can be arbitrarily long for mulitple line macros
936 */
__collect_line(void)937 extern void __collect_line(void)
938 {
939 register int32 c;
940 register char *chp;
941 int32 len;
942
943 for (;;) { c = my_getc(__in_s); if (!vis_nonnl_white_(c)) break; }
944 if (c == '\n' || c == EOF)
945 {
946 *__macwrkstr = '\0';
947 my_ungetc_(c, __in_s);
948 return;
949 }
950 for (chp = __macwrkstr, len = 0;;)
951 {
952 /* \\n is line continuation and must become ' ' in macro string line */
953 /* anything else added is part of escaped id */
954 if (c == '\\')
955 {
956 if ((c = my_getc(__in_s)) == '\n') { c = ' '; __lin_cnt++; }
957 else { my_ungetc_(c, __in_s); c = '\\'; }
958 }
959 addto_macwrkstr_(c);
960 c = my_getc(__in_s);
961 if (c == '\n' || c == EOF) { my_ungetc_(c, __in_s); break; }
962 }
963 /* notice trailing new line or eof removed */
964 *chp = '\0';
965 __mac_line_len = len;
966 }
967
968 /*
969 * skip over characters to a new line (skip ending or error stuff)
970 * know current char never new line
971 * this also skips over \\[newline]
972 *
973 * not counted as part of total source lines since skipped from ` conds
974 */
__skipover_line(void)975 extern void __skipover_line(void)
976 {
977 register int32 c;
978
979 for (;;)
980 {
981 if ((c = my_getc(__in_s)) == '\n' || c == EOF) break;
982 if (c == '\\')
983 {
984 /* \\n is just white space not end of line but \\EOF is still eof */
985 if ((c = my_getc(__in_s)) == EOF) break;
986 /* not counting continuation lines in total */
987 if (c == '\n') __lin_cnt++;
988 }
989 }
990 if (c != EOF) { my_ungetc_(c, __in_s); };
991 }
992
993 /*
994 * read a line into passed string
995 */
__my_getlin(register char * lp)996 extern int32 __my_getlin(register char *lp)
997 {
998 register int32 c, len;
999
1000 for (len = 0;;)
1001 {
1002 c = my_getc(__in_s);
1003 if (++len >= IDLEN)
1004 {
1005 __pv_ferr(2889, "`language section line too long (%d) - truncated",
1006 IDLEN - 1);
1007 }
1008 else *lp++ = c;
1009 if (c == '\n' || c == EOF) break;
1010 }
1011 *lp = '\0';
1012 return(c);
1013 }
1014
1015 /*
1016 * build the formal arg list and skip over
1017 * passed with mac wrk str pointing to leading (
1018 * returns ptr to one after ending ) or nil if error
1019 *
1020 * FIXME make table larger so can be 8 bit clean
1021 */
bld_macdef_arglist(int32 * nargs)1022 static char *bld_macdef_arglist(int32 *nargs)
1023 {
1024 register char *chp;
1025 char *chp2, *chp3;
1026 int32 argno, arglen, toolong;
1027 struct macarg_t *marp, *macarg_end;
1028 char argnam[IDLEN];
1029
1030 *nargs = 0;
1031 chp = &(__macwrkstr[1]);
1032 __macarg_hdr = NULL;
1033 macarg_end = NULL;
1034 for (argno = 1;; argno++)
1035 {
1036 toolong = FALSE;
1037 /* skip white space before arg */
1038 while (vis_nonnl_white_(*chp)) chp++;
1039 /* format argument can start with _ but not ` or $ */
1040 /* digit can be in id but not start it */
1041 if (__pv_ctab[(*chp & 0x7f)] != 0 || isdigit(*chp) || *chp == '$')
1042 {
1043 __pv_ferr(1292,
1044 "text macro formal argument %d identifier expected - %c read - if non argument macro, add ' ' before (",
1045 argno, *chp);
1046 /* on error just do not define macro */
1047 return(NULL);
1048 }
1049 arglen = 1;
1050 chp2 = chp++;
1051 chp3 = NULL;
1052 /* collect the chars in the formal name */
1053 while(__pv_ctab[(*chp & 0x7f)] == 0)
1054 {
1055 if (++arglen >= IDLEN - 1)
1056 {
1057 if (!toolong)
1058 {
1059 __pv_ferr(944,
1060 "text macro formal argument has too many characters (%d)",
1061 IDLEN - 1);
1062 toolong = TRUE;
1063 /* end is 1 past end where \0 will go */
1064 chp3 = chp;
1065 }
1066 }
1067 chp++;
1068 }
1069 if (chp3 == NULL) chp3 = chp;
1070 strncpy(argnam, chp2, chp3 - chp2);
1071 argnam[chp3 - chp2] = '\0';
1072 marp = (struct macarg_t *) __my_malloc(sizeof(struct macarg_t));
1073 marp->macargnam = __pv_stralloc(argnam);
1074 marp->macargnxt = NULL;
1075 if (macarg_end == NULL) __macarg_hdr = macarg_end = marp;
1076 else macarg_end->macargnxt = marp;
1077 macarg_end = marp;
1078 /* maybe skip white space */
1079 while (vis_nonnl_white_(*chp)) chp++;
1080 if (*chp == ')') break;
1081 if (*chp == ',') { chp++; continue; }
1082 /* wrong separator */
1083 __pv_ferr(1294,
1084 "text macro formal argument %d not followed by , or ) - char %c read",
1085 argno, *chp);
1086 return(NULL);
1087 }
1088 chp++;
1089 /* notice something like "`define aa(a,b) )()(" is legal, err later */
1090 *nargs = argno;
1091 return(chp);
1092 }
1093
1094 /*
1095 * remove any comments from macro body copy then build macwrkstr
1096 * error and return F if / * comment or string not completed
1097 *
1098 * only here for macro def. bodies, // \[escaped nl] is removed comment
1099 * / * can span escaped new lines - and always left as escaped in output
1100 * mchp must always point into mac wrk str
1101 *
1102 * this copies into temp and then puts back in macro string
1103 */
remchk_macdef_coms(char * mchp)1104 static char *remchk_macdef_coms(char *mchp)
1105 {
1106 register char *chp, *nchp;
1107 int32 llen, first_time;
1108 char *newwrkstr, *start_mchp;
1109
1110 /* macro text starts with non white */
1111 while(vis_nonnl_white_(*mchp)) mchp++;
1112 start_mchp = mchp;
1113
1114 /* region to allocate does not include possible args */
1115 llen = __mac_line_len - (mchp - __macwrkstr);
1116 /* will never be wider but may be same length */
1117 newwrkstr = __my_malloc(llen + 1);
1118
1119 for (first_time = TRUE, chp = mchp, nchp = newwrkstr; *chp != '\0';)
1120 {
1121 /* replace string of white space with one space */
1122 if (vis_nonnl_white_(*chp))
1123 {
1124 if (!first_time) *nchp++ = ' ';
1125 chp++;
1126 while(vis_nonnl_white_(*chp)) chp++;
1127 }
1128 first_time = FALSE;
1129
1130 switch (*chp) {
1131 case '/':
1132 /* handle comments - no quoted strings in comments */
1133 chp++;
1134 /* remove // comment - can go to end of area (real nl or esc. nl) */
1135 if (*chp == '/')
1136 {
1137 chp++;
1138 while (*chp != '\0')
1139 {
1140 /* both of these better be removed by collect line */
1141 if (*chp == '\n' || *chp == EOF) __misc_terr(__FILE__, __LINE__);
1142 chp++;
1143 }
1144 /* now skipped to end of // comment */
1145 *nchp = '\0';
1146 goto at_end;
1147 }
1148 /* remove / * comment - error if hit end of string */
1149 if (*chp == '*')
1150 {
1151 chp++;
1152 while (*chp != '*')
1153 {
1154 if (*chp == '\n' || *chp == EOF) __misc_terr(__FILE__, __LINE__);
1155 if (*chp == '\0')
1156 {
1157 __pv_ferr(930,
1158 "*/ in `define macro line without initial /* comment start");
1159 __my_free(newwrkstr, llen + 1);
1160 return(NULL);
1161 }
1162 if (*chp == '/' && chp[1] == '*')
1163 {
1164 __pv_fwarn(622, "nested /* in macro body /* style comment");
1165 }
1166 /* skip any escaped chars - can not end comment */
1167 if (*chp == '\\') { chp++; chp++; }
1168 chp++;
1169 }
1170 chp++;
1171 if (*chp == '/') { *nchp++ = ' '; chp++; continue; }
1172 break;
1173 }
1174 /* simple / so must keep in line */
1175 *nchp++ = '/';
1176 break;
1177 /* must copy any non white space escape and char */
1178 case '\\':
1179 /* escaped nl becomes space */
1180 if (chp[1] == '\n') { chp++; chp++; *nchp++ = ' '; break; }
1181 *nchp++ = *chp++;
1182 if (*chp == '\0')
1183 {
1184 __pv_ferr(931,
1185 "`define macro line ends with \\ - following escaped char required");
1186 return(NULL);
1187 }
1188 /* must copy any escaped char as is - cannot have any meaning */
1189 *nchp++ = *chp++;
1190 break;
1191 case '\0': goto at_end;
1192 case '"':
1193 *nchp++ = *chp++;
1194 while (*chp != '"')
1195 {
1196 if (*chp == '\\') *nchp++ = *chp++;
1197 if (*chp == '\0')
1198 {
1199 __pv_ferr(932,
1200 "`define macro contains unterminated string - not defined");
1201 return(NULL);
1202 }
1203 *nchp++ = *chp++;
1204 }
1205 /* exit and copy " */
1206 }
1207 *nchp++ = *chp++;
1208 }
1209 at_end:
1210 /* remove trailing white space */
1211 for (;;)
1212 {
1213 if (nchp == newwrkstr) break;
1214 nchp--;
1215 if (!vis_white_(*nchp)) { nchp++; break; }
1216 }
1217 *nchp = '\0';
1218
1219 /* DBG remove --- */
1220 if (nchp - newwrkstr > llen) __misc_terr(__FILE__, __LINE__);
1221 /* --- */
1222 strcpy(mchp, newwrkstr);
1223 __mac_line_len = (mchp - __macwrkstr) + (nchp - newwrkstr);
1224 __my_free(newwrkstr, llen + 1);
1225 return(start_mchp);
1226 }
1227
1228 /*
1229 * process an argument macro definition
1230 * know mac arg hdr global point to formal argument list
1231 *
1232 * know working out of collected line so new line impossible
1233 * expand arguments anywhere but within strings
1234 * know all comments changed to 1 space and multiple white space to 1 space
1235 * also know all quoted strings completed
1236 * LOOKATME - is it true this cannot fail
1237 */
bld_mac_expandtab(char * dnam,char * dval,int32 nargs)1238 static struct macexp_t *bld_mac_expandtab(char *dnam, char *dval, int32 nargs)
1239 {
1240 register char *chp;
1241 register int32 andx;
1242 register struct macarg_t *marp;
1243 byte *argutab;
1244 struct macexp_t *mxp, *mxp_hdr, *mxp_end;
1245 char *startchp, *startid, idnam[IDLEN];
1246
1247 argutab = (byte *) __my_malloc(nargs);
1248 memset(argutab, 0, nargs);
1249 mxp_hdr = mxp_end = NULL;
1250 startchp = dval;
1251 for (chp = dval; *chp != '\0';)
1252 {
1253 /* skip leading white space */
1254 while (vis_nonnl_white_(*chp)) chp++;
1255
1256 /* always skip quoted strings */
1257 if (*chp == '"')
1258 {
1259 chp++;
1260 /* must not match escaped quote */
1261 while (*chp != '"')
1262 {
1263 if (*chp == '\0')
1264 {
1265 __pv_ferr(932,
1266 "macro %s value contains unterminated string - macro undefined",
1267 dnam);
1268 return(NULL);
1269 }
1270 if (*chp == '\\') chp++;
1271 chp++;
1272 }
1273 chp++;
1274 continue;
1275 }
1276 /* if identifier or keyword remove and build record, else just skip */
1277 if (__pv_ctab[(*chp & 0x7f)] == 0 && (!isdigit(*chp) || *chp == '`'))
1278 {
1279 startid = chp;
1280 chp++;
1281 while(__pv_ctab[(*chp & 0x7f)] == 0) chp++;
1282 /* see if this is formal argument */
1283 strncpy(idnam, startid, chp - startid);
1284 idnam[chp - startid] = '\0';
1285 /* if does not match left in literal copy part and at next char */
1286 if ((andx = find_mac_formal_arg(idnam)) == -1) continue;
1287 argutab[andx] = 1;
1288 /* this is formal */
1289 mxp = (struct macexp_t *) __my_malloc(sizeof(struct macexp_t));
1290 mxp->leading_str = __my_malloc(startid - startchp + 1);
1291 strncpy(mxp->leading_str, startchp, startid - startchp);
1292 mxp->leading_str[startid - startchp] = '\0';
1293 mxp->leadlen = startid - startchp;
1294 mxp->ins_argno = andx;
1295 mxp->macexpnxt = NULL;
1296 if (mxp_end == NULL) mxp_hdr = mxp_end = mxp;
1297 else mxp_end->macexpnxt = mxp;
1298 mxp_end = mxp;
1299 /* reset fill to one after ID */
1300 startchp = chp;
1301 continue;
1302 }
1303 chp++;
1304 }
1305 for (andx = 0, marp = __macarg_hdr; andx < nargs; andx++,
1306 marp = marp->macargnxt)
1307 {
1308 if (argutab[andx] == 0)
1309 {
1310 __pv_fwarn(640,
1311 "%s macro definition formal argument %s (no. %d) not used in macro body",
1312 dnam, marp->macargnam, andx);
1313 }
1314 }
1315 __my_free((char *) argutab, nargs);
1316 argutab = NULL;
1317
1318 /* unless value is empty include trailing chars */
1319 /* if totally empty value, make it one space */
1320 if (chp == startchp && mxp_end == NULL)
1321 {
1322 __pv_fwarn(638, "argument macro %s expands to nothing - use `undef", dnam);
1323 return(NULL);
1324 }
1325 if (chp == startchp) return(mxp_hdr);
1326
1327 /* add the ending prefix with no argument to expand in */
1328 mxp = (struct macexp_t *) __my_malloc(sizeof(struct macexp_t));
1329 mxp->leading_str = __my_malloc(chp - startchp + 1);
1330 strncpy(mxp->leading_str, startchp, chp - startchp);
1331 mxp->leading_str[chp - startchp] = '\0';
1332 mxp->ins_argno = -1;
1333 mxp->macexpnxt = NULL;
1334 if (mxp_end == NULL) mxp_hdr = mxp_end = mxp;
1335 else mxp_end->macexpnxt = mxp;
1336 return(mxp_hdr);
1337 }
1338
1339 /*
1340 * search an formal argument list to match a legal ID name
1341 * returns nil if not found
1342 */
find_mac_formal_arg(char * argnam)1343 static int32 find_mac_formal_arg(char *argnam)
1344 {
1345 register int32 anum;
1346 register struct macarg_t *marp;
1347
1348 anum = 0;
1349 for (marp = __macarg_hdr; marp != NULL; marp = marp->macargnxt, anum++)
1350 { if (strcmp(marp->macargnam, argnam) == 0) return(anum); }
1351 return(-1);
1352 }
1353
1354 /*
1355 * define a text macro named dnam with value dval
1356 * this looks up in symbol table and stores "" ok and used for `ifdef
1357 * dval here is really rest of line that may be ""
1358 */
__do_macdefine(char * dnam,char * dval)1359 extern void __do_macdefine(char *dnam, char *dval)
1360 {
1361 struct tnode_t *tnp;
1362 struct sy_t *syp;
1363
1364 tnp = __vtfind(dnam, __pv_defsyms);
1365 /* now add the symbol */
1366 if (__sym_is_new)
1367 {
1368 /* allocate symbol and fill symbol */
1369 __add_sym(dnam, tnp);
1370 __pv_defsyms->numsyms++;
1371 syp = tnp->ndp;
1372 syp->sytyp = SYM_DEF;
1373 syp->sydecl = TRUE;
1374 }
1375 else
1376 {
1377 syp = tnp->ndp;
1378 /* if `define follows undef just define - no message */
1379 if (syp->sydecl)
1380 {
1381 if (syp->sy_argsmac)
1382 {
1383 __finform(415,
1384 "textmacro name %s redefined - previous but not new had args", dnam);
1385 free_macexplst(syp->el.eamacp->amxp);
1386 __my_free((char *) syp->el.eamacp, sizeof(struct amac_t));
1387 syp->sy_argsmac = FALSE;
1388 }
1389 else
1390 {
1391 __finform(415,
1392 "textmacro name %s redefined - neither has arguments", dnam);
1393 __my_free(syp->el.edfchp, strlen(syp->el.edfchp) + 1);
1394 }
1395 }
1396 /* if was undefined now defined */
1397 syp->sydecl = TRUE;
1398 }
1399 syp->el.edfchp = __pv_stralloc(dval);
1400 }
1401
1402 /*
1403 * free an args macro expand list
1404 */
free_macexplst(register struct macexp_t * mxp)1405 static void free_macexplst(register struct macexp_t *mxp)
1406 {
1407 register struct macexp_t *mxp2;
1408
1409 for (; mxp != NULL;)
1410 {
1411 mxp2 = mxp->macexpnxt;
1412 __my_free(mxp->leading_str, mxp->leadlen + 1);
1413 __my_free((char *) mxp, sizeof(struct macexp_t));
1414 mxp = mxp2;
1415 }
1416 }
1417
1418 /*
1419 * define a text macro with arguments named dnam with value dval
1420 * and macro subsitution list macp
1421 *
1422 * this looks up in symbol table and stores "" ok and used for `ifdef
1423 * dval here is really rest of line that may be ""
1424 * illegal conflicts with predefined compiler directives caught before here
1425 */
do_argmacdefine(char * dnam,struct macexp_t * mxp,int32 nformal_args)1426 static void do_argmacdefine(char *dnam, struct macexp_t *mxp, int32 nformal_args)
1427 {
1428 struct tnode_t *tnp;
1429 struct sy_t *syp;
1430
1431 tnp = __vtfind(dnam, __pv_defsyms);
1432 /* now add the symbol */
1433 if (__sym_is_new)
1434 {
1435 /* allocate symbol and fill symbol */
1436 __add_sym(dnam, tnp);
1437 __pv_defsyms->numsyms++;
1438 syp = tnp->ndp;
1439 syp->sytyp = SYM_DEF;
1440 syp->sy_argsmac = TRUE;
1441 syp->sydecl = TRUE;
1442 syp->el.eamacp = (struct amac_t *) __my_malloc(sizeof(struct amac_t));
1443 }
1444 else
1445 {
1446 syp = tnp->ndp;
1447 if (syp->sydecl)
1448 {
1449 if (syp->sy_argsmac)
1450 {
1451 __finform(415,
1452 "textmacro name %s redefined - previous and new have args",
1453 dnam);
1454 free_macexplst(syp->el.eamacp->amxp);
1455 }
1456 else
1457 {
1458 __finform(415,
1459 "textmacro name %s redefined - only new has args", dnam);
1460 __my_free(syp->el.edfchp, strlen(syp->el.edfchp) + 1);
1461 syp->el.eamacp = (struct amac_t *) __my_malloc(sizeof(struct amac_t));
1462 }
1463 }
1464 syp->sydecl = TRUE;
1465 }
1466 syp->el.eamacp->amxp = mxp;
1467 syp->el.eamacp->num_formal_args = nformal_args;
1468 syp->sy_argsmac = TRUE;
1469 }
1470
1471 /*
1472 * return F if remainder of line contains anything but comment
1473 * know all white space has been removed before call
1474 * if / * comment but be completed on line
1475 * return T if good
1476 */
__bqline_emptytail(register char * cp)1477 extern int32 __bqline_emptytail(register char *cp)
1478 {
1479 for (; *cp != '\0'; cp++)
1480 {
1481 switch (*cp) {
1482 case '/':
1483 cp++;
1484 if (*cp == '/') return(TRUE);
1485 if (*cp == '*')
1486 {
1487 /* in / * comment */
1488 for (cp++;; cp++)
1489 {
1490 if (*cp == '\0') return(FALSE);
1491 if (*cp == '*')
1492 {
1493 cp++;
1494 if (*cp == '/') goto nxt_white;
1495 cp--;
1496 continue;
1497 }
1498 }
1499 }
1500 continue;
1501 case '\\': cp++; continue;
1502 default: return(FALSE);
1503 }
1504 nxt_white:;
1505 }
1506 return(TRUE);
1507 }
1508
1509 /*
1510 * do the new `include directive - entire line consumed
1511 * must be called with file name (starting ") in token
1512 */
__do_include(void)1513 extern void __do_include(void)
1514 {
1515 register int32 idi;
1516 register char *cp;
1517 int32 inflen, plen, space;
1518 FILE *f;
1519 struct incloc_t *ilp;
1520 char *chp, incfnam[RECLEN], incpth[RECLEN];
1521 struct sy_t *syp;
1522
1523 cp = __macwrkstr;
1524 /* AIV 06/27/05 - handle the special `include `FILE case */
1525 if (*cp == '`')
1526 {
1527 /* strip the white space at the end of the line */
1528 plen = strlen(cp) - 1;
1529 space = FALSE;
1530 for (idi = plen; idi >= 0; idi--)
1531 {
1532 if (cp[idi] == ' ')
1533 {
1534 space = TRUE;
1535 cp[idi] = '\0';
1536 }
1537 else if (space) break;
1538 }
1539 /* find `define variable to ge the file name */
1540 if ((syp = __get_sym(cp, __pv_defsyms)) == NULL || !syp->sydecl)
1541 {
1542 __pv_fwarn(937,
1543 "`include name - text macro %s undefined or possibly compiler directive for other tool - ignored", cp);
1544 return;
1545 }
1546 /* set the file name pointer */
1547 cp = syp->el.edfchp;
1548 }
1549 chp = cp;
1550 if (*chp != '"')
1551 {
1552 bad_fnam:
1553 __pv_ferr(937,
1554 "`include name not surrounded by double quotation marks");
1555 return;
1556 }
1557 /* fill token to ending " - white space in file names ok */
1558 for (chp++;; chp++)
1559 {
1560 if (*chp == '\0') goto bad_fnam;
1561 if (*chp == '"') break;
1562 }
1563 /* replace ending quotes with \0 */
1564 *chp = '\0';
1565 /* cp now points file name skipping the first char (") */
1566 /* know not longer than 1024 because that is Verilog line length */
1567 strcpy(incfnam, &(cp[1]));
1568
1569 if ((f = __tilde_fopen(incfnam, "r")) == NULL)
1570 {
1571 /* if file absolute, do not search incdir list */
1572 /* AIV 09/15/04 - ./[name] form is relative not absolute */
1573 if (incfnam[0] == '/' || incfnam[0] == '~') goto nonrel_notfnd;
1574
1575 if (__last_incdir >= 0)
1576 {
1577 inflen = strlen(incfnam);
1578 for (idi = 0; idi <= __last_incdir; idi++)
1579 {
1580 plen = strlen(__incdirs[idi]) + inflen + 1;
1581 if (plen >= RECLEN)
1582 {
1583 chp = __my_malloc(plen);
1584 strcpy(chp, __incdirs[idi]);
1585 strcat(chp, incfnam);
1586 __pv_fwarn(571,
1587 "`include file +incdir+ path name %s too long (%d) - ignored", chp,
1588 RECLEN);
1589 __my_free(chp, plen);
1590 continue;
1591 }
1592 strcpy(incpth, __incdirs[idi]);
1593 strcat(incpth, incfnam);
1594 /* DBG remove --
1595 __cv_msg("*** attempting to open include path %s\n", chp);
1596 --- */
1597 if ((f = __tilde_fopen(incpth, "r")) != NULL)
1598 { strcpy(incfnam, incpth); goto found_path; }
1599 }
1600 __pv_ferr(933,
1601 "unable to open `include file %s - not found in any +incdir+", incfnam);
1602 return;
1603 }
1604 nonrel_notfnd:
1605 __pv_ferr(933, "unable to open `include file %s", incfnam);
1606 return;
1607 }
1608
1609 found_path:
1610 /* add include file to file list for error messages */
1611 /* __last_inf still used to find last non lib. input file */
1612 /* this dies if >64k */
1613 /* idea here is that initial build entire list of input then library files */
1614 /* while process arguments - when reading includes put on end of file list */
1615 /* so that contents can be read by debugger */
1616 if (++__last_lbf >= __siz_in_fils) __grow_infils(__last_lbf);
1617 __in_fils[__last_lbf] = __pv_stralloc(incfnam);
1618
1619 /* have good include file, add to include location list */
1620 ilp = (struct incloc_t *) __my_malloc(sizeof(struct incloc_t));
1621 /* link on end */
1622 if (__inclst_hdr == NULL) __inclst_hdr = __inclst_end = ilp;
1623 else __inclst_end->inclocnxt = ilp;
1624 ilp->inc_fnind = __last_lbf;
1625 ilp->incfrom_fnind = __cur_fnam_ind;
1626 ilp->incfrom_lcnt = __lin_cnt;
1627 ilp->inclocnxt = NULL;
1628
1629 /* save current __lin_cnt before pushing */
1630 if (__visp->vi_s != NULL) __visp->vilin_cnt = __lin_cnt;
1631 /* push new file on tos */
1632 __push_vinfil();
1633 /* notice push sets __visp */
1634 __visp->vifnam_ind = __last_lbf;
1635 __visp->vi_s = __in_s = f;
1636 __cur_fnam = __in_fils[__visp->vifnam_ind];
1637 __cur_fnam_ind = __visp->vifnam_ind;
1638 __lin_cnt = 1;
1639 if (__lib_verbose || __verbose)
1640 {
1641 if (__doing_langdir)
1642 {
1643 __cv_msg(" Reading `included `language non Verilog file \"%s\"\n",
1644 __cur_fnam);
1645 }
1646 else __cv_msg(" Compiling `included source file \"%s\"\n", __cur_fnam);
1647 }
1648 __file_just_op = TRUE;
1649 }
1650
1651 /*
1652 * skip to matching level else for `ifdef that is F
1653 * this reads ending `endif or `else and it line
1654 * returns -1 on not found error
1655 *
1656 * fortuntately never need to back up
1657 * this has a bug that needs to be documented - in sections that are
1658 * skipped only looks for match level `else or `endif - once starts skipping
1659 * a down level `ifdef does not catch extra `else's
1660 * notice this routines only uses local variables
1661 *
1662 * FIXME - looks like if `end never found in infinite loop?
1663 */
cskip_ifdef_section(FILE * f,int32 begtok)1664 static int32 cskip_ifdef_section(FILE *f, int32 begtok)
1665 {
1666 int32 level, ttyp2, sav_lin_cnt;
1667 int32 savfnam_ind;
1668
1669 /* ifdef must be on line by itself - anything treated as comment */
1670 __skipover_line();
1671 /* save the line count */
1672 savfnam_ind = __cur_fnam_ind;
1673 sav_lin_cnt = __lin_cnt;
1674 /* SJM 12/04/00 - need flag when skipping for ifdef section to */
1675 /* not emit rd num warnings since parameter substitution not right */
1676 __ifdef_skipping = TRUE;
1677 /* know reading stars after directive line */
1678 for (level = 0;;)
1679 {
1680 switch ((byte) (ttyp2 = __get1_vtok(f))) {
1681 case TEOF:
1682 /* if finished include or macro expansion just continue reading tokens */
1683 if (__pop_vifstk()) continue;
1684
1685 /* next try to replace just finished 0th element with new input file */
1686 /* notice these can cross file boundaries - real eof is all files */
1687 /* exhausted */
1688 if (__cur_infi < __last_inf)
1689 {
1690 __cur_infi++;
1691 if (__open_sfil()) continue;
1692 }
1693 /* for interactive can never get here since checking line begin fails */
1694 /* notice control here always ends with fata error */
1695 if (begtok == CDIR_IFDEF || begtok == CDIR_IFNDEF)
1696 {
1697 __pv_terr(313,
1698 "`ifdef/`ifndef line %s - no matching `else or `endif before **EOF**",
1699 __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));
1700 }
1701 else
1702 {
1703 __pv_terr(313, "`else line %s - no matching `endif before **EOF**",
1704 __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));
1705 }
1706 continue;
1707 case CDIR_IFDEF: case CDIR_IFNDEF:
1708 /* notice will not see if not 1st token of line */
1709 if (__chk_beg_line(ttyp2)) level++;
1710 __skipover_line();
1711 continue;
1712 case CDIR_ENDIF:
1713 if (!__chk_beg_line(CDIR_ENDIF)) break;
1714 __skipover_line();
1715 /* SJM 12/04/00 - when done skipping now need to turn off flag */
1716 /* flag needed because macros now alloed for number width */
1717 if (level == 0)
1718 { __ifdef_skipping = FALSE; return(CDIR_ENDIF); }
1719 level--;
1720 continue;
1721 case CDIR_ELSE:
1722 if (!__chk_beg_line(CDIR_ELSE)) break;
1723 __skipover_line();
1724 if (level == 0)
1725 {
1726 if (begtok == CDIR_ELSE)
1727 {
1728 __pv_ferr(1011,
1729 "`else line %s - followed by same nesting level `else",
1730 __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));
1731 /* keep looking for `endif */
1732 continue;
1733 }
1734 __ifdef_skipping = FALSE;
1735 return(CDIR_ELSE);
1736 }
1737 continue;
1738 case CDIR_LANG:
1739 /* here because can not tokenize included foreign language */
1740 savfnam_ind = __cur_fnam_ind;
1741 sav_lin_cnt = __lin_cnt;
1742 if (__notokenize_skiplines("`endlanguage") == TEOF)
1743 {
1744 __pv_terr(328,
1745 "skipped `language at %s in `ifdef/`ifndef no matching `endlanguage before **EOF**",
1746 __bld_lineloc(__xs, (word32) savfnam_ind, sav_lin_cnt));
1747 }
1748 break;
1749 case CDIR_TIMESCALE:
1750 /* SJM 12/02/99 - these require special scanning so can't just skip */
1751 /* must read line and ignore it - know always first on line */
1752 __skipover_line();
1753 continue;
1754 }
1755 }
1756 /*UNREACHABLE*/
1757 __ifdef_skipping = FALSE;
1758 return(-1);
1759 }
1760
1761 /*
1762 * INTERACTIVE ENVIRONMENT GET TOKEN ROUTINES
1763 */
1764
1765 /*
1766 * read an interactive line - must handle \[new line] escapes which
1767 * are left in and treated as white space
1768 *
1769 * __iahwrkline grows but must start out at least IDLEN + 1 characters lone
1770 * this returns TEOF on at eof and nothing in line (or error?)
1771 * return TOK_NONE on good
1772 *
1773 * caller must handle key file and parsing tokenization of read line
1774 * (command) and any adding to history list
1775 * ending new line is removed
1776 */
__rd_ialine(void)1777 extern int32 __rd_ialine(void)
1778 {
1779 int32 len, totlen, osize, intr_num;
1780 char *chp;
1781 FILE *f;
1782
1783 rd_again:
1784 __iahwrkline[0] = '\0';
1785 if (__cmd_s != NULL) { f = __cmd_s; __lin_cnt++; } else f = stdin;
1786 if (feof(f)) return(TEOF);
1787
1788 for (totlen = 0;;)
1789 {
1790 /* will not return NULL if any chars read */
1791 chp = &(__iahwrkline[totlen]);
1792 /* when iact debugger run from pipe, under FlexLM may be interrupted */
1793 /* and need to restart */
1794 intr_num = 0;
1795 again2:
1796 clearerr(f);
1797 if (fgets(chp, IDLEN + 1, f) == NULL)
1798 {
1799 if (++intr_num >= 512)
1800 {
1801 __ia_err(1450,
1802 "interactive input call interrupted %d consecutive times - assuming EOF",
1803 intr_num);
1804 break;
1805 }
1806 if (!feof(f) && errno == EINTR) goto again2;
1807 if (feof(f) && errno == EINTR)
1808 {
1809 __ia_warn(1603,
1810 "interactive input call interrupted (but EOF also seen?) - trying again");
1811 goto again2;
1812 }
1813 if (ferror(f))
1814 {
1815 __ia_err(1460,
1816 "interactive input call failed because: [%s] - assuming EOF",
1817 strerror(errno));
1818 }
1819 break;
1820 }
1821 if (__pending_enter_iact && __iact_reason == IAER_CTRLC)
1822 {
1823 __pending_enter_iact = FALSE;
1824 __iact_reason = IAER_UNKN;
1825
1826 if (__cmd_s == NULL) goto rd_again;
1827 /* ^c (interrupt signal) during $input interrupts and closes file */
1828 __ia_err(1457,
1829 "interactive $input file processing terminated by interrupt (^c)");
1830 totlen = 0;
1831 __iahwrkline[0] = '\0';
1832 return(TEOF);
1833 }
1834
1835 len = strlen(chp);
1836 if (len >= IDLEN)
1837 {
1838 __ia_err(1402, "interactive line too long (%d) - truncated", IDLEN - 1);
1839 chp[IDLEN - 1] = '\0';
1840 break;
1841 }
1842 totlen += len;
1843 /* know last char. always new line for fgets - see if escaped */
1844 if (chp[len - 2] != '\\') break;
1845 /* if escaped keep reading but first see if need to grow work line */
1846 if (totlen >= __iahwrklen - IDLEN - 4)
1847 {
1848 osize = __iahwrklen;
1849 __iahwrklen += IDLEN + 4;
1850 __iahwrkline = __my_realloc(__iahwrkline, osize, __iahwrklen);
1851 }
1852 /* if (f != NULL) __lin_cnt++; */
1853 }
1854 if (totlen == 0) return(TEOF);
1855 /* FIXME - lot file output only ?? */
1856 if (__echo_iactcmds_tolog && __log_s != NULL)
1857 __my_fprintf(__log_s, "%s", __iahwrkline);
1858
1859 /* final step change final unescaped new line to blank */
1860 /* if not blank error such as omitted ; previous token not seen */
1861 __iahwrkline[totlen - 1] = ' ';
1862 return(TOK_NONE);
1863 }
1864
1865 /*
1866 * ACTUAL TOKENIZATION CODE
1867 */
1868
1869 /*
1870 * ascii character table for processing end of ID tokens
1871 * 0: continue - legal ID char (letter, digit, _, $)
1872 * 1: end and don't back up (white space)
1873 * 2: end and back up (operators plus special back quote)
1874 * 3: inc lin_cnt and end - only new line
1875 * 4: illegal ID char
1876 *
1877 * notice special handling of . - if 1st char after comma or white space,
1878 * then dot part of .[name](port) for else . legal in ID, but can not
1879 * be 1st char of id
1880 * 0x24 is $ and 0x5f is _ both are legal starting and in IDs (value 0)
1881 */
1882 char __pv_ctab[128] = {
1883 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 3, 4, 1, 1, 4, 4, /* ^i,\n,\f,\r */
1884 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1885 /* need to handle " */
1886 1, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* sp,!,%,#,(,),*,',+,-,.,/ */
1887 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, /* digits, :,;,<,=,>,? */
1888 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @, cap letters */
1889 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, /* letters `,[,\\,],^, */
1890 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* `, letters */
1891 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2 /* letters, {, |, },~,EOF */
1892 };
1893
1894 /*
1895 * get a Verilog token
1896 * (modified from yylex in "The Unix Programming Environment" p. 337)
1897 */
__get1_vtok(FILE * f)1898 extern int32 __get1_vtok(FILE *f)
1899 {
1900 register int32 c, ctval;
1901 register char *cp;
1902 int32 c1, len, toolong;
1903 int32 t1typ;
1904
1905 again:
1906 /* not first line token since always push back new line except number */
1907 /* ending line required scan to make sure not ' */
1908 if (__first_num_eol) { __first_linetok = TRUE; __first_num_eol = FALSE; }
1909 else __first_linetok = FALSE;
1910
1911 again3:
1912 do { ctval = __pv_ctab[(c = my_getc(f)) & 0x7f]; } while (ctval == 1);
1913 if (c == '\n')
1914 {
1915 again2:
1916 __lin_cnt++;
1917 __total_rd_lines++;
1918 do { ctval = __pv_ctab[(c = my_getc(f)) & 0x7f]; } while (ctval == 1);
1919 if (c == '\n') goto again2;
1920 __first_linetok = TRUE;
1921 }
1922 switch (c) {
1923 case ';': return(SEMI);
1924 case ',': return(COMMA);
1925 case ':': return(COLON);
1926 case '#': return(SHARP);
1927 case '(':
1928 if ((c1 = my_getc(f)) != '*') { my_ungetc_(c1, f); return(LPAR); }
1929
1930 /* SJM 06/01/04 - for new @(*) form can't be attr - need to check */
1931 /* spaces possible because something like @(`star ) is possible */
1932 if (__canbe_impl_evctrl) { my_ungetc_(c1, f); return(LPAR); }
1933
1934 /* collect attribute into global string */
1935 rd_attribute(f);
1936 goto again;
1937 case ')': return(RPAR);
1938 case '[': return(LSB);
1939 case ']': return(RSB);
1940 case '{': return(LCB);
1941 case '}': return(RCB);
1942 /* notice dot can not start real number in Verilog - digit or sign only */
1943 case '.': return(DOT);
1944 case '?': return(QUEST);
1945 case '@': return(AT);
1946 case '=':
1947 if ((c1 = my_getc(f)) != '=')
1948 {
1949 if (c1 == '>') return(PPTHCON);
1950 my_ungetc_(c1, f);
1951 return(EQ);
1952 }
1953 if ((c1 = my_getc(f)) != '=') { my_ungetc_(c1, f); return(RELEQ); }
1954 return(RELCEQ);
1955 case '\'':
1956 return(rd_num(f, c));
1957 case '+': return(PLUS);
1958 case '-':
1959 if ((c1 = my_getc(f)) != '>') { my_ungetc_(c1, f); return(MINUS); }
1960 return(CAUSE);
1961
1962 case '0': case '1': case '2': case '3': case '4': case '5':
1963 case '6': case '7': case '8': case '9':
1964 return(rd_num(f, c));
1965 case '*':
1966 if ((c1 = my_getc(f)) != '>') { my_ungetc_(c1, f); return(TIMES); }
1967 return(FPTHCON);
1968 /* notice no C assignment op operators */
1969 case '/':
1970 if ((t1typ = rd_comment(f)) == UNDEF) goto again;
1971 if (t1typ == TEOF) return(TEOF);
1972 return(DIV);
1973 case '%': return(MOD);
1974 case '~':
1975 /* notice ~& and ~| parse as 2 that must be unaries */
1976 /* a ~| b is meaningless - since ~ is unary only */
1977 /* but ~^ is alternative form of xnor (^~) */
1978 if ((c1 = my_getc(f)) == '^') return(REDXNOR);
1979 my_ungetc_(c1, f);
1980 return(BITNOT);
1981 case '&':
1982 if ((c1 = my_getc(f)) != '&') { my_ungetc_(c1, f); return(BITREDAND); }
1983 if ((c1 = my_getc(f)) != '&') { my_ungetc_(c1, f); return(BOOLAND); }
1984 return(TCHKEVAND);
1985 case '|':
1986 if ((c1 = my_getc(f)) != '|') { my_ungetc_(c1, f); return(BITREDOR); }
1987 return(BOOLOR);
1988 /* also ^~ 2 unaries or bitwise xor of unary bit wise not */
1989 case '^':
1990 /* notice ^~ is not bit wise xor of bit wise negated unary result */
1991 /* but special built in operator */
1992 if ((c1 = my_getc(f)) == '~') return(REDXNOR);
1993 my_ungetc_(c1, f);
1994 return(BITREDXOR);
1995 case '!':
1996 if ((c1 = my_getc(f)) != '=') { my_ungetc_(c1, f); return(NOT); }
1997 if ((c1 = my_getc(f)) != '=') { my_ungetc_(c1, f); return(RELNEQ); }
1998 return(RELCNEQ);
1999 case '>':
2000 if ((c1 = my_getc(f)) == '=') return(RELGE);
2001 else if (c1 == '>')
2002 {
2003 /* SJM 10/01/03 - add >>> arithmetic right shift */
2004 if ((c1 = my_getc(f)) == '>') return(ASHIFTR);
2005 my_ungetc_(c1, f);
2006 return(SHIFTR);
2007 }
2008 my_ungetc_(c1, f);
2009 return(RELGT);
2010 case '<':
2011 if ((c1 = my_getc(f)) == '=') return(RELLE);
2012 else if (c1 == '<')
2013 {
2014 /* SJM 10/01/03 - add <<< arithmetic left shift */
2015 if ((c1 = my_getc(f)) == '<') return(ASHIFTL);
2016 my_ungetc_(c1, f);
2017 return(SHIFTL);
2018 }
2019 my_ungetc_(c1, f);
2020 return(RELLT);
2021 case '\\':
2022 /* escaped new line is white space and inc line counter */
2023 /* removed from macro bodies */
2024 if ((c1 = my_getc(f)) == '\n')
2025 { __lin_cnt++; __total_rd_lines++; goto again3; }
2026 else { my_ungetc_(c1, f); }
2027
2028 /* handle escaped ID */
2029 for (toolong = FALSE, len = 0, cp = __token;;)
2030 {
2031 /* should never happen since max. line is same as IDLEN */
2032 if (++len >= IDCHARS - 1)
2033 {
2034 if (!toolong)
2035 {
2036 __pv_ferr(942,
2037 "Verilog escaped identifier too many characters (%d)", IDCHARS - 2);
2038 toolong = TRUE;
2039 }
2040 }
2041 else *cp++ = c;
2042
2043 if ((c = my_getc(f)) == EOF) return(TEOF);
2044 /* 3 is new line, 1 end and don't back up (white space) */
2045 if ((ctval = __pv_ctab[c & 0x7f]) == 3) { my_ungetc_(c, f); break; }
2046 if (ctval == 1) break;
2047 }
2048 /* lrm says trailing white space not part of escaped ID */
2049 /* but must store space at end or name will not be output right */
2050 *cp++ = ' ';
2051 *cp = '\0';
2052 /* according to P1364 must store escaped that is legal as non escaped */
2053 /* but can not escape keyword */
2054 if (!try_chg_tononesc()) return(UNDEF);
2055 return(ID);
2056 case '"': return(vgetstr(f));
2057 case EOF: return(TEOF);
2058 }
2059 /* here know digits eliminated so only letters, $, and _ have ct val 0 */
2060 if (ctval != 0 && c != '`')
2061 {
2062 __pv_ferr(943, "identifier starts with illegal char '%c' (%x)", c & 0xff,
2063 c & 0xff);
2064 goto again;
2065 }
2066 /* try to recognize some kind of id - only */
2067 for (toolong = FALSE, cp = __token, len = 0;;)
2068 {
2069 if (++len >= IDCHARS)
2070 {
2071 if (!toolong)
2072 {
2073 __pv_ferr(944,
2074 "Verilog identifier has too many characters (%d)", IDCHARS - 1);
2075 toolong = TRUE;
2076 }
2077 }
2078 else *cp++ = c;
2079
2080 c = my_getc(f);
2081 if (__pv_ctab[c & 0x7f] == 0) continue;
2082
2083 /* must not process \n (3) until next time through */
2084 /* or lin_cnt wrong for errors */
2085 /* punctuation token end - unget it */
2086 /* must always put back char after token since even if white space */
2087 /* a .b .c is not xmr - even though think lrm says it is */
2088 /* unget causes any error to be caught later */
2089 my_ungetc_(c, f);
2090 goto end_id;
2091 }
2092 end_id:
2093 *cp = '\0';
2094 /* only keywords ($ system tasks are not keywords) can be in keyword table */
2095 t1typ = get_vkeywrd(__token);
2096 return(t1typ);
2097 }
2098
2099 /*
2100 * get character routine that can read from macro
2101 */
my_getc(FILE * f)2102 static int32 my_getc(FILE *f)
2103 {
2104 register int32 c;
2105
2106 again:
2107 if (f == NULL)
2108 {
2109 c = *__visp->vichp;
2110 /* for get ch from line form, must never move past \0 */
2111 if (c == '\0') return(EOF);
2112 (__visp->vichp)++;
2113 }
2114 else c = getc(f);
2115
2116 if ((__pv_ctab[c & 0x7f] == 4 || c > 127) && !__rding_comment && c != EOF)
2117 {
2118 __finform(416, "illegal non printable character (%x) ignored", c & 0xff);
2119 goto again;
2120 }
2121 return(c);
2122 }
2123
2124 /*
2125 * get a comment
2126 */
rd_comment(FILE * f)2127 static int32 rd_comment(FILE *f)
2128 {
2129 register int32 c;
2130 int32 c2;
2131
2132 /* // to EOL comment */
2133 if ((c2 = my_getc(f)) == '/')
2134 {
2135 __rding_comment = TRUE;
2136 while ((c = my_getc(f)) != '\n') if (c == EOF) return(TEOF);
2137 __rding_comment = FALSE;
2138 my_ungetc_(c, f);
2139 return(UNDEF);
2140 }
2141 /* slash-star comments don't nest */
2142 if (c2 == '*')
2143 {
2144 more_comment:
2145 __rding_comment = TRUE;
2146 while ((c = my_getc(f)) != '*')
2147 {
2148 /* error if / * comments nested */
2149 if (c == '/')
2150 {
2151 if ((c2 = my_getc(f)) == '*')
2152 {
2153 __pv_fwarn(622, "nested /* in /* style comment");
2154 continue;
2155 }
2156 c = c2;
2157 }
2158 if (c == EOF)
2159 {
2160 if (__iact_state)
2161 __pv_ferr(960,
2162 "interactive /* comment cannot extend across multiple lines - */ added");
2163 __rding_comment = FALSE;
2164 return(TEOF);
2165 }
2166 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
2167 }
2168 got_star:
2169 if ((c = my_getc(f)) == '/')
2170 {
2171 __rding_comment = FALSE;
2172 return(UNDEF);
2173 }
2174 if (c == '*') goto got_star;
2175 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
2176 goto more_comment;
2177 }
2178 /* not a comment so treat as name token */
2179 /* notice c2 here must be most recent because above if never falls through */
2180 my_ungetc_(c2, f);
2181 return(DIV);
2182 }
2183
2184 /* macro for adding char and growing attr wrk str */
2185 #define addto_attrwrkstr_(c) \
2186 do { \
2187 int32 osize; \
2188 if (++len >= __attrwrklen - 1) \
2189 { \
2190 osize = __attrwrklen; \
2191 __attrwrklen += IDLEN; \
2192 __attrwrkstr = __my_realloc(__attrwrkstr, osize, __attrwrklen); \
2193 chp = &(__attrwrkstr[len - 1]); \
2194 } \
2195 *chp++ = (c); \
2196 } while (0)
2197
2198 /*
2199 * read an attribute char by char into a saved line
2200 *
2201 * know (* read and reading ending ) of *)
2202 * collected into attr wrk str - parsed later
2203 *
2204 * error if comments in attribute section
2205 * since parsed in separate parser subroutine `ifdefs must be self contained
2206 *
2207 * LOOKATME - adding ; at end - not clear from grammar if required
2208 * assuming not for now
2209 */
rd_attribute(FILE * f)2210 static void rd_attribute(FILE *f)
2211 {
2212 register char *chp;
2213 int32 c, c2, len, wrk_fnam_ind, wrk_lin_cnt;
2214
2215 wrk_fnam_ind = __cur_fnam_ind;
2216 wrk_lin_cnt = __lin_cnt;
2217
2218 for (chp = __attrwrkstr, len = 0;;)
2219 {
2220 c = my_getc(f);
2221 if (c == EOF)
2222 {
2223 hit_eof:
2224 my_ungetc_(c, f);
2225 __pv_ferr(940, "end of file read inside attribute_instance (* ... *)");
2226 return;
2227 }
2228 switch (c) {
2229 case '\\':
2230 /* escaped can't end or comment */
2231 addto_attrwrkstr_(c);
2232 c = my_getc(__in_s);
2233 if (c == EOF) goto hit_eof;
2234 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
2235 addto_attrwrkstr_(c);
2236 continue;
2237 case '"':
2238 /* collect string to un-escaped " */
2239 addto_attrwrkstr_(c);
2240 for (;;)
2241 {
2242 if ((c = my_getc(f)) == EOF) goto hit_eof;
2243 if (c == '\\')
2244 {
2245 /* always also both escape and char after */
2246 addto_attrwrkstr_(c);
2247 c = my_getc(__in_s);
2248 if (c == EOF) goto hit_eof;
2249 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
2250 addto_attrwrkstr_(c);
2251 continue;
2252 }
2253 if (c == '"') { addto_attrwrkstr_(c); break; }
2254 if (c == '\n') { __lin_cnt++; __total_rd_lines++; }
2255 if (c == '\n' || c == '\r')
2256 {
2257 __pv_ferr(945,
2258 "string inside attribute_instance (* .. *) can not cross line boundary - must escape new line");
2259 if ((c = skipto_attr_end(f)) == EOF) goto hit_eof;
2260 return;
2261 }
2262 /* non speical char in string , just collect */
2263 addto_attrwrkstr_(c);
2264 }
2265 continue;
2266 case '/':
2267 addto_attrwrkstr_(c);
2268 c = my_getc(f);
2269 if (c == '/' || c == '*')
2270 {
2271 __pv_ferr(3402,
2272 "/%c comment inside attribute_instance (* ... *) illegal - must be moved outside", c);
2273 if ((c = skipto_attr_end(f)) == EOF) goto hit_eof;
2274 return;
2275 }
2276 my_ungetc_(c, f);
2277 continue;
2278 case '(':
2279 /* know starting (* read before proc called, this is ( inside */
2280 addto_attrwrkstr_(c);
2281 c = my_getc(f);
2282 if (c == '*')
2283 {
2284 __pv_ferr(3403,
2285 "atttribute start sequence (* illegal inside attribute_instance");
2286 }
2287 /* still include it */
2288 my_ungetc_(c, f);
2289 continue;
2290 case '*':
2291 /* do not include leading (* or ending *) */
2292 c2 = my_getc(f);
2293 if (c2 == ')') goto done;
2294 addto_attrwrkstr_(c);
2295 my_ungetc_(c2, f);
2296 continue;
2297 default:
2298 addto_attrwrkstr_(c);
2299 }
2300 }
2301 done:
2302 /* LOOKATME is semi required? */
2303 chp--;
2304 if (*chp != ';')
2305 {
2306 chp++;
2307 addto_attrwrkstr_(';');
2308 }
2309 else chp++;
2310 *chp = '\0';
2311
2312 /* length does not include added \0 */
2313 __attr_line_len = len;
2314
2315 if (__attr_prefix)
2316 {
2317 __pv_ferr(3401,
2318 "more than one attribute_instance in row - using last at %s instead of first at %s",
2319 __bld_lineloc(__xs, (word32) wrk_fnam_ind, wrk_lin_cnt),
2320 __bld_lineloc(__xs2, (word32) __attr_fnam_ind, __attr_lin_cnt));
2321 }
2322 __attr_fnam_ind = wrk_fnam_ind;
2323 __attr_lin_cnt = wrk_lin_cnt;
2324 __attr_prefix = TRUE;
2325 /* DBG remove -- */
2326 if (__debug_flg)
2327 {
2328 __dbg_msg("&&& at %s attribute_instance string [%s])\n",
2329 __bld_lineloc(__xs, (word32) __attr_fnam_ind, __attr_lin_cnt),
2330 __attrwrkstr);
2331 }
2332 /* --- */
2333 }
2334
2335 /*
2336 * skip to attribute ending *)
2337 */
skipto_attr_end(FILE * f)2338 static int32 skipto_attr_end(FILE *f)
2339 {
2340 register int32 c;
2341
2342 __attr_fnam_ind = 0;
2343 __attr_lin_cnt = 0;
2344 for (;;)
2345 {
2346 if ((c = my_getc(f)) == EOF) return(EOF);
2347 switch (c) {
2348 case '\\':
2349 if ((c = my_getc(f)) == EOF) return(EOF);
2350 continue;
2351 case '"':
2352 for (;;)
2353 {
2354 if ((c = my_getc(f)) == EOF) return(EOF);
2355 if (c == '\\')
2356 {
2357 if ((c = my_getc(f)) == EOF) return(EOF);
2358 continue;
2359 }
2360 if (c == '"') break;
2361 }
2362 continue;
2363 case '*':
2364 c = my_getc(f);
2365 if (c == ')') goto done;
2366 }
2367 /* non special keep reading */
2368 }
2369 done:
2370 return(c);
2371 }
2372
2373 /*
2374 * read a string token - Verilog string are wide numbers
2375 * notice %% must be left here as 2 characters - processed by display
2376 * also value collected in token is not a 0 terminated c string (no \0)
2377 */
vgetstr(FILE * f)2378 static int32 vgetstr(FILE *f)
2379 {
2380 register char *cp;
2381 int32 c, c1, len, toolong, nsize;
2382
2383 /* return string - should save length - Ver. strings not \0 terminated */
2384 if ((c = my_getc(f)) == '"')
2385 {
2386 /* "" is special case of 8 bit 0 */
2387 *__strtoken = '\0';
2388 len = 1;
2389 goto done;
2390 }
2391 for (toolong = FALSE, len = 0, cp = __strtoken;;)
2392 {
2393 switch (c) {
2394 case '\n': case '\r':
2395 __pv_ferr(945,
2396 "string cannot cross line boundary (new line must be escaped)");
2397 goto done;
2398 case '\\':
2399 c1 = my_getc(f);
2400 switch (c1) {
2401 case 't': c = '\t'; break;
2402 case 'n': c = '\n'; break;
2403 case '\\': c = '\\'; break;
2404 case '"': c = '"'; break;
2405 case '0': case '1': case '2': case '3': case '4': case '5':
2406 case '6': case '7':
2407 /* c is escaped char value (octal) */
2408 c = c1 - '0';
2409 /* this always reads one past and puts back - read always pushed back */
2410 c1 = my_getc(f);
2411 if (isdigit(c1) && c1 != '8' && c1 != '9')
2412 {
2413 c = (c << 3) + c1 - '0';
2414 c1 = my_getc(f);
2415 if (isdigit(c1) && c1 != '8' && c1 != '9') c = (c << 3) + c1 - '0';
2416 else my_ungetc_(c1, f);
2417 }
2418 else my_ungetc_(c1, f);
2419 break;
2420 default:
2421 /* skip escape and use next char as is */
2422 __pv_fwarn(555, "string \\ escaped character '%c' (%x) same as '%c'",
2423 c1 & 0x7f, c1 & 0x7f, c1 & 0x7f);
2424 c = c1;
2425 }
2426 break;
2427 case '"': goto done;
2428 }
2429 /* should never happen since max. line is same as IDLEN - nd " room */
2430 /* SJM 03/20/00 - now allow up to 1M length strings */
2431 if (++len >= __strtok_wid)
2432 {
2433 if (len >= MAXNUMBITS)
2434 {
2435 if (!toolong)
2436 {
2437 __pv_ferr(946, "string token has too many characters (%d)",
2438 MAXNUMBITS - 1);
2439 toolong = TRUE;
2440 }
2441 }
2442 else
2443 {
2444 /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
2445 /* AIV 04/20/06 - was incorrectly using num should be str */
2446 nsize = 2*__strtok_wid;
2447 __strtoken = __my_realloc(__strtoken, __strtok_wid, nsize);
2448 __strtok_wid = nsize;
2449 /* AIV 04/20/06 - need to reset chp pointer due to realloc */
2450 cp = &(__strtoken[len - 1]);
2451 *cp++ = c;
2452 }
2453 }
2454 else *cp++ = c;
2455
2456 if ((c = my_getc(f)) == EOF)
2457 {
2458 if (__iact_state)
2459 __pv_ferr(947, "interactive string terminator missing");
2460 else __pv_ferr(947, "end of file read inside string");
2461 strcpy(__strtoken, "");
2462 len = 1;
2463 goto done;
2464 }
2465 /* if (__debug_flg) __dbg_msg("&&& vgetstr read %c (%x)\n", c , c); */
2466 }
2467
2468 done:
2469 /* except for expr. node string bit - this is now normal val. bit pattern */
2470 /* assuming 8 bit bytes - on serious error len can be 0 */
2471 if ((__itoklen = 8*len) == 0) __itoklen = 1;
2472 /* string are actually sized token - must work in concatenates */
2473 __itoksized = TRUE;
2474 /* puts string into ac wrk and bc wrk - may adjust size */
2475 str_tovval();
2476 /* if (__debug_flg) __dbg_msg("&&& vgstrread [%s]\n", __strtoken); */
2477 /* notice even though converted to value - can print input from __token */
2478 return(LITSTR);
2479 }
2480
2481 /*
2482 * need to convert form escaped ID to normal if escaped (after \\ is legal)
2483 * notice although '$' is a class 0 and can go in IDs, it can not start ID
2484 */
try_chg_tononesc(void)2485 static int32 try_chg_tononesc(void)
2486 {
2487 register char *chp;
2488 register int32 len, ctval;
2489 char s1[IDLEN];
2490
2491 chp = __token;
2492 /* move past escape */
2493 chp++;
2494 for (len = 0; *chp != '\0'; chp++)
2495 {
2496 if ((ctval = __pv_ctab[*chp & 0x7f]) != 0)
2497 {
2498 if (ctval == 1 || ctval == 3)
2499 {
2500 /* if next is end of ID \0, then found legal non escaped */
2501 if (chp[1] == '\0')
2502 {
2503 if (strcmp(__token, "\\ ") == 0)
2504 {
2505 __pv_ferr(942,
2506 "Verilog escaped identifier empty - at least one non white space character required");
2507 return(FALSE);
2508 }
2509
2510 strcpy(s1, &(__token[1]));
2511 /* remove the ending white space char */
2512 s1[len] = '\0';
2513 strcpy(__token, s1);
2514 return(TRUE);
2515 }
2516 }
2517 return(TRUE);
2518 }
2519 /* first is one after escape this is present at entry */
2520 /* SJM - 05/26/99 - fixed bug where \222 were getting un-escaped */
2521 if (len == 0)
2522 {
2523 if (*chp == '$' || isdigit(*chp)) return(TRUE);
2524 /* SJM-09/18/00- FIXME must not unescape or - need to handle as keywrd */
2525 if (strcmp(chp, "or ") == 0) return(TRUE);
2526 }
2527 len++;
2528 }
2529 return(TRUE);
2530 }
2531
2532 /*
2533 * convert ascii user input string into ac wrk and bc wrk
2534 *
2535 * notice __ac wrk and __bc wrk not necessarily contiguous
2536 */
str_tovval(void)2537 static void str_tovval(void)
2538 {
2539 register int32 wlen;
2540
2541 wlen = wlen_(__itoklen);
2542 if (wlen > __abwrkwlen || (__abwrkwlen > DFLTIOWORDS && wlen <= DFLTIOWORDS))
2543 chg_abwrklen(wlen);
2544 zero_allbits_(__bcwrk, __itoklen);
2545 __vstr_to_vval(__acwrk, __strtoken, __itoklen);
2546 }
2547
2548 /*
2549 * convert Verilog literal style string to a Verilog numeric value
2550 * notice Verilog has built in 8 bit chars
2551 * know ap wide enough and all bits zeroed before called here
2552 * notice this has built in dependency on 32 bit words
2553 */
__vstr_to_vval(word32 * ap,char * s,int32 bitlen)2554 extern void __vstr_to_vval(word32 *ap, char *s, int32 bitlen)
2555 {
2556 register int32 i;
2557 register int32 bi;
2558 int32 slen;
2559
2560 slen = bitlen/8;
2561 /* fill val from low char (right str) to high char (const left to right) */
2562 for (i = slen - 1, bi = 0; i >= 0; i--)
2563 {
2564 if (bi == 0) *ap = (word32) s[i];
2565 else *ap |= (((word32) s[i]) << bi);
2566 if (bi == 24) { bi = 0; ap++; } else bi += 8;
2567 }
2568 }
2569
2570 /*
2571 * convert c style string to Verilog value
2572 * this pushes new v value onto stack
2573 */
__cstr_to_vval(char * s)2574 extern struct xstk_t *__cstr_to_vval(char *s)
2575 {
2576 int32 blen, slen;
2577 struct xstk_t *xsp;
2578
2579 slen = strlen(s);
2580 blen = 8*slen;
2581 push_xstk_(xsp, blen);
2582 zero_allbits_(xsp->ap, blen);
2583 zero_allbits_(xsp->bp, blen);
2584 __vstr_to_vval(xsp->ap, s, blen);
2585 return(xsp);
2586 }
2587
2588 /*
2589 * push back for internal use by unget routines where get1_vtok value
2590 * must be pushed back
2591 */
unget2_vtok(int32 ttyp)2592 static void unget2_vtok(int32 ttyp)
2593 {
2594 int32 save_ttyp;
2595
2596 save_ttyp = __toktyp;
2597 __toktyp = ttyp;
2598 __unget_vtok();
2599 __toktyp = save_ttyp;
2600 }
2601
2602 /*
2603 * push back an already read token operator or keyword token
2604 */
__unget_vtok(void)2605 extern void __unget_vtok(void)
2606 {
2607 __lasttoktyp = __toktyp;
2608 strcpy(__lasttoken, __token);
2609 /* SJM 10/16/00 - save any pending attribte - because does not really read */
2610 /* token the actual attr string and other vars will be right and preserved */
2611 __last_attr_prefix = __attr_prefix;
2612
2613 /* extremely rare number push back case */
2614 if (__toktyp == NUMBER)
2615 {
2616 int32 wlen;
2617
2618 __lastitokbase = __itokbase;
2619 __lastitoksized = __itoksized;
2620 __lastitoksizdflt = __itoksizdflt;
2621 __lastitok_signed = __itok_signed;
2622 __lastitoklen = __itoklen;
2623
2624 /* must malloc to save in rare pushed back case */
2625 /* SJM 03/20/00 - no unget of num token since already in a/b wrk as val */
2626 wlen = wlen_(__itoklen);
2627 __lastacwrk = (word32 *) __my_malloc(wlen*WRDBYTES);
2628 __lastbcwrk = (word32 *) __my_malloc(wlen*WRDBYTES);
2629 memcpy(__lastacwrk, __acwrk, wlen*WRDBYTES);
2630 memcpy(__lastbcwrk, __bcwrk, wlen*WRDBYTES);
2631 return;
2632 }
2633 if (__toktyp == REALNUM)
2634 {
2635 __lastitokbase = __itokbase;
2636 __lastitoksized = __itoksized;
2637 __lastitoksizdflt = __itoksizdflt;
2638 __lastitok_signed = __itok_signed;
2639 __lastitoklen = __itoklen;
2640 __lastitok_realval = __itok_realval;
2641 }
2642 }
2643
2644 /*
2645 * read a verilog style number
2646 * know first char digit or ' and reads number end char
2647 * width if present left in nwidtoken and value in token
2648 *
2649 * notice that maximun number can be IDLEN - 1 digits must leave
2650 * since other sizes like max. no. of const. bits set to prevent possibility
2651 * of overflow
2652 *
2653 * notice '_' in number are just ignored and not added to token, is this ok
2654 */
rd_num(FILE * f,int32 c1)2655 static int32 rd_num(FILE *f, int32 c1)
2656 {
2657 register char *chp;
2658 register int32 c;
2659 int32 len, toolong, isreal, errnum, blen, nsize;
2660 word32 v;
2661 double d1;
2662 char *endp;
2663 /* SJM 03/20 - FIXME - for now limiting dec unsized to 16k digits */
2664 char nwidtoken[4*IDLEN];
2665
2666 __itokbase = BDEC;
2667 __itoksized = FALSE;
2668 __itoksizdflt = FALSE;
2669 __itok_signed = FALSE;
2670 __itoklen = WBITS;
2671 strcpy(nwidtoken, "");
2672
2673 /* read the possible decimal size value or unsized unbased number */
2674 isreal = FALSE;
2675 len = 0;
2676 if ((c = c1) != '\'')
2677 {
2678 /* 06/22/00 - SJM - only 2 token number case if `[base][num] */
2679 __maybe_2tok_sized_num = FALSE;
2680 /* collect value */
2681 for (toolong = FALSE, chp = nwidtoken, len = 0;;)
2682 {
2683 while (c == '_') c = my_getc(f);
2684 switch (c) {
2685 case '0': case '1': case '2': case '3': case '4': case '5':
2686 case '6': case '7': case '8': case '9': break;
2687 /* - and + here */
2688 case 'e': case 'E': isreal = TRUE; break;
2689 case '.': isreal = TRUE; break;
2690 case '-': case '+':
2691 /* + and minus after exponent legal else end of number */
2692 /* this can never cause a number to be real */
2693 if (*(chp - 1) == 'e' || *(chp - 1) == 'E') break;
2694 goto end_unsiz;
2695 default: goto end_unsiz;
2696 }
2697 if (++len >= 4*IDLEN)
2698 {
2699 if (!toolong)
2700 {
2701 __pv_ferr(948,
2702 "Verilog size prefix or unsized number too many characters (%d)",
2703 4*IDLEN);
2704 toolong = TRUE;
2705 }
2706 }
2707 else *chp++ = c;
2708 c = my_getc(f);
2709 }
2710 end_unsiz:
2711 *chp = '\0';
2712
2713 /* know c is not a digit - punctuation ok */
2714 if (__pv_ctab[c & 0x7f] == 0)
2715 {
2716 /* numbers can end with letter in udp tables */
2717 if (__letendnum_state) goto ok_letend;
2718 __pv_ferr(949,
2719 "unsized number terminated with illegal char '%c' (%x)", c & 0xff,
2720 c & 0xff);
2721 goto ok_letend;
2722 }
2723 /* this skips across new line */
2724 c = voverwhite(f, c);
2725 if (c == EOF) __macro_sep_width = TRUE;
2726 }
2727
2728 /* know either c is char after unsized number or quote for Ver number */
2729 ok_letend:
2730 if (c != '\'')
2731 {
2732 /* 06/22/00 - SJM - only 2 token number case if `[base][num] */
2733 __maybe_2tok_sized_num = FALSE;
2734
2735 /* char after white space starts next token */
2736 /* this is case where next token is special first token on line */
2737 my_ungetc_(c, f);
2738 /* SJM - 03/20/00 - here just increase to size needed */
2739 if (len >= __numtok_wid)
2740 {
2741 /* 06/26/00 - increase size with realloc but unsized not too wide */
2742 __numtoken = __my_realloc(__numtoken, __numtok_wid, __numtok_wid
2743 + RECLEN);
2744 __numtok_wid = len + RECLEN;
2745 }
2746 strcpy(__numtoken, nwidtoken);
2747 strcpy(nwidtoken, "");
2748
2749 /* remove leading 0's but if first char is . put 1 back */
2750 if (!__letendnum_state) rem_lead_0chars(__numtoken);
2751 /* allowing any legal c real here - but maybe should not allow dot not */
2752 /* surrounded by digits */
2753 if (isreal)
2754 {
2755 d1 = __my_strtod(__numtoken, &endp, &errnum);
2756 if (errnum != 0 || *endp != '\0')
2757 __pv_ferr(950, "illegal real number %s", __numtoken);
2758 /* notice some compilers crash if doubles not 8 byte aligned ? */
2759 /* therefore need special routine for doubles */
2760 __itok_realval = d1;
2761 __itoklen = REALBITS;
2762 __itokbase = BDBLE;
2763 __macro_sep_width = FALSE;
2764 return(REALNUM);
2765 }
2766 /* SJM 10/02/03 - string of dec digits no '[base] is signed decimal */
2767 __itok_signed = TRUE;
2768 /* handle numbers that fit in 10 chars as special case */
2769 if (strlen(__numtoken) < 10)
2770 {
2771 v = __my_strtoul(__numtoken, &endp, &errnum);
2772 if (errnum != 0 || *endp != '\0') __misc_terr(__FILE__, __LINE__);
2773 __acwrk[0] = v;
2774 __bcwrk[0] = 0L;
2775 if (__macro_sep_width) __macro_sav_nwid = (int32) v;
2776 return(NUMBER);
2777 }
2778 /* for implied WBITS number convert and truncate */
2779 goto do_convert;
2780 }
2781
2782 /* know c is ' */
2783 /* know token read after this is not first token on line because */
2784 /* number becuase size number ' is on next line */
2785 /* know '[base] form is unsized and word32 but'[Ss][base] is signed */
2786
2787 /* AIV 07/09/04 - special case to handle: 8'h`DEFINE */
2788 /* if `define macro contains a 'base it is illegal */
2789 if (__macbs_flag)
2790 {
2791 __pv_ferr(3418,
2792 "number with '[base] macro expansion %s contains extra '[base]", __token);
2793 /* AIV 07/12/04 - not sure what happens with error resync here */
2794 return(UNDEF);
2795 }
2796
2797 /* if this is too wide will be caught later - this sets [size]' size */
2798 if (strcmp(nwidtoken, "") != 0)
2799 {
2800 blen = __my_strtoul(nwidtoken, &endp, &errnum);
2801 if (errnum != 0 || *endp != '\0')
2802 {
2803 __pv_ferr(952, "number size %s format bad", nwidtoken);
2804 __itoklen = WBITS;
2805 }
2806 else __itoklen = blen;
2807
2808 /* saying 0'[base]... is legal and becomes WBITS */
2809 if (__itoklen == 0)
2810 {
2811 __pv_fwarn(557, "INTERNAL - zero number size changed to %d", WBITS);
2812 __itoklen = WBITS;
2813 }
2814 __itoksized = TRUE;
2815 }
2816 else
2817 {
2818 /* 06/22/00 - SJM - this is 2nd part of sized num */
2819 if (__maybe_2tok_sized_num)
2820 {
2821 /* flags turned off later */
2822 __itoklen = __macro_sav_nwid;
2823 __itoksized = TRUE;
2824 }
2825 else __itoksizdflt = TRUE;
2826 }
2827
2828 /* '[base][number] is unsized 32 bits */
2829 if (__itoklen > MAXNUMBITS)
2830 {
2831 __pv_ferr(953, "number size too large (%d)", MAXNUMBITS);
2832 __itoklen = WBITS;
2833 __itoksized = FALSE;
2834 }
2835
2836 /* SJM 10/01/03 - add code that get the optional base signed char */
2837 /* and set signed flag for use when expression token constructed */
2838 c = my_getc(f);
2839 if (c == 's' || c == 'S')
2840 {
2841 __itok_signed = TRUE;
2842 c = my_getc(f);
2843 }
2844
2845 if ((__itokbase = __to_base(c)) == -1)
2846 {
2847 __pv_ferr(954,
2848 "illegal Verilog number base %c - for compiler directive use back quote(`)", c);
2849 my_ungetc_(c, f);
2850 __macro_sep_width = FALSE;
2851 return(UNDEF);
2852 }
2853 c = my_getc(f);
2854 c = voverwhite(f, c);
2855 /* AIV 07/09/04 - special case to handle: 8'h`DEFINE */
2856 if (c == '`')
2857 {
2858 int32 stok;
2859 my_ungetc_(c, f);
2860 /* save the base */
2861 stok = __itokbase;
2862 /* set the flag to make sure macro doesn't contain a base */
2863 __macbs_flag = TRUE;
2864 /* AIV 07/12/04 - need recursive call but can't read another number */
2865 __get_vtok();
2866 __macbs_flag = FALSE;
2867 __itokbase = stok;
2868 goto do_convert;
2869 }
2870
2871 /* know c is 1st character of sized number */
2872 toolong = FALSE;
2873 for (chp = __numtoken, len = 0;;)
2874 {
2875 while (c == '_') c = my_getc(f);
2876 c1 = __is_vdigit(c, __itokbase);
2877 if (c1 == -1) break;
2878 if (c1 == -2)
2879 {
2880 __pv_ferr(955, "digit %c illegal for base '%c", c,
2881 __to_baselet(__itokbase));
2882 c = c1 = '0';
2883 }
2884 /* using maximum length of Verilog line as 1024 (really ID len. max) */
2885 if (++len >= __numtok_wid)
2886 {
2887 if (len >= MAXNUMBITS)
2888 {
2889 if (!toolong)
2890 {
2891 __pv_ferr(956,
2892 "Verilog sized number too many characters (%d)", MAXNUMBITS);
2893 toolong = TRUE;
2894 }
2895 }
2896 else
2897 {
2898 /* LOOKATME - SJM 03/20/00 - doubling may be too fast growth */
2899 nsize = 2*__numtok_wid;
2900 __numtoken = __my_realloc(__numtoken, __numtok_wid, nsize);
2901 __numtok_wid = nsize;
2902 /* AIV 04/20/06 - need to reset chp pointer due to realloc */
2903 chp = &(__numtoken[len - 1]);
2904 *chp++ = c1;
2905 }
2906 }
2907 else *chp++ = c1;
2908 c = my_getc(f);
2909 }
2910 *chp = '\0';
2911
2912 if (strcmp(__numtoken, "") == 0)
2913 {
2914 __pv_ferr(957, "sized number value part empty");
2915 strcpy(__numtoken, "0");
2916 }
2917
2918 if (__pv_ctab[c & 0x7f] == 0)
2919 __pv_ferr(958, "sized number terminated with illegal char '%c' (%x)",
2920 c % 0xff, c & 0xff);
2921 my_ungetc_(c, f);
2922 /* finally do the conversion - know sizedness set and length in itok len */
2923 /* length never 0 */
2924
2925 /* notice this can never generate error */
2926 /* wide numbers truncated in here - do all non real numbers here */
2927 do_convert:
2928 /* this sets number bit length and allocates number if needed */
2929 __macro_sep_width = FALSE;
2930 __to_dhboval(__itokbase, TRUE);
2931 return(NUMBER);
2932 }
2933
2934 /*
2935 * remove leading 0 characters from numer string in token
2936 * this works in place
2937 */
rem_lead_0chars(char * s)2938 static void rem_lead_0chars(char *s)
2939 {
2940 register int32 i, j;
2941 int32 slen;
2942
2943 /* first set index to first non 0 char */
2944 for (i = 0; ; i++)
2945 {
2946 /* number all zero convert to 1 0 */
2947 if (s[i] == '\0') { s[0] = '0'; s[1] = '\0'; return; }
2948 if (s[i] != '0') break;
2949 }
2950 if (i == 0) return;
2951 /* if leading is . then must add 1 leading 0 - know at least 0. at start */
2952 if (s[i] == '.') i--;
2953
2954 /* copy to remove all leading 0's */
2955 slen = strlen(s);
2956 for (j = 0; j < slen - i; j++) s[j] = s[i + j];
2957 s[slen - i] = '\0';
2958 }
2959
2960 /*
2961 * skip over white space and return char just after
2962 * expects current character to be in c - no skip if current not white space
2963 */
voverwhite(FILE * f,register int32 c)2964 static int32 voverwhite(FILE *f, register int32 c)
2965 {
2966 int32 ct;
2967
2968 for (;; c = my_getc(f))
2969 {
2970 /* notice anthing escaped is not white space */
2971 if ((ct = __pv_ctab[c & 0x7f]) == 1) continue;
2972 if (ct == 3)
2973 { __lin_cnt++; __total_rd_lines++; __first_num_eol = TRUE; continue; }
2974 break;
2975 }
2976 return(c);
2977 }
2978
2979 /*
2980 * convert a character to a Verilog number base
2981 */
__to_base(int32 c)2982 extern int32 __to_base(int32 c)
2983 {
2984 switch (c) {
2985 case 'b': case 'B': return(BBIN);
2986 case 'o': case 'O': return(BOCT);
2987 case 'd': case 'D': return(BDEC);
2988 case 'h': case 'H': return(BHEX);
2989 }
2990 return(-1);
2991 }
2992
2993 /*
2994 * return TRUE if character can appear in Verilog number
2995 * return value if digit, -1 for non digit or -2 for out of range digit
2996 * (ends number)
2997 */
__is_vdigit(int32 c,int32 base)2998 extern int32 __is_vdigit(int32 c, int32 base)
2999 {
3000 switch (c) {
3001 case 'x': case 'X': return('x');
3002 case '?': case 'z': case 'Z': return('z');
3003 }
3004 if (!isxdigit(c)) return(-1);
3005 switch (base) {
3006 case BBIN:
3007 if (c != '0' && c != '1') return(-2);
3008 break;
3009 case BOCT:
3010 if (c < '0' || c > '7') return(-2);
3011 break;
3012 case BDEC:
3013 if (!isdigit(c)) return(-2);
3014 break;
3015 case BHEX:
3016 if (c >= 'A' && c <= 'F') return(tolower(c));
3017 break;
3018 default: __case_terr(__FILE__, __LINE__);
3019 }
3020 return(c);
3021 }
3022
3023 /*
3024 * ROUTINES TO CONVERT TO AB VALUE FROM SCANNED TOKEN
3025 */
3026
3027 /*
3028 * convert a scanned input number token to a h, b, or o value
3029 * this routines x/z extends from highest used digit if needed
3030 * warning if too many digits and truncates
3031 * this routine fills __ac wrk and __bc wrk, if needed will widen
3032 *
3033 * this is also used by tf_ string to value conversion routines
3034 * sets values in __numtoken, __itoklen, __itok_signed
3035 */
__to_dhboval(int32 base,int32 emit_warn)3036 extern void __to_dhboval(int32 base, int32 emit_warn)
3037 {
3038 register int32 chlen, wlen, srcwlen, ubits;
3039 int32 srcblen;
3040 word32 aival, bival;
3041 char s1[RECLEN];
3042
3043 chlen = strlen(__numtoken);
3044 /* must allow enough room in work string to convert number */
3045 /* even if much wider than itoklen - just at least wide estimate here */
3046 srcblen = chlen_to_bitlen(chlen, base);
3047 if (srcblen < __itoklen) srcblen = __itoklen;
3048
3049 /* SJM 10/02/03 now wide decimal or numbers with s/S base part signed */
3050 /* therefore itok is int32 global not accessed here */
3051
3052 wlen = wlen_(srcblen);
3053 /* if need to widen or wider than default, change allocated length */
3054 /* notice left until maybe changed next time used */
3055 if (wlen > __abwrkwlen || (__abwrkwlen > DFLTIOWORDS && wlen <= DFLTIOWORDS))
3056 chg_abwrklen(wlen);
3057
3058 /* now know __ac wrk and __bc wrk wide enough */
3059 memset(__acwrk, 0, wlen*WRDBYTES);
3060 memset(__bcwrk, 0, wlen*WRDBYTES);
3061
3062 /* convert number in token into work constant values */
3063 /* notice previous guess of src blen, made exact here */
3064 switch (base) {
3065 /* notice must trucate/widen after conversion here */
3066 case BDEC: to_dec(&srcblen); strcpy(s1, "decimal"); break;
3067 case BBIN: to_bin(chlen); strcpy(s1, "binary"); srcblen = chlen; break;
3068 case BOCT: to_oct(chlen); strcpy(s1, "octal"); srcblen = 3*chlen; break;
3069 case BHEX: to_hex(chlen); strcpy(s1, "hex"); srcblen = 4*chlen; break;
3070 default: __case_terr(__FILE__, __LINE__);
3071 }
3072
3073 /* words and occupied bits of number represented by chars */
3074 /* check case of number of character wider - maybe too wide number */
3075 /* __itoklen is number of bits that word32 must be stored in */
3076 /* srcblen is number of bits in source input number */
3077 if (srcblen > __itoklen)
3078 {
3079 srcwlen = wlen_(srcblen);
3080 if (vnum_toowide(__acwrk, srcblen) || vnum_toowide(__bcwrk, srcblen))
3081 {
3082 /* no warning for [3-1]'h[zx] or [2-1]'o[zx] in high position */
3083 /* notice for hex, must be in same word32 to have not too wide nibble */
3084 if (base == BHEX)
3085 {
3086 if (srcblen - __itoklen < 4 && wlen == srcwlen
3087 && nibblexz(__acwrk[wlen - 1], __bcwrk[wlen - 1], srcblen))
3088 goto do_mask;
3089 }
3090 else if (base == BOCT)
3091 {
3092 if (srcblen - __itoklen < 3 && octdigxz(__acwrk, __bcwrk, srcblen))
3093 goto do_mask;
3094 }
3095 /* SJM 12/04/00 - no warn if skipping over ifdef because will not */
3096 /* parse `macro_width_name h [number] right */
3097 if (emit_warn && !__ifdef_skipping)
3098 {
3099 if (__run_state == SS_SIM)
3100 __pv_warn(558, "redundant digit(s) in tf_strput number %s",
3101 decompnum_to_str(s1, __numtoken, base, __itoklen));
3102 else __pv_fwarn(558, "redundant digit(s) in number %s",
3103 decompnum_to_str(s1, __numtoken, base, __itoklen));
3104 }
3105 }
3106 /* if values 0 or vnum not too wide, no warn but still must mask */
3107
3108 /* must truncate the values to __itoklen */
3109 /* this leave high words as is but since unused - if used will be zeroed */
3110 /* before use */
3111 do_mask:
3112 ubits = ubits_(__itoklen);
3113 __acwrk[wlen - 1] &= __masktab[ubits];
3114 __bcwrk[wlen - 1] &= __masktab[ubits];
3115 }
3116 else if (srcblen < __itoklen)
3117 {
3118 /* case where widening needed */
3119 if (__numtoken[0] == 'z' || __numtoken[0] == 'Z')
3120 { aival = 0L; bival = 1L; }
3121 else if (__numtoken[0] == 'x' || __numtoken[0] == 'X')
3122 { aival = 1L; bival = 1L; }
3123 else { aival = 0L; bival = 0L; }
3124
3125 widen_val(__acwrk, __itoklen, srcblen, aival);
3126 widen_val(__bcwrk, __itoklen, srcblen, bival);
3127 }
3128 }
3129
3130 /*
3131 * computer number of bits + 1 needed to store number in base of chlen
3132 * worst case - could contain '_' place holders
3133 */
chlen_to_bitlen(int32 chlen,int32 base)3134 static int32 chlen_to_bitlen(int32 chlen, int32 base)
3135 {
3136 int32 bitlen;
3137 double d1;
3138
3139 switch (base) {
3140 case BDEC:
3141 /* here must make sure bit enough if rounding error */
3142 /* actual conversion will compute exact bit length */
3143 d1 = ((double) chlen)/LG2_DIV_LG10 + WBITS;
3144 bitlen = (int32) d1;
3145 break;
3146 case BBIN: bitlen = chlen; break;
3147 case BOCT: bitlen = 3*chlen; break;
3148 case BHEX: bitlen = 4*chlen; break;
3149 default: __case_terr(__FILE__, __LINE__); return(0);
3150 }
3151 return(bitlen);
3152 }
3153
3154 /*
3155 * change __ac wrk (and bc) work area length from blen if needed
3156 * only gets here if either blen (__itoklen) or abwork len wider than default
3157 * notice __ac wrk and __bc wrk not necessary contiguous
3158 */
chg_abwrklen(int32 wlen)3159 static void chg_abwrklen(int32 wlen)
3160 {
3161 int32 olen, nlen;
3162
3163 olen = WRDBYTES*__abwrkwlen;
3164 if (wlen <= DFLTIOWORDS) __abwrkwlen = DFLTIOWORDS; else __abwrkwlen = wlen;
3165 nlen = WRDBYTES*__abwrkwlen;
3166 __acwrk = (word32 *) __my_realloc((char *) __acwrk, olen, nlen);
3167 __bcwrk = (word32 *) __my_realloc((char *) __bcwrk, olen, nlen);
3168 }
3169
3170 /*
3171 * convert a number scanned token to a decimal value
3172 * know number initialized to 0 of itoklen width
3173 * LOOKATME - could maybe speed up by using scanf if fits in one word?
3174 */
to_dec(int32 * blen)3175 static void to_dec(int32 *blen)
3176 {
3177 /* know __ac wrk and __bc wrk set to 0 before this is called */
3178 if (strchr(__numtoken, 'z') != NULL)
3179 { one_allbits_(__bcwrk, __itoklen); *blen = __itoklen; return; }
3180 else if (strchr(__numtoken, 'x') != NULL)
3181 {
3182 /* 1 decimal digit will be at least this wide */
3183 one_allbits_(__acwrk, __itoklen);
3184 one_allbits_(__bcwrk, __itoklen);
3185 *blen = __itoklen;
3186 return;
3187 }
3188 /* do the conversion */
3189 wide_strtoverdec(*blen);
3190 /* finally, find real convert decimal number bit width by trimming */
3191 *blen = __trim1_0val(__acwrk, *blen);
3192 }
3193
3194 /*
3195 * convert a string in __numtoken into a decimal number in acwrk that is known
3196 * to be wide enough (blen width)
3197 * know all digits in token are legal decimal digits
3198 */
wide_strtoverdec(int32 blen)3199 static void wide_strtoverdec(int32 blen)
3200 {
3201 register char *chp;
3202 word32 *reg10, *newdig, *acc;
3203 int32 wlen;
3204 struct xstk_t *xsp;
3205
3206 wlen = wlen_(blen);
3207 push_xstk_(xsp, blen);
3208 /* build the constant 10 */
3209 reg10 = xsp->ap;
3210 memset(reg10, 0, wlen*WRDBYTES);
3211 reg10[0] = 10;
3212 /* and use b part to hold new digit to add */
3213 newdig = xsp->bp;
3214 memset(newdig, 0, wlen*WRDBYTES);
3215 push_xstk_(xsp, blen);
3216 acc = xsp->ap;
3217 memset(acc, 0, wlen*WRDBYTES);
3218
3219 chp = __numtoken;
3220 __acwrk[0] = *chp - '0';
3221 /* notice start with high (left) digit */
3222 for (chp++; *chp != '\0'; chp++)
3223 {
3224 /* 10 times current value plus new digit */
3225 __lmult(acc, __acwrk, reg10, blen);
3226 newdig[0] = *chp - '0';
3227 __ladd(acc, acc, newdig, blen);
3228 /* notice the accumulator must be copied into ac wrk since lmult res */
3229 /* must be different value than u and v */
3230 memcpy(__acwrk, acc, wlen*WRDBYTES);
3231 }
3232 /* value now in acwrk */
3233 __pop_xstk();
3234 __pop_xstk();
3235 }
3236
3237 /*
3238 * convert a number scanned token to binary in work string (acwrk and bcwrk)
3239 * input in token and token length set
3240 * know will fit and correct
3241 * notice caller know to have zerod __ac wrk and __bc wrk
3242 */
to_bin(int32 slen)3243 static void to_bin(int32 slen)
3244 {
3245 register int32 i;
3246 word32 a, b;
3247 int32 bi;
3248
3249 /* fill val from low char (rght str) to high char (const left to rght) */
3250 for (i = slen - 1, bi = 0; i >= 0; i--, bi++)
3251 {
3252 ch_tobits(&a, &b, __numtoken[i]);
3253 __lhsbsel(__acwrk, bi, a);
3254 __lhsbsel(__bcwrk, bi, b);
3255 }
3256 }
3257
3258 /*
3259 * convert binary plus z-x character to bit
3260 */
ch_tobits(word32 * ap,word32 * bp,int32 ch)3261 static int32 ch_tobits(word32 *ap, word32 *bp, int32 ch)
3262 {
3263 *ap = *bp = 0L;
3264 switch (ch) {
3265 case 'z': case 'Z': *bp = 1L; break;
3266 case 'x': case 'X': *ap = 1L; *bp = 1L; break;
3267 case '0': break;
3268 case '1': *ap = 1L; break;
3269 default: return(FALSE);
3270 }
3271 return(TRUE);
3272 }
3273
3274 /*
3275 * convert a number scanned token to octal in work string (acwrk and bcwrk)
3276 * input in token and token length set
3277 * know will fit and __ac wrk and __bc wrk zeroed
3278 */
to_oct(int32 slen)3279 static void to_oct(int32 slen)
3280 {
3281 register int32 i, bi;
3282 word32 a, b;
3283
3284 /* fill val from low char (rght str) to high char (const left to rght) */
3285 for (i = slen - 1, bi = 0; i >= 0; i--, bi += 3)
3286 {
3287 ch_toocts(&a, &b, __numtoken[i]);
3288 /* cant use literal shifts and mask because some octs split on boundary */
3289 __lhspsel(__acwrk, bi, &a, 3);
3290 __lhspsel(__bcwrk, bi, &b, 3);
3291 }
3292 }
3293
3294 /*
3295 * convert octal digit plus z-x character to bit
3296 */
ch_toocts(word32 * ap,word32 * bp,int32 ch)3297 static int32 ch_toocts(word32 *ap, word32 *bp, int32 ch)
3298 {
3299 *ap = *bp = 0L;
3300 switch (ch) {
3301 case 'z': case 'Z': *bp = 0x7L; break;
3302 case 'x': case 'X': *ap = 0x7L; *bp = 0x7L; break;
3303 default:
3304 if (ch < '0' || ch > '7') return(FALSE);
3305 *ap = (word32) ((ch - '0') & 0x7L);
3306 }
3307 return(TRUE);
3308 }
3309
3310 /*
3311 * convert number scanned token to hex in work string (__ac wrk and __bc wrk)
3312 * input in token and itoklen set
3313 * know will fit and know acwrk and bcwrk already zeroed
3314 * sets tokval or tokptr if > WBITS
3315 */
to_hex(int32 slen)3316 static void to_hex(int32 slen)
3317 {
3318 register int32 i, bi;
3319 register word32 *ap, *bp;
3320 word32 a, b;
3321
3322 /* fill val from low char (right str) to high char (const left to right) */
3323 ap = __acwrk;
3324 bp = __bcwrk;
3325 for (i = slen - 1, bi = 0; i >= 0; i--)
3326 {
3327 /* know already checked for out of range before here */
3328 ch_tohexs(&a, &b, __numtoken[i]);
3329 if (bi == 0) { *ap = a; *bp = b; bi += 4; continue; }
3330 *ap |= a << bi;
3331 *bp |= b << bi;
3332 if (bi == 28) { bi = 0; ap++; bp++; } else bi += 4;
3333 }
3334 }
3335
3336 /*
3337 * convert hex digit plus x and z to bit pattern
3338 */
ch_tohexs(word32 * ap,word32 * bp,int32 ch)3339 static int32 ch_tohexs(word32 *ap, word32 *bp, int32 ch)
3340 {
3341 *ap = *bp = 0L;
3342 switch (ch) {
3343 case 'z': case 'Z': *bp = 0xfL; break;
3344 case 'x': case 'X': *ap = 0xfL; *bp = 0xfL; break;
3345 default:
3346 if (ch >= '0' && ch <= '9')
3347 {
3348 *ap = (word32) ((ch - '0') & 0xfL);
3349 break;
3350 }
3351 if (isupper(ch)) ch = tolower(ch);
3352 if (ch >= 'a' && ch <= 'f')
3353 {
3354 *ap = (word32) ((10 + ch - 'a') & 0xfL);
3355 break;
3356 }
3357 /* should have already been caught */
3358 /* illegal 'h radix digit */
3359 return(FALSE);
3360 }
3361 return(TRUE);
3362 }
3363
3364 /*
3365 * return T if source input number at wp of length srcblen wider
3366 * than __itoklen - if all high bits 0 returns F (not too wide)
3367 *
3368 * only called if srcblen > __itoklen
3369 * if too wide only because x or z hex or oct digit returns T here
3370 * but change to not too wide later
3371 */
vnum_toowide(word32 * wp,int32 srcblen)3372 static int32 vnum_toowide(word32 *wp, int32 srcblen)
3373 {
3374 register int32 i;
3375 int32 srcwlen, storwlen, storubits;
3376
3377 srcwlen = wlen_(srcblen);
3378 storwlen = wlen_(__itoklen);
3379 storubits = ubits_(__itoklen);
3380 /* if high bits of high word32 from storage token length, too wide */
3381 if ((wp[storwlen - 1] & ~__masktab[storubits]) != 0L) return(TRUE);
3382 for (i = storwlen; i < srcwlen; i++) if (wp[i] != 0L) return(TRUE);
3383 return(FALSE);
3384 }
3385
3386 /*
3387 * return T if high unused bits of high 4 bit nibble x or z
3388 * know shubits is aligned on 4 bit boundary and both in same word
3389 * know if all high bits 0 won't get here
3390 */
nibblexz(word32 aw,word32 bw,int32 srcblen)3391 static int32 nibblexz(word32 aw, word32 bw, int32 srcblen)
3392 {
3393 int32 itokubits;
3394 word32 tmp;
3395
3396 /* know __itoklen has at least 1 high bit unused or will not get here */
3397 itokubits = ubits_(__itoklen);
3398 bw >>= itokubits;
3399 aw >>= itokubits;
3400 switch (srcblen - __itoklen) {
3401 case 1:
3402 /* notice this will shift so 1 extra bit is in low position not 8 pos. */
3403 if ((bw & 1L) == 0L) return(FALSE);
3404 break;
3405 case 2:
3406 /* if 2, b part bits are not 11 or a part 01 or 10 then not ok nibble */
3407 if ((bw & 3L) != 3L || ((tmp = aw & 3L) == 01L || tmp == 02L))
3408 return(FALSE);
3409 break;
3410 case 3:
3411 /* if 3 extra, b part bits 111 and a part not 000 or 111, not ok nibble */
3412 if ((bw & 7L) != 7L || ((tmp = aw & 7L) != 7L && tmp != 0L))
3413 return(FALSE);
3414 break;
3415 default: __case_terr(__FILE__, __LINE__);
3416 }
3417 return(TRUE);
3418 }
3419
3420 /*
3421 * return T if high unused bits of high 3 bit nibble x or z
3422 */
octdigxz(word32 * ap,word32 * bp,int32 srcblen)3423 static int32 octdigxz(word32 *ap, word32 *bp, int32 srcblen)
3424 {
3425 word32 tmp, aw, bw;
3426
3427 /* part select needed to isolate bits, oct can overlap word32 boundary */
3428 __rhspsel(&bw, bp, __itoklen - 1, 3);
3429 switch (srcblen - __itoklen) {
3430 case 1:
3431 if ((bw & 4L) != 0L) return(FALSE); break;
3432 case 2:
3433 if ((bw & 6L) != 6L) return(FALSE);
3434 __rhspsel(&aw, ap, __itoklen - 1, 3);
3435 /* for 2 bits must both be x aw=11? or z aw=00? */
3436 /* not a high x/z if 010 or 100 after masking */
3437 if ((tmp = aw & 6L) == 2L || tmp == 4L) return(FALSE);
3438 break;
3439 default: __case_terr(__FILE__, __LINE__);
3440 }
3441 return(TRUE);
3442 }
3443
3444 /*
3445 * widen a shorter value into a longer value in place (either a or b)
3446 * highval determines kind of ext. (0 = 0, 1 = 1)
3447 * do not know what is in higher values
3448 * know valwp wide enough
3449 */
widen_val(word32 * vwp,int32 lngblen,int32 shblen,word32 highval)3450 static void widen_val(word32 *vwp, int32 lngblen, int32 shblen, word32 highval)
3451 {
3452 register int32 i;
3453 register word32 *wp;
3454 word32 mask;
3455 int32 shwlen, shubits, lngwlen, lngubits;
3456
3457 shwlen = wlen_(shblen);
3458 shubits = ubits_(shblen);
3459 lngwlen = wlen_(lngblen);
3460 lngubits = ubits_(lngblen);
3461 /* first extend unused part of old short high word32 */
3462 if (shubits != 0)
3463 {
3464 mask = __masktab[shubits];
3465 vwp[shwlen - 1] &= mask;
3466 if (highval == 1L) vwp[shwlen - 1] |= ~mask;
3467 }
3468 /* done if widen up to max of WBITS or words same length */
3469 if (lngwlen == 1 || lngwlen == shwlen) goto done;
3470
3471 /* next set all higher words to highval */
3472 if (highval == 0L) memset(&(vwp[shwlen]), 0, WRDBYTES*(lngwlen - shwlen));
3473 else
3474 {
3475 /* notice if incing wp cannot use indexed later */
3476 for (i = shwlen, wp = &(vwp[shwlen]); i < lngwlen; i++) *wp++ = ALL1W;
3477 }
3478
3479 done:
3480 /* finally zero unused portion of high word32 */
3481 vwp[lngwlen - 1] &= __masktab[lngubits];
3482 }
3483
3484 /*
3485 * MISC. TOKEN HANDLING ROUTINES
3486 */
3487
3488 /*
3489 * version of print vtoken where value is not in global _toktyp
3490 * for use inside get token routines
3491 */
prt2_vtok(int32 ttyp)3492 static char *prt2_vtok(int32 ttyp)
3493 {
3494 int32 save_ttyp;
3495 char *chp;
3496
3497 save_ttyp = __toktyp;
3498 __toktyp = ttyp;
3499 chp = __prt_vtok();
3500 __toktyp = save_ttyp;
3501 return(chp);
3502 }
3503
3504 /*
3505 * print a token for error messages - indicate token is a keyword for msg
3506 *
3507 */
__prt_kywrd_vtok(void)3508 extern char *__prt_kywrd_vtok(void)
3509 {
3510 char s1[RECLEN];
3511
3512 if (get_vkeywrd(__token) != ID)
3513 {
3514 /* know pv varnam always has enough room for keyword */
3515 sprintf(s1, "Verilog keyword: %s", __prt_vtok());
3516 strcpy(__pv_varnam, s1);
3517 return(__pv_varnam);
3518 }
3519 return(__prt_vtok());
3520 }
3521
3522 /*
3523 * print the value of a token
3524 * only for current token (i.e. moves punct./op. to token)
3525 * i.e. typ cannot be old
3526 */
__prt_vtok(void)3527 extern char *__prt_vtok(void)
3528 {
3529 /* notice this must not change current val. of token */
3530 if (__toktyp >= BKEYS)
3531 { __get_vkeynam(__pv_varnam, __toktyp); return(__pv_varnam); }
3532
3533 switch ((byte) __toktyp) {
3534 case TEOF:
3535 if (__run_state == SS_SIM && __cmd_s == NULL) strcpy(__token, "**EOL**");
3536 else strcpy(__token, "**EOF**");
3537 break;
3538 case ID: return(__token);
3539 case NUMBER: return(__numtoken);
3540 case REALNUM: sprintf(__token, "%#g", __itok_realval); break;
3541 case LITSTR: return(__strtoken);
3542 case SEMI: strcpy(__token, ";"); break;
3543 case COMMA: strcpy(__token, ","); break;
3544 case COLON: strcpy(__token, ":"); break;
3545 case SHARP: strcpy(__token, "#"); break;
3546 case LPAR: strcpy(__token, "("); break;
3547 case RPAR: strcpy(__token, ")"); break;
3548 case LSB: strcpy(__token, "["); break;
3549 case RSB: strcpy(__token, "]"); break;
3550 case LCB: strcpy(__token, "{"); break;
3551 case RCB: strcpy(__token, "}"); break;
3552 case DOT: strcpy(__token, "."); break;
3553 case QUEST: strcpy(__token, "?"); break;
3554 case AT: strcpy(__token, "@"); break;
3555 case CAUSE: strcpy(__token, "->"); break;
3556 case PLUS: strcpy(__token, "+"); break;
3557 case MINUS: strcpy(__token, "-"); break;
3558 case TIMES: strcpy(__token, "*"); break;
3559 case DIV: strcpy(__token, "/"); break;
3560 case MOD: strcpy(__token, "%"); break;
3561 case BITNOT: strcpy(__token, "~"); break;
3562 case BITREDAND: strcpy(__token, "&"); break;
3563 case BITREDOR: strcpy(__token, "|"); break;
3564 case BITREDXOR: strcpy(__token, "^"); break;
3565 /* notice ~ ^ are 2 unary operators */
3566 case REDXNOR: strcpy(__token, "^~"); break;
3567 case RELGE: strcpy(__token, ">="); break;
3568 case RELGT: strcpy(__token, ">"); break;
3569 case RELLE: strcpy(__token, "<="); break;
3570 case RELLT: strcpy(__token, "<"); break;
3571 case RELCEQ: strcpy(__token, "==="); break;
3572 case RELEQ: strcpy(__token, "=="); break;
3573 case RELCNEQ: strcpy(__token, "!=="); break;
3574 case RELNEQ: strcpy(__token, "!="); break;
3575 case BOOLAND: strcpy(__token, "&&"); break;
3576 case BOOLOR: strcpy(__token, "||"); break;
3577 case NOT: strcpy(__token, "!"); break;
3578 case SHIFTL: strcpy(__token, "<<"); break;
3579 case ASHIFTL: strcpy(__token, "<<<"); break;
3580 case SHIFTR: strcpy(__token, ">>"); break;
3581 case ASHIFTR: strcpy(__token, ">>>"); break;
3582 case EQ: strcpy(__token, "="); break;
3583 case FPTHCON: strcpy(__token, "*>"); break;
3584 case PPTHCON: strcpy(__token, "=>"); break;
3585 case TCHKEVAND: strcpy(__token, "&&&"); break;
3586 case UNDEF: strcpy(__token, "**NONE**"); break;
3587 default: __case_terr(__FILE__, __LINE__);
3588 }
3589 return(__token);
3590 }
3591
3592 /*
3593 * convert a punct./operator token to a name
3594 * only for current token (i.e. moves punct./op. to token)
3595 * non expression token removed when tree built but included here
3596 * result
3597 */
__to_opname(word32 otyp)3598 extern char *__to_opname(word32 otyp)
3599 {
3600 /* token number %d illegal in expression */
3601 if (otyp > TEOF) __misc_fterr(__FILE__, __LINE__);
3602 return(__opinfo[otyp].opnam);
3603 }
3604
3605 /* note! - must be kept in alphabetical order */
3606 /* keyword types (already know token is a name) */
3607 /* making as many things as possible Verilog since they are reserved */
3608 struct vkeywds_t {
3609 char *vknam;
3610 int32 vknum;
3611 };
3612
3613 static struct vkeywds_t vkeywds[] = {
3614 { "`accelerate", CDIR_ACCEL },
3615 { "`autoexpand_vectornets", CDIR_AEXPVECNETS },
3616 { "`celldefine", CDIR_CELLDEF },
3617 { "`default_decay_time", CDIR_DFLTDECAYTIME },
3618 { "`default_nettype", CDIR_DFLNTYP },
3619 { "`default_trireg_strength", CDIR_DFLTTRIREGSTREN },
3620 { "`define", CDIR_DEFINE },
3621 { "`delay_mode_distributed", CDIR_DELMODEDIST },
3622 { "`delay_mode_path", CDIR_DELMODEPATH },
3623 { "`delay_mode_unit", CDIR_DELMODEUNIT },
3624 { "`delay_mode_zero", CDIR_DELMODEZERO },
3625 { "`else", CDIR_ELSE },
3626 { "`endcelldefine", CDIR_ECELLDEF },
3627 { "`endif", CDIR_ENDIF },
3628 { "`endprotect", CDIR_ENDPROTECT },
3629 { "`endprotected", CDIR_ENDPROTECTED },
3630 { "`expand_vectornets", CDIR_XPNDVNETS },
3631 { "`ifdef", CDIR_IFDEF },
3632 { "`ifndef", CDIR_IFNDEF },
3633 { "`include", CDIR_INCLUDE },
3634 { "`language", CDIR_LANG },
3635 { "`noaccelerate", CDIR_NOACCEL },
3636 { "`noexpand_vectornets", CDIR_NOXPNDVNETS },
3637 { "`noremove_gatenames", CDIR_NOREMGATENAMES },
3638 { "`noremove_netnames", CDIR_NOREMNETNAMES },
3639 { "`nounconnected_drive", CDIR_NOUNCONNDRIVE },
3640 { "`protect", CDIR_PROTECT },
3641 { "`protected", CDIR_PROTECTED },
3642 { "`remove_gatenames", CDIR_REMGATESNAMES },
3643 { "`remove_netnames", CDIR_REMNETNAMES },
3644 { "`resetall", CDIR_RESETALL },
3645 { "`timescale", CDIR_TIMESCALE },
3646 { "`unconnected_drive", CDIR_UNCONNDRIVE },
3647 { "`undef", CDIR_UNDEF },
3648
3649 { "always", ALWAYS },
3650 { "assign", ASSIGN },
3651 { "begin", Begin },
3652 { "case", CASE },
3653 { "casex", CASEX },
3654 { "casez", CASEZ },
3655 { "deassign", DEASSIGN },
3656 { "default", DEFAULT },
3657 { "defparam", DEFPARAM },
3658 { "disable", DISABLE },
3659 { "edge", EDGE },
3660 { "else", ELSE },
3661 { "end", END },
3662 { "endcase", ENDCASE },
3663 { "endfunction", ENDFUNCTION },
3664 { "endgenerate", ENDGENERATE },
3665 { "endmodule", ENDMODULE },
3666 { "endprimitive", ENDPRIMITIVE },
3667 { "endspecify", ENDSPECIFY },
3668 { "endtable", ENDTABLE },
3669 { "endtask", ENDTASK },
3670 { "event", EVENT },
3671 { "for", FOR },
3672 { "force", FORCE },
3673 { "forever", FOREVER },
3674 { "fork", FORK },
3675 { "function", FUNCTION },
3676 { "generate", GENERATE },
3677 { "highz0", HIGHZ0 },
3678 { "highz1", HIGHZ1 },
3679 { "if", IF },
3680 { "ifnone", IFNONE },
3681 { "initial", INITial },
3682 { "inout", INOUT },
3683 { "input", INPUT },
3684 /* not int32 */
3685 { "integer", INTEGER },
3686 { "join", JOIN },
3687 { "large", LARGE },
3688 { "localparam", LOCALPARAM },
3689 { "macromodule", MACROMODULE },
3690 { "medium", MEDIUM },
3691 { "module", MODULE },
3692 { "negedge", NEGEDGE },
3693 { "output", OUTPUT },
3694 { "parameter", PARAMETER },
3695 { "posedge", POSEDGE },
3696 { "primitive", PRIMITIVE },
3697 { "pull0", PULL0 },
3698 { "pull1", PULL1 },
3699 { "real", REAL },
3700 { "realtime", REALTIME },
3701 { "reg", REG },
3702 { "release", RELEASE },
3703 { "repeat", REPEAT },
3704 { "scalared", SCALARED },
3705 { "signed", SIGNED },
3706 { "small", SMALL },
3707 { "specify", SPECIFY },
3708 { "specparam", SPECPARAM },
3709 { "strength", Strength },
3710 { "strong0", STRONG0 },
3711 { "strong1", STRONG1 },
3712 { "supply0", SUPPLY0 },
3713 { "supply1", SUPPLY1 },
3714 { "table", TABLE },
3715 { "task", TASK },
3716 { "time", TIME },
3717 { "tri", TRI },
3718 { "tri0", TRI0 },
3719 { "tri1", TRI1 },
3720 { "triand", TRIAND },
3721 { "trior", TRIOR },
3722 { "trireg", TRIREG },
3723 { "vectored", VECTORED },
3724 { "wait", WAIT },
3725 { "wand", WAND },
3726 { "weak0", WEAK0 },
3727 { "weak1", WEAK1 },
3728 { "while", WHILE },
3729 { "wire", WIRE },
3730 { "wor", WOR }
3731 };
3732 #define NVKEYWDS (sizeof(vkeywds) / sizeof(struct vkeywds_t))
3733
3734 /*
3735 * determine type of keyword or ident
3736 * binary search because the table is so big
3737 */
get_vkeywrd(register char * tstr)3738 static int32 get_vkeywrd(register char *tstr)
3739 {
3740 int32 l, h;
3741 register int32 m, cv;
3742
3743 l = 0; h = NVKEYWDS - 1;
3744 for (;;)
3745 {
3746 m = (l + h)/2;
3747 if ((cv = strcmp(vkeywds[m].vknam, tstr)) == 0) return(vkeywds[m].vknum);
3748 if (cv < 0) l = m + 1; else h = m - 1;
3749 if (h < l) break;
3750 }
3751 return(ID);
3752 }
3753
3754 /*
3755 * determine keyword name from number
3756 * must use linear search since not sorted
3757 */
__get_vkeynam(char * s,int32 knum)3758 extern char *__get_vkeynam(char *s, int32 knum)
3759 {
3760 register int32 vi;
3761
3762 for (vi = 0; vi < NVKEYWDS; vi++)
3763 {
3764 if (vkeywds[vi].vknum == knum)
3765 {
3766 strcpy(s, vkeywds[vi].vknam);
3767 return(s);
3768 }
3769 }
3770 strcpy(s, "--none--");
3771 return(s);
3772 }
3773
3774 /*
3775 * ROUTINES FOR RESYNCING AFTER ERROR
3776 */
3777
3778 /*
3779 * skip to symbol - if not found only end module/primitive ends
3780 * rest of module not checked
3781 * return T if found targ1 else F
3782 */
__vskipto_modend(int32 targ1)3783 extern int32 __vskipto_modend(int32 targ1)
3784 {
3785 int32 sav_letendnum;
3786
3787 /* SJM 11/30/04 - save and restore edge illegal num errors when skip mod */
3788 sav_letendnum = __letendnum_state;
3789 __letendnum_state = TRUE;
3790 for (;;)
3791 {
3792 if (__toktyp == targ1)
3793 {
3794 __letendnum_state = sav_letendnum;
3795 return(TRUE);
3796 }
3797 switch ((byte) __toktyp) {
3798 case ENDMODULE: case ENDPRIMITIVE:
3799 goto done;
3800 case PRIMITIVE: case MODULE: case MACROMODULE:
3801 __unget_vtok(); goto done;
3802 }
3803 if (__toktyp == TEOF)
3804 __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
3805 __get_vtok();
3806 }
3807 done:
3808 __letendnum_state = sav_letendnum;
3809 return(FALSE);
3810 }
3811
3812 /*
3813 * skip to 2 symbols - if not found only end module/primitive ends
3814 * rest of module not checked
3815 * return T if found targ1 else F
3816 */
__vskipto2_modend(int32 targ1,int32 targ2)3817 extern int32 __vskipto2_modend(int32 targ1, int32 targ2)
3818 {
3819 int32 sav_letendnum;
3820
3821 /* SJM 11/30/04 - save and restore edge illegal num errors when skip mod */
3822 sav_letendnum = __letendnum_state;
3823 __letendnum_state = TRUE;
3824 for (;;)
3825 {
3826 if (__toktyp == targ1 || __toktyp == targ2)
3827 {
3828 __letendnum_state = sav_letendnum;
3829 return(TRUE);
3830 }
3831 switch ((byte) __toktyp) {
3832 case ENDMODULE: case ENDPRIMITIVE:
3833 goto done;
3834 case PRIMITIVE: case MODULE: case MACROMODULE:
3835 __unget_vtok();
3836 goto done;
3837 }
3838 if (__toktyp == TEOF)
3839 __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
3840 __get_vtok();
3841 }
3842 done:
3843 __letendnum_state = sav_letendnum;
3844 return(FALSE);
3845 }
3846
3847 /*
3848 * skip to 3 symbols - if not found only end module/primitive ends
3849 * est of module not checked
3850 * return T if found targ1 else F
3851 */
__vskipto3_modend(int32 targ1,int32 targ2,int32 targ3)3852 extern int32 __vskipto3_modend(int32 targ1, int32 targ2, int32 targ3)
3853 {
3854 int32 sav_letendnum;
3855
3856 /* SJM 11/30/04 - save and restore edge illegal num errors when skip mod */
3857 sav_letendnum = __letendnum_state;
3858 __letendnum_state = TRUE;
3859 for (;;)
3860 {
3861 if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
3862 {
3863 __letendnum_state = sav_letendnum;
3864 return(TRUE);
3865 }
3866 switch ((byte) __toktyp) {
3867 case ENDMODULE: case ENDPRIMITIVE:
3868 goto done;
3869 case PRIMITIVE: case MODULE: case MACROMODULE:
3870 __unget_vtok();
3871 goto done;
3872 }
3873 if (__toktyp == TEOF)
3874 __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
3875 __get_vtok();
3876 }
3877 done:
3878 __letendnum_state = sav_letendnum;
3879 return(FALSE);
3880 }
3881
3882 /*
3883 * skip to any start of stmt/item symbol
3884 * general sync algorithm.
3885 *
3886 * if finds specific thing, return T
3887 * else sets syncto_class and return F
3888 *
3889 * possibilities are:
3890 * SYNC_FLEVEL - file level mod/prim
3891 * SYNC_MODLEVEL - module level declaration or item
3892 * SYNC_STMT - start of statement
3893 * SYNC_TARG - target found and return T
3894 */
__vskipto_any(int32 targ1)3895 extern int32 __vskipto_any(int32 targ1)
3896 {
3897 /* for interactive just give up on any error - but must skip to end of line */
3898 if (__iact_state) longjmp(__iact_jmpbuf, 1);
3899
3900 for (;;)
3901 {
3902 if (__toktyp == targ1) { __syncto_class = SYNC_TARG; return(TRUE); }
3903 if (set_syncto_tokclass((byte) __toktyp)) break;
3904 if (__toktyp == TEOF)
3905 __fterr(315, "unexpected EOF while skipping to statement token %s",
3906 prt2_vtok(targ1));
3907 __get_vtok();
3908 }
3909 return(FALSE);
3910 }
3911
__vskipto2_any(int32 targ1,int32 targ2)3912 extern int32 __vskipto2_any(int32 targ1, int32 targ2)
3913 {
3914 if (__iact_state) longjmp(__iact_jmpbuf, 1);
3915 for (;;)
3916 {
3917 if (__toktyp == targ1 || __toktyp == targ2)
3918 { __syncto_class = SYNC_TARG; return(TRUE); }
3919 if (set_syncto_tokclass((byte) __toktyp)) break;
3920 if (__toktyp == TEOF)
3921 __fterr(315, "unexpected EOF while skipping to statement token %s",
3922 prt2_vtok(targ1));
3923 __get_vtok();
3924 }
3925 return(FALSE);
3926 }
3927
__vskipto3_any(int32 targ1,int32 targ2,int32 targ3)3928 extern int32 __vskipto3_any(int32 targ1, int32 targ2, int32 targ3)
3929 {
3930 if (__iact_state) longjmp(__iact_jmpbuf, 1);
3931 for (;;)
3932 {
3933 if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
3934 { __syncto_class = SYNC_TARG; return(TRUE); }
3935 if (set_syncto_tokclass((byte) __toktyp)) break;
3936 if (__toktyp == TEOF)
3937 __fterr(315, "unexpected EOF while skipping to statement token %s",
3938 prt2_vtok(targ1));
3939 __get_vtok();
3940 }
3941 return(FALSE);
3942 }
3943
__vskipto4_any(int32 targ1,int32 targ2,int32 targ3,int32 targ4)3944 extern int32 __vskipto4_any(int32 targ1, int32 targ2, int32 targ3, int32 targ4)
3945 {
3946 if (__iact_state) longjmp(__iact_jmpbuf, 1);
3947 for (;;)
3948 {
3949 if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3
3950 || __toktyp == targ4)
3951 { __syncto_class = SYNC_TARG; return(TRUE); }
3952 if (set_syncto_tokclass((byte) __toktyp)) break;
3953 if (__toktyp == TEOF)
3954 __fterr(315, "unexpected EOF while skipping to statement token %s",
3955 prt2_vtok(targ1));
3956 __get_vtok();
3957 }
3958 return(FALSE);
3959 }
3960
3961 /*
3962 * skip to end of list of port port decl element
3963 *
3964 * special case because resyncs at port name keyword ID
3965 * notice can't be used for new list of parameters form
3966 */
__vskipto_lofp_end()3967 extern int32 __vskipto_lofp_end()
3968 {
3969 /* only for list of ports decl so can't be invoked from iact state */
3970 if (__iact_state) __misc_terr(__FILE__, __LINE__);
3971
3972 for (;;)
3973 {
3974 /* semi can end because end of list ) always followed by ; */
3975 if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT
3976 || __toktyp == RPAR || __toktyp == SEMI)
3977 { __syncto_class = SYNC_TARG; return(TRUE); }
3978 if (set_syncto_tokclass((byte) __toktyp)) break;
3979 if (__toktyp == TEOF)
3980 __fterr(315,
3981 "unexpected EOF while skipping over list of port declaration");
3982 __get_vtok();
3983 }
3984 return(FALSE);
3985 }
3986
3987 /*
3988 * skip to end of list of port port decl element from inside port name comma
3989 * list
3990 *
3991 * special case because resyncs at port name keyword ID
3992 * notice can't be used for new list of parameters form
3993 */
__vskipto2_lofp_end()3994 extern int32 __vskipto2_lofp_end()
3995 {
3996 /* only for list of ports decl so can't be invoked from iact state */
3997 if (__iact_state) __misc_terr(__FILE__, __LINE__);
3998
3999 for (;;)
4000 {
4001 /* semi can end because end of list ) always followed by ; */
4002 if (__toktyp == INPUT || __toktyp == OUTPUT || __toktyp == INOUT
4003 || __toktyp == RPAR || __toktyp == SEMI || __toktyp == COMMA)
4004 { __syncto_class = SYNC_TARG; return(TRUE); }
4005
4006 if (set_syncto_tokclass((byte) __toktyp)) break;
4007
4008 if (__toktyp == TEOF)
4009 __fterr(315,
4010 "unexpected EOF while skipping over list of port declaration");
4011 __get_vtok();
4012 }
4013 return(FALSE);
4014 }
4015
4016 /*
4017 * set __token class - return T if not a sync to
4018 */
set_syncto_tokclass(byte ttyp)4019 static int32 set_syncto_tokclass(byte ttyp)
4020 {
4021 switch (ttyp) {
4022 /* file level item */
4023 case ENDMODULE: case ENDPRIMITIVE:
4024 __syncto_class = SYNC_FLEVEL;
4025 break;
4026 case PRIMITIVE: case MODULE: case MACROMODULE:
4027 __unget_vtok();
4028 __syncto_class = SYNC_FLEVEL;
4029 break;
4030 /* module item end - must assume next things is good item */
4031 /* because [id] [type](inst) is common */
4032 case ENDFUNCTION: case ENDTASK: case ENDSPECIFY:
4033 __syncto_class = SYNC_MODLEVEL;
4034 break;
4035 case INITial: case ALWAYS:
4036 case DEFPARAM: case SPECIFY: case TASK: case FUNCTION:
4037 case PARAMETER: case LOCALPARAM: case ASSIGN:
4038 case INPUT: case OUTPUT: case INOUT:
4039 case WIRE: case TRI: case TRI0: case TRI1: case TRIAND:
4040 case TRIOR: case TRIREG: case WAND: case WOR: case SUPPLY0:
4041 case SUPPLY1: case REG: case INTEGER: case TIME: case REAL: case REALTIME:
4042 case EVENT:
4043 __unget_vtok();
4044 __syncto_class = SYNC_MODLEVEL;
4045 break;
4046 /* stmt begin things - sync so next get tok will be stmt start */
4047 /* these are likely module item previous ends and assume so */
4048 /* but could be part of wrong list of stmts */
4049 /* SJM 01/14/1999 - moved else from statement start case to stmt end */
4050 /* LOOKATME - is there a problem with this? */
4051 case END: case JOIN: case ENDCASE: case ELSE:
4052 __syncto_class = SYNC_STMT;
4053 break;
4054 case SHARP: case AT:
4055 case IF: case IFNONE: case CASE: case CASEX: case CASEZ:
4056 case Begin: case FORK: case CAUSE:
4057 case FOREVER: case REPEAT: case WHILE: case FOR: case WAIT:
4058 case DISABLE: case FORCE: case RELEASE:
4059 __unget_vtok();
4060 __syncto_class = SYNC_STMT;
4061 break;
4062 default: return(FALSE);
4063 }
4064 return(TRUE);
4065 }
4066
4067 /*
4068 * for specify normal skip to any except also specify item level
4069 */
__spec_vskipto_any(int32 targ1)4070 extern int32 __spec_vskipto_any(int32 targ1)
4071 {
4072 for (;;)
4073 {
4074 if (__toktyp == targ1) { __syncto_class = SYNC_TARG; return(TRUE); }
4075 if (set_syncto_tokclass((byte) __toktyp))
4076 {
4077 if (__toktyp == IF) __syncto_class = SYNC_SPECITEM;
4078 break;
4079 }
4080 if (set_specitem_class()) break;
4081 if (__toktyp == TEOF)
4082 __fterr(315, "unexpected EOF while skipping to statement token %s",
4083 prt2_vtok(targ1));
4084 __get_vtok();
4085 }
4086 return(FALSE);
4087 }
4088
__spec_vskipto2_any(int32 targ1,int32 targ2)4089 extern int32 __spec_vskipto2_any(int32 targ1, int32 targ2)
4090 {
4091 for (;;)
4092 {
4093 if (__toktyp == targ1 || __toktyp == targ2)
4094 { __syncto_class = SYNC_TARG; return(TRUE); }
4095 if (set_syncto_tokclass((byte) __toktyp))
4096 {
4097 if (__toktyp == IF) __syncto_class = SYNC_SPECITEM;
4098 break;
4099 }
4100 if (set_specitem_class()) break;
4101 if (__toktyp == TEOF)
4102 __fterr(315, "unexpected EOF while skipping to statement token %s",
4103 prt2_vtok(targ1));
4104 __get_vtok();
4105 }
4106 return(FALSE);
4107 }
4108
__spec_vskipto3_any(int32 targ1,int32 targ2,int32 targ3)4109 extern int32 __spec_vskipto3_any(int32 targ1, int32 targ2, int32 targ3)
4110 {
4111 for (;;)
4112 {
4113 if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
4114 { __syncto_class = SYNC_TARG; return(TRUE); }
4115 if (set_syncto_tokclass((byte) __toktyp))
4116 {
4117 if (__toktyp == IF) __syncto_class = SYNC_SPECITEM;
4118 break;
4119 }
4120 if (set_specitem_class()) break;
4121 if (__toktyp == TEOF)
4122 __fterr(315, "unexpected EOF while skipping to statement token %s",
4123 prt2_vtok(targ1));
4124 __get_vtok();
4125 }
4126 return(FALSE);
4127 }
4128
4129 /*
4130 * set specify level for token that can begin specify section
4131 * returns T if found sync to place
4132 * this needs to access global toktyp and token
4133 * notice - cannot sync to most common ( for path start
4134 */
set_specitem_class(void)4135 static int32 set_specitem_class(void)
4136 {
4137 if (__toktyp == ID && *__token == '$')
4138 {
4139 if (__fr_tcnam(__token) != -1)
4140 {
4141 __unget_vtok();
4142 __syncto_class = SYNC_SPECITEM;
4143 return(TRUE);
4144 }
4145 }
4146 return(FALSE);
4147 }
4148
4149 /*
4150 * skip to udp symbol
4151 */
4152 /*
4153 * skip to udp symbol -
4154 * return T if found targ1 else F
4155 */
__udp_vskipto_any(int32 targ1)4156 extern int32 __udp_vskipto_any(int32 targ1)
4157 {
4158 for (;;)
4159 {
4160 if (__toktyp == targ1) { __syncto_class = SYNC_TARG; return(TRUE); }
4161 if (set_udpsyncto((byte) __toktyp)) break;
4162 if (__toktyp == TEOF)
4163 __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
4164 __get_vtok();
4165 }
4166 return(FALSE);
4167 }
4168
__udp_vskipto2_any(int32 targ1,int32 targ2)4169 extern int32 __udp_vskipto2_any(int32 targ1, int32 targ2)
4170 {
4171 for (;;)
4172 {
4173 if (__toktyp == targ1 || __toktyp == targ2)
4174 { __syncto_class = SYNC_TARG; return(TRUE); }
4175 if (set_udpsyncto((byte) __toktyp)) break;
4176 if (__toktyp == TEOF)
4177 __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
4178 __get_vtok();
4179 }
4180 return(FALSE);
4181 }
4182
__udp_vskipto3_any(int32 targ1,int32 targ2,int32 targ3)4183 extern int32 __udp_vskipto3_any(int32 targ1, int32 targ2, int32 targ3)
4184 {
4185 for (;;)
4186 {
4187 if (__toktyp == targ1 || __toktyp == targ2 || __toktyp == targ3)
4188 { __syncto_class = SYNC_TARG; return(TRUE); }
4189 if (set_udpsyncto((byte) __toktyp)) break;
4190 if (__toktyp == TEOF)
4191 __fterr(315, "unexpected EOF while skipping to %s", prt2_vtok(targ1));
4192 __get_vtok();
4193 }
4194 return(FALSE);
4195 }
4196
4197 /*
4198 * set udp token class - return T if token not a sync to
4199 */
set_udpsyncto(byte ttyp)4200 static int32 set_udpsyncto(byte ttyp)
4201 {
4202 switch (ttyp) {
4203 /* file level item */
4204 case ENDMODULE: case ENDPRIMITIVE:
4205 __syncto_class = SYNC_FLEVEL;
4206 break;
4207 case PRIMITIVE: case MODULE: case MACROMODULE:
4208 __unget_vtok();
4209 __syncto_class = SYNC_FLEVEL;
4210 break;
4211 case INPUT: case OUTPUT: case REG: case TABLE:
4212 __unget_vtok();
4213 __syncto_class = SYNC_UDPLEVEL;
4214 break;
4215 default: return(FALSE);
4216 }
4217 return(TRUE);
4218 }
4219
4220 /*
4221 * LIB. INPUT ROUTINES
4222 * BEWARE - must open file, use all, close file before using other get func.
4223 */
4224
4225 /*
4226 * ascii character table for processing ID tokens
4227 * 0 - continue, 1 - end and don't back up, 2 - end and back up
4228 * notice here any non white space contiguous chars good since can be path
4229 */
4230 static char __lbctab[128] = {
4231 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 1, 0, 0, /* ^i,\n,\f \r */
4232 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4233 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* sp */
4234 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4235 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4236 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4237 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4238 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* eof */
4239 };
4240
4241 /*
4242 * get a -f file option token - only white space and semi separation
4243 * (modified from yylex in "The Unix Programming Environment" p. 337)
4244 * notice no push back token here
4245 * also handles normal / * and // comments
4246 */
__get_cmdtok(FILE * f)4247 extern int32 __get_cmdtok(FILE *f)
4248 {
4249 /* the char must be an int32 for machine independence */
4250 register int32 c;
4251 register char *cp;
4252 int32 namlen;
4253
4254 again:
4255 while ((c = getc(f)) == ' ' || c == '\t' || c == '\f' || c == '\r') ;
4256 /* SJM 12/06/03 - only new line needs line cnt inc and pushed back */
4257 if (c == '\n') { __lin_cnt++; goto again; }
4258
4259 /* // or / * comments legal */
4260 if (c == '/') if (get_cmdcomment(f)) goto again;
4261
4262 /* get here by falling through case */
4263 for (cp = __token, namlen = 0;;)
4264 {
4265 if (++namlen >= IDCHARS - 1)
4266 __pv_ferr(919,
4267 "command option token too long (%d) - ignored", IDCHARS - 1);
4268
4269 *cp++ = c;
4270 if ((c = getc(f)) == EOF) return(TEOF);
4271 switch (__lbctab[c & 0x7f]) {
4272 case 0: continue; /* normal in ID char */
4273 case 1: goto end_nam; /* white space token end - swallow it */
4274 /* or lin_cnt wrong for errors */
4275 case 2: ungetc(c, f); goto end_nam; /* non white space end token */
4276 }
4277 }
4278 end_nam:
4279 *cp = '\0';
4280 /* does not need canonical token since not related to output */
4281 /* Verilog world options are case sensitive */
4282 return(ID);
4283 }
4284
4285 /*
4286 * ascii character table for processing config tokens
4287 * 0 - continue, 1 - end and don't back up, 2 - end and back up
4288 * notice here any non white space contiguous chars good since can be path
4289 */
4290 static char cfgctab[128] = {
4291 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 1, 0, 0, /* ^i,\n,\f \r */
4292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4293 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, /* sp, , */
4294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, /* ; */
4295 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* eof */
4299 };
4300
4301 /*
4302 * get a cfg -L or default map.lib file token
4303 * (modified from yylex in "The Unix Programming Environment" p. 337)
4304 * AIV 10/30/03 - added for new 2001 cfg feature
4305 *
4306 * notice no push back token here and tok typ glb not set
4307 * also handles normal / * and // comments
4308 *
4309 * allowing ' and " quotes and back slash escaping of quotes in quoted
4310 * strings but not allowing embedded new lines in tokens
4311 *
4312 * complicated because need warnings and must handle quoting and
4313 * escaping but only within quoted names
4314 */
__get_cfgtok(FILE * f)4315 extern int32 __get_cfgtok(FILE *f)
4316 {
4317 /* the char must be an int32 for machine independence */
4318 register int32 c;
4319 register char *cp;
4320 int32 namlen, ttyp, qchar;
4321
4322 again:
4323 while ((c = getc(f)) == ' ' || c == '\t' || c == '\f' || c == '\r') ;
4324 /* SJM 12/06/03 - only new line needs line cnt inc and pushed back */
4325 if (c == '\n') { __lin_cnt++; goto again; }
4326 /* AIV since push back ; if ';' */
4327 if (c == ';') return(CFG_SEMI);
4328 if (c == ',') return(CFG_COMMA);
4329 /* // or / * comments legal */
4330 if (c == '/') if (get_cmdcomment(f)) goto again;
4331
4332 if (c == '\'' || c == '"')
4333 {
4334 qchar = c;
4335 c = getc(f);
4336 /* get here by falling through case */
4337 for (cp = __token, namlen = 0;;)
4338 {
4339 if (++namlen >= IDCHARS - 1)
4340 {
4341 __pv_ferr(919,
4342 "config file token (path?) too long (%d) - rest discarded",
4343 IDCHARS - 1);
4344 for (;;)
4345 {
4346 if (c == '\\') { c = getc(f); continue; }
4347 if (c == qchar) break;
4348 if (c == EOF) return(CFG_EOF);
4349 c = getc(f);
4350 }
4351 *cp = '\0';
4352 return(CFG_ID);
4353 }
4354 /* escaped chars legal but only in quoted strings */
4355 if (c == '\\')
4356 {
4357 c = getc(f);
4358 if (c == EOF) return(CFG_EOF);
4359 *cp++ = c;
4360 }
4361 else
4362 {
4363 /* ending quote not part of ID and can't be key word32 */
4364 if (c == qchar)
4365 {
4366 if (strcmp(__token, "") == 0)
4367 {
4368 __pv_fwarn(3125, "quoted map library token empty string");
4369 }
4370 break;
4371 }
4372 }
4373 if (c == '\n')
4374 {
4375 if (strcmp(__token, "") == 0)
4376 {
4377 __pv_fwarn(3126,
4378 "quoted map library token contains embedded new line");
4379 }
4380 }
4381 *cp++ = c;
4382 c = getc(f);
4383 }
4384 *cp = '\0';
4385 return(CFG_ID);
4386 }
4387
4388 /* get here by falling through case */
4389 for (cp = __token, namlen = 0;;)
4390 {
4391 if (++namlen >= IDCHARS - 1)
4392 __pv_ferr(919,
4393 "config file token (path?) too long (%d) - rest discarded", IDCHARS - 1);
4394
4395 *cp++ = c;
4396 if ((c = getc(f)) == EOF) { __toktyp = CFG_EOF; return(CFG_EOF); }
4397 switch (cfgctab[c & 0x7f]) {
4398 case 0: continue; /* normal in ID char */
4399 case 1: goto end_nam; /* white space token end - swallow it */
4400 case 2: ungetc(c, f); goto end_nam; /* non white space end token */
4401 }
4402 }
4403 end_nam:
4404 *cp = '\0';
4405 ttyp = get_cfgkeywrd(__token);
4406 return(ttyp);
4407 }
4408
4409 /*
4410 * look up a cfg file ID and convert to a keyword NUMBER
4411 *
4412 * notice keyword numbers disjoint32 from and overlap Verilog keywords
4413 * FIXME - should use binary search
4414 */
get_cfgkeywrd(char * tstr)4415 static int32 get_cfgkeywrd(char *tstr)
4416 {
4417 if (strcmp(tstr, "library") == 0) return(CFG_LIBRARY);
4418 if (strcmp(tstr, "config") == 0) return(CFG_CFG);
4419 if (strcmp(tstr, "design") == 0) return(CFG_DESIGN);
4420 if (strcmp(tstr, "liblist") == 0) return(CFG_LIBLIST);
4421 if (strcmp(tstr, "instance") == 0) return(CFG_INSTANCE);
4422 if (strcmp(tstr, "cell") == 0) return(CFG_CELL);
4423 if (strcmp(tstr, "use") == 0) return(CFG_USE);
4424 if (strcmp(tstr, "endconfig") == 0) return(CFG_ENDCFG);
4425 if (strcmp(tstr, "default") == 0) return(CFG_DEFAULT);
4426 return(CFG_ID);
4427 }
4428
4429 /*
4430 * convert cfg toktyp number to name
4431 */
__to_cfgtoknam(char * s,int32 ttyp)4432 extern char *__to_cfgtoknam(char *s, int32 ttyp)
4433 {
4434 switch (ttyp) {
4435 case CFG_UNKNOWN: strcpy(s, "??CFG-UNKNOWN??"); break;
4436 case CFG_ID: strcpy(s, __token); break;
4437 case CFG_COMMA: strcpy(s, ","); break;
4438 case CFG_SEMI: strcpy(s, ";"); break;
4439 case CFG_EOF: strcpy(s, "**CFG EOF**"); break;
4440 case CFG_LIBRARY: strcpy(s, "library"); break;
4441 case CFG_CFG: strcpy(s, "config"); break;
4442 case CFG_INCLUDE: strcpy(s, "include"); break;
4443 case CFG_DESIGN: strcpy(s, "design"); break;
4444 case CFG_LIBLIST: strcpy(s, "liblist"); break;
4445 case CFG_INSTANCE: strcpy(s, "instance"); break;
4446 case CFG_CELL: strcpy(s, "cell"); break;
4447 case CFG_USE: strcpy(s, "use"); break;
4448 case CFG_ENDCFG: strcpy(s, "endconfig"); break;
4449 case CFG_DEFAULT: strcpy(s, "default"); break;
4450 default: __case_terr(__FILE__, __LINE__);
4451 }
4452 return(s);
4453 }
4454
4455 /*
4456 * get a comment
4457 */
get_cmdcomment(FILE * f)4458 static int32 get_cmdcomment(FILE *f)
4459 {
4460 register int32 c;
4461 int32 c2;
4462
4463 /* // to EOL comment */
4464 if ((c2 = getc(f)) == '/')
4465 {
4466 while ((c = getc(f)) != '\n') if (c == EOF) { ungetc(c, f); return(TRUE); }
4467 ungetc(c, f);
4468 return(TRUE);
4469 }
4470 /* slash-star comments don't nest */
4471 if (c2 == '*')
4472 {
4473 more_comment:
4474 while ((c = getc(f)) != '*')
4475 {
4476 if (c == EOF) { ungetc(c, f); return(TRUE); }
4477 if (c == '\n') __lin_cnt++;
4478 if (c == '/')
4479 {
4480 if ((c2 = getc(f)) == '*')
4481 {
4482 __pv_fwarn(622, "nested /* in /* style -f argument file comment");
4483 continue;
4484 }
4485 c = c2;
4486 }
4487 }
4488
4489 got_star:
4490 if ((c = getc(f)) == '/') return(TRUE);
4491 if (c == '*') goto got_star;
4492 if (c == '\n') __lin_cnt++;
4493 goto more_comment;
4494 }
4495 /* / not followed by / or * so put back and return SLASH token */
4496 ungetc(c2, f);
4497 return(FALSE);
4498 }
4499
4500 /*
4501 * SYMBOL TABLE ROUTINES
4502 */
4503
4504 /*
4505 * locate a currently accessible symbol - for non path qualified names
4506 * use __find_sym if needs to be addded when not found
4507 * notice this works for frozen symbol tables since get sym determines type
4508 *
4509 * LOOKATME - could make variable routine if if in this inner loop to slow
4510 */
__get_sym_env(char * nam)4511 extern struct sy_t *__get_sym_env(char *nam)
4512 {
4513 int32 sti;
4514 struct sy_t *syp;
4515 struct symtab_t *sytp;
4516
4517 /* LOOKATME - special convenience variable symbol table could go here */
4518 if (!__iact_state)
4519 {
4520 for (sti = __top_sti; sti >= 0; sti--)
4521 {
4522 sytp = __venviron[sti];
4523 if ((syp = __get_sym(nam, sytp)) != NULL) return(syp);
4524 }
4525 return(NULL);
4526 }
4527
4528 if (__scope_tskp == NULL)
4529 __last_iasytp = __scope_ptr->itip->imsym->el.emdp->msymtab;
4530 else __last_iasytp = __scope_tskp->tsksymtab;
4531 /* know parent of task is top level module instance and of module is nil */
4532 for (; __last_iasytp != NULL; __last_iasytp = __last_iasytp->sytpar)
4533 { if ((syp = __get_sym(nam, __last_iasytp)) != NULL) return(syp); }
4534 return(NULL);
4535 }
4536
4537 /*
4538 * find a symbol (will add SYM_UNKN symbol if needed)
4539 * if needs to be implicit wire decl. caller must add and set net
4540 */
__find_sym(char * nam)4541 extern struct sy_t *__find_sym(char *nam)
4542 {
4543 register int32 sti;
4544 struct sy_t *syp;
4545 struct tnode_t *tnp;
4546 struct symtab_t *sytp;
4547
4548 /* top module level is lowest in task/function symbol table stack */
4549 for (sti = __top_sti; sti >= 0; sti--)
4550 {
4551 sytp = __venviron[sti];
4552 if ((syp = __get_sym(nam, sytp)) != NULL)
4553 { __sym_is_new = FALSE; return(syp); }
4554 }
4555 sytp = __venviron[__top_sti];
4556 tnp = __vtfind(nam, sytp);
4557 /* know symbol will be new */
4558 /* allocate symbol and fill symbol */
4559 __add_sym(nam, tnp);
4560 (__venviron[__top_sti]->numsyms)++;
4561 syp = tnp->ndp;
4562 return(syp);
4563 }
4564
4565 /*
4566 * declare a symbol - caller determines where declared
4567 *
4568 * this is used to add sym to symbol table - sydecl not set
4569 * when real source declaration (maybe implicit) sydecl set
4570 */
__decl_sym(char * nam,struct symtab_t * sytp)4571 extern struct sy_t *__decl_sym(char *nam, struct symtab_t *sytp)
4572 {
4573 struct sy_t *syp;
4574 struct tnode_t *tnp;
4575
4576 if ((syp = __get_sym(nam, sytp)) != NULL)
4577 { __sym_is_new = FALSE; return(syp); }
4578 tnp = __vtfind(nam, sytp);
4579 /* allocate symbol and fill symbol */
4580 __add_sym(nam, tnp);
4581 (sytp->numsyms)++;
4582 return(tnp->ndp);
4583 }
4584
4585 /*
4586 * add a symbol, caller must fill and set type
4587 * expects symbol tree node to be inserted in avl tree and passed here
4588 * symbol always added to symbol table on top of module/task nesting stack
4589 */
__add_sym(char * snam,struct tnode_t * tnp)4590 extern void __add_sym(char *snam, struct tnode_t *tnp)
4591 {
4592 struct sy_t *syp;
4593
4594 syp = (struct sy_t *) __my_malloc(sizeof(struct sy_t));
4595 tnp->ndp = syp;
4596 __init_sy(syp);
4597 syp->synam = pv_stralloc2(snam);
4598 }
4599
4600 /*
4601 * allocate a string from a big block
4602 * this must allocate the 1 char null string for `define as flag
4603 */
pv_stralloc2(char * s)4604 static char *pv_stralloc2(char *s)
4605 {
4606 char *cp;
4607 int32 slen;
4608
4609 if (*s == '\0') slen = 1; else slen = strlen(s) + 1;
4610 cp = nfbig_alloc(slen);
4611 __memstr_use += slen;
4612 /* this just copies '\0' for "" case */
4613 strcpy(cp, s);
4614 return(cp);
4615 }
4616
4617 /*
4618 * initialize a symbol
4619 * requires set current file and line number
4620 */
__init_sy(struct sy_t * syp)4621 extern void __init_sy(struct sy_t *syp)
4622 {
4623 syp->synam = NULL;
4624 syp->sytyp = SYM_UNKN;
4625 /* notice all symbols add during input phase */
4626 syp->sydecl = FALSE;
4627 syp->syundefmod = FALSE;
4628 syp->sy_impldecl = FALSE;
4629 syp->sy_argsmac = FALSE;
4630 syp->sy_giabase = FALSE;
4631 syp->el.enp = NULL;
4632 syp->syfnam_ind = __cur_fnam_ind;
4633 syp->sylin_cnt = __lin_cnt;
4634 syp->spltsy = NULL;
4635 }
4636
4637 /*
4638 * BALANCED TREE ACCESS ROUTINES NETS
4639 * MUST GO HERE BECAUSE GLOBALS USE FIND_NET MECHANISM
4640 */
4641
4642 /*
4643 * search one symbol table and if found return sym node
4644 * call __vtfind if need to add if not found
4645 */
__get_sym(char * nam,struct symtab_t * sytp)4646 extern struct sy_t *__get_sym(char *nam, struct symtab_t *sytp)
4647 {
4648 struct tnode_t *cur;
4649 int32 cv;
4650
4651 /* interactive bld node accesses frozen symbol table */
4652 if (sytp->stsyms != NULL)
4653 return(__zget_sym(nam, sytp->stsyms, sytp->numsyms));
4654
4655 /* FIXME - SJM - 09/16/99 when copied n_head may be non nil for empty tab */
4656 if (sytp->n_head == NULL || sytp->numsyms == 0) return(NULL);
4657 for (cur = sytp->n_head;;)
4658 {
4659 if ((cv = strcmp(nam, cur->ndp->synam)) == 0) return(cur->ndp);
4660 if ((cur = (cv < 0) ? cur->lp : cur->rp) == NULL) break;
4661 }
4662 return(NULL);
4663 }
4664
4665 /*
4666 * special vpi/sdf version of get sym that fails for g/i array base name
4667 *
4668 * LOOKATME - change this if allowing vpi_ access to arrays of gates/insts
4669 */
__get_nongia_sym(char * nam,struct symtab_t * sytp)4670 extern struct sy_t *__get_nongia_sym(char *nam, struct symtab_t *sytp)
4671 {
4672 struct sy_t *syp;
4673
4674 if ((syp = __get_sym(nam, sytp)) == NULL) return(NULL);
4675 if (syp->sy_giabase) return(NULL);
4676 return(syp);
4677 }
4678
4679 /*
4680 * find an entry in symbol node tree and add if needed
4681 * expects caller to connect in sy_t and fill it
4682 */
__vtfind(char * nam,struct symtab_t * sytp)4683 extern struct tnode_t *__vtfind(char *nam, struct symtab_t *sytp)
4684 {
4685 register struct tnode_t *cur, *down;
4686 struct tnode_t *balpt_par, *bal_pt, *vtnew, *bal_down;
4687 int32 cv;
4688
4689 /* DBG remove --
4690 if (sytp->stsyms != NULL) __misc_terr(__FILE__, __LINE__);
4691 --- */
4692
4693 vtnew = NULL;
4694 if (sytp->n_head == NULL)
4695 { sytp->n_head = alloc_tnode(sytp); return(sytp->n_head); }
4696 for (balpt_par = NULL, bal_pt = cur = sytp->n_head;;)
4697 {
4698 if ((cv = strcmp(nam, cur->ndp->synam)) == 0)
4699 { __sym_is_new = FALSE; return(cur); }
4700
4701 if (cv < 0) { cur->via_dir = BLEFT; down = cur->lp; }
4702 else { cur->via_dir = BRIGHT; down = cur->rp; }
4703 if (down == NULL)
4704 {
4705 down = alloc_tnode(sytp);
4706 if (cur->via_dir == BLEFT) cur->lp = down; else cur->rp = down;
4707 vtnew = down;
4708 break;
4709 }
4710 if (down->bal != BEVEN) { balpt_par = cur; bal_pt = down; }
4711 cur = down;
4712 }
4713
4714 /* bal down is one below balance point */
4715 if (bal_pt->via_dir == BLEFT) bal_down = bal_pt->lp;
4716 else bal_down = bal_pt->rp;
4717 /* know all nodes from bal_pt down to but not including new had balance 0 */
4718 /* adjust up to but not including balance of new */
4719 for (cur = bal_down; cur != vtnew;)
4720 {
4721 cur->bal = cur->via_dir;
4722 if (cur->via_dir == BLEFT) cur = cur->lp; else cur = cur->rp;
4723 }
4724 /* since only unbalanced by 1 put off doing anything */
4725 if (bal_pt->bal == BEVEN) { bal_pt->bal = bal_pt->via_dir; return(vtnew); }
4726
4727 /* tree got more balanced */
4728 /* check for bal and even dir opposite or both even */
4729 if ((bal_pt->bal == BEVEN && bal_pt->via_dir == BEVEN)
4730 || (bal_pt->bal == BLEFT && bal_pt->via_dir == BRIGHT)
4731 || (bal_pt->bal == BRIGHT && bal_pt->via_dir == BLEFT))
4732 {
4733 bal_pt->bal = BEVEN;
4734 return(vtnew);
4735 }
4736
4737 __tmp_head = sytp->n_head;
4738 /* these routines may update global __tmp_head */
4739 /* tree more out of balance - needs rebalancing */
4740 if (bal_down->bal == bal_pt->via_dir) one_rot(bal_pt, bal_down, balpt_par);
4741 else two_rot(bal_pt, bal_down, balpt_par);
4742 sytp->n_head = __tmp_head;
4743
4744 return(vtnew);
4745 }
4746
4747 /*
4748 * single rotation
4749 */
one_rot(struct tnode_t * bal_pt,struct tnode_t * bal_down,struct tnode_t * balpt_par)4750 static void one_rot(struct tnode_t *bal_pt, struct tnode_t *bal_down,
4751 struct tnode_t *balpt_par)
4752 {
4753 if (bal_pt->via_dir == BLEFT)
4754 {
4755 bal_pt->lp = bal_down->rp;
4756 bal_down->rp = bal_pt;
4757 }
4758 else
4759 {
4760 bal_pt->rp = bal_down->lp;
4761 bal_down->lp = bal_pt;
4762 }
4763 bal_pt->bal = bal_down->bal = BEVEN;
4764
4765 if (balpt_par == NULL) __tmp_head = bal_down;
4766 else if (balpt_par->via_dir == BLEFT) balpt_par->lp = bal_down;
4767 else balpt_par->rp = bal_down;
4768 }
4769
4770 /*
4771 * double rotation
4772 */
two_rot(struct tnode_t * bal_pt,struct tnode_t * bal_down,struct tnode_t * balpt_par)4773 static void two_rot(struct tnode_t *bal_pt, struct tnode_t *bal_down,
4774 struct tnode_t *balpt_par)
4775 {
4776 struct tnode_t *tmp;
4777
4778 if (bal_pt->via_dir == BLEFT)
4779 {
4780 tmp = bal_down->rp;
4781 bal_down->rp = tmp->lp;
4782 tmp->lp = bal_down;
4783 bal_pt->lp = tmp->rp;
4784 tmp->rp = bal_pt;
4785 }
4786 else
4787 {
4788 tmp = bal_down->lp;
4789 bal_down->lp = tmp->rp;
4790 tmp->rp = bal_down;
4791 bal_pt->rp = tmp->lp;
4792 tmp->lp = bal_pt;
4793 }
4794
4795 /* update the balances */
4796 if (tmp->bal == BEVEN) bal_pt->bal = bal_down->bal = BEVEN;
4797 else if (tmp->bal == bal_pt->via_dir)
4798 {
4799 if (bal_pt->via_dir == BRIGHT) bal_pt->bal = BLEFT;
4800 else if (bal_pt->via_dir == BLEFT) bal_pt->bal = BRIGHT;
4801 else bal_pt->bal = BEVEN;
4802 bal_down->bal = BEVEN;
4803 }
4804 else { bal_pt->bal = BEVEN; bal_down->bal = bal_pt->via_dir; }
4805 tmp->bal = BEVEN;
4806
4807 /* point node above balance point to new high node */
4808 if (balpt_par == NULL) __tmp_head = tmp;
4809 else if (balpt_par->via_dir == BLEFT) balpt_par->lp = tmp;
4810 else balpt_par->rp = tmp;
4811 }
4812
4813 /*
4814 * allocate a node
4815 */
alloc_tnode(struct symtab_t * sytp)4816 static struct tnode_t *alloc_tnode(struct symtab_t *sytp)
4817 {
4818 struct tnode_t *tnp;
4819 register struct tnblk_t *tnbp;
4820
4821 if (!sytp->freezes)
4822 tnp = (struct tnode_t *) __my_malloc(sizeof(struct tnode_t));
4823 else
4824 {
4825 if (__tnblk_nxti == -1)
4826 {
4827 tnbp = (struct tnblk_t *) __my_malloc(sizeof(struct tnblk_t));
4828 tnbp->tnblks = (struct tnode_t *) __my_malloc(BIG_ALLOC_SIZE);
4829 tnbp->tnblknxt = __hdr_tnblks;
4830 __hdr_tnblks = tnbp;
4831 __tnblk_nxti = 0;
4832 }
4833 tnp = (struct tnode_t *) &(__hdr_tnblks->tnblks[__tnblk_nxti]);
4834 if (++__tnblk_nxti > ((BIG_ALLOC_SIZE/sizeof(struct tnode_t)) - 1))
4835 __tnblk_nxti = -1;
4836 }
4837
4838 tnp->lp = tnp->rp = NULL;
4839 tnp->bal = BEVEN;
4840 tnp->via_dir = BEVEN;
4841 __sym_is_new = TRUE;
4842 tnp->ndp = NULL;
4843 return(tnp);
4844 }
4845
4846 /*
4847 * find a symbol in the current scope
4848 */
4849
4850 /*
4851 * get a symbol in frozen table - notice nsyms is num. not last
4852 */
__zget_sym(char * nam,struct sy_t ** syms,word32 nsyms)4853 extern struct sy_t *__zget_sym(char *nam, struct sy_t **syms, word32 nsyms)
4854 {
4855 register int32 l, h;
4856 register int32 m, cv;
4857
4858 if (nsyms == 0) return(NULL);
4859 l = 0; h = nsyms - 1;
4860 for (;;)
4861 {
4862 m = (l + h)/2;
4863 if ((cv = strcmp(syms[m]->synam, nam)) == 0) return(syms[m]);
4864 if (cv < 0) l = m + 1; else h = m - 1;
4865 if (h < l) break;
4866 }
4867 return(NULL);
4868 }
4869
4870 /*
4871 * allocate a new empty symbol table
4872 */
__alloc_symtab(int32 freezes)4873 extern struct symtab_t *__alloc_symtab(int32 freezes)
4874 {
4875 struct symtab_t *sytp;
4876
4877 sytp = (struct symtab_t *) __my_malloc(sizeof(struct symtab_t));
4878 sytp->n_head = NULL;
4879 sytp->stsyms = NULL;
4880 sytp->sytpar = NULL;
4881 sytp->sytsib = NULL;
4882 sytp->sytofs = NULL;
4883 sytp->sypofsyt = NULL;
4884 sytp->numsyms = 0;
4885 sytp->freezes = freezes;
4886 return(sytp);
4887 }
4888
4889 /*
4890 * MISC. REPRESENTATION CHANGE RROUTINES
4891 */
4892
4893 /*
4894 * routine to find index in ip table and it roots of top level module
4895 *
4896 * here __top_ipind is sorted array of indexes into top_iptab which
4897 * is || to __it_roots
4898 */
__ip_indsrch(char * nam)4899 extern int32 __ip_indsrch(char *nam)
4900 {
4901 int32 l, h;
4902 register int32 m, cv;
4903
4904 if (__numtopm == 0) return(-1);
4905 l = 0; h = __numtopm - 1;
4906 for (;;)
4907 {
4908 m = (l + h)/2;
4909 if ((cv = strcmp(__top_itab[__top_ipind[m]]->imsym->synam, nam)) == 0)
4910 return(__top_ipind[m]);
4911 if (cv < 0) l = m + 1; else h = m - 1;
4912 if (h < l) break;
4913 }
4914 return(-1);
4915 }
4916
4917 /*
4918 * convert an identifier to either global or id name
4919 */
__to_idnam(struct expr_t * xp)4920 extern char *__to_idnam(struct expr_t *xp)
4921 {
4922 char *chp;
4923
4924 if (xp->optyp == ID)
4925 {
4926 if (xp->locqualnam) return(xp->ru.qnchp); else return(xp->lu.sy->synam);
4927 }
4928 else if (xp->optyp == GLBREF) chp = xp->ru.grp->gnam;
4929 else { chp = NULL; __case_terr(__FILE__, __LINE__); }
4930 return(chp);
4931 }
4932
4933 /*
4934 * convert port name to string - maybe unnamed (chp nil)
4935 */
__to_mpnam(char * s,char * chp)4936 extern char *__to_mpnam(char *s, char *chp)
4937 {
4938 if (chp == NULL) strcpy(s, "*unnamed*"); else strcpy(s, chp);
4939 return(s);
4940 }
4941
4942
4943 /*
4944 * convert from a wire type token number to its wtyp value (-1 if no match)
4945 */
__fr_wtnam(int32 ttyp)4946 extern int32 __fr_wtnam(int32 ttyp)
4947 {
4948 int32 wtyp;
4949
4950 switch ((byte) ttyp) {
4951 case WIRE: wtyp = N_WIRE; break;
4952 case TRI: wtyp = N_TRI; break;
4953 case TRI0: wtyp = N_TRI0; break;
4954 case TRI1: wtyp = N_TRI1; break;
4955 case TRIOR: wtyp = N_TRIOR; break;
4956 case TRIAND: wtyp = N_TRIAND; break;
4957 case TRIREG: wtyp = N_TRIREG; break;
4958 case WAND: wtyp = N_WA; break;
4959 case WOR: wtyp = N_WO; break;
4960 /* notice pulls never explicitly declared */
4961 case SUPPLY0: wtyp = N_SUPPLY0; break;
4962 case SUPPLY1: wtyp = N_SUPPLY1; break;
4963 case REG: wtyp = N_REG; break;
4964 case TIME: wtyp = N_TIME; break;
4965 case INTEGER: wtyp = N_INT; break;
4966 case REAL: case REALTIME: wtyp = N_REAL; break;
4967 case EVENT: wtyp = N_EVENT; break;
4968 default: wtyp = -1; break;
4969 }
4970 return(wtyp);
4971 }
4972
4973 /*
4974 * convert a net to its wire type
4975 */
__to_wtnam(char * s,struct net_t * np)4976 extern char *__to_wtnam(char *s, struct net_t *np)
4977 {
4978 return(__to_wtnam2(s, np->ntyp));
4979 }
4980
4981 /*
4982 * convert a wire type value into a output name (2nd variant constant wtyp)
4983 * not for I/O port types
4984 */
__to_wtnam2(char * s,word32 typ)4985 extern char *__to_wtnam2(char *s, word32 typ)
4986 {
4987 switch ((byte) typ) {
4988 case N_WIRE: strcpy(s, "wire"); break;
4989 case N_TRI: strcpy(s, "tri"); break;
4990 case N_TRI0: strcpy(s, "tri0"); break;
4991 case N_TRI1: strcpy(s, "tri1"); break;
4992 case N_TRIOR: strcpy(s, "wor"); break;
4993 case N_TRIAND: strcpy(s, "wand"); break;
4994 case N_TRIREG: strcpy(s, "trireg"); break;
4995 case N_WA: strcpy(s, "wand"); break;
4996 case N_WO: strcpy(s, "wor"); break;
4997 case N_SUPPLY0: strcpy(s, "supply0"); break;
4998 case N_SUPPLY1: strcpy(s, "supply1"); break;
4999 /* these need special syntax for declaration */
5000 case N_REG: strcpy(s, "reg"); break;
5001 case N_TIME: strcpy(s, "time"); break;
5002 case N_INT: strcpy(s, "integer"); break;
5003 case N_REAL: strcpy(s, "real"); break;
5004 case N_EVENT: strcpy(s, "event"); break;
5005 default: __case_terr(__FILE__, __LINE__);
5006 }
5007 return(s);
5008 }
5009
5010 /*
5011 * convert an i/o port type to a name (use lower case for these)
5012 */
__to_ptnam(char * s,word32 ptyp)5013 extern char *__to_ptnam(char *s, word32 ptyp)
5014 {
5015 switch ((byte) ptyp) {
5016 case IO_IN: strcpy(s, "input"); break;
5017 case IO_OUT: strcpy(s, "output"); break;
5018 case IO_BID: strcpy(s, "inout"); break;
5019 case IO_UNKN: strcpy(s, "-unknown-"); break;
5020 case NON_IO: strcpy(s, "-non-io-"); break;
5021 default: __case_terr(__FILE__, __LINE__);
5022 }
5023 return(s);
5024 }
5025
5026 /*
5027 * convert a wire splitting type to scalared/vectored state
5028 */
__to_splt_nam(char * s,int32 sptyp)5029 extern char *__to_splt_nam(char *s, int32 sptyp)
5030 {
5031 if (sptyp == SPLT_SCAL) strcpy(s, "scalared");
5032 else if (sptyp == SPLT_VECT) strcpy(s, "vectored");
5033 else { __case_terr(__FILE__, __LINE__); strcpy(s,""); }
5034 return(s);
5035 }
5036
5037 /*
5038 * convert from a token type number to a strength symbolic constant
5039 * return NO_STREN on not a strength - checking must be elsewhere
5040 */
__fr_stren_nam(int32 ttyp)5041 extern word32 __fr_stren_nam(int32 ttyp)
5042 {
5043 switch ((byte) ttyp) {
5044 case HIGHZ0: case HIGHZ1: return(ST_HIGHZ);
5045 case SMALL: return(ST_SMALL);
5046 case MEDIUM: return(ST_MEDIUM);
5047 case WEAK0: case WEAK1: return(ST_WEAK);
5048 case LARGE: return(ST_LARGE);
5049 case PULL0: case PULL1: return(ST_PULL);
5050 case STRONG0: case STRONG1: return(ST_STRONG);
5051 case SUPPLY0: case SUPPLY1: return(ST_SUPPLY);
5052 }
5053 return(NO_STREN);
5054 }
5055
5056 /*
5057 * convert a strength pair to a name
5058 * use this to write cap strength
5059 */
__to_stren_nam(char * s,int32 stren1,int32 stren2)5060 extern char *__to_stren_nam(char *s, int32 stren1, int32 stren2)
5061 {
5062 char s1[RECLEN], s2[RECLEN];
5063
5064 if (__is_capstren(stren1))
5065 sprintf(s, "(%s)", __to1_stren_nam(s1, stren1, 2));
5066 else sprintf(s, "(%s, %s)", __to1_stren_nam(s1, stren1, 0),
5067 __to1_stren_nam(s2, stren2, 1));
5068 return(s);
5069 }
5070
5071 /*
5072 * convert a stval coded strength name
5073 * not for cap. strength
5074 * and notice value coded in 6 bits (i.e. no value in low 2 bits
5075 */
__to_stval_nam(char * s,word32 stval)5076 extern char *__to_stval_nam(char *s, word32 stval)
5077 {
5078 int32 st0, st1;
5079 char s1[RECLEN], s2[RECLEN];
5080
5081 st0 = (int32) (stval >> 3) & 7;
5082 st1 = (int32) (stval) & 7;
5083 sprintf(s, "(%s, %s)", __to1_stren_nam(s1, st0, 0),
5084 __to1_stren_nam(s2, st1, 1));
5085 return(s);
5086 }
5087
5088 /*
5089 * convert from a strength type and 0/1 value to a strength name
5090 * this is source driving strength - not net strength value
5091 */
__to1_stren_nam(char * s,int32 st,int32 st01dir)5092 extern char *__to1_stren_nam(char *s, int32 st, int32 st01dir)
5093 {
5094 switch ((byte) st) {
5095 case ST_HIGHZ: strcpy(s, "highz"); break;
5096 case ST_SMALL: strcpy(s, "small"); return(s);
5097 case ST_MEDIUM: strcpy(s, "medium"); return(s);
5098 case ST_WEAK: strcpy(s, "weak"); break;
5099 case ST_LARGE: strcpy(s, "large"); return(s);
5100 case ST_PULL: strcpy(s, "pull"); break;
5101 case ST_STRONG: strcpy(s, "strong"); break;
5102 case ST_SUPPLY: strcpy(s, "supply"); break;
5103 default: __case_terr(__FILE__, __LINE__);
5104 }
5105 if (st01dir == 0) strcat(s, "0");
5106 else if (st01dir == 1) strcat(s, "1");
5107 return(s);
5108 }
5109
5110 /*
5111 * return T if strength value is cap. strength
5112 */
__is_capstren(int32 st)5113 extern int32 __is_capstren(int32 st)
5114 {
5115 switch ((byte) st) {
5116 case ST_SMALL: case ST_MEDIUM: case ST_LARGE: return(TRUE);
5117 }
5118 return(FALSE);
5119 }
5120
5121 /*
5122 * convert from a capacitor size constant to a capacitor strength
5123 */
__fr_cap_size(int32 capsiz)5124 extern int32 __fr_cap_size(int32 capsiz)
5125 {
5126 int32 st;
5127
5128 switch ((byte) capsiz) {
5129 case CAP_NONE: st = ST_STRONG; break;
5130 case CAP_SMALL: st = ST_SMALL; break;
5131 case CAP_MED: st = ST_MEDIUM; break;
5132 case CAP_LARGE: st = ST_LARGE; break;
5133 default: st = ST_STRONG; __case_terr(__FILE__, __LINE__);
5134 }
5135 return(st);
5136 }
5137
5138 /*
5139 * convert to a capacitor size constant from a capacitor strength
5140 * must catch non cap size strength input before here
5141 */
__to_cap_size(int32 st)5142 extern word32 __to_cap_size(int32 st)
5143 {
5144 int32 capsiz;
5145
5146 switch ((byte) st) {
5147 case ST_STRONG: capsiz = CAP_NONE; break;
5148 case ST_SMALL: capsiz = CAP_SMALL; break;
5149 case ST_MEDIUM: capsiz = CAP_MED; break;
5150 case ST_LARGE: capsiz = CAP_LARGE; break;
5151 default: capsiz = CAP_NONE; __case_terr(__FILE__, __LINE__);
5152 }
5153 return(capsiz);
5154 }
5155
5156 /*
5157 * build a $display style 2 char strength string
5158 */
__to_dispst_str(char * s,word32 st)5159 extern char *__to_dispst_str(char *s, word32 st)
5160 {
5161 switch ((byte) st) {
5162 case ST_HIGHZ: strcpy(s, "Hi"); break;
5163 case ST_SMALL: strcpy(s, "Sm"); break;
5164 case ST_MEDIUM: strcpy(s, "Me"); break;
5165 case ST_WEAK: strcpy(s, "We"); break;
5166 case ST_LARGE: strcpy(s, "La"); break;
5167 case ST_PULL: strcpy(s, "Pu"); break;
5168 case ST_STRONG: strcpy(s, "St"); break;
5169 case ST_SUPPLY: strcpy(s, "Su"); break;
5170 default: __case_terr(__FILE__, __LINE__);
5171 }
5172 return(s);
5173 }
5174
5175 /*
5176 * build a symbol class name
5177 */
__to_sytyp(char * s,word32 styp)5178 extern char *__to_sytyp(char *s, word32 styp)
5179 {
5180 switch ((byte) styp) {
5181 case SYM_UNKN: strcpy(s, "--unknown--"); break;
5182 case SYM_I: strcpy(s, "instance"); break;
5183 case SYM_M: strcpy(s, "module"); break;
5184 case SYM_PRIM: strcpy(s, "primitive"); break;
5185 case SYM_UDP: strcpy(s, "udp define"); break;
5186 case SYM_N: strcpy(s, "variable"); break;
5187 case SYM_TSK: strcpy(s, "task"); break;
5188 case SYM_STSK: strcpy(s, "systask"); break;
5189 case SYM_LB: strcpy(s, "named block"); break;
5190 case SYM_F: strcpy(s, "function"); break;
5191 case SYM_SF: strcpy(s, "sysfunction"); break;
5192 case SYM_DEF: strcpy(s, "preprocessor `define"); break;
5193 case SYM_CA: strcpy(s, "continuous assign"); break;
5194 case SYM_PTH: strcpy(s, "delay path"); break;
5195 case SYM_TCHK: strcpy(s, "timing check"); break;
5196 default: __case_terr(__FILE__, __LINE__);
5197 }
5198 return(s);
5199 }
5200
5201 /*
5202 * build a task type name - tskt is token number
5203 */
__to_tsktyp(char * s,word32 tskt)5204 extern char *__to_tsktyp(char *s, word32 tskt)
5205 {
5206 switch ((byte) tskt) {
5207 case Begin: strcpy(s, "named begin"); break;
5208 case FORK: strcpy(s, "named fork"); break;
5209 case FUNCTION: strcpy(s, "function"); break;
5210 case TASK: strcpy(s, "task"); break;
5211 }
5212 return(s);
5213 }
5214
5215 /*
5216 * build a statement type name
5217 */
__to_sttyp(char * s,word32 sttyp)5218 extern char *__to_sttyp(char *s, word32 sttyp)
5219 {
5220 switch ((byte) sttyp) {
5221 case S_NULL: strcpy(s, "empty"); break;
5222 case S_STNONE: strcpy(s, "empty block"); break;
5223 case S_PROCA: strcpy(s, "proc. assign"); break;
5224 case S_FORASSGN: strcpy(s, "for initial assign"); break;
5225 case S_NBPROCA: strcpy(s, "non-blocking proc. assign"); break;
5226 case S_RHSDEPROCA: strcpy(s, "proc. assign (rhs delay/event)"); break;
5227 case S_IF: strcpy(s, "if"); break;
5228 case S_CASE: strcpy(s, "case/casex/casez"); break;
5229 case S_FOREVER: strcpy(s, "forever"); break;
5230 case S_REPEAT: strcpy(s, "repeat"); break;
5231 case S_WHILE: strcpy(s, "while"); break;
5232 case S_WAIT: strcpy(s, "wait"); break;
5233 case S_FOR : strcpy(s, "for loop"); break;
5234 case S_DELCTRL: strcpy(s, "delay control"); break;
5235 case S_NAMBLK : strcpy(s, "named block"); break;
5236 case S_UNBLK : strcpy(s, "unnamed block"); break;
5237 case S_UNFJ: strcpy(s, "parallel block"); break;
5238 case S_TSKCALL: strcpy(s, "task enable"); break;
5239 case S_QCONTA: strcpy(s, "quasi-continuous assign"); break;
5240 case S_QCONTDEA: strcpy(s, "quasi-continous deassign"); break;
5241 case S_CAUSE: strcpy(s, "cause"); break;
5242 case S_DSABLE: strcpy(s, "disable"); break;
5243 case S_REPSETUP: strcpy(s, "**added loop setup"); break;
5244 case S_REPDCSETUP: strcpy(s, "**added repeat event control setup"); break;
5245 case S_GOTO: strcpy(s, "**added goto"); break;
5246 default: __case_terr(__FILE__, __LINE__);
5247 }
5248 return(s);
5249 }
5250
5251 /*
5252 * build the quasi-continue statement type name
5253 */
__to_qctyp(char * s,word32 qctyp)5254 extern char *__to_qctyp(char *s, word32 qctyp)
5255 {
5256 switch ((byte) qctyp) {
5257 case FORCE: strcpy(s, "force"); break;
5258 case RELEASE: strcpy(s, "release"); break;
5259 case ASSIGN: strcpy(s, "assign"); break;
5260 case DEASSIGN: strcpy(s, "deassign"); break;
5261 default: __case_terr(__FILE__, __LINE__);
5262 }
5263 return(s);
5264 }
5265
5266 /*
5267 * build an event type name
5268 */
__to_tetyp(char * s,word32 tetyp)5269 extern char *__to_tetyp(char *s, word32 tetyp)
5270 {
5271 switch ((byte) tetyp) {
5272 case TE_THRD: strcpy(s, "procedural"); break;
5273 case TE_G: strcpy(s, "gate assign"); break;
5274 case TE_CA: strcpy(s, "conta assign"); break;
5275 case TE_WIRE: strcpy(s, "wire delay"); break;
5276 case TE_BIDPATH: strcpy(s, "inout path dest."); break;
5277 case TE_MIPD_NCHG: strcpy(s, "MIPD change"); break;
5278 case TE_NBPA: strcpy(s, "NB assign"); break;
5279 case TE_TFSETDEL: strcpy(s, "tf_ set delay"); break;
5280 case TE_SYNC: strcpy(s, "tf_ #0 synchronize"); break;
5281 case TE_TFPUTPDEL: strcpy(s, "tf_ delayed strputp"); break;
5282 case TE_VPIPUTVDEL: strcpy(s, "vpi_ put value"); break;
5283 case TE_VPIDRVDEL: strcpy(s, "vpi_ add drv. chg."); break;
5284 case TE_VPICBDEL: strcpy(s, "vpi_ delay cb"); break;
5285 case TE_UNKN:
5286 /*FALLTHRU */
5287 default:
5288 strcpy(s, "**UNKNOWN**");
5289 /* __case_terr(__FILE__, __LINE__); */
5290 }
5291 return(s);
5292 }
5293
5294 /*
5295 * build a net-pin connection/action type
5296 */
__to_npptyp(char * s,struct net_pin_t * npp)5297 extern char *__to_npptyp(char *s, struct net_pin_t *npp)
5298 {
5299 char s1[RECLEN];
5300
5301 switch ((byte) npp->npntyp) {
5302 case NP_ICONN: strcpy(s, "instance port"); break;
5303 case NP_PB_ICONN: strcpy(s, "instance per bit port"); break;
5304 case NP_MDPRT: strcpy(s, "module port"); break;
5305 case NP_PB_MDPRT: strcpy(s, "module per bit port"); break;
5306 case NP_MIPD_NCHG: strcpy(s, "MIPD input/inout port"); break;
5307 case NP_CONTA:
5308 if (npp->elnpp.ecap->ca_pb_sim) strcpy(s, "per bit cont. assign lvalue");
5309 else strcpy(s, "cont. assign lvalue"); break;
5310 break;
5311 case NP_TFRWARG: strcpy(s, "tf_ PLI rw arg wire driver"); break;
5312 case NP_VPIPUTV: strcpy(s, "vpi_put_value wire driver"); break;
5313 case NP_GATE: strcpy(s, "gate terminal"); break;
5314 case NP_TRANIF: strcpy(s, "tranif enable"); break;
5315 case NP_TCHG:
5316 sprintf(s, "bit change(%s)", __to_nppsubtyp(s1, npp->chgsubtyp));
5317 break;
5318 case NP_PULL: strcpy(s, "pull driver"); break;
5319 default: __case_terr(__FILE__, __LINE__);
5320 }
5321 return(s);
5322 }
5323
5324 /*
5325 * build the net change subtype name
5326 */
__to_nppsubtyp(char * s,word32 subtyp)5327 static char *__to_nppsubtyp(char *s, word32 subtyp)
5328 {
5329 switch ((byte) subtyp) {
5330 case NPCHG_TCSTART: strcpy(s, "tchk start ref."); break;
5331 case NPCHG_TCCHK: strcpy(s, "tchk data end"); break;
5332 case NPCHG_PTHSRC: strcpy(s, "path source"); break;
5333 default: __case_terr(__FILE__, __LINE__);
5334 }
5335 return(s);
5336 }
5337
5338 /*
5339 * build a delay type name string
5340 */
__to_deltypnam(char * s,word32 dtyp)5341 extern char *__to_deltypnam(char *s, word32 dtyp)
5342 {
5343 switch ((byte) dtyp) {
5344 case DT_NONE: strcpy(s, "?none?"); break;
5345 case DT_1V: strcpy(s, "one"); break;
5346 case DT_IS1V: case DT_IS1V1: case DT_IS1V2:
5347 strcpy(s, "one instance specific");
5348 break;
5349 case DT_4V: strcpy(s, "(r, f, toz)"); break;
5350 case DT_IS4V: case DT_IS4V1: case DT_IS4V2:
5351 strcpy(s, "(r, f, toz) instance specific");
5352 break;
5353 case DT_16V: strcpy(s, "path 2,3,6,12 value"); break;
5354 case DT_IS16V: case DT_IS16V1: case DT_IS16V2:
5355 strcpy(s, "path 2,3,6,12 value instance specific");
5356 break;
5357 case DT_1X: strcpy(s, "one non constant"); break;
5358 case DT_4X: strcpy(s, "(r, f, toz) non constant"); break;
5359 case DT_PTHDST: strcpy(s, "internal path descriptor non"); break;
5360 case DT_CMPLST: strcpy(s, "translation time expression list"); break;
5361 default: __case_terr(__FILE__, __LINE__);
5362 }
5363 return(s);
5364 }
5365
5366 /*
5367 * convert timing check type to name
5368 */
__to_tcnam(char * s,word32 tctyp)5369 extern char *__to_tcnam(char *s, word32 tctyp)
5370 {
5371 switch ((byte) tctyp) {
5372 case TCHK_SETUP: strcpy(s, "$setup"); break;
5373 case TCHK_HOLD: strcpy(s, "$hold"); break;
5374 case TCHK_WIDTH: strcpy(s, "$width"); break;
5375 case TCHK_PERIOD: strcpy(s, "$period"); break;
5376 case TCHK_SKEW: strcpy(s, "$skew"); break;
5377 case TCHK_RECOVERY: strcpy(s, "$recovery"); break;
5378 case TCHK_SETUPHOLD: strcpy(s, "$setuphold"); break;
5379 case TCHK_NOCHANGE: strcpy(s, "$nochange"); break;
5380 /* SJM 12/15/03 - new 2001 timing checks - if used not read with warn */
5381 case TCHK_FULLSKEW: strcpy(s, "$fullskew"); break;
5382 case TCHK_REMOVAL: strcpy(s, "$removal"); break;
5383 case TCHK_RECREM: strcpy(s, "$recrem"); break;
5384 case TCHK_TIMESKEW: strcpy(s, "$timeskew"); break;
5385 default: __case_terr(__FILE__, __LINE__);
5386 }
5387 return(s);
5388 }
5389
5390 /*
5391 * convert timing check name to type number - returns -1 if not found
5392 * expected the leading $
5393 */
__fr_tcnam(char * tcnam)5394 extern int32 __fr_tcnam(char *tcnam)
5395 {
5396 if (*tcnam != '$') return(-1);
5397 switch (tcnam[1]) {
5398 case 'f':
5399 if (strcmp(&(tcnam[2]), "ullskew") == 0) return(TCHK_FULLSKEW);
5400 break;
5401 case 'h': if (strcmp(&(tcnam[2]), "old") == 0) return(TCHK_HOLD); break;
5402 case 'n':
5403 if (strcmp(&(tcnam[2]), "ochange") == 0) return(TCHK_NOCHANGE); break;
5404 case 'p': if (strcmp(&(tcnam[2]), "eriod") == 0) return(TCHK_PERIOD); break;
5405 case 'r':
5406 /* SJM - 11/21/03 - must also recognize recrem */
5407 if (strcmp(&(tcnam[2]), "ecovery") == 0) return(TCHK_RECOVERY);
5408 if (strcmp(&(tcnam[2]), "ecrem") == 0) return(TCHK_RECREM);
5409 if (strcmp(&(tcnam[2]), "emoval") == 0) return(TCHK_REMOVAL);
5410 break;
5411 case 's':
5412 if (tcnam[2] == 'k')
5413 { if (strcmp(&(tcnam[3]), "ew") == 0) return(TCHK_SKEW); break; }
5414 else if (strcmp(&(tcnam[2]), "etuphold") == 0) return(TCHK_SETUPHOLD);
5415 else if (strcmp(&(tcnam[2]), "etup") == 0) return(TCHK_SETUP);
5416 break;
5417 case 't':
5418 if (strcmp(&(tcnam[2]), "imeskew") == 0) return(TCHK_TIMESKEW);
5419 break;
5420 case 'w': if (strcmp(&(tcnam[2]), "idth") == 0) return(TCHK_WIDTH); break;
5421 }
5422 return(-1);
5423 }
5424
5425 /*
5426 * output a number that is decomposed from input token but not yet converted
5427 * to value for errors during input number processing
5428 */
decompnum_to_str(char * s,char * digs,int32 base,int32 width)5429 static char *decompnum_to_str(char *s, char *digs, int32 base, int32 width)
5430 {
5431 sprintf(s, "%d'%c%s", width, __to_baselet(base), digs);
5432 return(s);
5433 }
5434
5435 /*
5436 * convert gate output value to printable
5437 * tricky because depending on gate class and stval may or may not need stren
5438 */
__to_gonam(char * s,struct gate_t * gp,word32 v)5439 extern char *__to_gonam(char *s, struct gate_t *gp, word32 v)
5440 {
5441 switch ((byte) gp->g_class) {
5442 case GC_LOGIC: case GC_UDP:
5443 if (gp->g_hasst)
5444 {
5445 if (v != 2) v |= (gp->g_stval << 2);
5446 __to_vvstnam(s, (word32) __stren_map_tab[v]);
5447 }
5448 else __to_vvnam(s, (word32) v);
5449 break;
5450 case GC_TRANIF:
5451 /* here gate "output" is conducting state */
5452 if (v == 0) strcpy(s, "*OFF*");
5453 else if (v == 1) strcpy(s, "*ON*");
5454 else if (v == 3) strcpy(s, "*UNKNOWN*");
5455 else __misc_terr(__FILE__, __LINE__);
5456 break;
5457 case GC_TRAN: case GC_PULL:
5458 __case_terr(__FILE__, __LINE__); strcpy(s, "");
5459 /* mos and bufif outputs always strength */
5460 default: __to_vvstnam(s, (word32) v);
5461 }
5462 return(s);
5463 }
5464
5465 /*
5466 * convert gate value to printable
5467 * tricky because depending on gate class and stval may or may not need stren
5468 */
__to_ginam(char * s,struct gate_t * gp,word32 v,int32 i)5469 extern char *__to_ginam(char *s, struct gate_t *gp, word32 v, int32 i)
5470 {
5471 switch ((byte) gp->g_class) {
5472 /* bufif inputs non stength even though drives strength */
5473 /* tranif 3rd input non strength and value not just on/off */
5474 case GC_LOGIC: case GC_UDP: case GC_BUFIF: case GC_TRANIF:
5475 __to_vvnam(s, (word32) v);
5476 break;
5477 /* mos input 1 strength (added if needed) but control input non stren */
5478 case GC_MOS: case GC_CMOS:
5479 /* only 1st mos or cmos input has strength not control(s) */
5480 if (i == 1) __to_vvstnam(s, (word32) v); else __to_vvnam(s, (word32) v);
5481 break;
5482 /* tran and pull cannot use this routine */
5483 default: __case_terr(__FILE__, __LINE__);
5484 }
5485 return(s);
5486 }
5487
5488 /*
5489 * convert net value to printable
5490 */
__to_vnam(char * s,word32 is_stren,word32 v)5491 extern char *__to_vnam(char *s, word32 is_stren, word32 v)
5492 {
5493 if (is_stren) __to_vvstnam(s, (word32) v); else __to_vvnam(s, (word32) v);
5494 return(s);
5495 }
5496
5497 /*
5498 * convert a strength value to a 3 letter name string
5499 * know always 3 characters
5500 *
5501 * SJM 08/16/01 - BEWARE this routine must not be changed because it is
5502 * only way debug switch determines if mistake in table or algorithm
5503 * has caused one of the illegal 129 stren values to be created
5504 * algorithms do something slightly and undectably wrong if this happens
5505 */
__to_vvstnam(char * s,word32 stval)5506 extern char *__to_vvstnam(char *s, word32 stval)
5507 {
5508 word32 st0, st1;
5509 byte val;
5510 char ch;
5511
5512 /* decode stren byte */
5513 val = (byte) stval & 3;
5514 st0 = (stval >> 5) & 7;
5515 st1 = (stval >> 2) & 7;
5516
5517 switch (val) {
5518 case 0: ch = '0'; break;
5519 case 1: ch = '1'; break;
5520 case 2:
5521 /* real HiZ */
5522 if (st0 != 0 || st1 != 0)__misc_terr(__FILE__, __LINE__);
5523 strcpy(s, "HiZ");
5524 return(s);
5525 case 3:
5526 /* this should be Z not X */
5527 if (st0 == 0 && st1 == 0) __misc_terr(__FILE__, __LINE__);
5528
5529 /* z with hiz 0 strength component is H */
5530 if (st0 == 0) { __to_dispst_str(s, st1); s[2] = 'H'; s[3] = '\0'; }
5531 /* z with hiz 1 strength component is L */
5532 else if (st1 == 0) { __to_dispst_str(s, st0); s[2] = 'L'; s[3] = '\0'; }
5533 else { ch = 'X'; break; }
5534 return(s);
5535 default: __case_terr(__FILE__, __LINE__); return(NULL);
5536 }
5537
5538 /* finally known case strength is range with value */
5539 /* notice strength letters always 2 chars */
5540 if (st0 == st1)
5541 {
5542 /* DBG remove --- */
5543 /* for normal value strength cannot both be 0 */
5544 if (st0 == 0) __misc_terr(__FILE__, __LINE__);
5545 /* --- */
5546 __to_dispst_str(s, st0);
5547 s[2] = ch;
5548 }
5549 else { s[0] = '0' + st0; s[1] = '0' + st1; s[2] = ch; }
5550 s[3] = '\0';
5551 return(s);
5552 }
5553
5554 /*
5555 * convert a 2 bit number to its verilog value name
5556 */
__to_vvnam(char * s,word32 v)5557 extern char *__to_vvnam(char *s, word32 v)
5558 {
5559 switch ((byte) v) {
5560 case 0: strcpy(s, "0"); break;
5561 case 1: strcpy(s, "1"); break;
5562 case 2: strcpy(s, "z"); break;
5563 case 3: default: strcpy(s, "x"); break;
5564 }
5565 return(s);
5566 }
5567
5568 /* same but for udp 3-values */
__to_uvvnam(char * s,word32 v)5569 extern char *__to_uvvnam(char *s, word32 v)
5570 {
5571 switch ((byte) v) {
5572 case 0: strcpy(s, "0"); break;
5573 case 1: strcpy(s, "1"); break;
5574 default: strcpy(s, "x"); break;
5575 }
5576 return(s);
5577 }
5578
5579 /*
5580 * convert base code to letter
5581 */
__to_baselet(int32 bcod)5582 extern char __to_baselet(int32 bcod)
5583 {
5584 char ch;
5585
5586 switch ((byte) bcod) {
5587 case BBIN: ch = 'b'; break;
5588 case BHEX: ch = 'h'; break;
5589 case BOCT: ch = 'o'; break;
5590 case BDEC: ch = 'd'; break;
5591 default: ch = '?'; __case_terr(__FILE__, __LINE__);
5592 }
5593 return(ch);
5594 }
5595
5596 /*
5597 * convert time unit string (0-15) code to time unit name
5598 */
__to_timunitnam(char * s,word32 unit)5599 extern char *__to_timunitnam(char *s, word32 unit)
5600 {
5601 switch ((byte) unit) {
5602 case 0: strcpy(s, "1 s"); break;
5603 case 1: strcpy(s, "100 ms"); break;
5604 case 2: strcpy(s, "10 ms"); break;
5605 case 3: strcpy(s, "1 ms"); break;
5606 case 4: strcpy(s, "100 us"); break;
5607 case 5: strcpy(s, "10 us"); break;
5608 case 6: strcpy(s, "1 us"); break;
5609 case 7: strcpy(s, "100 ns"); break;
5610 case 8: strcpy(s, "10 ns"); break;
5611 case 9: strcpy(s, "1 ns"); break;
5612 case 10: strcpy(s, "100 ps"); break;
5613 case 11: strcpy(s, "10 ps"); break;
5614 case 12: strcpy(s, "1 ps"); break;
5615 case 13: strcpy(s, "100 fs"); break;
5616 case 14: strcpy(s, "10 fs"); break;
5617 case 15: strcpy(s, "1 fs"); break;
5618 default: __case_terr(__FILE__, __LINE__);
5619 }
5620 return(s);
5621 }
5622
5623 /*
5624 * convert an edge bit byte into an edge name string
5625 * if posedge or negedge use name else use [...] form
5626 */
__to_edgenam(char * s,word32 eval)5627 extern char *__to_edgenam(char *s, word32 eval)
5628 {
5629 int32 first_time;
5630 byte ebyte;
5631
5632 switch ((ebyte = (byte) eval)) {
5633 case E_POSEDGE: strcpy(s, "posedge"); break;
5634 case E_NEGEDGE: strcpy(s, "negedge"); break;
5635 case NOEDGE: strcpy(s, ""); break;
5636 default:
5637 strcpy(s, "edge[");
5638 first_time = TRUE;
5639 if ((ebyte & EDGE01) != 0)
5640 {
5641 if (first_time) first_time = FALSE; else strcat(s, ", ");
5642 strcat(s, "01");
5643 }
5644 if ((ebyte & EDGE10) != 0)
5645 {
5646 if (first_time) first_time = FALSE; else strcat(s, ", ");
5647 strcat(s, "10");
5648 }
5649 if ((ebyte & EDGE0X) != 0)
5650 {
5651 if (first_time) first_time = FALSE; else strcat(s, ", ");
5652 strcat(s, "0x");
5653 }
5654 if ((ebyte & EDGEX1) != 0)
5655 {
5656 if (first_time) first_time = FALSE; else strcat(s, ", ");
5657 strcat(s, "x1");
5658 }
5659 if ((ebyte & EDGE1X) != 0)
5660 {
5661 if (first_time) first_time = FALSE; else strcat(s, ", ");
5662 strcat(s, "1x");
5663 }
5664 if ((ebyte & EDGEX0) != 0)
5665 {
5666 if (first_time) first_time = FALSE; else strcat(s, ", ");
5667 strcat(s, "x0");
5668 }
5669 strcat(s, "]");
5670 }
5671 return(s);
5672 }
5673
5674 /*
5675 * convert an delay control type to a name
5676 */
__to_dcenam(char * s,word32 dctyp)5677 extern char *__to_dcenam(char *s, word32 dctyp)
5678 {
5679 switch ((byte) dctyp) {
5680 case DC_NONE: strcpy(s, "**NONE?**"); break;
5681 case DC_EVENT: strcpy(s,"event"); break;
5682 case DC_DELAY: strcpy(s, "delay"); break;
5683 case DC_RHSEVENT:strcpy(s,"rhs event"); break;
5684 case DC_RHSDELAY:strcpy(s, "rhs delay"); break;
5685 case DC_WAITEVENT: strcpy(s,"wait event"); break;
5686 default: __case_terr(__FILE__, __LINE__);
5687 }
5688 return(s);
5689 }
5690
5691 /*
5692 * SPECIAL MEMORY ALLOCATION ROUTINES
5693 * USES OWN STRUCT AND CONSTANTS BELOW
5694 */
5695
5696 /*
5697 * allocate a string for use during elaboration - adds the ending \0
5698 * this must allocate the 1 char null string for `define as flag
5699 */
__pv_stralloc(char * s)5700 extern char *__pv_stralloc(char *s)
5701 {
5702 char *cp;
5703 int32 slen;
5704
5705 if (*s == '\0') slen = 1; else slen = strlen(s) + 1;
5706 cp = __my_malloc(slen);
5707 __memstr_use += slen;
5708 /* this just copies '\0' for "" case */
5709 strcpy(cp, s);
5710 return(cp);
5711 }
5712
5713 /*
5714 * memory allocator for non freed memory
5715 * and allocate small piece from a large allocated block
5716 * aligns on 4 byte boundaries for VAX and 68000 too
5717 * notice this is 32 bit word32 dependent
5718 *
5719 * could save space in pc by allocating only on bytes but would need always
5720 * at least 4 bytes - no since now using free by size header table
5721 */
nfbig_alloc(int32 size)5722 static char *nfbig_alloc(int32 size)
5723 {
5724 char *cp;
5725 int32 rem, real_size;
5726
5727 if ((rem = size % 4) != 0) real_size = size + 4 - rem;
5728 else real_size = size;
5729
5730 if ((__start_sp + real_size + 4) >= __end_sp)
5731 {
5732 __start_sp = __my_malloc(BIG_ALLOC_SIZE);
5733 __end_sp = __start_sp + BIG_ALLOC_SIZE - 16;
5734 }
5735 cp = __start_sp;
5736 __start_sp += real_size;
5737 return(cp);
5738 }
5739
5740 /*
5741 * call to malloc that dies if no memory available
5742 * these are normal OS memory allocation with error terminaton
5743 */
__my_malloc(int32 size)5744 extern char *__my_malloc(int32 size)
5745 {
5746 char *cp;
5747
5748 /* DBG remove --- */
5749 if (size <= 0) __arg_terr(__FILE__, __LINE__);
5750 /* --- */
5751
5752 if ((cp = (char *) malloc((word32) size)) == NULL)
5753 {
5754 __sysfatal_msg(
5755 "**fatal err[1]: No more memory - at file %s line %d allocated %ld bytes\n",
5756 __cur_fnam, __lin_cnt, __mem_use);
5757 __my_exit(4, TRUE);
5758 }
5759 __mem_use += size;
5760 __mem_allocated += size;
5761 /* DBG remove ---
5762 if (__debug_flg) __dbg_msg("my_malloc - allocated %d bytes - use %ld\n",
5763 size, __mem_use);
5764 --- */
5765 return(cp);
5766 }
5767
5768 /*
5769 * call to free
5770 */
__my_free(char * mp,int32 size)5771 extern void __my_free(char *mp, int32 size)
5772 {
5773 /* DBG remove --- */
5774 if (size <= 0) return;
5775 /* --- */
5776 free(mp);
5777 __mem_use -= size;
5778 __mem_freed += size;
5779 /* DBG remove ---
5780 if (__debug_flg) __dbg_msg("freeing %d bytes - memuse now %ld\n", size,
5781 __mem_use);
5782 --- */
5783 }
5784
5785 /*
5786 * interface to system realloc()
5787 * can only call with malloced mp or cannot realloc
5788 */
__my_realloc(char * mp,int32 osize,int32 nsize)5789 extern char *__my_realloc(char *mp, int32 osize, int32 nsize)
5790 {
5791 char *cp;
5792
5793 if ((cp = (char *) realloc(mp, (word32) nsize)) == NULL)
5794 {
5795 __sysfatal_msg(
5796 "**fatal err[1]: realloc failed - allocated %ld bytes\n", __mem_use);
5797 __my_exit(4, TRUE);
5798 }
5799 /* DBG remove ---
5800 if (__debug_flg)
5801 __dbg_msg("realloc: freeing %d byte and allocating %d bytes\n",
5802 osize, nsize);
5803 --- */
5804 __mem_use -= osize;
5805 __mem_use += nsize;
5806 return(cp);
5807 }
5808
5809 /*
5810 * INTERFACE TO OS ROUTINES
5811 */
5812
5813 /*
5814 * version of fclose that ends with fatal error if cannot close
5815 * some unixes do not return anything on fclose failure
5816 */
__my_fclose(FILE * f)5817 extern void __my_fclose(FILE *f)
5818 {
5819 if (f == NULL) __misc_terr(__FILE__, __LINE__);
5820 if (fclose(f) == EOF)
5821 {
5822 __crit_msg("**fatal err[1]: OS fclose failed: %s\n", strerror(errno));
5823 __my_exit(5, TRUE);
5824 }
5825 }
5826
5827
5828 /*
5829 * version of fd close that ends with fatal error if cannot close
5830 * some unixes do not return anything on close failure
5831 */
__my_close(int32 fd)5832 extern void __my_close(int32 fd)
5833 {
5834 if (fd == -1) __misc_terr(__FILE__, __LINE__);
5835 if (close(fd) == -1)
5836 {
5837 __crit_msg("**fatal err[1]: OS fclose failed: %s\n", strerror(errno));
5838 __my_exit(5, TRUE);
5839 }
5840 }
5841
5842 /*
5843 * interface to system rewind routine
5844 */
__my_rewind(FILE * f)5845 extern void __my_rewind(FILE *f)
5846 {
5847 if (fseek(f, 0L, 0) == -1)
5848 {
5849 __crit_msg("**fatal err[1]: OS rewind failed: %s\n", strerror(errno));
5850 __my_exit(5, TRUE);
5851 }
5852 }
5853
5854 /*
5855 * version of unbuffered open that performs tilde expansion
5856 * FIXME - should allow ~[dir] form and look at some network directory
5857 * and allow ~ anywhere in path name
5858 */
__tilde_open(char * pthnam,int32 opmask)5859 extern int32 __tilde_open(char *pthnam, int32 opmask)
5860 {
5861 int32 newlen;
5862 char *chp;
5863 int32 fd;
5864
5865 if (*pthnam != '~') return(open(pthnam, opmask));
5866 if ((chp = tilde_expand(pthnam, &newlen)) == NULL) return(-1);
5867 fd = open(chp, opmask);
5868 __my_free(chp, newlen);
5869 return(fd);
5870 }
5871
5872 /*
5873 * open with expand of leading tilde in file name using home
5874 */
__tilde_fopen(char * pthnam,char * opmod)5875 extern FILE *__tilde_fopen(char *pthnam, char *opmod)
5876 {
5877 int32 newlen;
5878 char *chp;
5879 FILE *f;
5880
5881 if (*pthnam != '~') return(__my_fopen(pthnam, opmod));
5882 if ((chp = tilde_expand(pthnam, &newlen)) == NULL) return(NULL);
5883 f = __my_fopen(chp, opmod);
5884 __my_free(chp, newlen);
5885 return(f);
5886 }
5887
5888 /*
5889 * perform prefix tilde expansion
5890 * only called if path starts with tilde
5891 * notice for now silently returns
5892 *
5893 * LOOKATME could allow /~/ component anywhere in path name for net addrs?
5894 */
tilde_expand(char * pthnam,int32 * newlen)5895 static char *tilde_expand(char *pthnam, int32 *newlen)
5896 {
5897 char *chp, *chp2;
5898 int32 hlen, plen;
5899 char usernam[RECLEN];
5900
5901 /* first ~/ form */
5902 if (pthnam[1] == '/') { chp2 = __pv_homedir; goto bld_expanded; }
5903
5904 /* ~[user] form - look up if possible */
5905 if ((chp = strchr(pthnam, '/')) == NULL) return(NULL);
5906 strncpy(usernam, &(pthnam[1]), chp - pthnam - 1);
5907 usernam[chp - pthnam - 1] = '\0';
5908 /* pathname now has / prefix but ~[name] removed */
5909 pthnam = chp - 1;
5910
5911 /* if do not know system, assume vanilla non networked BSD unix */
5912 {
5913 struct passwd *pwp;
5914
5915 if ((pwp = getpwnam(usernam)) == NULL) return(NULL);
5916 chp2 = pwp->pw_dir;
5917 }
5918 goto bld_expanded;
5919
5920 bld_expanded:
5921 /* know home dir does not have ending / and . if HOMEDIR not set */
5922 hlen = strlen(chp2);
5923 plen = strlen(pthnam);
5924 *newlen = hlen - 1 + plen + 1;
5925 chp = __my_malloc(*newlen);
5926 strcpy(chp, chp2);
5927 strcpy(&(chp[hlen]), &(pthnam[1]));
5928 return(chp);
5929 }
5930
5931 /*
5932 * unbuffered creat for writing with expand leading tilde in file name using
5933 */
__tilde_creat(char * pthnam)5934 extern int32 __tilde_creat(char *pthnam)
5935 {
5936 int32 newlen;
5937 char *chp;
5938 int32 fd;
5939
5940 if (*pthnam != '~') return(__my_creat(pthnam));
5941 if ((chp = tilde_expand(pthnam, &newlen)) == NULL) return(-1);
5942 fd = __my_creat(chp);
5943 __my_free(chp, newlen);
5944 return(fd);
5945 }
5946
5947 /*
5948 * version of open that returns NULL when directory opened
5949 * unix allows opening directories for reading
5950 */
__my_fopen(char * fnam,char * opmod)5951 extern FILE *__my_fopen(char *fnam, char *opmod)
5952 {
5953 FILE *f;
5954 struct stat sbuf;
5955
5956 if ((f = fopen(fnam, opmod)) == NULL) return(NULL);
5957 if (fstat(fileno(f), &sbuf) == -1)
5958 {
5959 __crit_msg("**fatal err[1]: OS file stat operation failed: %s\n",
5960 strerror(errno));
5961 __my_exit(5, TRUE);
5962 }
5963 /* anything but directory is ok */
5964 if ((S_IFDIR & sbuf.st_mode) == 0) return(f);
5965
5966 /* ---
5967 __inform(417, "open failed because %s is directory or special file", fnam);
5968 --- */
5969 __my_fclose(f);
5970 return(NULL);
5971 }
5972
5973 /*
5974 * version of non buffered creat that returns -1 when directory opened
5975 * unix allows opening directories for reading
5976 */
__my_creat(char * fnam)5977 extern int32 __my_creat(char *fnam)
5978 {
5979 int32 fd;
5980 struct stat sbuf;
5981
5982 if ((fd = creat(fnam, 0666)) == -1) return(-1);
5983 if (fstat(fd, &sbuf) == -1)
5984 {
5985 __crit_msg("**fatal err[1]: OS file stat operation failed: %s\n",
5986 strerror(errno));
5987 __my_exit(5, TRUE);
5988 }
5989 /* anything but directory is ok */
5990 if ((S_IFDIR & sbuf.st_mode) == 0) return(fd);
5991
5992 /* ---
5993 __inform(417, "open failed because %s is directory or special file", fnam);
5994 --- */
5995 close(fd);
5996 return(-1);
5997 }
5998
5999 /*
6000 * routine to truncate (chop) a string for output
6001 * one constant per run value for ID string chopped length
6002 * notice this always copies
6003 */
__schop(char * s1,char * s2)6004 extern char *__schop(char *s1, char *s2)
6005 {
6006 int32 slen, sendi;
6007
6008 slen = strlen(s2);
6009 if (slen < (sendi = MSGTRUNCLEN - 4)) strcpy(s1, s2);
6010 else { strncpy(s1, s2, sendi); strcpy(&s1[sendi], "..."); }
6011 return(s1);
6012 }
6013
6014 /*
6015 * build a **<file>(<line. no.) reference
6016 * this chops file name so know will fit
6017 * s must be RECLEN wide
6018 */
__bld_lineloc(char * s,word32 fnind,int32 fnlcnt)6019 extern char *__bld_lineloc(char *s, word32 fnind, int32 fnlcnt)
6020 {
6021 char s1[RECLEN];
6022
6023 sprintf(s, "**%s(%d)", __schop(s1, __in_fils[fnind]), fnlcnt);
6024 return(s);
6025 }
6026
6027 /*
6028 * MESSAGE ROUTINES
6029 */
6030
6031 /*
6032 * intellectual property (IP) message unsuppressable except by special simctrlb
6033 * IP messages suppression also stops log
6034 */
6035 /*VARARGS*/
__ip_msg(char * s,...)6036 extern void __ip_msg(char *s, ...)
6037 {
6038 va_list va, va2;
6039
6040 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6041 va_start(va, s);
6042 va_start(va2, s);
6043 vfprintf(stdout, s, va);
6044 if (__log_s != NULL) vfprintf(__log_s, s, va2);
6045 va_end(va);
6046 va_end(va2);
6047 }
6048
6049 /*
6050 * intellectual property (IP) message
6051 *
6052 * suppressable before customer1 cb if -q flag
6053 * IP messages suppression also stops log
6054 */
6055 /*VARARGS*/
__ip2_msg(char * s,...)6056 extern void __ip2_msg(char *s, ...)
6057 {
6058 va_list va, va2;
6059
6060 if (__quiet_msgs) return;
6061
6062 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6063 va_start(va, s);
6064 va_start(va2, s);
6065 vfprintf(stdout, s, va);
6066 if (__log_s != NULL) vfprintf(__log_s, s, va2);
6067 va_end(va);
6068 va_end(va2);
6069 }
6070
6071 /*
6072 * critical Copyright, licensing, OS failure, malloc failure etc.
6073 * never suppressed
6074 */
6075 /*VARARGS*/
__crit_msg(char * s,...)6076 extern void __crit_msg(char *s, ...)
6077 {
6078 va_list va, va2;
6079
6080
6081 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6082 va_start(va, s);
6083 va_start(va2, s);
6084 vfprintf(stdout, s, va);
6085 if (__log_s != NULL) vfprintf(__log_s, s, va2);
6086 va_end(va);
6087 va_end(va2);
6088 }
6089
6090 /*
6091 * never suppressed special OS failure (can't call malloc or os calls)
6092 * vendor 1 must detect -4 (inverse of vpi vpiSystem error level)
6093 * BEWARE - this can't call system or malloc
6094 */
6095 /*VARARGS*/
__sysfatal_msg(char * s,...)6096 extern void __sysfatal_msg(char *s, ...)
6097 {
6098 va_list va, va2;
6099
6100
6101 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6102 va_start(va, s);
6103 va_start(va2, s);
6104 vfprintf(stdout, s, va);
6105 if (__log_s != NULL) vfprintf(__log_s, s, va2);
6106 va_end(va);
6107 va_end(va2);
6108 }
6109
6110 /*
6111 * all normal (supressable with -q) messages
6112 * Cver progress, -d, status options
6113 */
6114 /*VARARGS*/
__cv_msg(char * s,...)6115 extern void __cv_msg(char *s, ...)
6116 {
6117 va_list va, va2;
6118
6119 if (__quiet_msgs) return;
6120
6121 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6122 va_start(va, s);
6123 va_start(va2, s);
6124 vfprintf(stdout, s, va);
6125 if (__log_s != NULL) vfprintf(__log_s, s, va2);
6126 va_end(va);
6127 va_end(va2);
6128 }
6129
6130 /*
6131 * cver simulation output messages (from system tasks such as $showvars)
6132 * version 1 to both stdout and log file
6133 *
6134 * also all debugger output since interchangeable with system tasks
6135 * never suppressed
6136 */
6137 /*VARARGS*/
__cvsim_msg(char * s,...)6138 extern void __cvsim_msg(char *s, ...)
6139 {
6140 va_list va, va2;
6141
6142 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6143 va_start(va, s);
6144 va_start(va2, s);
6145 vfprintf(stdout, s, va);
6146 if (__log_s != NULL) vfprintf(__log_s, s, va2);
6147 va_end(va);
6148 va_end(va2);
6149 }
6150
6151 /*
6152 * cver simulation output messages - * version 2 to just stdout
6153 */
6154 /*VARARGS*/
__cvsim2_msg(char * s,...)6155 extern void __cvsim2_msg(char *s, ...)
6156 {
6157 va_list va;
6158
6159 va_start(va, s);
6160 vfprintf(stdout, s, va);
6161 va_end(va);
6162 }
6163
6164 /*
6165 * cver simulation output messages
6166 * version 3 only to log file
6167 *
6168 * from system tasks such as $showvars and debugger output
6169 * never suppressed and log file not suppresable
6170 */
6171 /*VARARGS*/
__cvsim3_msg(char * s,...)6172 extern void __cvsim3_msg(char *s, ...)
6173 {
6174 va_list va;
6175
6176 va_start(va, s);
6177 if (__log_s != NULL) vfprintf(__log_s, s, va);
6178 va_end(va);
6179 }
6180
6181 /*
6182 * debugger (not debugger output) messages - not callback stopable
6183 * goes to both stdout and log file
6184 */
6185 /*VARARGS*/
__dbg_msg(char * s,...)6186 extern void __dbg_msg(char *s, ...)
6187 {
6188 va_list va;
6189 va_list va2;
6190
6191 va_start(va, s);
6192 va_start(va2, s);
6193 __my_vfprintf(stdout, s, va, va2);
6194 va_end(va2);
6195 va_end(va);
6196 }
6197
6198 /*
6199 * trace message printf - to trace file unless stdout (the default)
6200 * LOOATME - maybe should default trace file to verilog.trace
6201 */
6202 /*VARARGS*/
__tr_msg(char * s,...)6203 extern void __tr_msg(char *s, ...)
6204 {
6205 va_list va, va2;
6206
6207 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6208 va_start(va, s);
6209 va_start(va2, s);
6210 vfprintf(__tr_s, s, va);
6211 if (__tr_s == stdout && __log_s != NULL) vfprintf(__log_s, s, va2);
6212 va_end(va);
6213 va_end(va2);
6214 }
6215
6216 /*
6217 * ERROR MESSAGE ROUTINES
6218 */
6219
6220 /*
6221 * miscellaneous (most) internal fatal errors
6222 */
__misc_terr(char * fnam,int32 lno)6223 extern void __misc_terr(char *fnam, int32 lno)
6224 {
6225 /* SJM DBG REMOVE - malloc_chain_check(1); */
6226 if (lno == -1039)
6227 {
6228 __pv_terr(304,
6229 "cver.lic file or single job lock invalid or removed - run licprobe -lockcheck");
6230 }
6231 __pv_terr(303,
6232 "MISC INTERNAL - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
6233 fnam, lno, __cur_fnam, __lin_cnt, __in_fils[__sfnam_ind], __slin_cnt);
6234 }
6235
6236 /*
6237 * file miscellaneous (most) internal fatal errors (input file place known)
6238 */
__misc_fterr(char * fnam,int32 lno)6239 extern void __misc_fterr(char *fnam, int32 lno)
6240 {
6241 __fterr(303, "MISC INTERNAL - source line **%s(%d)", fnam, lno);
6242 }
6243
6244 /*
6245 * global analysis phase internal error - object provides line number
6246 */
__misc_gfterr(char * fnam,int32 lno,word32 gfnam_ind,int32 gflin_cnt)6247 extern void __misc_gfterr(char *fnam, int32 lno, word32 gfnam_ind,
6248 int32 gflin_cnt)
6249 {
6250 __gfterr(303, gfnam_ind, gflin_cnt,
6251 "MISC INTERNAL - source line **%s(%d)", fnam, lno);
6252 }
6253
6254 /*
6255 * non execution statement type error __sfnam_ind contains location
6256 */
__misc_sgfterr(char * fnam,int32 lno)6257 extern void __misc_sgfterr(char *fnam, int32 lno)
6258 {
6259 __gfterr(303, __sfnam_ind, __slin_cnt,
6260 "MISC INTERNAL - source lint **%s(%d)", fnam, lno);
6261 }
6262
6263 /*
6264 * simple case fatal error - can always find with debugger
6265 */
__case_terr(char * fnam,int32 lno)6266 extern void __case_terr(char *fnam, int32 lno)
6267 {
6268 __pv_terr(324,
6269 "CASE INTERNAL - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
6270 fnam, lno, __cur_fnam, __lin_cnt, __in_fils[__sfnam_ind], __slin_cnt);
6271 }
6272
6273 /*
6274 * simple argument passed to routine internal error
6275 */
__arg_terr(char * fnam,int32 lno)6276 extern void __arg_terr(char *fnam, int32 lno)
6277 {
6278 __pv_terr(322,
6279 "ARG INTERNAL - source line **%s(%d) - maybe at **%s(%d) or **%s(%d)",
6280 fnam, lno, __cur_fnam, __lin_cnt, __in_fils[__sfnam_ind], __slin_cnt);
6281 }
6282
6283 /*
6284 * error with fatal termination
6285 * arg s is a format specification string for sprintf
6286 *
6287 * notice error messages longer than 4k bytes will cause crash
6288 * caller of error routines must make sure no more than 4 ID called
6289 */
__pv_terr(int32 id_num,char * s,...)6290 extern void __pv_terr(int32 id_num, char *s, ...)
6291 {
6292 va_list va, va2, va3;
6293 int32 slen;
6294 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6295
6296 if (__vpierr_cb_active && !__iact_state)
6297 {
6298 /* reset in case user called sim control operation from wrong place */
6299 __errorcb_suppress_msg = FALSE;
6300
6301 sprintf(vpis1, "**FATAL ERROR** [%d] ", id_num);
6302 va_start(va, s);
6303 vsprintf(vpis2, s, va);
6304 va_end(va);
6305
6306 slen = strlen(vpis1) + strlen(vpis2) + 1;
6307 vpichp = __my_malloc(slen);
6308 strcpy(vpichp, vpis1);
6309 strcat(vpichp, vpis2);
6310
6311 __cberror_fill_einfo(FATAL, id_num, vpichp, "[NONE]", 0);
6312 __vpi_error_trycall();
6313
6314 __my_free(vpichp, slen);
6315 /* if vpi_ontrol used to suppress emsg, used up so turned off here */
6316 if (__errorcb_suppress_msg)
6317 { __errorcb_suppress_msg = FALSE; __my_exit(1, TRUE); }
6318 }
6319 __my_fprintf(stdout, "**FATAL ERROR** [%d] ", id_num);
6320
6321 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6322 va_start(va2, s);
6323 va_start(va3, s);
6324 __my_vfprintf(stdout, s, va2, va3);
6325 va_end(va2);
6326 va_end(va3);
6327 my_putc_('\n', stdout);
6328 __my_exit(1, TRUE);
6329 }
6330
6331 /*
6332 * vpi error with fatal termination and no error cb try call
6333 * arg s is a format specification string for sprintf
6334 *
6335 * notice error messages longer than 4k bytes will cause crash
6336 * caller of error routines must make sure no more than 4 ID called
6337 */
__pv_vpi_terr(int32 id_num,char * s,...)6338 extern void __pv_vpi_terr(int32 id_num, char *s, ...)
6339 {
6340 va_list va, va2, va3;
6341 int32 slen;
6342 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6343
6344 if (__vpierr_cb_active && !__iact_state)
6345 {
6346 /* reset in case user called sim control operation from wrong place */
6347 __errorcb_suppress_msg = FALSE;
6348
6349 sprintf(vpis1, "**FATAL ERROR** [%d] ", id_num);
6350 va_start(va, s);
6351 vsprintf(vpis2, s, va);
6352 va_end(va);
6353
6354 slen = strlen(vpis1) + strlen(vpis2) + 1;
6355 vpichp = __my_malloc(slen);
6356 strcpy(vpichp, vpis1);
6357 strcat(vpichp, vpis2);
6358
6359 __my_free(vpichp, slen);
6360 /* if vpi_ontrol used to suppress emsg, used up so turned off here */
6361 if (__errorcb_suppress_msg)
6362 { __errorcb_suppress_msg = FALSE; __my_exit(1, TRUE); }
6363 }
6364 __my_fprintf(stdout, "**FATAL ERROR** [%d] ", id_num);
6365
6366 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6367 va_start(va2, s);
6368 va_start(va3, s);
6369 __my_vfprintf(stdout, s, va2, va3);
6370 va_end(va2);
6371 va_end(va3);
6372 my_putc_('\n', stdout);
6373 __my_exit(1, TRUE);
6374 }
6375
6376 /*
6377 * note ferr forms all take a variable prefix for acc_ and tf_ and debugger
6378 */
6379
6380 /*VARARGS*/
__fterr(int32 id_num,char * s,...)6381 extern void __fterr(int32 id_num, char *s, ...)
6382 {
6383 va_list va, va2, va3;
6384 int32 slen;
6385 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6386
6387 if (__vpierr_cb_active && !__iact_state)
6388 {
6389 /* reset in case user called sim control operation from wrong place */
6390 __errorcb_suppress_msg = FALSE;
6391
6392 sprintf(vpis1, "**%s(%d) FATAL ERROR** [%d] ", __cur_fnam,
6393 __lin_cnt, id_num);
6394 va_start(va, s);
6395 vsprintf(vpis2, s, va);
6396 va_end(va);
6397
6398 slen = strlen(vpis1) + strlen(vpis2) + 1;
6399 vpichp = __my_malloc(slen);
6400 strcpy(vpichp, vpis1);
6401 strcat(vpichp, vpis2);
6402
6403 __cberror_fill_einfo(FATAL, id_num, vpichp, __cur_fnam, __lin_cnt);
6404 __vpi_error_trycall();
6405
6406 __my_free(vpichp, slen);
6407 /* if vpi_control used to suppress emsg, used up so turned off here */
6408 if (__errorcb_suppress_msg)
6409 { __errorcb_suppress_msg = FALSE; __my_exit(2, TRUE); }
6410 }
6411
6412 __my_fprintf(stdout, "**%s(%d) FATAL ERROR** [%d] ", __cur_fnam,
6413 __lin_cnt, id_num);
6414
6415 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6416 va_start(va2, s);
6417 va_start(va3, s);
6418 __my_vfprintf(stdout, s, va2, va3);
6419 va_end(va2);
6420 va_end(va3);
6421 my_putc_('\n', stdout);
6422 __my_exit(2, TRUE);
6423 }
6424
6425 /*VARARGS*/
__sgfterr(int32 id_num,char * s,...)6426 extern void __sgfterr(int32 id_num, char *s, ...)
6427 {
6428 va_list va, va2, va3;
6429 int32 slen;
6430 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6431 char s1[RECLEN], s2[RECLEN];
6432
6433 if (__run_state == SS_SIM)
6434 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
6435 else strcpy(s1, "");
6436
6437 if (__vpierr_cb_active && !__iact_state)
6438 {
6439 /* reset in case user called sim control operation from wrong place */
6440 __errorcb_suppress_msg = FALSE;
6441
6442 sprintf(vpis1, "**%s(%d) FATAL ERROR**%s [%d] ", __in_fils[__sfnam_ind],
6443 __slin_cnt, s1, id_num);
6444 va_start(va, s);
6445 vsprintf(vpis2, s, va);
6446 va_end(va);
6447
6448 slen = strlen(vpis1) + strlen(vpis2) + 1;
6449 vpichp = __my_malloc(slen);
6450 strcpy(vpichp, vpis1);
6451 strcat(vpichp, vpis2);
6452
6453 __cberror_fill_einfo(FATAL, id_num, vpichp, __in_fils[__sfnam_ind],
6454 __slin_cnt);
6455 __vpi_error_trycall();
6456
6457 __my_free(vpichp, slen);
6458 /* if vpi_control used to suppress emsg, used up so turned off here */
6459 if (__errorcb_suppress_msg)
6460 { __errorcb_suppress_msg = FALSE; __my_exit(2, TRUE); }
6461 }
6462
6463 __my_fprintf(stdout, "**%s(%d) FATAL ERROR**%s [%d] ",
6464 __in_fils[__sfnam_ind], __slin_cnt, s1, id_num);
6465
6466 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6467 va_start(va2, s);
6468 va_start(va3, s);
6469 __my_vfprintf(stdout, s, va2, va3);
6470 va_end(va2);
6471 va_end(va3);
6472 my_putc_('\n', stdout);
6473 __my_exit(2, TRUE);
6474 }
6475
6476 /*VARARGS*/
__gfterr(int32 id_num,word32 gfnam_ind,int32 gflin_cnt,char * s,...)6477 extern void __gfterr(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
6478 char *s, ...)
6479 {
6480 va_list va, va2, va3;
6481 int32 slen;
6482 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6483 char s1[RECLEN], s2[RECLEN];
6484
6485 if (__run_state == SS_SIM)
6486 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
6487 else strcpy(s1, "");
6488
6489 if (__vpierr_cb_active && !__iact_state)
6490 {
6491 /* reset in case user called sim control operation from wrong place */
6492 __errorcb_suppress_msg = FALSE;
6493
6494 sprintf(vpis1, "**%s(%d) FATAL ERROR**%s [%d] ",
6495 __in_fils[gfnam_ind], gflin_cnt, s1, id_num);
6496 va_start(va, s);
6497 vsprintf(vpis2, s, va);
6498 va_end(va);
6499
6500 slen = strlen(vpis1) + strlen(vpis2) + 1;
6501 vpichp = __my_malloc(slen);
6502 strcpy(vpichp, vpis1);
6503 strcat(vpichp, vpis2);
6504
6505 __cberror_fill_einfo(FATAL, id_num, vpichp, __in_fils[gfnam_ind],
6506 gflin_cnt);
6507 __vpi_error_trycall();
6508
6509 __my_free(vpichp, slen);
6510 /* if vpi_control used to suppress emsg, used up so turned off here */
6511 if (__errorcb_suppress_msg)
6512 { __errorcb_suppress_msg = FALSE; __my_exit(2, TRUE); }
6513 }
6514
6515 __my_fprintf(stdout, "**%s(%d) FATAL ERROR**%s [%d] ",
6516 __in_fils[gfnam_ind], gflin_cnt, s1, id_num);
6517
6518 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6519 va_start(va2, s);
6520 va_start(va3, s);
6521 __my_vfprintf(stdout, s, va2, va3);
6522 va_end(va2);
6523 va_end(va3);
6524 my_putc_('\n', stdout);
6525 __my_exit(2, TRUE);
6526 }
6527
6528 /*
6529 * serious but non-fatal error
6530 */
6531 /*VARARGS*/
__pv_err(int32 id_num,char * s,...)6532 extern void __pv_err(int32 id_num, char *s, ...)
6533 {
6534 va_list va, va2, va3;
6535 int32 slen;
6536 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6537
6538 __pv_err_cnt++;
6539 if (!__no_errs)
6540 {
6541 if (__vpierr_cb_active && !__iact_state)
6542 {
6543 /* reset in case user called sim control operation from wrong place */
6544 __errorcb_suppress_msg = FALSE;
6545
6546 sprintf(vpis1, "** ERROR** [%d] ", id_num);
6547 va_start(va, s);
6548 vsprintf(vpis2, s, va);
6549 va_end(va);
6550
6551 slen = strlen(vpis1) + strlen(vpis2) + 1;
6552 vpichp = __my_malloc(slen);
6553 strcpy(vpichp, vpis1);
6554 strcat(vpichp, vpis2);
6555
6556 __cberror_fill_einfo(ERROR, id_num, vpichp, "[NONE]", 0);
6557 __vpi_error_trycall();
6558
6559 __my_free(vpichp, slen);
6560 /* if vpi_control used to suppress emsg, used up so turn off here */
6561 if (__errorcb_suppress_msg)
6562 { __errorcb_suppress_msg = FALSE; return; }
6563 }
6564 __my_fprintf(stdout, "** ERROR** [%d] ", id_num);
6565
6566 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6567 va_start(va2, s);
6568 va_start(va3, s);
6569 __my_vfprintf(stdout, s, va2, va3);
6570 va_end(va2);
6571 va_end(va3);
6572
6573 my_putc_('\n', stdout);
6574 }
6575 if (__run_state == SS_SIM)
6576 if ((__run_state == SS_COMP || __run_state == SS_LOAD)
6577 && __max_errors != 0 && __pv_err_cnt > __max_errors)
6578 __pv_terr(id_num, "maximum error count exceeded");
6579 }
6580
6581 /*VARARGS*/
__pv_ferr(int32 id_num,char * s,...)6582 extern void __pv_ferr(int32 id_num, char *s, ...)
6583 {
6584 va_list va, va2, va3;
6585 int32 slen;
6586 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6587
6588 __pv_err_cnt++;
6589 if (__iact_state)
6590 {
6591 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6592 va_start(va, s);
6593 va_start(va2, s);
6594 __via_err(id_num, s, va, va2);
6595 va_end(va);
6596 va_end(va2);
6597 return;
6598 }
6599
6600 if (!__no_errs)
6601 {
6602 if (__vpierr_cb_active)
6603 {
6604 /* reset in case user called sim control operation from wrong place */
6605 __errorcb_suppress_msg = FALSE;
6606
6607 sprintf(vpis1, "**%s(%d) ERROR** [%d] ", __cur_fnam, __lin_cnt, id_num);
6608 va_start(va, s);
6609 vsprintf(vpis2, s, va);
6610 va_end(va);
6611
6612 slen = strlen(vpis1) + strlen(vpis2) + 1;
6613 vpichp = __my_malloc(slen);
6614 strcpy(vpichp, vpis1);
6615 strcat(vpichp, vpis2);
6616
6617 __cberror_fill_einfo(ERROR, id_num, vpichp, __cur_fnam, __lin_cnt);
6618 __vpi_error_trycall();
6619
6620 __my_free(vpichp, slen);
6621 /* if vpi_control used to suppress emsg, used up so turn off here */
6622 if (__errorcb_suppress_msg)
6623 { __errorcb_suppress_msg = FALSE; return; }
6624 }
6625 __my_fprintf(stdout, "**%s(%d) ERROR** [%d] ", __cur_fnam, __lin_cnt,
6626 id_num);
6627
6628 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6629 va_start(va2, s);
6630 va_start(va3, s);
6631 __my_vfprintf(stdout, s, va2, va3);
6632 va_end(va2);
6633 va_end(va3);
6634 my_putc_('\n', stdout);
6635 }
6636 if ((__run_state == SS_COMP || __run_state == SS_LOAD)
6637 && __max_errors != 0 && __pv_err_cnt > __max_errors)
6638 __pv_terr(id_num, "maximum error count exceeded");
6639 }
6640
6641 /*VARARGS*/
__sgferr(int32 id_num,char * s,...)6642 extern void __sgferr(int32 id_num, char *s, ...)
6643 {
6644 va_list va, va2, va3;
6645 int32 slen;
6646 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6647 char s1[RECLEN], s2[RECLEN];
6648
6649 __pv_err_cnt++;
6650 if (!__no_errs)
6651 {
6652 if (__run_state == SS_SIM)
6653 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
6654 else strcpy(s1, "");
6655
6656 if (__vpierr_cb_active && !__iact_state)
6657 {
6658 /* reset in case user called sim control operation from wrong place */
6659 __errorcb_suppress_msg = FALSE;
6660
6661 sprintf(vpis1, "**%s(%d) ERROR**%s [%d] ", __in_fils[__sfnam_ind],
6662 __slin_cnt, s1, id_num);
6663 va_start(va, s);
6664 vsprintf(vpis2, s, va);
6665 va_end(va);
6666
6667 slen = strlen(vpis1) + strlen(vpis2) + 1;
6668 vpichp = __my_malloc(slen);
6669 strcpy(vpichp, vpis1);
6670 strcat(vpichp, vpis2);
6671
6672 __cberror_fill_einfo(ERROR, id_num, vpichp, __in_fils[__sfnam_ind],
6673 __slin_cnt);
6674 __vpi_error_trycall();
6675
6676 __my_free(vpichp, slen);
6677 /* if vpi_control used to suppress emsg, used up so turn off here */
6678 if (__errorcb_suppress_msg)
6679 { __errorcb_suppress_msg = FALSE; return; }
6680 }
6681
6682 __my_fprintf(stdout, "**%s(%d) ERROR**%s [%d] ", __in_fils[__sfnam_ind],
6683 __slin_cnt, s1, id_num);
6684
6685 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6686 va_start(va2, s);
6687 va_start(va3, s);
6688 __my_vfprintf(stdout, s, va2, va3);
6689 va_end(va2);
6690 va_end(va3);
6691 my_putc_('\n', stdout);
6692 }
6693 if ((__run_state == SS_COMP || __run_state == SS_LOAD)
6694 && __max_errors != 0 && __pv_err_cnt > __max_errors)
6695 __pv_terr(id_num, "maximum error count exceeded");
6696 }
6697
6698 /*VARARGS*/
__gferr(int32 id_num,word32 gfnam_ind,int32 gflin_cnt,char * s,...)6699 extern void __gferr(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
6700 char *s, ...)
6701 {
6702 va_list va, va2, va3;
6703 int32 slen;
6704 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6705 char s1[RECLEN], s2[RECLEN];
6706
6707 __pv_err_cnt++;
6708 if (!__no_errs)
6709 {
6710 if (__run_state == SS_SIM)
6711 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
6712 else strcpy(s1, "");
6713
6714 if (__vpierr_cb_active && !__iact_state)
6715 {
6716 /* reset in case user called sim control operation from wrong place */
6717 __errorcb_suppress_msg = FALSE;
6718
6719 sprintf(vpis1, "**%s(%d) ERROR**%s [%d] ", __in_fils[gfnam_ind],
6720 gflin_cnt, s1, id_num);
6721
6722 va_start(va, s);
6723 vsprintf(vpis2, s, va);
6724 va_end(va);
6725
6726 slen = strlen(vpis1) + strlen(vpis2) + 1;
6727 vpichp = __my_malloc(slen);
6728 strcpy(vpichp, vpis1);
6729 strcat(vpichp, vpis2);
6730
6731 __cberror_fill_einfo(ERROR, id_num, vpichp, __in_fils[gfnam_ind],
6732 gflin_cnt);
6733 __vpi_error_trycall();
6734
6735 __my_free(vpichp, slen);
6736 /* if vpi_control used to suppress emsg, used up so turn off here */
6737 if (__errorcb_suppress_msg)
6738 { __errorcb_suppress_msg = FALSE; return; }
6739 }
6740
6741 __my_fprintf(stdout, "**%s(%d) ERROR**%s [%d] ", __in_fils[gfnam_ind],
6742 gflin_cnt, s1, id_num);
6743
6744 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6745 va_start(va2, s);
6746 va_start(va3, s);
6747 __my_vfprintf(stdout, s, va2, va3);
6748 va_end(va2);
6749 va_end(va3);
6750 my_putc_('\n', stdout);
6751 }
6752 if ((__run_state == SS_COMP || __run_state == SS_LOAD)
6753 && __max_errors != 0 && __pv_err_cnt > __max_errors)
6754 __pv_terr(id_num, "maximum error count exceeded");
6755 }
6756
6757 /*
6758 * interactive command error
6759 * this output still goes to log file
6760 * notice this routine does not increment err number
6761 */
6762 /*VARARGS*/
__ia_err(int32 id_num,char * s,...)6763 extern void __ia_err(int32 id_num, char *s, ...)
6764 {
6765 va_list va, va2;
6766
6767 /* can suppress any interactive error */
6768 if (__em_suppr(id_num)) return;
6769
6770 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6771 va_start(va, s);
6772 va_start(va2, s);
6773 __via_err(id_num, s, va, va2);
6774 va_end(va);
6775 va_end(va2);
6776 }
6777
6778 /*VARARGS*/
__via_err(int32 id_num,char * s,va_list args,va_list args2)6779 extern void __via_err(int32 id_num, char *s, va_list args, va_list args2)
6780 {
6781 if (__cmd_s == NULL) __my_fprintf(stdout, "--CMD ERROR** [%d] ", id_num);
6782 else __my_fprintf(stdout, "--%s(%d) CMD ERROR** [%d] ", __cmd_fnam,
6783 __lin_cnt, id_num);
6784 __my_vfprintf(stdout, s, args, args2);
6785 my_putc_('\n', stdout);
6786 }
6787
6788 /*VARARGS*/
__pv_warn(int32 id_num,char * s,...)6789 extern void __pv_warn(int32 id_num, char *s, ...)
6790 {
6791 va_list va, va2, va3;
6792 int32 slen;
6793 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6794
6795 __pv_warn_cnt++;
6796 if (__no_warns || __em_suppr(id_num)) return;
6797
6798 if (__vpierr_cb_active && !__iact_state)
6799 {
6800 /* reset in case user called sim control operation from wrong place */
6801 __errorcb_suppress_msg = FALSE;
6802
6803 sprintf(vpis1,"** WARN** [%d] ", id_num);
6804 va_start(va, s);
6805 vsprintf(vpis2, s, va);
6806 va_end(va);
6807
6808 slen = strlen(vpis1) + strlen(vpis2) + 1;
6809 vpichp = __my_malloc(slen);
6810 strcpy(vpichp, vpis1);
6811 strcat(vpichp, vpis2);
6812
6813 __cberror_fill_einfo(WARN, id_num, vpichp, "[NONE]", 0);
6814 __vpi_error_trycall();
6815
6816 __my_free(vpichp, slen);
6817 /* if vpi_control used to suppress emsg, used up so turn off here */
6818 if (__errorcb_suppress_msg)
6819 { __errorcb_suppress_msg = FALSE; return; }
6820 }
6821
6822 __my_fprintf(stdout,"** WARN** [%d] ", id_num);
6823
6824 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6825 va_start(va2, s);
6826 va_start(va3, s);
6827 __my_vfprintf(stdout, s, va2, va3);
6828 va_end(va2);
6829 va_end(va3);
6830 my_putc_('\n', stdout);
6831 }
6832
6833 /*VARARGS*/
__pv_fwarn(int32 id_num,char * s,...)6834 extern void __pv_fwarn(int32 id_num, char *s, ...)
6835 {
6836 va_list va, va2, va3;
6837 int32 slen;
6838 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6839
6840 __pv_warn_cnt++;
6841 if (__no_warns || __em_suppr(id_num)) { va_end(va); return; }
6842
6843 if (__iact_state)
6844 {
6845 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6846 va_start(va, s);
6847 va_start(va2, s);
6848 __via_err(id_num, s, va, va2);
6849 va_end(va);
6850 va_end(va2);
6851 return;
6852 }
6853
6854 if (__vpierr_cb_active)
6855 {
6856 /* reset in case user called sim control operation from wrong place */
6857 __errorcb_suppress_msg = FALSE;
6858
6859 sprintf(vpis1, "**%s(%d) WARN** [%d] ", __cur_fnam, __lin_cnt, id_num);
6860 va_start(va, s);
6861 vsprintf(vpis2, s, va);
6862 va_end(va);
6863
6864 slen = strlen(vpis1) + strlen(vpis2) + 1;
6865 vpichp = __my_malloc(slen);
6866 strcpy(vpichp, vpis1);
6867 strcat(vpichp, vpis2);
6868
6869 __cberror_fill_einfo(WARN, id_num, vpichp, __cur_fnam, __lin_cnt);
6870 __vpi_error_trycall();
6871
6872 __my_free(vpichp, slen);
6873 /* if vpi_control used to suppress emsg, used up so turn off here */
6874 if (__errorcb_suppress_msg)
6875 { __errorcb_suppress_msg = FALSE; return; }
6876 }
6877
6878 __my_fprintf(stdout, "**%s(%d) WARN** [%d] ", __cur_fnam, __lin_cnt, id_num);
6879
6880 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6881 va_start(va2, s);
6882 va_start(va3, s);
6883 __my_vfprintf(stdout, s, va2, va3);
6884 va_end(va2);
6885 va_end(va3);
6886 my_putc_('\n', stdout);
6887 }
6888
6889 /*VARARGS*/
__sgfwarn(int32 id_num,char * s,...)6890 extern void __sgfwarn(int32 id_num, char *s, ...)
6891 {
6892 va_list va, va2, va3;
6893 int32 slen;
6894 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6895 char s1[RECLEN], s2[RECLEN];
6896
6897 __pv_warn_cnt++;
6898 if (__no_warns || __em_suppr(id_num)) return;
6899
6900 if (__run_state == SS_SIM)
6901 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
6902 else strcpy(s1, "");
6903
6904 if (__vpierr_cb_active && !__iact_state)
6905 {
6906 /* reset in case user called sim control operation from wrong place */
6907 __errorcb_suppress_msg = FALSE;
6908
6909 sprintf(vpis1, "**%s(%d) WARN**%s [%d] ", __in_fils[__sfnam_ind],
6910 __slin_cnt, s1, id_num);
6911
6912 va_start(va, s);
6913 vsprintf(vpis2, s, va);
6914 va_end(va);
6915
6916 slen = strlen(vpis1) + strlen(vpis2) + 1;
6917 vpichp = __my_malloc(slen);
6918 strcpy(vpichp, vpis1);
6919 strcat(vpichp, vpis2);
6920
6921 __cberror_fill_einfo(WARN, id_num, vpichp, __in_fils[__sfnam_ind],
6922 __slin_cnt);
6923 __vpi_error_trycall();
6924
6925 __my_free(vpichp, slen);
6926 /* if vpi_control used to suppress emsg, used up so turn off here */
6927 if (__errorcb_suppress_msg)
6928 { __errorcb_suppress_msg = FALSE; return; }
6929 }
6930
6931 __my_fprintf(stdout, "**%s(%d) WARN**%s [%d] ", __in_fils[__sfnam_ind],
6932 __slin_cnt, s1, id_num);
6933
6934 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6935 va_start(va2, s);
6936 va_start(va3, s);
6937 __my_vfprintf(stdout, s, va2, va3);
6938 va_end(va2);
6939 va_end(va3);
6940 my_putc_('\n', stdout);
6941 }
6942
6943 /*VARARGS*/
__gfwarn(int32 id_num,word32 gfnam_ind,int32 gflin_cnt,char * s,...)6944 extern void __gfwarn(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
6945 char *s, ...)
6946 {
6947 va_list va, va2, va3;
6948 int32 slen;
6949 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
6950 char s1[RECLEN], s2[RECLEN];
6951
6952 __pv_warn_cnt++;
6953 if (__no_warns || __em_suppr(id_num)) return;
6954
6955 if (__run_state == SS_SIM)
6956 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
6957 else strcpy(s1, "");
6958
6959 if (__vpierr_cb_active && !__iact_state)
6960 {
6961 /* reset in case user called sim control operation from wrong place */
6962 __errorcb_suppress_msg = FALSE;
6963
6964 sprintf(vpis1, "**%s(%d) WARN**%s [%d] ", __in_fils[gfnam_ind],
6965 gflin_cnt, s1, id_num);
6966
6967 va_start(va, s);
6968 vsprintf(vpis2, s, va);
6969 va_end(va);
6970
6971 slen = strlen(vpis1) + strlen(vpis2) + 1;
6972 vpichp = __my_malloc(slen);
6973 strcpy(vpichp, vpis1);
6974 strcat(vpichp, vpis2);
6975
6976 __cberror_fill_einfo(WARN, id_num, vpichp, __in_fils[gfnam_ind],
6977 gflin_cnt);
6978 __vpi_error_trycall();
6979
6980 __my_free(vpichp, slen);
6981 /* if vpi_control used to suppress emsg, used up so turn off here */
6982 if (__errorcb_suppress_msg)
6983 { __errorcb_suppress_msg = FALSE; return; }
6984 }
6985
6986 __my_fprintf(stdout, "**%s(%d) WARN**%s [%d] ", __in_fils[gfnam_ind],
6987 gflin_cnt, s1, id_num);
6988
6989 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
6990 va_start(va2, s);
6991 va_start(va3, s);
6992 __my_vfprintf(stdout, s, va2, va3);
6993 va_end(va2);
6994 va_end(va3);
6995 my_putc_('\n', stdout);
6996 }
6997
6998 /*
6999 * interactive command warning
7000 * this output still goes to log file
7001 * notice this routine does not increment warn number
7002 */
7003 /*VARARGS*/
__ia_warn(int32 id_num,char * s,...)7004 extern void __ia_warn(int32 id_num, char *s, ...)
7005 {
7006 va_list va, va2;
7007
7008 if (id_num >= 1700) __arg_terr(__FILE__, __LINE__);
7009 /* can suppress any interactive error */
7010 if (__em_suppr(id_num)) return;
7011
7012 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
7013 va_start(va, s);
7014 va_start(va2, s);
7015 __via_warn(id_num, s, va, va2);
7016 va_end(va);
7017 va_end(va2);
7018 }
7019
7020 /*VARARGS*/
__via_warn(int32 id_num,char * s,va_list args,va_list args2)7021 extern void __via_warn(int32 id_num, char *s, va_list args, va_list args2)
7022 {
7023 if (__cmd_s == NULL) __my_fprintf(stdout, "--CMD WARN** [%d] ", id_num);
7024 else __my_fprintf(stdout, "--%s(%d) CMD WARN** [%d] ", __cmd_fnam,
7025 __lin_cnt, id_num);
7026 __my_vfprintf(stdout, s, args, args2);
7027 my_putc_('\n', stdout);
7028 }
7029
7030 /*VARARGS*/
__inform(int32 id_num,char * s,...)7031 extern void __inform(int32 id_num, char *s, ...)
7032 {
7033 va_list va, va2, va3;
7034 int32 slen;
7035 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
7036
7037 __inform_cnt++;
7038 if (__no_informs || __em_suppr(id_num)) return;
7039
7040 if (__vpierr_cb_active && !__iact_state)
7041 {
7042 /* reset in case user called sim control operation from wrong place */
7043 __errorcb_suppress_msg = FALSE;
7044
7045 sprintf(vpis1, "--INFORM: [%d] ", id_num);
7046 va_start(va, s);
7047 vsprintf(vpis2, s, va);
7048 va_end(va);
7049
7050 slen = strlen(vpis1) + strlen(vpis2) + 1;
7051 vpichp = __my_malloc(slen);
7052 strcpy(vpichp, vpis1);
7053 strcat(vpichp, vpis2);
7054
7055 __cberror_fill_einfo(INFORM, id_num, vpichp, "[NONE]", 0);
7056 __vpi_error_trycall();
7057
7058 __my_free(vpichp, slen);
7059 /* if vpi_control used to suppress emsg, used up so turn off here */
7060 if (__errorcb_suppress_msg)
7061 { __errorcb_suppress_msg = FALSE; return; }
7062 }
7063
7064 __my_fprintf(stdout, "--INFORM: [%d] ", id_num);
7065
7066 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
7067 va_start(va2, s);
7068 va_start(va3, s);
7069 __my_vfprintf(stdout, s, va2, va3);
7070 va_end(va2);
7071 va_end(va3);
7072 my_putc_('\n', stdout);
7073 }
7074
7075 /*VARARGS*/
__finform(int32 id_num,char * s,...)7076 extern void __finform(int32 id_num, char *s, ...)
7077 {
7078 va_list va, va2, va3;
7079 int32 slen;
7080 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
7081
7082 __inform_cnt++;
7083 if (__no_informs || __em_suppr(id_num)) return;
7084
7085 if (__vpierr_cb_active && !__iact_state)
7086 {
7087 /* reset in case user called sim control operation from wrong place */
7088 __errorcb_suppress_msg = FALSE;
7089
7090 sprintf(vpis1, "--%s(%d) INFORM-- [%d] ", __cur_fnam, __lin_cnt, id_num);
7091 va_start(va, s);
7092 vsprintf(vpis2, s, va);
7093 va_end(va);
7094
7095 slen = strlen(vpis1) + strlen(vpis2) + 1;
7096 vpichp = __my_malloc(slen);
7097 strcpy(vpichp, vpis1);
7098 strcat(vpichp, vpis2);
7099
7100 __cberror_fill_einfo(INFORM, id_num, vpichp, __cur_fnam, __lin_cnt);
7101 __vpi_error_trycall();
7102
7103 __my_free(vpichp, slen);
7104 /* if vpi_control used to suppress emsg, used up so turn off here */
7105 if (__errorcb_suppress_msg)
7106 { __errorcb_suppress_msg = FALSE; return; }
7107 }
7108
7109 __my_fprintf(stdout, "--%s(%d) INFORM-- [%d] ", __cur_fnam,
7110 __lin_cnt, id_num);
7111
7112 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
7113 va_start(va2, s);
7114 va_start(va3, s);
7115 __my_vfprintf(stdout, s, va2, va3);
7116 va_end(va2);
7117 va_end(va3);
7118 my_putc_('\n', stdout);
7119 }
7120
7121 /*VARARGS*/
__sgfinform(int32 id_num,char * s,...)7122 extern void __sgfinform(int32 id_num, char *s, ...)
7123 {
7124 va_list va, va2, va3;
7125 int32 slen;
7126 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
7127 char s1[RECLEN], s2[RECLEN];
7128
7129 __inform_cnt++;
7130 if (__no_informs || __em_suppr(id_num)) return;
7131
7132 if (__run_state == SS_SIM)
7133 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
7134 else strcpy(s1, "");
7135
7136 if (__vpierr_cb_active && !__iact_state)
7137 {
7138 /* reset in case user called sim control operation from wrong place */
7139 __errorcb_suppress_msg = FALSE;
7140
7141 sprintf(vpis1, "--%s(%d) INFORM--%s [%d] ", __in_fils[__sfnam_ind],
7142 __slin_cnt, s1, id_num);
7143 va_start(va, s);
7144 vsprintf(vpis2, s, va);
7145 va_end(va);
7146
7147 slen = strlen(vpis1) + strlen(vpis2) + 1;
7148 vpichp = __my_malloc(slen);
7149 strcpy(vpichp, vpis1);
7150 strcat(vpichp, vpis2);
7151
7152 __cberror_fill_einfo(INFORM, id_num, vpichp, __in_fils[__sfnam_ind],
7153 __slin_cnt);
7154 __vpi_error_trycall();
7155
7156 __my_free(vpichp, slen);
7157 /* if vpi_control used to suppress emsg, used up so turn off here */
7158 if (__errorcb_suppress_msg)
7159 { __errorcb_suppress_msg = FALSE; return; }
7160 }
7161
7162 __my_fprintf(stdout, "--%s(%d) INFORM--%s [%d] ", __in_fils[__sfnam_ind],
7163 __slin_cnt, s1, id_num);
7164
7165 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
7166 va_start(va2, s);
7167 va_start(va3, s);
7168 __my_vfprintf(stdout, s, va2, va3);
7169 va_end(va2);
7170 va_end(va3);
7171 my_putc_('\n', stdout);
7172 }
7173
7174 /*VARARGS*/
__gfinform(int32 id_num,word32 gfnam_ind,int32 gflin_cnt,char * s,...)7175 extern void __gfinform(int32 id_num, word32 gfnam_ind, int32 gflin_cnt,
7176 char *s, ...)
7177 {
7178 va_list va, va2, va3;
7179 int32 slen;
7180 char vpis1[IDLEN], vpis2[4*IDLEN], *vpichp;
7181 char s1[RECLEN], s2[RECLEN];
7182
7183 __inform_cnt++;
7184 if (__no_informs || __em_suppr(id_num)) return;
7185
7186 if (__run_state == SS_SIM)
7187 sprintf(s1, " now %s", __to_timstr(s2, &__simtime));
7188 else strcpy(s1, "");
7189
7190 if (__vpierr_cb_active && !__iact_state)
7191 {
7192 /* reset in case user called sim control operation from wrong place */
7193 __errorcb_suppress_msg = FALSE;
7194
7195 sprintf(vpis1, "--%s(%d) INFORM--%s [%d] ", __in_fils[gfnam_ind],
7196 gflin_cnt, s1, id_num);
7197 va_start(va, s);
7198 vsprintf(vpis2, s, va);
7199 va_end(va);
7200
7201 slen = strlen(vpis1) + strlen(vpis2) + 1;
7202 vpichp = __my_malloc(slen);
7203 strcpy(vpichp, vpis1);
7204 strcat(vpichp, vpis2);
7205
7206 __cberror_fill_einfo(INFORM, id_num, vpichp, __in_fils[gfnam_ind],
7207 gflin_cnt);
7208 __vpi_error_trycall();
7209
7210 __my_free(vpichp, slen);
7211 /* if vpi_control used to suppress emsg, used up so turn off here */
7212 if (__errorcb_suppress_msg)
7213 { __errorcb_suppress_msg = FALSE; return; }
7214 }
7215
7216 __my_fprintf(stdout, "--%s(%d) INFORM--%s [%d] ", __in_fils[gfnam_ind],
7217 gflin_cnt, s1, id_num);
7218
7219 /* SJM 10/13/99 - ansii std says varargs not usable after vprintf called */
7220 va_start(va2, s);
7221 va_start(va3, s);
7222 __my_vfprintf(stdout, s, va2, va3);
7223 va_end(va2);
7224 va_end(va3);
7225 my_putc_('\n', stdout);
7226 }
7227
7228 /*
7229 * return T if this message marked to be suppressed
7230 * if warnings off all suppressed
7231 */
__em_suppr(int32 id)7232 extern int32 __em_suppr(int32 id)
7233 {
7234 word32 w;
7235 int32 bi, wi;
7236
7237 bi = id % WBITS;
7238 wi = id / WBITS;
7239 w = __wsupptab[wi];
7240 if ((w & (1L << bi)) != 0) return(TRUE);
7241 return(FALSE);
7242 }
7243
7244 /*
7245 * my fprintf - normal fprintf except if f is stdout then also to log file
7246 *
7247 * SJM 10/13/99 - ansii std says varargs not usable after vprintf called
7248 */
7249 /*VARARGS*/
__my_fprintf(FILE * f,char * s,...)7250 extern void __my_fprintf(FILE *f, char *s, ...)
7251 {
7252 va_list va, va2;
7253
7254 va_start(va, s);
7255 va_start(va2, s);
7256 vfprintf(f, s, va);
7257 if (f == stdout && __log_s != NULL) vfprintf(__log_s, s, va2);
7258 va_end(va);
7259 va_end(va2);
7260 }
7261
7262 /*
7263 * version of my fprintf when caller passed variable arg list
7264 *
7265 * SJM 10/13/99 - ansii std says varargs not usable after vprintf called
7266 */
__my_vfprintf(FILE * f,char * s,va_list args,va_list args2)7267 extern void __my_vfprintf(FILE *f, char *s, va_list args, va_list args2)
7268 {
7269 vfprintf(f, s, args);
7270 if (f == stdout && __log_s != NULL) vfprintf(__log_s, s, args2);
7271 }
7272