]> granicus.if.org Git - yasm/commitdiff
Add lexing, parsing, and internal format for strings and character constants.
authorPeter Johnson <peter@tortall.net>
Wed, 25 Jul 2001 00:33:10 +0000 (00:33 -0000)
committerPeter Johnson <peter@tortall.net>
Wed, 25 Jul 2001 00:33:10 +0000 (00:33 -0000)
Completely handle data declarations (db/dw/etc) and reserve space declarations
(resb/resw/etc).

svn path=/trunk/yasm/; revision=129

16 files changed:
libyasm/bytecode.c
libyasm/bytecode.h
libyasm/errwarn.c
libyasm/errwarn.h
modules/parsers/nasm/bison.y.in
modules/parsers/nasm/nasm-bison.y
modules/parsers/nasm/token.l.in
src/bison.y.in
src/bytecode.c
src/bytecode.h
src/errwarn.c
src/errwarn.h
src/parsers/nasm/bison.y.in
src/parsers/nasm/nasm-bison.y
src/parsers/nasm/token.l.in
src/token.l.in

index 4f3e631e443f0e437e96cf362cbeebf613877a51..9af7ad0de22aaa66269266b6a11498b6b9f8b818 100644 (file)
@@ -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 <stdio.h>
+#include <stdlib.h>
 #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; i<bc->len; 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 : "<UNKNOWN>", 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;
+    }
+}
+
index 6b971c33c4e2b159bf401fb3f7a10eca2fd6642d..fafb3b4422101324cb0133016abc99bcf2093ebf 100644 (file)
@@ -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
index cd296f6436578c339a37a47daff6d28c82f69d13..b6c4e2637e0c1dfe12ee4841e832c7125ac51790 100644 (file)
@@ -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
index a1e2044b4f7bf849ec76845cf0f6513d6466141e..51bf7175c693458edf4510a5c2578ed0e4e30be3 100644 (file)
@@ -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);
index 5a4accf58c2dea68821b79cf3d8433774f94b934..d0e1af44351ff0d2066ce6e03b7f319d5186135d 100644 (file)
@@ -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 <int_val> INTNUM
 %token <double_val> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL
+%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
 %token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_val> DECLARE_DATA
 %token <int_val> RESERVE_SPACE
@@ -86,10 +88,11 @@ extern void yyerror(char *);
 %type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea_val> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr
+%type <exp> expr expr_no_string
 %type <syminfo> explabel
 %type <sym> label_id
 %type <tgt_val> target
+%type <data> 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;
+}
+
index 364f84cf7b149000ba9d54038745b0fff9179a57..94f11f124b1ab2a8bc2ff3e7abea86ddffb71dde 100644 (file)
@@ -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 <int_val> INTNUM
 %token <double_val> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL
+%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
 %token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_val> DECLARE_DATA
 %token <int_val> RESERVE_SPACE
@@ -86,10 +88,11 @@ extern void yyerror(char *);
 %type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea_val> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr
+%type <exp> expr expr_no_string
 %type <syminfo> explabel
 %type <sym> label_id
 %type <tgt_val> target
+%type <data> 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;
+}
+
index b9f29ab858278a967f8d28636d700afe3cac5d18..0cde489fcc346349279c06745a97a24bfa79f3e4 100644 (file)
@@ -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
 #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 '['; }
 <DIRECTIVE>"]"     { BEGIN INITIAL; return ']'; }
index 5a4accf58c2dea68821b79cf3d8433774f94b934..d0e1af44351ff0d2066ce6e03b7f319d5186135d 100644 (file)
@@ -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 <int_val> INTNUM
 %token <double_val> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL
+%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
 %token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_val> DECLARE_DATA
 %token <int_val> RESERVE_SPACE
@@ -86,10 +88,11 @@ extern void yyerror(char *);
 %type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea_val> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr
+%type <exp> expr expr_no_string
 %type <syminfo> explabel
 %type <sym> label_id
 %type <tgt_val> target
+%type <data> 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;
+}
+
index 4f3e631e443f0e437e96cf362cbeebf613877a51..9af7ad0de22aaa66269266b6a11498b6b9f8b818 100644 (file)
@@ -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 <stdio.h>
+#include <stdlib.h>
 #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; i<bc->len; 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 : "<UNKNOWN>", 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;
+    }
+}
+
index 6b971c33c4e2b159bf401fb3f7a10eca2fd6642d..fafb3b4422101324cb0133016abc99bcf2093ebf 100644 (file)
@@ -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
index cd296f6436578c339a37a47daff6d28c82f69d13..b6c4e2637e0c1dfe12ee4841e832c7125ac51790 100644 (file)
@@ -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
index a1e2044b4f7bf849ec76845cf0f6513d6466141e..51bf7175c693458edf4510a5c2578ed0e4e30be3 100644 (file)
@@ -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);
index 5a4accf58c2dea68821b79cf3d8433774f94b934..d0e1af44351ff0d2066ce6e03b7f319d5186135d 100644 (file)
@@ -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 <int_val> INTNUM
 %token <double_val> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL
+%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
 %token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_val> DECLARE_DATA
 %token <int_val> RESERVE_SPACE
@@ -86,10 +88,11 @@ extern void yyerror(char *);
 %type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea_val> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr
+%type <exp> expr expr_no_string
 %type <syminfo> explabel
 %type <sym> label_id
 %type <tgt_val> target
+%type <data> 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;
+}
+
index 364f84cf7b149000ba9d54038745b0fff9179a57..94f11f124b1ab2a8bc2ff3e7abea86ddffb71dde 100644 (file)
@@ -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 <int_val> INTNUM
 %token <double_val> FLTNUM
-%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL
+%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
 %token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
 %token <int_val> DECLARE_DATA
 %token <int_val> RESERVE_SPACE
@@ -86,10 +88,11 @@ extern void yyerror(char *);
 %type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
 %type <ea_val> rm8 rm16 rm32 rm64 rm128
 %type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
-%type <exp> expr
+%type <exp> expr expr_no_string
 %type <syminfo> explabel
 %type <sym> label_id
 %type <tgt_val> target
+%type <data> 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;
+}
+
index b9f29ab858278a967f8d28636d700afe3cac5d18..0cde489fcc346349279c06745a97a24bfa79f3e4 100644 (file)
@@ -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
 #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 '['; }
 <DIRECTIVE>"]"     { BEGIN INITIAL; return ']'; }
index b9f29ab858278a967f8d28636d700afe3cac5d18..0cde489fcc346349279c06745a97a24bfa79f3e4 100644 (file)
@@ -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
 #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 '['; }
 <DIRECTIVE>"]"     { BEGIN INITIAL; return ']'; }