iverilog/lexor.lex

880 lines
22 KiB
Plaintext
Raw Normal View History

1998-11-04 00:28:49 +01:00
%{
/*
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
1998-11-04 00:28:49 +01:00
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#if !defined(WINNT) && !defined(macintosh)
#ident "$Id: lexor.lex,v 1.45 2000/06/27 04:36:29 steve Exp $"
1998-11-04 00:28:49 +01:00
#endif
//# define YYSTYPE lexval
# include <iostream.h>
# include "compiler.h"
1998-11-04 00:28:49 +01:00
# include "parse_misc.h"
# include "parse.h"
# include <ctype.h>
1999-07-10 03:03:18 +02:00
# include <string.h>
2000-03-12 18:09:40 +01:00
# include "lexor_keyword.h"
1998-11-04 00:28:49 +01:00
extern FILE*vl_input;
1998-12-09 05:02:47 +01:00
extern string vl_file;
1998-11-04 00:28:49 +01:00
# define YY_USER_INIT reset_lexor();
# define yylval VLlval
extern YYLTYPE yylloc;
static void reset_lexor();
static void line_directive();
static void line_directive2();
1998-11-04 00:28:49 +01:00
static verinum*make_sized_binary(const char*txt);
static verinum*make_sized_dec(const char*txt);
static verinum*make_unsized_dec(const char*txt);
1998-11-04 00:28:49 +01:00
static verinum*make_sized_octal(const char*txt);
static verinum*make_sized_hex(const char*txt);
1999-05-06 06:09:28 +02:00
static verinum*make_unsized_binary(const char*txt);
static verinum*make_unsized_dec(const char*txt);
static verinum*make_unsized_octal(const char*txt);
static verinum*make_unsized_hex(const char*txt);
1998-11-04 00:28:49 +01:00
static int comment_enter;
1998-11-04 00:28:49 +01:00
%}
%x CCOMMENT
%x LCOMMENT
1998-11-04 00:28:49 +01:00
%x CSTRING
%s UDPTABLE
1999-06-12 22:35:27 +02:00
%x PPTIMESCALE
1998-11-04 00:28:49 +01:00
1999-07-11 19:15:16 +02:00
W [ \t\b\f\r]+
1998-11-04 00:28:49 +01:00
%%
^"#line"[ ]+\"[^\"]*\"[ ]+[0-9]+.* { line_directive(); }
^"`line"[ ]+[0-9]+[ ]+\"[^\"]*\".* { line_directive2(); }
1998-11-04 00:28:49 +01:00
[ \t\b\f\r] { ; }
\n { yylloc.first_line += 1; }
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
<LCOMMENT>. { yymore(); }
<LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
1998-11-04 00:28:49 +01:00
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
1998-11-04 00:28:49 +01:00
<CCOMMENT>. { yymore(); }
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
<CCOMMENT>"*/" { BEGIN(comment_enter); }
1998-11-04 00:28:49 +01:00
"<<" { return K_LS; }
">>" { return K_RS; }
1998-11-04 00:28:49 +01:00
"<=" { return K_LE; }
">=" { return K_GE; }
1999-06-19 05:21:21 +02:00
"=>" { return K_EG; }
"*>" { return K_SG; }
"==" { return K_EQ; }
"!=" { return K_NE; }
"===" { return K_CEQ; }
"!==" { return K_CNE; }
"||" { return K_LOR; }
"&&" { return K_LAND; }
1999-06-13 19:30:23 +02:00
"~|" { return K_NOR; }
"~^" { return K_NXOR; }
"^~" { return K_NXOR; }
"~&" { return K_NAND; }
"->" { return K_TRIGGER; }
1999-06-13 19:30:23 +02:00
1998-11-04 00:28:49 +01:00
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
1998-11-04 00:28:49 +01:00
\" { BEGIN(CSTRING); }
<CSTRING>\\\" { yymore(); }
<CSTRING>\n { BEGIN(0);
1999-07-10 03:03:18 +02:00
yylval.text = strdup(yytext);
1998-11-04 00:28:49 +01:00
VLerror(yylloc, "Missing close quote of string.");
yylloc.first_line += 1;
1998-11-04 00:28:49 +01:00
return STRING; }
<CSTRING>\" { BEGIN(0);
1999-07-10 03:03:18 +02:00
yylval.text = strdup(yytext);
yylval.text[strlen(yytext)-1] = 0;
1998-11-04 00:28:49 +01:00
return STRING; }
<CSTRING>. { yymore(); }
2000-03-05 07:14:10 +01:00
<UDPTABLE>\(\?0\) { return '_'; }
<UDPTABLE>\(\?1\) { return '+'; }
<UDPTABLE>\(\?[xX]\) { return '%'; }
<UDPTABLE>\(\?\?\) { return '*'; }
<UDPTABLE>\(01\) { return 'r'; }
<UDPTABLE>\(0[xX]\) { return 'P'; }
<UDPTABLE>\(10\) { return 'f'; }
<UDPTABLE>\(1[xX]\) { return 'N'; }
<UDPTABLE>\([xX]0\) { return 'F'; }
<UDPTABLE>\([xX]1\) { return 'R'; }
<UDPTABLE>[bB] { return 'b'; }
<UDPTABLE>[fF] { return 'f'; }
<UDPTABLE>[rR] { return 'r'; }
<UDPTABLE>[xX] { return 'x'; }
<UDPTABLE>[pPnN01\?\*\-] { return yytext[0]; }
1998-11-04 00:28:49 +01:00
[a-zA-Z_][a-zA-Z0-9$_]* {
2000-03-12 18:09:40 +01:00
int rc = lexor_keyword_code(yytext, yyleng);
1998-11-04 00:28:49 +01:00
if (rc == IDENTIFIER)
1999-07-10 03:03:18 +02:00
yylval.text = strdup(yytext);
1998-11-04 00:28:49 +01:00
else
yylval.text = 0;
2000-03-12 18:09:40 +01:00
return rc;
}
1998-11-04 00:28:49 +01:00
1999-06-16 05:13:29 +02:00
[a-zA-Z_][a-zA-Z0-9$_]*(\.[a-zA-Z_][a-zA-Z0-9$_]*)+ {
1999-07-10 03:03:18 +02:00
yylval.text = strdup(yytext);
1999-06-16 05:13:29 +02:00
return HIDENTIFIER; }
1998-11-04 00:28:49 +01:00
\\[^ \t\b\f\r]+ {
1999-07-10 03:03:18 +02:00
yylval.text = strdup(yytext);
1998-11-04 00:28:49 +01:00
return IDENTIFIER; }
\$([a-zA-Z0-9$_]+) {
if (strcmp(yytext,"$attribute") == 0)
return KK_attribute;
1999-07-10 03:03:18 +02:00
yylval.text = strdup(yytext);
1998-11-04 00:28:49 +01:00
return SYSTEM_IDENTIFIER; }
\.{W}?[a-zA-Z_][a-zA-Z0-9$_]* {
char*cp = yytext+1;
while (! (isalpha(*cp) || (*cp == '_')))
cp += 1;
yylval.text = strdup(cp);
1999-05-08 22:19:20 +02:00
return PORTNAME; }
2000-01-07 04:45:49 +01:00
[0-9][0-9_]*[ \t]*\'[sS]?[dD][ \t]*[0-9][0-9_]* {
1999-06-14 05:15:14 +02:00
yylval.number = make_sized_dec(yytext);
return NUMBER; }
2000-01-07 04:45:49 +01:00
[0-9][0-9_]*[ \t]*\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ {
1999-06-14 05:15:14 +02:00
yylval.number = make_sized_binary(yytext);
return NUMBER; }
2000-01-07 04:45:49 +01:00
[0-9][0-9_]*[ \t]*\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ {
1999-06-14 05:15:14 +02:00
yylval.number = make_sized_octal(yytext);
return NUMBER; }
2000-01-07 04:45:49 +01:00
[0-9][0-9_]*[ \t]*\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ {
1999-06-14 05:15:14 +02:00
yylval.number = make_sized_hex(yytext);
return NUMBER; }
2000-01-07 04:45:49 +01:00
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
return NUMBER; }
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
1999-06-14 05:15:14 +02:00
return NUMBER; }
2000-01-07 04:45:49 +01:00
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
1999-05-06 06:09:28 +02:00
return NUMBER; }
2000-01-07 04:45:49 +01:00
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
1999-06-14 05:15:14 +02:00
return NUMBER; }
1999-05-06 06:09:28 +02:00
1998-11-04 00:28:49 +01:00
[0-9][0-9_]* {
/* Handle the special case of the unsized decimal number. */
unsigned long value = 0;
for (const char*cp = yytext ; *cp ; cp += 1) {
if (*cp != '_')
value = 10 * value + (*cp - '0');
}
1999-06-07 01:08:00 +02:00
assert(INTEGER_WIDTH <= (8*sizeof(value)));
unsigned nbits = INTEGER_WIDTH;
1998-11-04 00:28:49 +01:00
verinum::V*bits = new verinum::V[8 * sizeof value];
for (unsigned idx = 0 ; idx < nbits ; idx += 1, value >>= 1) {
bits[idx] = (value&1) ? verinum::V1 : verinum::V0;
}
yylval.number = new verinum(bits, nbits, false);
2000-01-07 04:45:49 +01:00
yylval.number->has_sign(true);
1998-11-04 00:28:49 +01:00
delete[]bits;
return NUMBER; }
1999-06-15 04:50:02 +02:00
[0-9][0-9_]*\.[0-9][0-9_]*([Ee][+-]?[0-9][0-9_]*)? {
yylval.realtime = new verireal(yytext);
return REALTIME; }
[0-9][0-9_]*[Ee][+-]?[0-9][0-9_]* {
yylval.realtime = new verireal(yytext);
return REALTIME; }
1999-07-11 19:15:16 +02:00
/* Notice and handle the timescale directive. */
1999-06-15 04:50:02 +02:00
1999-06-12 22:35:27 +02:00
`timescale { BEGIN(PPTIMESCALE); }
<PPTIMESCALE>. { ; }
<PPTIMESCALE>\n {
cerr << yylloc.text << ":" << yylloc.first_line
<< ": Sorry, `timescale not supported." << endl;
yylloc.first_line += 1;
BEGIN(0); }
1998-12-09 05:02:47 +01:00
1999-07-11 19:15:16 +02:00
/* These are directives that I do not yet support. I think that IVL
should handle these, not an external preprocessor. */
^`celldefine{W}?.* { }
^`default_nettype{W}?.* { }
^`delay_mode_distributed{W}?.* { }
^`delay_mode_unit{W}?.* { }
^`delay_mode_path{W}?.* { }
^`disable_portfaults{W}?.* { }
^`enable_portfaults{W}?.* { }
^`endcelldefine{W}?.* { }
^`endprotect{W}?.* { }
^`nosuppress_faults{W}?.* { }
^`nounconnected_drive{W}?.* { }
1999-07-11 19:15:16 +02:00
^`protect{W}?.* { }
^`resetall{W}?.* { }
^`suppress_faults{W}?.* { }
^`unconnected_drive{W}?.* { }
1999-07-11 19:15:16 +02:00
^`uselib{W}?.* { }
/* These are directives that are not supported by me and should have
been handled by an external preprocessor such as ivlpp. */
^`define{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `define not supported. Use an external preprocessor."
<< endl;
}
^{W}?`else{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `else not supported. Use an external preprocessor."
<< endl;
}
^{W}?`endif{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `endif not supported. Use an external preprocessor."
<< endl;
}
^{W}?`ifdef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `ifdef not supported. Use an external preprocessor."
<< endl;
}
^`include{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `include not supported. Use an external preprocessor."
<< endl;
}
^`undef{W}?.* {
cerr << yylloc.text << ":" << yylloc.first_line <<
": `undef not supported. Use an external preprocessor."
<< endl;
}
/* Final catchall. something got lost or mishandled. */
1998-11-04 00:28:49 +01:00
. { cerr << yylloc.first_line << ": unmatched character (";
if (isgraph(yytext[0]))
cerr << yytext[0];
else
cerr << (unsigned)yytext[0];
cerr << ")" << endl; }
%%
/*
* The UDP state table needs some slightly different treatment by the
* lexor. The level characters are normally accepted as other things,
* so the parser needs to switch my mode when it believes in needs to.
*/
void lex_start_table()
{
BEGIN(UDPTABLE);
}
void lex_end_table()
{
BEGIN(INITIAL);
}
static verinum*make_binary_with_size(unsigned size, bool fixed, const char*ptr)
1998-11-04 00:28:49 +01:00
{
2000-01-07 04:45:49 +01:00
bool sign_flag = false;
1998-11-04 00:28:49 +01:00
verinum::V*bits = new verinum::V[size];
2000-01-07 04:45:49 +01:00
if (tolower(ptr[0]) == 's') {
ptr += 1;
sign_flag = true;
}
assert(tolower(*ptr) == 'b');
ptr += 1;
2000-01-07 04:45:49 +01:00
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
unsigned idx = 0;
1999-05-06 06:09:28 +02:00
const char*eptr = ptr + strlen(ptr) - 1;
while ((eptr >= ptr) && (idx < size)) {
1998-11-04 00:28:49 +01:00
switch (*eptr) {
case '_':
break;
1998-11-04 00:28:49 +01:00
case '0':
bits[idx++] = verinum::V0;
break;
case '1':
bits[idx++] = verinum::V1;
break;
case 'z': case 'Z': case '?':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vz;
break;
case 'x': case 'X':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vx;
break;
default:
assert(0);
}
eptr -= 1;
}
// Zero-extend binary number, except that z or x is extended
// if it is the highest supplied digit.
while (idx < size) {
switch (ptr[0]) {
1998-11-04 00:28:49 +01:00
case '0':
case '1':
bits[idx++] = verinum::V0;
break;
case 'z': case 'Z': case '?':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vz;
break;
case 'x': case 'X':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vx;
break;
default:
assert(0);
}
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size, fixed);
delete[]bits;
out->has_sign(sign_flag);
return out;
1998-11-04 00:28:49 +01:00
}
1999-05-06 06:09:28 +02:00
static verinum*make_sized_binary(const char*txt)
{
char*ptr;
unsigned size = strtoul(txt,&ptr,10);
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
1999-05-06 06:09:28 +02:00
assert(*ptr == '\'');
ptr += 1;
return make_binary_with_size(size, true, ptr);
1999-05-06 06:09:28 +02:00
}
static verinum*make_unsized_binary(const char*txt)
{
2000-01-07 04:45:49 +01:00
bool sign_flag = false;
1999-06-14 05:15:14 +02:00
const char*ptr = txt;
assert(*ptr == '\'');
ptr += 1;
2000-01-07 04:45:49 +01:00
if (tolower(*ptr) == 's') {
sign_flag = true;
ptr += 1;
}
1999-06-14 05:15:14 +02:00
assert(tolower(*ptr) == 'b');
while (*ptr && ((*ptr == 'b') || (*ptr == ' ') || (*ptr == '\t')))
1999-06-14 05:15:14 +02:00
ptr += 1;
unsigned size = 0;
for (const char*idx = ptr ; *idx ; idx += 1)
if (*idx != '_') size += 1;
verinum::V*bits = new verinum::V[size];
unsigned idx = size;
while (*ptr) {
switch (ptr[0]) {
case '0':
bits[--idx] = verinum::V0;
break;
case '1':
bits[--idx] = verinum::V1;
break;
case 'z': case 'Z': case '?':
1999-06-14 05:15:14 +02:00
bits[--idx] = verinum::Vz;
break;
case 'x': case 'X':
bits[--idx] = verinum::Vx;
break;
case '_':
break;
default:
fprintf(stderr, "%c\n", ptr[0]);
1999-06-14 05:15:14 +02:00
assert(0);
}
ptr += 1;
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size);
out->has_sign(sign_flag);
delete[]bits;
return out;
1999-05-06 06:09:28 +02:00
}
1998-11-04 00:28:49 +01:00
static verinum*make_sized_octal(const char*txt)
{
2000-01-07 04:45:49 +01:00
bool sign_flag = false;
1998-11-04 00:28:49 +01:00
char*ptr;
2000-01-07 04:45:49 +01:00
1998-11-04 00:28:49 +01:00
unsigned size = strtoul(txt,&ptr,10);
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
1998-11-04 00:28:49 +01:00
assert(*ptr == '\'');
ptr += 1;
2000-01-07 04:45:49 +01:00
if (tolower(*ptr) == 's') {
sign_flag = true;
ptr += 1;
}
1998-11-04 00:28:49 +01:00
assert(tolower(*ptr) == 'o');
1999-09-13 05:08:52 +02:00
/* We know from the size number how bit to make the verinom
array, so make it now. */
1998-11-04 00:28:49 +01:00
verinum::V*bits = new verinum::V[size];
1999-09-13 05:08:52 +02:00
/* skip white space between size and the base token. */
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
1999-09-13 05:08:52 +02:00
/* Find the end of the digits. ptr already points to the start. */
1998-11-04 00:28:49 +01:00
char*eptr = ptr + strlen(ptr);
1999-09-13 05:08:52 +02:00
/* From the last digit and forward, build up the number, least
significant bit first. This loop will not get the last few
bits if the size is not a multiple of 3. */
unsigned idx = 0;
while ((eptr > ptr) && ((idx/3) < (size/3))) switch (*--eptr) {
case 'x': case 'X':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vx;
bits[idx++] = verinum::Vx;
bits[idx++] = verinum::Vx;
break;
1999-09-13 05:08:52 +02:00
case 'z': case 'Z': case '?':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vz;
bits[idx++] = verinum::Vz;
bits[idx++] = verinum::Vz;
break;
1999-09-13 05:08:52 +02:00
1998-11-04 00:28:49 +01:00
default: {
unsigned val = *eptr - '0';
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
}
}
1999-09-13 05:08:52 +02:00
if ((eptr > ptr) && (idx < size)) switch (*--eptr) {
case 'x': case 'X':
1999-09-13 05:08:52 +02:00
for ( ; idx < size ; idx += 1)
bits[idx] = verinum::Vx;
1998-11-04 00:28:49 +01:00
break;
1999-09-13 05:08:52 +02:00
case 'z': case 'Z': case '?':
1999-09-13 05:08:52 +02:00
for ( ; idx < size ; idx += 1)
bits[idx] = verinum::Vz;
1998-11-04 00:28:49 +01:00
break;
1999-09-13 05:08:52 +02:00
default: {
unsigned val = *eptr - '0';
for ( ; idx < size ; idx += 1) {
bits[idx] = (val&1)? verinum::V1 : verinum::V0;
val >>= 1;
}
break;
}
} else {
// zero extend octal numbers
while (idx < size) switch (ptr[1]) {
case 'x': case 'X':
bits[idx++] = verinum::Vx;
break;
case 'z': case 'Z': case '?':
bits[idx++] = verinum::Vz;
break;
default:
bits[idx++] = verinum::V0;
}
1998-11-04 00:28:49 +01:00
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size, true);
delete[]bits;
out->has_sign(sign_flag);
return out;
1998-11-04 00:28:49 +01:00
}
1999-05-06 06:09:28 +02:00
static verinum*make_unsized_octal(const char*txt)
{
2000-01-07 04:45:49 +01:00
bool sign_flag = false;
1999-06-13 19:30:23 +02:00
const char*ptr = txt;
assert(*ptr == '\'');
ptr += 1;
2000-01-07 04:45:49 +01:00
if (tolower(*ptr) == 's') {
sign_flag = true;
ptr += 1;
}
1999-06-13 19:30:23 +02:00
assert(tolower(*ptr) == 'o');
ptr += 1;
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
unsigned size = 0;
for (const char*idx = ptr ; *idx ; idx += 1)
if (*idx != '_') size += 3;
1999-06-13 19:30:23 +02:00
verinum::V*bits = new verinum::V[size];
unsigned idx = size;
while (*ptr) {
unsigned val;
switch (ptr[0]) {
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
val = *ptr - '0';
bits[--idx] = (val&4) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&2) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&1) ? verinum::V1 : verinum::V0;
break;
case 'x': case 'X':
1999-06-13 19:30:23 +02:00
bits[--idx] = verinum::Vx;
bits[--idx] = verinum::Vx;
bits[--idx] = verinum::Vx;
break;
case 'z': case 'Z': case '?':
1999-06-13 19:30:23 +02:00
bits[--idx] = verinum::Vz;
bits[--idx] = verinum::Vz;
bits[--idx] = verinum::Vz;
break;
1999-06-14 05:15:14 +02:00
case '_':
break;
1999-06-13 19:30:23 +02:00
default:
assert(0);
}
ptr += 1;
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size);
out->has_sign(sign_flag);
delete[]bits;
return out;
1999-05-06 06:09:28 +02:00
}
1998-11-04 00:28:49 +01:00
static verinum*make_sized_hex(const char*txt)
{
2000-01-07 04:45:49 +01:00
bool sign_flag = false;
1998-11-04 00:28:49 +01:00
char*ptr;
unsigned size = strtoul(txt,&ptr,10);
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
1998-11-04 00:28:49 +01:00
assert(*ptr == '\'');
ptr += 1;
2000-01-07 04:45:49 +01:00
if (tolower(*ptr) == 's') {
sign_flag = true;
ptr += 1;
}
1998-11-04 00:28:49 +01:00
assert(tolower(*ptr) == 'h');
1999-06-14 05:15:14 +02:00
ptr += 1;
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
verinum::V*bits = new verinum::V[(size+3)&~3];
1998-11-04 00:28:49 +01:00
unsigned idx = 0;
char*eptr = ptr + strlen(ptr) - 1;
1998-11-04 00:28:49 +01:00
while ((eptr >= ptr) && (idx < size)) {
1998-11-04 00:28:49 +01:00
switch (*eptr) {
case 'x': case 'X':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vx;
bits[idx++] = verinum::Vx;
bits[idx++] = verinum::Vx;
bits[idx++] = verinum::Vx;
break;
case 'z': case 'Z': case '?':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vz;
bits[idx++] = verinum::Vz;
bits[idx++] = verinum::Vz;
bits[idx++] = verinum::Vz;
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
{
unsigned val = tolower(*eptr) - 'a' + 10;
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
bits[idx++] = (val&8)? verinum::V1 : verinum::V0;
break;
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
1998-11-04 00:28:49 +01:00
{
unsigned val = *eptr - '0';
bits[idx++] = (val&1)? verinum::V1 : verinum::V0;
bits[idx++] = (val&2)? verinum::V1 : verinum::V0;
bits[idx++] = (val&4)? verinum::V1 : verinum::V0;
bits[idx++] = (val&8)? verinum::V1 : verinum::V0;
break;
1998-11-04 00:28:49 +01:00
}
1999-06-14 05:15:14 +02:00
case '_':
break;
default:
assert(0);
1998-11-04 00:28:49 +01:00
}
eptr -= 1;
}
// zero extend octal numbers
while (idx < size) switch (ptr[1]) {
case 'x': case 'X':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vx;
break;
case 'z': case 'Z': case '?':
1998-11-04 00:28:49 +01:00
bits[idx++] = verinum::Vz;
break;
default:
bits[idx++] = verinum::V0;
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size, true);
out->has_sign(sign_flag);
delete[]bits;
return out;
1998-11-04 00:28:49 +01:00
}
1999-05-06 06:09:28 +02:00
static verinum*make_unsized_hex(const char*txt)
{
2000-01-07 04:45:49 +01:00
bool sign_flag = false;
1999-06-13 19:30:23 +02:00
const char*ptr = txt;
assert(*ptr == '\'');
ptr += 1;
2000-01-07 04:45:49 +01:00
if (tolower(*ptr) == 's') {
sign_flag = true;
ptr += 1;
}
1999-06-13 19:30:23 +02:00
assert(tolower(*ptr) == 'h');
1999-06-14 05:15:14 +02:00
1999-06-13 19:30:23 +02:00
ptr += 1;
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
unsigned size = 0;
for (const char*idx = ptr ; *idx ; idx += 1)
if (*idx != '_') size += 4;
1999-06-13 19:30:23 +02:00
verinum::V*bits = new verinum::V[size];
unsigned idx = size;
while (*ptr) {
unsigned val;
switch (ptr[0]) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
val = *ptr - '0';
bits[--idx] = (val&8) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&4) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&2) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&1) ? verinum::V1 : verinum::V0;
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
val = tolower(*ptr) - 'a' + 10;
bits[--idx] = (val&8) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&4) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&2) ? verinum::V1 : verinum::V0;
bits[--idx] = (val&1) ? verinum::V1 : verinum::V0;
break;
case 'x': case 'X':
1999-06-13 19:30:23 +02:00
bits[--idx] = verinum::Vx;
bits[--idx] = verinum::Vx;
bits[--idx] = verinum::Vx;
bits[--idx] = verinum::Vx;
break;
case 'z': case 'Z': case '?':
1999-06-13 19:30:23 +02:00
bits[--idx] = verinum::Vz;
bits[--idx] = verinum::Vz;
bits[--idx] = verinum::Vz;
bits[--idx] = verinum::Vz;
break;
1999-06-14 05:15:14 +02:00
case '_':
break;
1999-06-13 19:30:23 +02:00
default:
assert(0);
}
ptr += 1;
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size);
out->has_sign(sign_flag);
delete[]bits;
return out;
1999-05-06 06:09:28 +02:00
}
/*
* Making a decimal number is much easier then the other base numbers
* because there are no z or x values to worry about.
*/
static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
{
2000-01-07 04:45:49 +01:00
bool signed_flag = false;
if (tolower(*ptr) == 's') {
signed_flag = true;
ptr += 1;
}
assert(tolower(*ptr) == 'd');
1999-06-14 05:15:14 +02:00
ptr += 1;
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
unsigned long value = 0;
1999-06-14 05:15:14 +02:00
for ( ; *ptr ; ptr += 1)
if (isdigit(*ptr)) {
value *= 10;
value += *ptr - '0';
} else {
assert(*ptr == '_');
}
verinum::V*bits = new verinum::V[size];
for (unsigned idx = 0 ; idx < size ; idx += 1) {
bits[idx] = (value&1)? verinum::V1 : verinum::V0;
value /= 2;
}
2000-01-07 04:45:49 +01:00
verinum*out = new verinum(bits, size, fixed);
out->has_sign(signed_flag);
delete[]bits;
return out;
}
static verinum*make_sized_dec(const char*txt)
{
char*ptr;
unsigned size = strtoul(txt,&ptr,10);
1999-06-14 05:15:14 +02:00
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
ptr += 1;
assert(*ptr == '\'');
ptr += 1;
return make_dec_with_size(size, true, ptr);
}
static verinum*make_unsized_dec(const char*txt)
{
return make_dec_with_size(INTEGER_WIDTH, false, txt+1);
}
1998-12-09 05:02:47 +01:00
static int yywrap()
1998-12-09 05:02:47 +01:00
{
return 1;
1998-12-09 05:02:47 +01:00
}
/*
* The line directive matches lines of the form #line "foo" N and
* calls this function. Here I parse out the file name and line
* number, and change the yylloc to suite.
*/
static void line_directive()
1998-12-09 05:02:47 +01:00
{
char*qt1 = strchr(yytext, '"');
assert(qt1);
qt1 += 1;
1998-12-09 05:02:47 +01:00
char*qt2 = strchr(qt1, '"');
assert(qt2);
1998-12-09 05:02:47 +01:00
char*buf = new char[qt2-qt1+1];
strncpy(buf, qt1, qt2-qt1);
buf[qt2-qt1] = 0;
1998-12-09 05:02:47 +01:00
delete[]yylloc.text;
yylloc.text = buf;
qt2 += 1;
yylloc.first_line = strtoul(qt2,0,0);
1998-12-09 05:02:47 +01:00
}
static void line_directive2()
{
assert(strncmp(yytext,"`line",5) == 0);
char*cp = yytext + strlen("`line");
cp += strspn(cp, " ");
yylloc.first_line = strtoul(cp,&cp,10);
cp += strspn(cp, " ");
if (*cp == 0) return;
char*qt1 = strchr(yytext, '"');
assert(qt1);
qt1 += 1;
char*qt2 = strchr(qt1, '"');
assert(qt2);
char*buf = new char[qt2-qt1+1];
strncpy(buf, qt1, qt2-qt1);
buf[qt2-qt1] = 0;
delete[]yylloc.text;
yylloc.text = buf;
}
1998-11-04 00:28:49 +01:00
static void reset_lexor()
{
yyrestart(vl_input);
yylloc.first_line = 1;
yylloc.text = strdup(vl_file.c_str());
1998-11-04 00:28:49 +01:00
}