From 1fa31332b607919d11f639543bdadf1c910c2c17 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Wed, 25 Jul 2001 00:33:10 +0000 Subject: [PATCH] Add lexing, parsing, and internal format for strings and character constants. Completely handle data declarations (db/dw/etc) and reserve space declarations (resb/resw/etc). svn path=/trunk/yasm/; revision=129 --- libyasm/bytecode.c | 183 +++++++++++++++++++++++++++--- libyasm/bytecode.h | 41 ++++++- libyasm/errwarn.c | 12 +- libyasm/errwarn.h | 12 +- modules/parsers/nasm/bison.y.in | 71 ++++++++++-- modules/parsers/nasm/nasm-bison.y | 71 ++++++++++-- modules/parsers/nasm/token.l.in | 46 +++++++- src/bison.y.in | 71 ++++++++++-- src/bytecode.c | 183 +++++++++++++++++++++++++++--- src/bytecode.h | 41 ++++++- src/errwarn.c | 12 +- src/errwarn.h | 12 +- src/parsers/nasm/bison.y.in | 71 ++++++++++-- src/parsers/nasm/nasm-bison.y | 71 ++++++++++-- src/parsers/nasm/token.l.in | 46 +++++++- src/token.l.in | 46 +++++++- 16 files changed, 893 insertions(+), 96 deletions(-) diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 4f3e631e..9af7ad0d 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -1,4 +1,4 @@ -/* $Id: bytecode.c,v 1.13 2001/07/11 23:16:50 peter Exp $ +/* $Id: bytecode.c,v 1.14 2001/07/25 00:33:10 peter Exp $ * Bytecode utility functions * * Copyright (C) 2001 Peter Johnson @@ -20,6 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include "globals.h" #include "bytecode.h" #include "errwarn.h" @@ -336,21 +337,77 @@ BuildBC_JmpRel (bytecode *bc, BuildBC_Common(bc); } -/* TODO: implement. Shouldn't be difficult. */ -unsigned char * -ConvertBCInsnToBytes (unsigned char *ptr, bytecode *bc, int *len) +void +BuildBC_Data (bytecode *bc, + dataval *data, + unsigned long size) { - if(bc->type != BC_INSN) - return (unsigned char *)NULL; - return (unsigned char *)NULL; + dataval *cur = data; + + /* First check to see if all the data elements are valid for the size + * being set. + * Validity table: + * db (1) -> expr, string + * dw (2) -> expr, string + * dd (4) -> expr, float, string + * dq (8) -> expr, float, string + * dt (10) -> float, string + * + * Once we calculate expr we'll have to validate it against the size + * and warn/error appropriately (symbol constants versus labels: + * constants (equ's) should always be legal, but labels should raise + * warnings when used in db or dq context at the minimum). + */ + while(cur) { + switch(cur->type) { + case DV_EMPTY: + case DV_STRING: + /* string is valid in every size */ + break; + case DV_FLOAT: + if(size == 1) + Error(ERR_DECLDATA_FLOAT, (char *)NULL, "DB"); + else if(size == 2) + Error(ERR_DECLDATA_FLOAT, (char *)NULL, "DW"); + break; + case DV_EXPR: + if(size == 10) + Error(ERR_DECLDATA_EXPR, (char *)NULL, "DT"); + break; + } + cur = cur->next; + } + + bc->next = (bytecode *)NULL; + bc->type = BC_DATA; + + bc->data.data.data = data; + bc->data.data.size = size; + + BuildBC_Common(bc); } void -DebugPrintBC (bytecode *bc) +BuildBC_Reserve (bytecode *bc, + expr *numitems, + unsigned long itemsize) { - unsigned long i; + bc->next = (bytecode *)NULL; + bc->type = BC_RESERVE; + bc->data.reserve.numitems = numitems; + bc->data.reserve.itemsize = itemsize; + + BuildBC_Common(bc); +} + +void +DebugPrintBC (bytecode *bc) +{ switch(bc->type) { + case BC_EMPTY: + printf("_Empty_\n"); + break; case BC_INSN: printf("_Instruction_\n"); printf("Effective Address:\n"); @@ -431,14 +488,17 @@ DebugPrintBC (bytecode *bc) break; case BC_DATA: printf("_Data_\n"); - for(i=0; ilen; i++) { - printf("%2x ", (unsigned int)bc->data.data.data[i]); - if((i & ~0xFFFF) == i) - printf("\n"); - } + printf("Final Element Size=%u\n", + (unsigned int)bc->data.data.size); + printf("Elements:\n"); + dataval_print(bc->data.data.data); break; case BC_RESERVE: printf("_Reserve_\n"); + printf("Num Items="); + expr_print(bc->data.reserve.numitems); + printf("\nItem Size=%u\n", + (unsigned int)bc->data.reserve.itemsize); break; default: printf("_Unknown_\n"); @@ -448,3 +508,98 @@ DebugPrintBC (bytecode *bc) bc->filename ? bc->filename : "", bc->lineno); printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits); } + +dataval * +dataval_new_expr (expr *exp) +{ + dataval *retval = malloc(sizeof(dataval)); + + if(!retval) + Fatal(FATAL_NOMEM); + + retval->next = (dataval *)NULL; + retval->last = retval; + retval->type = DV_EXPR; + retval->data.exp = exp; + + return retval; +} + +dataval * +dataval_new_float (double float_val) +{ + dataval *retval = malloc(sizeof(dataval)); + + if(!retval) + Fatal(FATAL_NOMEM); + + retval->next = (dataval *)NULL; + retval->last = retval; + retval->type = DV_FLOAT; + retval->data.float_val = float_val; + + return retval; +} + +dataval * +dataval_new_string (char *str_val) +{ + dataval *retval = malloc(sizeof(dataval)); + + if(!retval) + Fatal(FATAL_NOMEM); + + retval->next = (dataval *)NULL; + retval->last = retval; + retval->type = DV_STRING; + retval->data.str_val = str_val; + + return retval; +} + +dataval * +dataval_append (dataval *list, dataval *item) +{ + if(item) + item->next = (dataval *)NULL; + + if(!list) { + item->last = item; + return item; + } else { + if(item) { + list->last->next = item; + list->last = item; + item->last = (dataval *)NULL; + } + return list; + } +} + +void +dataval_print (dataval *start) +{ + dataval *cur = start; + + while(cur) { + switch(cur->type) { + case DV_EMPTY: + printf(" Empty\n"); + break; + case DV_EXPR: + printf(" Expr="); + expr_print(cur->data.exp); + printf("\n"); + break; + case DV_FLOAT: + printf(" Float=%e\n", cur->data.float_val); + break; + case DV_STRING: + printf(" String=%s\n", cur->data.str_val); + break; + } + + cur = cur->next; + } +} + diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 6b971c33..fafb3b44 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -1,4 +1,4 @@ -/* $Id: bytecode.h,v 1.14 2001/07/11 23:16:50 peter Exp $ +/* $Id: bytecode.h,v 1.15 2001/07/25 00:33:10 peter Exp $ * Bytecode utility functions header file * * Copyright (C) 2001 Peter Johnson @@ -47,6 +47,18 @@ typedef struct immval_s { unsigned char f_sign; /* 1 if final imm should be signed */ } immval; +typedef struct dataval_s { + struct dataval_s *next, *last; + + enum { DV_EMPTY, DV_EXPR, DV_FLOAT, DV_STRING } type; + + union { + struct expr_s *exp; + double float_val; + char *str_val; + } data; +} dataval; + typedef enum jmprel_opcode_sel_e { JR_NONE, JR_SHORT, @@ -64,7 +76,7 @@ typedef struct targetval_s { typedef struct bytecode_s { struct bytecode_s *next; - enum { BC_INSN, BC_JMPREL, BC_DATA, BC_RESERVE } type; + enum { BC_EMPTY, BC_INSN, BC_JMPREL, BC_DATA, BC_RESERVE } type; union { struct { @@ -97,8 +109,15 @@ typedef struct bytecode_s { unsigned char lockrep_pre; /* 0 indicates no prefix */ } jmprel; struct { - unsigned char *data; + dataval *data; /* non-converted data (linked list) */ + + /* final (converted) size of each element (in bytes) */ + unsigned char size; } data; + struct { + struct expr_s *numitems; /* number of items to reserve */ + unsigned char itemsize; /* size of each item (in bytes) */ + } reserve; } data; unsigned long len; /* total length of entire bytecode */ @@ -154,8 +173,22 @@ void BuildBC_JmpRel(bytecode *bc, unsigned char near_op2, unsigned char addrsize); -unsigned char *ConvertBCInsnToBytes(unsigned char *ptr, bytecode *bc, int *len); +void BuildBC_Data(bytecode *bc, + dataval *data, + unsigned long size); + +void BuildBC_Reserve(bytecode *bc, + struct expr_s *numitems, + unsigned long itemsize); void DebugPrintBC(bytecode *bc); +dataval *dataval_new_expr(struct expr_s *exp); +dataval *dataval_new_float(double float_val); +dataval *dataval_new_string(char *str_val); + +dataval *dataval_append(dataval *list, dataval *item); + +void dataval_print(dataval *start); + #endif diff --git a/libyasm/errwarn.c b/libyasm/errwarn.c index cd296f64..b6c4e263 100644 --- a/libyasm/errwarn.c +++ b/libyasm/errwarn.c @@ -1,4 +1,4 @@ -/* $Id: errwarn.c,v 1.16 2001/07/11 23:16:50 peter Exp $ +/* $Id: errwarn.c,v 1.17 2001/07/25 00:33:10 peter Exp $ * Error and warning reporting and related functions. * * Copyright (C) 2001 Peter Johnson @@ -67,7 +67,12 @@ static char *err_msgs[] = { "expression syntax error", "duplicate definition of `%1'; previously defined line %2", "mismatch in operand sizes", - "no %s form of that jump instruction exists" + "no %s form of that jump instruction exists", + "unterminated string", + "unexpected end of file in string", + "expression syntax error", + "floating-point constant encountered in `%s'", + "non-floating-point value encountered in `%s'" }; /* Warning messages. Match up with warn_num enum in errwarn.h. */ @@ -78,7 +83,8 @@ static char *warn_msgs[] = { "multiple segment overrides, using leftmost", "multiple LOCK or REP prefixes, using leftmost", "no non-local label before '%s'", - "multiple SHORT or NEAR specifiers, using leftmost" + "multiple SHORT or NEAR specifiers, using leftmost", + "character constant too large, ignoring trailing characters" }; /* I hate to define these strings as static buffers; a better solution would be diff --git a/libyasm/errwarn.h b/libyasm/errwarn.h index a1e2044b..51bf7175 100644 --- a/libyasm/errwarn.h +++ b/libyasm/errwarn.h @@ -1,4 +1,4 @@ -/* $Id: errwarn.h,v 1.10 2001/07/11 23:16:50 peter Exp $ +/* $Id: errwarn.h,v 1.11 2001/07/25 00:33:10 peter Exp $ * Error and warning reporting and related functions header file. * * Copyright (C) 2001 Peter Johnson @@ -45,7 +45,12 @@ typedef enum { ERR_EXP_SYNTAX, ERR_DUPLICATE_DEF, ERR_OP_SIZE_MISMATCH, - ERR_NO_JMPREL_FORM + ERR_NO_JMPREL_FORM, + ERR_STRING_UNTERM, + ERR_STRING_EOF, + ERR_EXPR_SYNTAX, + ERR_DECLDATA_FLOAT, + ERR_DECLDATA_EXPR } err_num; /* Warning constants. Match up with warn_msgs in errwarn.c. */ @@ -56,7 +61,8 @@ typedef enum { WARN_MULT_SEG_OVERRIDE, WARN_MULT_LOCKREP_PREFIX, WARN_NO_BASE_LABEL, - WARN_MULT_SHORTNEAR + WARN_MULT_SHORTNEAR, + WARN_CHAR_CONST_TOO_BIG } warn_num; char *conv_unprint(char ch); diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index 5a4accf5..d0e1af44 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -1,4 +1,4 @@ -/* $Id: bison.y.in,v 1.21 2001/07/11 21:04:58 peter Exp $ +/* $Id: bison.y.in,v 1.22 2001/07/25 00:33:10 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -33,6 +33,7 @@ void init_table(void); extern int yylex(void); extern void yyerror(char *); +static unsigned long ConvertCharConstToInt(char *); %} @@ -50,12 +51,13 @@ extern void yyerror(char *); expr *exp; immval im_val; targetval tgt_val; + dataval *data; bytecode bc; -} +} %token INTNUM %token FLTNUM -%token DIRECTIVE_NAME DIRECTIVE_VAL +%token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA %token RESERVE_SPACE @@ -86,10 +88,11 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 -%type expr +%type expr expr_no_string %type explabel %type label_id %type target +%type dataval datavals %left '|' %left '^' @@ -104,15 +107,34 @@ input: /* empty */ | input line { OutputError(); OutputWarning(); line_number++; } ; -line: '\n' { $$.len = 0; } +line: '\n' { $$.type = BC_EMPTY; } | exp '\n' { DebugPrintBC(&$1); $$ = $1; } | label exp '\n' { DebugPrintBC(&$2); $$ = $2; } | label '\n' - | directive '\n' { } - | error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; } + | directive '\n' { $$.type = BC_EMPTY; } + | error '\n' { + Error(ERR_INVALID_LINE, (char *)NULL); + $$.type = BC_EMPTY; + yyerrok; + } ; exp: instr + | DECLARE_DATA datavals { BuildBC_Data(&$$, $2, $1); } + | RESERVE_SPACE expr { BuildBC_Reserve(&$$, $2, $1); } +; + +datavals: dataval + | datavals ',' dataval { $$ = dataval_append($1, $3); } +; + +dataval: expr_no_string { $$ = dataval_new_expr($1); } + | FLTNUM { $$ = dataval_new_float($1); } + | STRING { $$ = dataval_new_string($1); } + | error { + Error(ERR_EXPR_SYNTAX, (char *)NULL); + $$ = (dataval *)NULL; + } ; label: label_id { $1->value = 0; } /* TODO: calculate offset */ @@ -312,8 +334,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr: - INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } | explabel { $$ = expr_new_ident (EXPR_SYM, ExprSym(sym_use_get ($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree ($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree ($1, EXPR_OR, $3); } @@ -340,6 +361,10 @@ expr: | '(' expr ')' { $$ = $2; } ; +expr: expr_no_string + | STRING { $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); } +; + explabel: ID | SPECIAL_ID | LOCAL_ID ; instr: instrbase @@ -360,3 +385,31 @@ instr: instrbase /* instruction grammars (dynamically generated) */ /* @INSTRUCTIONS@ */ +%% + +static unsigned long +ConvertCharConstToInt(char *cc) +{ + unsigned long retval = 0; + size_t len = strlen(cc); + + if(len > 4) + Warning(WARN_CHAR_CONST_TOO_BIG, (char *)NULL); + + switch(len) { + case 4: + retval |= (unsigned long)cc[3]; + retval <<= 8; + case 3: + retval |= (unsigned long)cc[2]; + retval <<= 8; + case 2: + retval |= (unsigned long)cc[1]; + retval <<= 8; + case 1: + retval |= (unsigned long)cc[0]; + } + + return retval; +} + diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index 364f84cf..94f11f12 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -1,4 +1,4 @@ -/* $Id: nasm-bison.y,v 1.21 2001/07/11 21:04:58 peter Exp $ +/* $Id: nasm-bison.y,v 1.22 2001/07/25 00:33:10 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -33,6 +33,7 @@ void init_table(void); extern int yylex(void); extern void yyerror(char *); +static unsigned long ConvertCharConstToInt(char *); %} @@ -50,12 +51,13 @@ extern void yyerror(char *); expr *exp; immval im_val; targetval tgt_val; + dataval *data; bytecode bc; -} +} %token INTNUM %token FLTNUM -%token DIRECTIVE_NAME DIRECTIVE_VAL +%token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA %token RESERVE_SPACE @@ -86,10 +88,11 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 -%type expr +%type expr expr_no_string %type explabel %type label_id %type target +%type dataval datavals %left '|' %left '^' @@ -104,15 +107,34 @@ input: /* empty */ | input line { OutputError(); OutputWarning(); line_number++; } ; -line: '\n' { $$.len = 0; } +line: '\n' { $$.type = BC_EMPTY; } | exp '\n' { DebugPrintBC(&$1); $$ = $1; } | label exp '\n' { DebugPrintBC(&$2); $$ = $2; } | label '\n' - | directive '\n' { } - | error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; } + | directive '\n' { $$.type = BC_EMPTY; } + | error '\n' { + Error(ERR_INVALID_LINE, (char *)NULL); + $$.type = BC_EMPTY; + yyerrok; + } ; exp: instr + | DECLARE_DATA datavals { BuildBC_Data(&$$, $2, $1); } + | RESERVE_SPACE expr { BuildBC_Reserve(&$$, $2, $1); } +; + +datavals: dataval + | datavals ',' dataval { $$ = dataval_append($1, $3); } +; + +dataval: expr_no_string { $$ = dataval_new_expr($1); } + | FLTNUM { $$ = dataval_new_float($1); } + | STRING { $$ = dataval_new_string($1); } + | error { + Error(ERR_EXPR_SYNTAX, (char *)NULL); + $$ = (dataval *)NULL; + } ; label: label_id { $1->value = 0; } /* TODO: calculate offset */ @@ -312,8 +334,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr: - INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } | explabel { $$ = expr_new_ident (EXPR_SYM, ExprSym(sym_use_get ($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree ($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree ($1, EXPR_OR, $3); } @@ -340,6 +361,10 @@ expr: | '(' expr ')' { $$ = $2; } ; +expr: expr_no_string + | STRING { $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); } +; + explabel: ID | SPECIAL_ID | LOCAL_ID ; instr: instrbase @@ -360,3 +385,31 @@ instr: instrbase /* instruction grammars (dynamically generated) */ /* @INSTRUCTIONS@ */ +%% + +static unsigned long +ConvertCharConstToInt(char *cc) +{ + unsigned long retval = 0; + size_t len = strlen(cc); + + if(len > 4) + Warning(WARN_CHAR_CONST_TOO_BIG, (char *)NULL); + + switch(len) { + case 4: + retval |= (unsigned long)cc[3]; + retval <<= 8; + case 3: + retval |= (unsigned long)cc[2]; + retval <<= 8; + case 2: + retval |= (unsigned long)cc[1]; + retval <<= 8; + case 1: + retval |= (unsigned long)cc[0]; + } + + return retval; +} + diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index b9f29ab8..0cde489f 100644 --- a/modules/parsers/nasm/token.l.in +++ b/modules/parsers/nasm/token.l.in @@ -1,4 +1,4 @@ -/* $Id: token.l.in,v 1.11 2001/07/11 21:01:54 peter Exp $ +/* $Id: token.l.in,v 1.12 2001/07/25 00:33:10 peter Exp $ * Main lexer * * Copyright (C) 2001 Peter Johnson @@ -37,6 +37,15 @@ #include "expr.h" #include "bison.h" +/* starting size of string buffer */ +#define STRBUF_ALLOC_SIZE 128 + +/* string buffer used when parsing strings/character constants */ +static char *strbuf = (char *)NULL; + +/* length of strbuf (including terminating NULL character) */ +static size_t strbuf_size = 0; + %} %option noyywrap %option nounput @@ -89,6 +98,41 @@ WS [ \t\r] yylval.double_val = strtod(yytext, (char **)NULL); return FLTNUM; } + + /* string/character constant values */ +["'] { + int inch, count; + char endch = yytext[0]; + + strbuf = malloc(STRBUF_ALLOC_SIZE); + if(!strbuf) + Fatal(FATAL_NOMEM); + + strbuf_size = STRBUF_ALLOC_SIZE; + inch = input(); + count = 0; + while(inch != EOF && inch != endch && inch != '\n') { + strbuf[count++] = inch; + if(count >= strbuf_size) { + strbuf = realloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE); + if(!strbuf) + Fatal(FATAL_NOMEM); + strbuf_size += STRBUF_ALLOC_SIZE; + } + inch = input(); + } + + if(inch == '\n') + Error(ERR_STRING_UNTERM, (char *)NULL); + else if(inch == EOF) + Error(ERR_STRING_EOF, (char *)NULL); + + strbuf[count] = '\0'; + + yylval.str_val = strbuf; + return STRING; +} + /* directive: [name value] */ ^"[" { BEGIN DIRECTIVE; return '['; } "]" { BEGIN INITIAL; return ']'; } diff --git a/src/bison.y.in b/src/bison.y.in index 5a4accf5..d0e1af44 100644 --- a/src/bison.y.in +++ b/src/bison.y.in @@ -1,4 +1,4 @@ -/* $Id: bison.y.in,v 1.21 2001/07/11 21:04:58 peter Exp $ +/* $Id: bison.y.in,v 1.22 2001/07/25 00:33:10 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -33,6 +33,7 @@ void init_table(void); extern int yylex(void); extern void yyerror(char *); +static unsigned long ConvertCharConstToInt(char *); %} @@ -50,12 +51,13 @@ extern void yyerror(char *); expr *exp; immval im_val; targetval tgt_val; + dataval *data; bytecode bc; -} +} %token INTNUM %token FLTNUM -%token DIRECTIVE_NAME DIRECTIVE_VAL +%token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA %token RESERVE_SPACE @@ -86,10 +88,11 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 -%type expr +%type expr expr_no_string %type explabel %type label_id %type target +%type dataval datavals %left '|' %left '^' @@ -104,15 +107,34 @@ input: /* empty */ | input line { OutputError(); OutputWarning(); line_number++; } ; -line: '\n' { $$.len = 0; } +line: '\n' { $$.type = BC_EMPTY; } | exp '\n' { DebugPrintBC(&$1); $$ = $1; } | label exp '\n' { DebugPrintBC(&$2); $$ = $2; } | label '\n' - | directive '\n' { } - | error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; } + | directive '\n' { $$.type = BC_EMPTY; } + | error '\n' { + Error(ERR_INVALID_LINE, (char *)NULL); + $$.type = BC_EMPTY; + yyerrok; + } ; exp: instr + | DECLARE_DATA datavals { BuildBC_Data(&$$, $2, $1); } + | RESERVE_SPACE expr { BuildBC_Reserve(&$$, $2, $1); } +; + +datavals: dataval + | datavals ',' dataval { $$ = dataval_append($1, $3); } +; + +dataval: expr_no_string { $$ = dataval_new_expr($1); } + | FLTNUM { $$ = dataval_new_float($1); } + | STRING { $$ = dataval_new_string($1); } + | error { + Error(ERR_EXPR_SYNTAX, (char *)NULL); + $$ = (dataval *)NULL; + } ; label: label_id { $1->value = 0; } /* TODO: calculate offset */ @@ -312,8 +334,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr: - INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } | explabel { $$ = expr_new_ident (EXPR_SYM, ExprSym(sym_use_get ($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree ($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree ($1, EXPR_OR, $3); } @@ -340,6 +361,10 @@ expr: | '(' expr ')' { $$ = $2; } ; +expr: expr_no_string + | STRING { $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); } +; + explabel: ID | SPECIAL_ID | LOCAL_ID ; instr: instrbase @@ -360,3 +385,31 @@ instr: instrbase /* instruction grammars (dynamically generated) */ /* @INSTRUCTIONS@ */ +%% + +static unsigned long +ConvertCharConstToInt(char *cc) +{ + unsigned long retval = 0; + size_t len = strlen(cc); + + if(len > 4) + Warning(WARN_CHAR_CONST_TOO_BIG, (char *)NULL); + + switch(len) { + case 4: + retval |= (unsigned long)cc[3]; + retval <<= 8; + case 3: + retval |= (unsigned long)cc[2]; + retval <<= 8; + case 2: + retval |= (unsigned long)cc[1]; + retval <<= 8; + case 1: + retval |= (unsigned long)cc[0]; + } + + return retval; +} + diff --git a/src/bytecode.c b/src/bytecode.c index 4f3e631e..9af7ad0d 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1,4 +1,4 @@ -/* $Id: bytecode.c,v 1.13 2001/07/11 23:16:50 peter Exp $ +/* $Id: bytecode.c,v 1.14 2001/07/25 00:33:10 peter Exp $ * Bytecode utility functions * * Copyright (C) 2001 Peter Johnson @@ -20,6 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include "globals.h" #include "bytecode.h" #include "errwarn.h" @@ -336,21 +337,77 @@ BuildBC_JmpRel (bytecode *bc, BuildBC_Common(bc); } -/* TODO: implement. Shouldn't be difficult. */ -unsigned char * -ConvertBCInsnToBytes (unsigned char *ptr, bytecode *bc, int *len) +void +BuildBC_Data (bytecode *bc, + dataval *data, + unsigned long size) { - if(bc->type != BC_INSN) - return (unsigned char *)NULL; - return (unsigned char *)NULL; + dataval *cur = data; + + /* First check to see if all the data elements are valid for the size + * being set. + * Validity table: + * db (1) -> expr, string + * dw (2) -> expr, string + * dd (4) -> expr, float, string + * dq (8) -> expr, float, string + * dt (10) -> float, string + * + * Once we calculate expr we'll have to validate it against the size + * and warn/error appropriately (symbol constants versus labels: + * constants (equ's) should always be legal, but labels should raise + * warnings when used in db or dq context at the minimum). + */ + while(cur) { + switch(cur->type) { + case DV_EMPTY: + case DV_STRING: + /* string is valid in every size */ + break; + case DV_FLOAT: + if(size == 1) + Error(ERR_DECLDATA_FLOAT, (char *)NULL, "DB"); + else if(size == 2) + Error(ERR_DECLDATA_FLOAT, (char *)NULL, "DW"); + break; + case DV_EXPR: + if(size == 10) + Error(ERR_DECLDATA_EXPR, (char *)NULL, "DT"); + break; + } + cur = cur->next; + } + + bc->next = (bytecode *)NULL; + bc->type = BC_DATA; + + bc->data.data.data = data; + bc->data.data.size = size; + + BuildBC_Common(bc); } void -DebugPrintBC (bytecode *bc) +BuildBC_Reserve (bytecode *bc, + expr *numitems, + unsigned long itemsize) { - unsigned long i; + bc->next = (bytecode *)NULL; + bc->type = BC_RESERVE; + bc->data.reserve.numitems = numitems; + bc->data.reserve.itemsize = itemsize; + + BuildBC_Common(bc); +} + +void +DebugPrintBC (bytecode *bc) +{ switch(bc->type) { + case BC_EMPTY: + printf("_Empty_\n"); + break; case BC_INSN: printf("_Instruction_\n"); printf("Effective Address:\n"); @@ -431,14 +488,17 @@ DebugPrintBC (bytecode *bc) break; case BC_DATA: printf("_Data_\n"); - for(i=0; ilen; i++) { - printf("%2x ", (unsigned int)bc->data.data.data[i]); - if((i & ~0xFFFF) == i) - printf("\n"); - } + printf("Final Element Size=%u\n", + (unsigned int)bc->data.data.size); + printf("Elements:\n"); + dataval_print(bc->data.data.data); break; case BC_RESERVE: printf("_Reserve_\n"); + printf("Num Items="); + expr_print(bc->data.reserve.numitems); + printf("\nItem Size=%u\n", + (unsigned int)bc->data.reserve.itemsize); break; default: printf("_Unknown_\n"); @@ -448,3 +508,98 @@ DebugPrintBC (bytecode *bc) bc->filename ? bc->filename : "", bc->lineno); printf("Offset=%lx BITS=%u\n", bc->offset, bc->mode_bits); } + +dataval * +dataval_new_expr (expr *exp) +{ + dataval *retval = malloc(sizeof(dataval)); + + if(!retval) + Fatal(FATAL_NOMEM); + + retval->next = (dataval *)NULL; + retval->last = retval; + retval->type = DV_EXPR; + retval->data.exp = exp; + + return retval; +} + +dataval * +dataval_new_float (double float_val) +{ + dataval *retval = malloc(sizeof(dataval)); + + if(!retval) + Fatal(FATAL_NOMEM); + + retval->next = (dataval *)NULL; + retval->last = retval; + retval->type = DV_FLOAT; + retval->data.float_val = float_val; + + return retval; +} + +dataval * +dataval_new_string (char *str_val) +{ + dataval *retval = malloc(sizeof(dataval)); + + if(!retval) + Fatal(FATAL_NOMEM); + + retval->next = (dataval *)NULL; + retval->last = retval; + retval->type = DV_STRING; + retval->data.str_val = str_val; + + return retval; +} + +dataval * +dataval_append (dataval *list, dataval *item) +{ + if(item) + item->next = (dataval *)NULL; + + if(!list) { + item->last = item; + return item; + } else { + if(item) { + list->last->next = item; + list->last = item; + item->last = (dataval *)NULL; + } + return list; + } +} + +void +dataval_print (dataval *start) +{ + dataval *cur = start; + + while(cur) { + switch(cur->type) { + case DV_EMPTY: + printf(" Empty\n"); + break; + case DV_EXPR: + printf(" Expr="); + expr_print(cur->data.exp); + printf("\n"); + break; + case DV_FLOAT: + printf(" Float=%e\n", cur->data.float_val); + break; + case DV_STRING: + printf(" String=%s\n", cur->data.str_val); + break; + } + + cur = cur->next; + } +} + diff --git a/src/bytecode.h b/src/bytecode.h index 6b971c33..fafb3b44 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -1,4 +1,4 @@ -/* $Id: bytecode.h,v 1.14 2001/07/11 23:16:50 peter Exp $ +/* $Id: bytecode.h,v 1.15 2001/07/25 00:33:10 peter Exp $ * Bytecode utility functions header file * * Copyright (C) 2001 Peter Johnson @@ -47,6 +47,18 @@ typedef struct immval_s { unsigned char f_sign; /* 1 if final imm should be signed */ } immval; +typedef struct dataval_s { + struct dataval_s *next, *last; + + enum { DV_EMPTY, DV_EXPR, DV_FLOAT, DV_STRING } type; + + union { + struct expr_s *exp; + double float_val; + char *str_val; + } data; +} dataval; + typedef enum jmprel_opcode_sel_e { JR_NONE, JR_SHORT, @@ -64,7 +76,7 @@ typedef struct targetval_s { typedef struct bytecode_s { struct bytecode_s *next; - enum { BC_INSN, BC_JMPREL, BC_DATA, BC_RESERVE } type; + enum { BC_EMPTY, BC_INSN, BC_JMPREL, BC_DATA, BC_RESERVE } type; union { struct { @@ -97,8 +109,15 @@ typedef struct bytecode_s { unsigned char lockrep_pre; /* 0 indicates no prefix */ } jmprel; struct { - unsigned char *data; + dataval *data; /* non-converted data (linked list) */ + + /* final (converted) size of each element (in bytes) */ + unsigned char size; } data; + struct { + struct expr_s *numitems; /* number of items to reserve */ + unsigned char itemsize; /* size of each item (in bytes) */ + } reserve; } data; unsigned long len; /* total length of entire bytecode */ @@ -154,8 +173,22 @@ void BuildBC_JmpRel(bytecode *bc, unsigned char near_op2, unsigned char addrsize); -unsigned char *ConvertBCInsnToBytes(unsigned char *ptr, bytecode *bc, int *len); +void BuildBC_Data(bytecode *bc, + dataval *data, + unsigned long size); + +void BuildBC_Reserve(bytecode *bc, + struct expr_s *numitems, + unsigned long itemsize); void DebugPrintBC(bytecode *bc); +dataval *dataval_new_expr(struct expr_s *exp); +dataval *dataval_new_float(double float_val); +dataval *dataval_new_string(char *str_val); + +dataval *dataval_append(dataval *list, dataval *item); + +void dataval_print(dataval *start); + #endif diff --git a/src/errwarn.c b/src/errwarn.c index cd296f64..b6c4e263 100644 --- a/src/errwarn.c +++ b/src/errwarn.c @@ -1,4 +1,4 @@ -/* $Id: errwarn.c,v 1.16 2001/07/11 23:16:50 peter Exp $ +/* $Id: errwarn.c,v 1.17 2001/07/25 00:33:10 peter Exp $ * Error and warning reporting and related functions. * * Copyright (C) 2001 Peter Johnson @@ -67,7 +67,12 @@ static char *err_msgs[] = { "expression syntax error", "duplicate definition of `%1'; previously defined line %2", "mismatch in operand sizes", - "no %s form of that jump instruction exists" + "no %s form of that jump instruction exists", + "unterminated string", + "unexpected end of file in string", + "expression syntax error", + "floating-point constant encountered in `%s'", + "non-floating-point value encountered in `%s'" }; /* Warning messages. Match up with warn_num enum in errwarn.h. */ @@ -78,7 +83,8 @@ static char *warn_msgs[] = { "multiple segment overrides, using leftmost", "multiple LOCK or REP prefixes, using leftmost", "no non-local label before '%s'", - "multiple SHORT or NEAR specifiers, using leftmost" + "multiple SHORT or NEAR specifiers, using leftmost", + "character constant too large, ignoring trailing characters" }; /* I hate to define these strings as static buffers; a better solution would be diff --git a/src/errwarn.h b/src/errwarn.h index a1e2044b..51bf7175 100644 --- a/src/errwarn.h +++ b/src/errwarn.h @@ -1,4 +1,4 @@ -/* $Id: errwarn.h,v 1.10 2001/07/11 23:16:50 peter Exp $ +/* $Id: errwarn.h,v 1.11 2001/07/25 00:33:10 peter Exp $ * Error and warning reporting and related functions header file. * * Copyright (C) 2001 Peter Johnson @@ -45,7 +45,12 @@ typedef enum { ERR_EXP_SYNTAX, ERR_DUPLICATE_DEF, ERR_OP_SIZE_MISMATCH, - ERR_NO_JMPREL_FORM + ERR_NO_JMPREL_FORM, + ERR_STRING_UNTERM, + ERR_STRING_EOF, + ERR_EXPR_SYNTAX, + ERR_DECLDATA_FLOAT, + ERR_DECLDATA_EXPR } err_num; /* Warning constants. Match up with warn_msgs in errwarn.c. */ @@ -56,7 +61,8 @@ typedef enum { WARN_MULT_SEG_OVERRIDE, WARN_MULT_LOCKREP_PREFIX, WARN_NO_BASE_LABEL, - WARN_MULT_SHORTNEAR + WARN_MULT_SHORTNEAR, + WARN_CHAR_CONST_TOO_BIG } warn_num; char *conv_unprint(char ch); diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index 5a4accf5..d0e1af44 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -1,4 +1,4 @@ -/* $Id: bison.y.in,v 1.21 2001/07/11 21:04:58 peter Exp $ +/* $Id: bison.y.in,v 1.22 2001/07/25 00:33:10 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -33,6 +33,7 @@ void init_table(void); extern int yylex(void); extern void yyerror(char *); +static unsigned long ConvertCharConstToInt(char *); %} @@ -50,12 +51,13 @@ extern void yyerror(char *); expr *exp; immval im_val; targetval tgt_val; + dataval *data; bytecode bc; -} +} %token INTNUM %token FLTNUM -%token DIRECTIVE_NAME DIRECTIVE_VAL +%token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA %token RESERVE_SPACE @@ -86,10 +88,11 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 -%type expr +%type expr expr_no_string %type explabel %type label_id %type target +%type dataval datavals %left '|' %left '^' @@ -104,15 +107,34 @@ input: /* empty */ | input line { OutputError(); OutputWarning(); line_number++; } ; -line: '\n' { $$.len = 0; } +line: '\n' { $$.type = BC_EMPTY; } | exp '\n' { DebugPrintBC(&$1); $$ = $1; } | label exp '\n' { DebugPrintBC(&$2); $$ = $2; } | label '\n' - | directive '\n' { } - | error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; } + | directive '\n' { $$.type = BC_EMPTY; } + | error '\n' { + Error(ERR_INVALID_LINE, (char *)NULL); + $$.type = BC_EMPTY; + yyerrok; + } ; exp: instr + | DECLARE_DATA datavals { BuildBC_Data(&$$, $2, $1); } + | RESERVE_SPACE expr { BuildBC_Reserve(&$$, $2, $1); } +; + +datavals: dataval + | datavals ',' dataval { $$ = dataval_append($1, $3); } +; + +dataval: expr_no_string { $$ = dataval_new_expr($1); } + | FLTNUM { $$ = dataval_new_float($1); } + | STRING { $$ = dataval_new_string($1); } + | error { + Error(ERR_EXPR_SYNTAX, (char *)NULL); + $$ = (dataval *)NULL; + } ; label: label_id { $1->value = 0; } /* TODO: calculate offset */ @@ -312,8 +334,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr: - INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } | explabel { $$ = expr_new_ident (EXPR_SYM, ExprSym(sym_use_get ($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree ($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree ($1, EXPR_OR, $3); } @@ -340,6 +361,10 @@ expr: | '(' expr ')' { $$ = $2; } ; +expr: expr_no_string + | STRING { $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); } +; + explabel: ID | SPECIAL_ID | LOCAL_ID ; instr: instrbase @@ -360,3 +385,31 @@ instr: instrbase /* instruction grammars (dynamically generated) */ /* @INSTRUCTIONS@ */ +%% + +static unsigned long +ConvertCharConstToInt(char *cc) +{ + unsigned long retval = 0; + size_t len = strlen(cc); + + if(len > 4) + Warning(WARN_CHAR_CONST_TOO_BIG, (char *)NULL); + + switch(len) { + case 4: + retval |= (unsigned long)cc[3]; + retval <<= 8; + case 3: + retval |= (unsigned long)cc[2]; + retval <<= 8; + case 2: + retval |= (unsigned long)cc[1]; + retval <<= 8; + case 1: + retval |= (unsigned long)cc[0]; + } + + return retval; +} + diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index 364f84cf..94f11f12 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -1,4 +1,4 @@ -/* $Id: nasm-bison.y,v 1.21 2001/07/11 21:04:58 peter Exp $ +/* $Id: nasm-bison.y,v 1.22 2001/07/25 00:33:10 peter Exp $ * Main bison parser * * Copyright (C) 2001 Peter Johnson, Michael Urman @@ -33,6 +33,7 @@ void init_table(void); extern int yylex(void); extern void yyerror(char *); +static unsigned long ConvertCharConstToInt(char *); %} @@ -50,12 +51,13 @@ extern void yyerror(char *); expr *exp; immval im_val; targetval tgt_val; + dataval *data; bytecode bc; -} +} %token INTNUM %token FLTNUM -%token DIRECTIVE_NAME DIRECTIVE_VAL +%token DIRECTIVE_NAME DIRECTIVE_VAL STRING %token BYTE WORD DWORD QWORD TWORD DQWORD %token DECLARE_DATA %token RESERVE_SPACE @@ -86,10 +88,11 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 -%type expr +%type expr expr_no_string %type explabel %type label_id %type target +%type dataval datavals %left '|' %left '^' @@ -104,15 +107,34 @@ input: /* empty */ | input line { OutputError(); OutputWarning(); line_number++; } ; -line: '\n' { $$.len = 0; } +line: '\n' { $$.type = BC_EMPTY; } | exp '\n' { DebugPrintBC(&$1); $$ = $1; } | label exp '\n' { DebugPrintBC(&$2); $$ = $2; } | label '\n' - | directive '\n' { } - | error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; } + | directive '\n' { $$.type = BC_EMPTY; } + | error '\n' { + Error(ERR_INVALID_LINE, (char *)NULL); + $$.type = BC_EMPTY; + yyerrok; + } ; exp: instr + | DECLARE_DATA datavals { BuildBC_Data(&$$, $2, $1); } + | RESERVE_SPACE expr { BuildBC_Reserve(&$$, $2, $1); } +; + +datavals: dataval + | datavals ',' dataval { $$ = dataval_append($1, $3); } +; + +dataval: expr_no_string { $$ = dataval_new_expr($1); } + | FLTNUM { $$ = dataval_new_float($1); } + | STRING { $$ = dataval_new_string($1); } + | error { + Error(ERR_EXPR_SYNTAX, (char *)NULL); + $$ = (dataval *)NULL; + } ; label: label_id { $1->value = 0; } /* TODO: calculate offset */ @@ -312,8 +334,7 @@ target: expr { $$.val = $1; $$.op_sel = JR_NONE; } ; /* expression trees */ -expr: - INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } +expr_no_string: INTNUM { $$ = expr_new_ident (EXPR_NUM, ExprNum($1)); } | explabel { $$ = expr_new_ident (EXPR_SYM, ExprSym(sym_use_get ($1.name, SYM_LABEL))); } /*| expr '||' expr { $$ = expr_new_tree ($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree ($1, EXPR_OR, $3); } @@ -340,6 +361,10 @@ expr: | '(' expr ')' { $$ = $2; } ; +expr: expr_no_string + | STRING { $$ = expr_new_ident (EXPR_NUM, ExprNum(ConvertCharConstToInt($1))); } +; + explabel: ID | SPECIAL_ID | LOCAL_ID ; instr: instrbase @@ -360,3 +385,31 @@ instr: instrbase /* instruction grammars (dynamically generated) */ /* @INSTRUCTIONS@ */ +%% + +static unsigned long +ConvertCharConstToInt(char *cc) +{ + unsigned long retval = 0; + size_t len = strlen(cc); + + if(len > 4) + Warning(WARN_CHAR_CONST_TOO_BIG, (char *)NULL); + + switch(len) { + case 4: + retval |= (unsigned long)cc[3]; + retval <<= 8; + case 3: + retval |= (unsigned long)cc[2]; + retval <<= 8; + case 2: + retval |= (unsigned long)cc[1]; + retval <<= 8; + case 1: + retval |= (unsigned long)cc[0]; + } + + return retval; +} + diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index b9f29ab8..0cde489f 100644 --- a/src/parsers/nasm/token.l.in +++ b/src/parsers/nasm/token.l.in @@ -1,4 +1,4 @@ -/* $Id: token.l.in,v 1.11 2001/07/11 21:01:54 peter Exp $ +/* $Id: token.l.in,v 1.12 2001/07/25 00:33:10 peter Exp $ * Main lexer * * Copyright (C) 2001 Peter Johnson @@ -37,6 +37,15 @@ #include "expr.h" #include "bison.h" +/* starting size of string buffer */ +#define STRBUF_ALLOC_SIZE 128 + +/* string buffer used when parsing strings/character constants */ +static char *strbuf = (char *)NULL; + +/* length of strbuf (including terminating NULL character) */ +static size_t strbuf_size = 0; + %} %option noyywrap %option nounput @@ -89,6 +98,41 @@ WS [ \t\r] yylval.double_val = strtod(yytext, (char **)NULL); return FLTNUM; } + + /* string/character constant values */ +["'] { + int inch, count; + char endch = yytext[0]; + + strbuf = malloc(STRBUF_ALLOC_SIZE); + if(!strbuf) + Fatal(FATAL_NOMEM); + + strbuf_size = STRBUF_ALLOC_SIZE; + inch = input(); + count = 0; + while(inch != EOF && inch != endch && inch != '\n') { + strbuf[count++] = inch; + if(count >= strbuf_size) { + strbuf = realloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE); + if(!strbuf) + Fatal(FATAL_NOMEM); + strbuf_size += STRBUF_ALLOC_SIZE; + } + inch = input(); + } + + if(inch == '\n') + Error(ERR_STRING_UNTERM, (char *)NULL); + else if(inch == EOF) + Error(ERR_STRING_EOF, (char *)NULL); + + strbuf[count] = '\0'; + + yylval.str_val = strbuf; + return STRING; +} + /* directive: [name value] */ ^"[" { BEGIN DIRECTIVE; return '['; } "]" { BEGIN INITIAL; return ']'; } diff --git a/src/token.l.in b/src/token.l.in index b9f29ab8..0cde489f 100644 --- a/src/token.l.in +++ b/src/token.l.in @@ -1,4 +1,4 @@ -/* $Id: token.l.in,v 1.11 2001/07/11 21:01:54 peter Exp $ +/* $Id: token.l.in,v 1.12 2001/07/25 00:33:10 peter Exp $ * Main lexer * * Copyright (C) 2001 Peter Johnson @@ -37,6 +37,15 @@ #include "expr.h" #include "bison.h" +/* starting size of string buffer */ +#define STRBUF_ALLOC_SIZE 128 + +/* string buffer used when parsing strings/character constants */ +static char *strbuf = (char *)NULL; + +/* length of strbuf (including terminating NULL character) */ +static size_t strbuf_size = 0; + %} %option noyywrap %option nounput @@ -89,6 +98,41 @@ WS [ \t\r] yylval.double_val = strtod(yytext, (char **)NULL); return FLTNUM; } + + /* string/character constant values */ +["'] { + int inch, count; + char endch = yytext[0]; + + strbuf = malloc(STRBUF_ALLOC_SIZE); + if(!strbuf) + Fatal(FATAL_NOMEM); + + strbuf_size = STRBUF_ALLOC_SIZE; + inch = input(); + count = 0; + while(inch != EOF && inch != endch && inch != '\n') { + strbuf[count++] = inch; + if(count >= strbuf_size) { + strbuf = realloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE); + if(!strbuf) + Fatal(FATAL_NOMEM); + strbuf_size += STRBUF_ALLOC_SIZE; + } + inch = input(); + } + + if(inch == '\n') + Error(ERR_STRING_UNTERM, (char *)NULL); + else if(inch == EOF) + Error(ERR_STRING_EOF, (char *)NULL); + + strbuf[count] = '\0'; + + yylval.str_val = strbuf; + return STRING; +} + /* directive: [name value] */ ^"[" { BEGIN DIRECTIVE; return '['; } "]" { BEGIN INITIAL; return ']'; } -- 2.40.0