-/* $Id: errwarn.h,v 1.4 2001/05/30 07:38:42 peter Exp $
+/* $Id: errwarn.h,v 1.5 2001/06/13 05:43:59 mu Exp $
* Error and warning reporting and related functions header file.
*
* Copyright (C) 2001 Peter Johnson
WARN_UNREC_CHAR,
WARN_VALUE_EXCEEDS_BOUNDS,
WARN_MULT_SEG_OVERRIDE,
- WARN_MULT_LOCKREP_PREFIX
+ WARN_MULT_LOCKREP_PREFIX,
+ WARN_NO_BASE_LABEL
} warn_num;
void Warning(warn_num, char *, ...);
-/* $Id: globals.h,v 1.1 2001/05/15 05:28:06 peter Exp $
+/* $Id: globals.h,v 1.2 2001/06/13 05:43:59 mu Exp $
* Globals header file
*
* Copyright (C) 2001 Peter Johnson
extern unsigned int line_number;
extern unsigned int mode_bits;
+extern struct symrec_s *locallabel_base;
#endif
-/* $Id: symrec.h,v 1.2 2001/05/18 21:40:54 peter Exp $
+/* $Id: symrec.h,v 1.3 2001/06/13 05:43:59 mu Exp $
* Symbol table handling header file
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Michael Urman
*
* This file is part of YASM.
*
#ifndef _SYMREC_H_
#define _SYMREC_H_
+typedef enum {
+ SYM_NOSTATUS = 0,
+ SYM_USED = 1 << 0, /* for using variables before declared */
+ SYM_DECLARED = 1 << 1, /* once it's been declared */
+ SYM_VALUED = 1 << 2 /* once its value has been determined */
+} SymStatus;
+
+typedef enum {
+ SYM_CONSTANT, /* for EQU defined symbols */
+ SYM_LABEL, /* for labels */
+ SYM_DATA /* for variables */
+} SymType;
+
typedef struct symrec_s {
char *name;
- int type;
- union {
- double var;
- double (*fnctptr)(void);
- } value;
- struct symrec_s *next;
+ SymType type;
+ SymStatus status;
+ int line;
+ double value;
} symrec;
-extern symrec *sym_table;
+typedef struct symtab_s {
+ symrec rec;
+ struct symtab_s *next;
+} symtab;
+
+extern symtab *sym_table;
+
+/*symrec *putsym(char *, SymType);*/
+/*symrec *getsym(char *);*/
-symrec *putsym(char *, int);
-symrec *getsym(char *);
+symrec *sym_use_get (char *, SymType);
+symrec *sym_def_get (char *, SymType);
+void sym_foreach (int(*)(symrec *));
#endif
-/* $Id: errwarn.c,v 1.5 2001/05/30 07:38:42 peter Exp $
+/* $Id: errwarn.c,v 1.6 2001/06/13 05:43:59 mu Exp $
* Error and warning reporting and related functions.
*
* Copyright (C) 2001 Peter Johnson
"ignoring unrecognized character '%s'",
"%s value exceeds bounds",
"multiple segment overrides, using leftmost",
- "multiple LOCK or REP prefixes, using leftmost"
+ "multiple LOCK or REP prefixes, using leftmost",
+ "no non-local label before '%s'"
};
/* hate to define these as static buffers; better solution would be to use
-/* $Id: errwarn.h,v 1.4 2001/05/30 07:38:42 peter Exp $
+/* $Id: errwarn.h,v 1.5 2001/06/13 05:43:59 mu Exp $
* Error and warning reporting and related functions header file.
*
* Copyright (C) 2001 Peter Johnson
WARN_UNREC_CHAR,
WARN_VALUE_EXCEEDS_BOUNDS,
WARN_MULT_SEG_OVERRIDE,
- WARN_MULT_LOCKREP_PREFIX
+ WARN_MULT_LOCKREP_PREFIX,
+ WARN_NO_BASE_LABEL
} warn_num;
void Warning(warn_num, char *, ...);
-/* $Id: linemgr.h,v 1.1 2001/05/15 05:28:06 peter Exp $
+/* $Id: linemgr.h,v 1.2 2001/06/13 05:43:59 mu Exp $
* Globals header file
*
* Copyright (C) 2001 Peter Johnson
extern unsigned int line_number;
extern unsigned int mode_bits;
+extern struct symrec_s *locallabel_base;
#endif
-/* $Id: symrec.c,v 1.1 2001/05/15 05:24:04 peter Exp $
+/* $Id: symrec.c,v 1.2 2001/06/13 05:43:59 mu Exp $
* Symbol table handling
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Michael Urman
*
* This file is part of YASM.
*
#include <stdlib.h>
#include <string.h>
#include "symrec.h"
+#include "globals.h"
+#include "errwarn.h"
-/* The symbol table: a chain of `symrec'. */
-symrec *sym_table = (symrec *)NULL;
+/* private functions */
+static symtab *symtab_get (char *);
+static symtab *symtab_new (char *, SymType);
+static symtab *symtab_get_or_new (char *, SymType);
+static void symtab_insert (symtab *);
+/* The symbol table: a chain of `symtab'. */
+symtab *sym_table = (symtab *)NULL;
+
+/* insert a symtab into the global sym_table */
+void symtab_insert (symtab *tab)
+{
+ tab->next = (symtab *)sym_table;
+ sym_table = tab;
+}
+
+/* find a symtab in the global sym_table */
+symtab *symtab_get (char *name)
+{
+ symtab *tab;
+ for (tab = sym_table; tab != NULL; tab = tab->next)
+ {
+ if (strcmp (tab->rec.name, name) == 0)
+ {
+ return tab;
+ }
+ }
+ return NULL;
+}
+
+/* call a function with each symrec. stop early if 0 returned */
+void sym_foreach (int(*mapfunc)(symrec *))
+{
+ symtab *tab;
+ for (tab = sym_table; tab != NULL; tab = tab->next)
+ {
+ if (mapfunc(&(tab->rec)) == 0)
+ {
+ return;
+ }
+ }
+}
+
+/* create a new symtab */
+symtab *symtab_new (char *name, SymType type)
+{
+ symtab *tab;
+ tab = malloc(sizeof(symtab));
+ if (tab == NULL) return NULL;
+ tab->rec.name = malloc(strlen(name)+1);
+ if (tab->rec.name == NULL)
+ {
+ free (tab);
+ return NULL;
+ }
+ strcpy(tab->rec.name, name);
+ tab->rec.type = type;
+ tab->rec.value = 0;
+ tab->rec.line = line_number;
+ tab->rec.status = SYM_NOSTATUS;
+ symtab_insert (tab);
+ return tab;
+}
+
+symtab *symtab_get_or_new (char *name, SymType type)
+{
+ symtab *tab;
+ tab = symtab_get (name);
+ if (tab == NULL)
+ {
+ tab = symtab_new (name, type);
+ if (tab == NULL)
+ {
+ Fatal (FATAL_NOMEM);
+ }
+ }
+ return tab;
+}
+
+symrec *sym_use_get (char *name, SymType type)
+{
+ symtab *tab;
+ tab = symtab_get_or_new (name, type);
+ tab->rec.status |= SYM_USED;
+ return &(tab->rec);
+}
+
+symrec *sym_def_get (char *name, SymType type)
+{
+ symtab *tab;
+ tab = symtab_get_or_new (name, type);
+ tab->rec.status |= SYM_DECLARED;
+ return &(tab->rec);
+}
+
+#if 0
symrec *putsym(char *sym_name, int sym_type)
{
symrec *ptr;
return ptr;
return 0;
}
-
+#endif /* 0 */
-/* $Id: symrec.h,v 1.2 2001/05/18 21:40:54 peter Exp $
+/* $Id: symrec.h,v 1.3 2001/06/13 05:43:59 mu Exp $
* Symbol table handling header file
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Michael Urman
*
* This file is part of YASM.
*
#ifndef _SYMREC_H_
#define _SYMREC_H_
+typedef enum {
+ SYM_NOSTATUS = 0,
+ SYM_USED = 1 << 0, /* for using variables before declared */
+ SYM_DECLARED = 1 << 1, /* once it's been declared */
+ SYM_VALUED = 1 << 2 /* once its value has been determined */
+} SymStatus;
+
+typedef enum {
+ SYM_CONSTANT, /* for EQU defined symbols */
+ SYM_LABEL, /* for labels */
+ SYM_DATA /* for variables */
+} SymType;
+
typedef struct symrec_s {
char *name;
- int type;
- union {
- double var;
- double (*fnctptr)(void);
- } value;
- struct symrec_s *next;
+ SymType type;
+ SymStatus status;
+ int line;
+ double value;
} symrec;
-extern symrec *sym_table;
+typedef struct symtab_s {
+ symrec rec;
+ struct symtab_s *next;
+} symtab;
+
+extern symtab *sym_table;
+
+/*symrec *putsym(char *, SymType);*/
+/*symrec *getsym(char *);*/
-symrec *putsym(char *, int);
-symrec *getsym(char *);
+symrec *sym_use_get (char *, SymType);
+symrec *sym_def_get (char *, SymType);
+void sym_foreach (int(*)(symrec *));
#endif
-/* $Id: bison.y.in,v 1.9 2001/05/30 07:41:27 peter Exp $
+/* $Id: bison.y.in,v 1.10 2001/06/13 05:43:59 mu Exp $
* Main bison parser
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Peter Johnson, Michael Urman
*
* This file is part of YASM.
*
char *str_val;
double double_val;
symrec *sym;
+ struct {
+ char *name;
+ int line;
+ } syminfo;
effaddr ea_val;
immval im_val;
bytecode bc;
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
%token START_SECTION_OFFSET ENTRY_POINT
-%token <sym> ID
+%token <syminfo> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
/* @TYPES@ */
-%type <bc> line exp instr instrbase
+%type <bc> line exp instr instrbase label
%type <int_val> fpureg reg32 reg16 reg8 segreg
%type <ea_val> mem memaddr memexp
%type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
%type <ea_val> rm8 rm16 rm32 rm64 rm128
%type <im_val> immexp imm imm8x imm16x imm32x imm8 imm16 imm32
+%type <sym> label_id
%left '-' '+'
%left '*' '/'
line: '\n' { $$.len = 0; }
| exp '\n' { DebugPrintBC(&$1); $$ = $1; }
+ | label exp '\n' { DebugPrintBC(&$2); $$ = $2; }
+ | label '\n'
| directive '\n' { }
| error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; }
;
exp: instr
;
+label: label_id { $1->value = 0; } /* TODO: calculate offset */
+ | label_id ':' { $1->value = 0; } /* TODO: calculate offset */
+;
+
+label_id: ID { $$ = locallabel_base = sym_def_get ($1.name, SYM_LABEL); }
+ | SPECIAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+ | LOCAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+;
+
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
-/* $Id: nasm-bison.y,v 1.9 2001/05/30 07:41:27 peter Exp $
+/* $Id: nasm-bison.y,v 1.10 2001/06/13 05:43:59 mu Exp $
* Main bison parser
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Peter Johnson, Michael Urman
*
* This file is part of YASM.
*
char *str_val;
double double_val;
symrec *sym;
+ struct {
+ char *name;
+ int line;
+ } syminfo;
effaddr ea_val;
immval im_val;
bytecode bc;
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
%token START_SECTION_OFFSET ENTRY_POINT
-%token <sym> ID
+%token <syminfo> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
/* @TYPES@ */
-%type <bc> line exp instr instrbase
+%type <bc> line exp instr instrbase label
%type <int_val> fpureg reg32 reg16 reg8 segreg
%type <ea_val> mem memaddr memexp
%type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
%type <ea_val> rm8 rm16 rm32 rm64 rm128
%type <im_val> immexp imm imm8x imm16x imm32x imm8 imm16 imm32
+%type <sym> label_id
%left '-' '+'
%left '*' '/'
line: '\n' { $$.len = 0; }
| exp '\n' { DebugPrintBC(&$1); $$ = $1; }
+ | label exp '\n' { DebugPrintBC(&$2); $$ = $2; }
+ | label '\n'
| directive '\n' { }
| error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; }
;
exp: instr
;
+label: label_id { $1->value = 0; } /* TODO: calculate offset */
+ | label_id ':' { $1->value = 0; } /* TODO: calculate offset */
+;
+
+label_id: ID { $$ = locallabel_base = sym_def_get ($1.name, SYM_LABEL); }
+ | SPECIAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+ | LOCAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+;
+
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
-/* $Id: token.l.in,v 1.5 2001/05/21 22:10:02 peter Exp $
+/* $Id: token.l.in,v 1.6 2001/06/13 05:43:59 mu Exp $
* Main lexer
*
* Copyright (C) 2001 Peter Johnson
#include "symrec.h"
#include "bytecode.h"
#include "errwarn.h"
+#include "util.h"
#include "bison.tab.h"
%}
%option noyywrap
%option nounput
%option case-insensitive
- static char *locallabel_base = (char *)NULL;
+ symrec *locallabel_base = (symrec *)NULL;
+ int line_number;
%x DIRECTIVE DIRECTIVE2
<DIRECTIVE2>{WS}+ ;
<DIRECTIVE>[a-z]+ {
BEGIN DIRECTIVE2;
- yylval.str_val = strdup(yytext);
+ yylval.str_val = y_strdup(yytext);
if(!yylval.str_val)
Fatal(FATAL_NOMEM);
return DIRECTIVE_NAME;
}
/* everything printable except for ' ', '[' and ']'. */
<DIRECTIVE2>[!-@a-z\\^-`{|}~]+ {
- yylval.str_val = strdup(yytext);
+ yylval.str_val = y_strdup(yytext);
if(!yylval.str_val)
Fatal(FATAL_NOMEM);
return DIRECTIVE_VAL;
/* special non-local ..@label */
\.\.@[a-z0-9_$#@~.?]+ {
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
- return s->type;
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ yylval.syminfo.line = line_number;
+
+ return SPECIAL_ID;
}
/* local label (.label) */
\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* {
- /* TODO: append yytext to locallabel_base before testing */
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
- return s->type;
+ if (locallabel_base == NULL)
+ {
+ Warning (WARN_NO_BASE_LABEL, (char *)NULL, yytext);
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ }
+ else
+ {
+ yylval.syminfo.name = malloc (strlen (yytext)
+ + strlen (locallabel_base->name)
+ + 1);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ strcpy (yylval.syminfo.name, locallabel_base->name);
+ strcat (yylval.syminfo.name, yytext);
+ }
+ yylval.syminfo.line = line_number;
+
+ return LOCAL_ID;
}
/* instructions */
/* label */
[a-z_?][a-z0-9_$#@~.?]* {
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
-
- /* TODO: optimize to decrease number of allocations */
- if(locallabel_base)
- free(locallabel_base);
- locallabel_base = strdup(yytext);
- if(!locallabel_base)
- Fatal(FATAL_NOMEM);
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ yylval.syminfo.line = line_number;
- return s->type;
+ return ID;
}
;.* ;
-/* $Id: bison.y.in,v 1.9 2001/05/30 07:41:27 peter Exp $
+/* $Id: bison.y.in,v 1.10 2001/06/13 05:43:59 mu Exp $
* Main bison parser
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Peter Johnson, Michael Urman
*
* This file is part of YASM.
*
char *str_val;
double double_val;
symrec *sym;
+ struct {
+ char *name;
+ int line;
+ } syminfo;
effaddr ea_val;
immval im_val;
bytecode bc;
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
%token START_SECTION_OFFSET ENTRY_POINT
-%token <sym> ID
+%token <syminfo> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
/* @TYPES@ */
-%type <bc> line exp instr instrbase
+%type <bc> line exp instr instrbase label
%type <int_val> fpureg reg32 reg16 reg8 segreg
%type <ea_val> mem memaddr memexp
%type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
%type <ea_val> rm8 rm16 rm32 rm64 rm128
%type <im_val> immexp imm imm8x imm16x imm32x imm8 imm16 imm32
+%type <sym> label_id
%left '-' '+'
%left '*' '/'
line: '\n' { $$.len = 0; }
| exp '\n' { DebugPrintBC(&$1); $$ = $1; }
+ | label exp '\n' { DebugPrintBC(&$2); $$ = $2; }
+ | label '\n'
| directive '\n' { }
| error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; }
;
exp: instr
;
+label: label_id { $1->value = 0; } /* TODO: calculate offset */
+ | label_id ':' { $1->value = 0; } /* TODO: calculate offset */
+;
+
+label_id: ID { $$ = locallabel_base = sym_def_get ($1.name, SYM_LABEL); }
+ | SPECIAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+ | LOCAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+;
+
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
-/* $Id: errwarn.c,v 1.5 2001/05/30 07:38:42 peter Exp $
+/* $Id: errwarn.c,v 1.6 2001/06/13 05:43:59 mu Exp $
* Error and warning reporting and related functions.
*
* Copyright (C) 2001 Peter Johnson
"ignoring unrecognized character '%s'",
"%s value exceeds bounds",
"multiple segment overrides, using leftmost",
- "multiple LOCK or REP prefixes, using leftmost"
+ "multiple LOCK or REP prefixes, using leftmost",
+ "no non-local label before '%s'"
};
/* hate to define these as static buffers; better solution would be to use
-/* $Id: errwarn.h,v 1.4 2001/05/30 07:38:42 peter Exp $
+/* $Id: errwarn.h,v 1.5 2001/06/13 05:43:59 mu Exp $
* Error and warning reporting and related functions header file.
*
* Copyright (C) 2001 Peter Johnson
WARN_UNREC_CHAR,
WARN_VALUE_EXCEEDS_BOUNDS,
WARN_MULT_SEG_OVERRIDE,
- WARN_MULT_LOCKREP_PREFIX
+ WARN_MULT_LOCKREP_PREFIX,
+ WARN_NO_BASE_LABEL
} warn_num;
void Warning(warn_num, char *, ...);
-/* $Id: globals.h,v 1.1 2001/05/15 05:28:06 peter Exp $
+/* $Id: globals.h,v 1.2 2001/06/13 05:43:59 mu Exp $
* Globals header file
*
* Copyright (C) 2001 Peter Johnson
extern unsigned int line_number;
extern unsigned int mode_bits;
+extern struct symrec_s *locallabel_base;
#endif
-/* $Id: linemgr.h,v 1.1 2001/05/15 05:28:06 peter Exp $
+/* $Id: linemgr.h,v 1.2 2001/06/13 05:43:59 mu Exp $
* Globals header file
*
* Copyright (C) 2001 Peter Johnson
extern unsigned int line_number;
extern unsigned int mode_bits;
+extern struct symrec_s *locallabel_base;
#endif
-/* $Id: bison.y.in,v 1.9 2001/05/30 07:41:27 peter Exp $
+/* $Id: bison.y.in,v 1.10 2001/06/13 05:43:59 mu Exp $
* Main bison parser
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Peter Johnson, Michael Urman
*
* This file is part of YASM.
*
char *str_val;
double double_val;
symrec *sym;
+ struct {
+ char *name;
+ int line;
+ } syminfo;
effaddr ea_val;
immval im_val;
bytecode bc;
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
%token START_SECTION_OFFSET ENTRY_POINT
-%token <sym> ID
+%token <syminfo> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
/* @TYPES@ */
-%type <bc> line exp instr instrbase
+%type <bc> line exp instr instrbase label
%type <int_val> fpureg reg32 reg16 reg8 segreg
%type <ea_val> mem memaddr memexp
%type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
%type <ea_val> rm8 rm16 rm32 rm64 rm128
%type <im_val> immexp imm imm8x imm16x imm32x imm8 imm16 imm32
+%type <sym> label_id
%left '-' '+'
%left '*' '/'
line: '\n' { $$.len = 0; }
| exp '\n' { DebugPrintBC(&$1); $$ = $1; }
+ | label exp '\n' { DebugPrintBC(&$2); $$ = $2; }
+ | label '\n'
| directive '\n' { }
| error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; }
;
exp: instr
;
+label: label_id { $1->value = 0; } /* TODO: calculate offset */
+ | label_id ':' { $1->value = 0; } /* TODO: calculate offset */
+;
+
+label_id: ID { $$ = locallabel_base = sym_def_get ($1.name, SYM_LABEL); }
+ | SPECIAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+ | LOCAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+;
+
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
-/* $Id: nasm-bison.y,v 1.9 2001/05/30 07:41:27 peter Exp $
+/* $Id: nasm-bison.y,v 1.10 2001/06/13 05:43:59 mu Exp $
* Main bison parser
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Peter Johnson, Michael Urman
*
* This file is part of YASM.
*
char *str_val;
double double_val;
symrec *sym;
+ struct {
+ char *name;
+ int line;
+ } syminfo;
effaddr ea_val;
immval im_val;
bytecode bc;
%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
%token START_SECTION_OFFSET ENTRY_POINT
-%token <sym> ID
+%token <syminfo> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TOKENS@ */
/* @TYPES@ */
-%type <bc> line exp instr instrbase
+%type <bc> line exp instr instrbase label
%type <int_val> fpureg reg32 reg16 reg8 segreg
%type <ea_val> mem memaddr memexp
%type <ea_val> rm8x rm16x rm32x /*rm64x rm128x*/
%type <ea_val> rm8 rm16 rm32 rm64 rm128
%type <im_val> immexp imm imm8x imm16x imm32x imm8 imm16 imm32
+%type <sym> label_id
%left '-' '+'
%left '*' '/'
line: '\n' { $$.len = 0; }
| exp '\n' { DebugPrintBC(&$1); $$ = $1; }
+ | label exp '\n' { DebugPrintBC(&$2); $$ = $2; }
+ | label '\n'
| directive '\n' { }
| error '\n' { Error(ERR_INVALID_LINE, (char *)NULL); yyerrok; }
;
exp: instr
;
+label: label_id { $1->value = 0; } /* TODO: calculate offset */
+ | label_id ':' { $1->value = 0; } /* TODO: calculate offset */
+;
+
+label_id: ID { $$ = locallabel_base = sym_def_get ($1.name, SYM_LABEL); }
+ | SPECIAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+ | LOCAL_ID { $$ = sym_def_get ($1.name, SYM_LABEL); }
+;
+
/* directives */
directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' {
printf("Directive: Name='%s' Value='%s'\n", $2, $3);
-/* $Id: token.l.in,v 1.5 2001/05/21 22:10:02 peter Exp $
+/* $Id: token.l.in,v 1.6 2001/06/13 05:43:59 mu Exp $
* Main lexer
*
* Copyright (C) 2001 Peter Johnson
#include "symrec.h"
#include "bytecode.h"
#include "errwarn.h"
+#include "util.h"
#include "bison.tab.h"
%}
%option noyywrap
%option nounput
%option case-insensitive
- static char *locallabel_base = (char *)NULL;
+ symrec *locallabel_base = (symrec *)NULL;
+ int line_number;
%x DIRECTIVE DIRECTIVE2
<DIRECTIVE2>{WS}+ ;
<DIRECTIVE>[a-z]+ {
BEGIN DIRECTIVE2;
- yylval.str_val = strdup(yytext);
+ yylval.str_val = y_strdup(yytext);
if(!yylval.str_val)
Fatal(FATAL_NOMEM);
return DIRECTIVE_NAME;
}
/* everything printable except for ' ', '[' and ']'. */
<DIRECTIVE2>[!-@a-z\\^-`{|}~]+ {
- yylval.str_val = strdup(yytext);
+ yylval.str_val = y_strdup(yytext);
if(!yylval.str_val)
Fatal(FATAL_NOMEM);
return DIRECTIVE_VAL;
/* special non-local ..@label */
\.\.@[a-z0-9_$#@~.?]+ {
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
- return s->type;
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ yylval.syminfo.line = line_number;
+
+ return SPECIAL_ID;
}
/* local label (.label) */
\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* {
- /* TODO: append yytext to locallabel_base before testing */
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
- return s->type;
+ if (locallabel_base == NULL)
+ {
+ Warning (WARN_NO_BASE_LABEL, (char *)NULL, yytext);
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ }
+ else
+ {
+ yylval.syminfo.name = malloc (strlen (yytext)
+ + strlen (locallabel_base->name)
+ + 1);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ strcpy (yylval.syminfo.name, locallabel_base->name);
+ strcat (yylval.syminfo.name, yytext);
+ }
+ yylval.syminfo.line = line_number;
+
+ return LOCAL_ID;
}
/* instructions */
/* label */
[a-z_?][a-z0-9_$#@~.?]* {
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
-
- /* TODO: optimize to decrease number of allocations */
- if(locallabel_base)
- free(locallabel_base);
- locallabel_base = strdup(yytext);
- if(!locallabel_base)
- Fatal(FATAL_NOMEM);
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ yylval.syminfo.line = line_number;
- return s->type;
+ return ID;
}
;.* ;
-/* $Id: symrec.c,v 1.1 2001/05/15 05:24:04 peter Exp $
+/* $Id: symrec.c,v 1.2 2001/06/13 05:43:59 mu Exp $
* Symbol table handling
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Michael Urman
*
* This file is part of YASM.
*
#include <stdlib.h>
#include <string.h>
#include "symrec.h"
+#include "globals.h"
+#include "errwarn.h"
-/* The symbol table: a chain of `symrec'. */
-symrec *sym_table = (symrec *)NULL;
+/* private functions */
+static symtab *symtab_get (char *);
+static symtab *symtab_new (char *, SymType);
+static symtab *symtab_get_or_new (char *, SymType);
+static void symtab_insert (symtab *);
+/* The symbol table: a chain of `symtab'. */
+symtab *sym_table = (symtab *)NULL;
+
+/* insert a symtab into the global sym_table */
+void symtab_insert (symtab *tab)
+{
+ tab->next = (symtab *)sym_table;
+ sym_table = tab;
+}
+
+/* find a symtab in the global sym_table */
+symtab *symtab_get (char *name)
+{
+ symtab *tab;
+ for (tab = sym_table; tab != NULL; tab = tab->next)
+ {
+ if (strcmp (tab->rec.name, name) == 0)
+ {
+ return tab;
+ }
+ }
+ return NULL;
+}
+
+/* call a function with each symrec. stop early if 0 returned */
+void sym_foreach (int(*mapfunc)(symrec *))
+{
+ symtab *tab;
+ for (tab = sym_table; tab != NULL; tab = tab->next)
+ {
+ if (mapfunc(&(tab->rec)) == 0)
+ {
+ return;
+ }
+ }
+}
+
+/* create a new symtab */
+symtab *symtab_new (char *name, SymType type)
+{
+ symtab *tab;
+ tab = malloc(sizeof(symtab));
+ if (tab == NULL) return NULL;
+ tab->rec.name = malloc(strlen(name)+1);
+ if (tab->rec.name == NULL)
+ {
+ free (tab);
+ return NULL;
+ }
+ strcpy(tab->rec.name, name);
+ tab->rec.type = type;
+ tab->rec.value = 0;
+ tab->rec.line = line_number;
+ tab->rec.status = SYM_NOSTATUS;
+ symtab_insert (tab);
+ return tab;
+}
+
+symtab *symtab_get_or_new (char *name, SymType type)
+{
+ symtab *tab;
+ tab = symtab_get (name);
+ if (tab == NULL)
+ {
+ tab = symtab_new (name, type);
+ if (tab == NULL)
+ {
+ Fatal (FATAL_NOMEM);
+ }
+ }
+ return tab;
+}
+
+symrec *sym_use_get (char *name, SymType type)
+{
+ symtab *tab;
+ tab = symtab_get_or_new (name, type);
+ tab->rec.status |= SYM_USED;
+ return &(tab->rec);
+}
+
+symrec *sym_def_get (char *name, SymType type)
+{
+ symtab *tab;
+ tab = symtab_get_or_new (name, type);
+ tab->rec.status |= SYM_DECLARED;
+ return &(tab->rec);
+}
+
+#if 0
symrec *putsym(char *sym_name, int sym_type)
{
symrec *ptr;
return ptr;
return 0;
}
-
+#endif /* 0 */
-/* $Id: symrec.h,v 1.2 2001/05/18 21:40:54 peter Exp $
+/* $Id: symrec.h,v 1.3 2001/06/13 05:43:59 mu Exp $
* Symbol table handling header file
*
- * Copyright (C) 2001 Peter Johnson
+ * Copyright (C) 2001 Michael Urman
*
* This file is part of YASM.
*
#ifndef _SYMREC_H_
#define _SYMREC_H_
+typedef enum {
+ SYM_NOSTATUS = 0,
+ SYM_USED = 1 << 0, /* for using variables before declared */
+ SYM_DECLARED = 1 << 1, /* once it's been declared */
+ SYM_VALUED = 1 << 2 /* once its value has been determined */
+} SymStatus;
+
+typedef enum {
+ SYM_CONSTANT, /* for EQU defined symbols */
+ SYM_LABEL, /* for labels */
+ SYM_DATA /* for variables */
+} SymType;
+
typedef struct symrec_s {
char *name;
- int type;
- union {
- double var;
- double (*fnctptr)(void);
- } value;
- struct symrec_s *next;
+ SymType type;
+ SymStatus status;
+ int line;
+ double value;
} symrec;
-extern symrec *sym_table;
+typedef struct symtab_s {
+ symrec rec;
+ struct symtab_s *next;
+} symtab;
+
+extern symtab *sym_table;
+
+/*symrec *putsym(char *, SymType);*/
+/*symrec *getsym(char *);*/
-symrec *putsym(char *, int);
-symrec *getsym(char *);
+symrec *sym_use_get (char *, SymType);
+symrec *sym_def_get (char *, SymType);
+void sym_foreach (int(*)(symrec *));
#endif
-/* $Id: token.l.in,v 1.5 2001/05/21 22:10:02 peter Exp $
+/* $Id: token.l.in,v 1.6 2001/06/13 05:43:59 mu Exp $
* Main lexer
*
* Copyright (C) 2001 Peter Johnson
#include "symrec.h"
#include "bytecode.h"
#include "errwarn.h"
+#include "util.h"
#include "bison.tab.h"
%}
%option noyywrap
%option nounput
%option case-insensitive
- static char *locallabel_base = (char *)NULL;
+ symrec *locallabel_base = (symrec *)NULL;
+ int line_number;
%x DIRECTIVE DIRECTIVE2
<DIRECTIVE2>{WS}+ ;
<DIRECTIVE>[a-z]+ {
BEGIN DIRECTIVE2;
- yylval.str_val = strdup(yytext);
+ yylval.str_val = y_strdup(yytext);
if(!yylval.str_val)
Fatal(FATAL_NOMEM);
return DIRECTIVE_NAME;
}
/* everything printable except for ' ', '[' and ']'. */
<DIRECTIVE2>[!-@a-z\\^-`{|}~]+ {
- yylval.str_val = strdup(yytext);
+ yylval.str_val = y_strdup(yytext);
if(!yylval.str_val)
Fatal(FATAL_NOMEM);
return DIRECTIVE_VAL;
/* special non-local ..@label */
\.\.@[a-z0-9_$#@~.?]+ {
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
- return s->type;
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ yylval.syminfo.line = line_number;
+
+ return SPECIAL_ID;
}
/* local label (.label) */
\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* {
- /* TODO: append yytext to locallabel_base before testing */
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
- return s->type;
+ if (locallabel_base == NULL)
+ {
+ Warning (WARN_NO_BASE_LABEL, (char *)NULL, yytext);
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ }
+ else
+ {
+ yylval.syminfo.name = malloc (strlen (yytext)
+ + strlen (locallabel_base->name)
+ + 1);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ strcpy (yylval.syminfo.name, locallabel_base->name);
+ strcat (yylval.syminfo.name, yytext);
+ }
+ yylval.syminfo.line = line_number;
+
+ return LOCAL_ID;
}
/* instructions */
/* label */
[a-z_?][a-z0-9_$#@~.?]* {
- symrec *s = getsym(yytext);
- if(!s)
- s = putsym(yytext, ID);
- yylval.sym = s;
-
- /* TODO: optimize to decrease number of allocations */
- if(locallabel_base)
- free(locallabel_base);
- locallabel_base = strdup(yytext);
- if(!locallabel_base)
- Fatal(FATAL_NOMEM);
+ yylval.syminfo.name = y_strdup (yytext);
+ if (yylval.syminfo.name == NULL) Fatal (FATAL_NOMEM);
+ yylval.syminfo.line = line_number;
- return s->type;
+ return ID;
}
;.* ;