From: Michael Urman Date: Wed, 13 Jun 2001 05:43:59 +0000 (-0000) Subject: Added handling of labels including: X-Git-Tag: v0.1.0~460 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a6ef33c04cb0351c241a5c308985cfffd295e0e1;p=yasm Added handling of labels including: better symbol table functions calling them from yacc rather than lex a new warning for .label before normal_label locallabel_base now a symrec* instead of a strdup'd string. Still needs some more error checking (to not allow multiple copies of the same label, etc.) Also includes move to y_strdup for bison.y.in (ANSI compatibility) svn path=/trunk/yasm/; revision=51 --- diff --git a/include/errwarn.h b/include/errwarn.h index d46703a0..bad9abbd 100644 --- a/include/errwarn.h +++ b/include/errwarn.h @@ -1,4 +1,4 @@ -/* $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 @@ -49,7 +49,8 @@ typedef enum { 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 *, ...); diff --git a/include/globals.h b/include/globals.h index 8aee77cf..8e183374 100644 --- a/include/globals.h +++ b/include/globals.h @@ -1,4 +1,4 @@ -/* $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 @@ -24,5 +24,6 @@ extern unsigned int line_number; extern unsigned int mode_bits; +extern struct symrec_s *locallabel_base; #endif diff --git a/include/symrec.h b/include/symrec.h index 0ad25246..525c4bd5 100644 --- a/include/symrec.h +++ b/include/symrec.h @@ -1,7 +1,7 @@ -/* $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. * @@ -22,19 +22,39 @@ #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 diff --git a/libyasm/errwarn.c b/libyasm/errwarn.c index fb7b71d2..2c4983ee 100644 --- a/libyasm/errwarn.c +++ b/libyasm/errwarn.c @@ -1,4 +1,4 @@ -/* $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 @@ -51,7 +51,8 @@ static char *warn_msgs[] = { "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 diff --git a/libyasm/errwarn.h b/libyasm/errwarn.h index d46703a0..bad9abbd 100644 --- a/libyasm/errwarn.h +++ b/libyasm/errwarn.h @@ -1,4 +1,4 @@ -/* $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 @@ -49,7 +49,8 @@ typedef enum { 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 *, ...); diff --git a/libyasm/linemgr.h b/libyasm/linemgr.h index ba42d109..81208ecb 100644 --- a/libyasm/linemgr.h +++ b/libyasm/linemgr.h @@ -1,4 +1,4 @@ -/* $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 @@ -24,5 +24,6 @@ extern unsigned int line_number; extern unsigned int mode_bits; +extern struct symrec_s *locallabel_base; #endif diff --git a/libyasm/symrec.c b/libyasm/symrec.c index aff2e6ea..12a7ba46 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -1,7 +1,7 @@ -/* $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. * @@ -22,10 +22,105 @@ #include #include #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; @@ -47,4 +142,4 @@ symrec *getsym(char *sym_name) return ptr; return 0; } - +#endif /* 0 */ diff --git a/libyasm/symrec.h b/libyasm/symrec.h index 0ad25246..525c4bd5 100644 --- a/libyasm/symrec.h +++ b/libyasm/symrec.h @@ -1,7 +1,7 @@ -/* $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. * @@ -22,19 +22,39 @@ #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 diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index 6820f05d..bb0b71bb 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -1,7 +1,7 @@ -/* $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. * @@ -40,6 +40,10 @@ extern void yyerror(char *); char *str_val; double double_val; symrec *sym; + struct { + char *name; + int line; + } syminfo; effaddr ea_val; immval im_val; bytecode bc; @@ -63,14 +67,14 @@ extern void yyerror(char *); %token 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 ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ /* @TYPES@ */ -%type line exp instr instrbase +%type line exp instr instrbase label %type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp @@ -79,6 +83,7 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type immexp imm imm8x imm16x imm32x imm8 imm16 imm32 +%type label_id %left '-' '+' %left '*' '/' @@ -90,6 +95,8 @@ input: /* empty */ 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; } ; @@ -97,6 +104,15 @@ line: '\n' { $$.len = 0; } 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); diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index 1c9cd278..ef594f2a 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -1,7 +1,7 @@ -/* $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. * @@ -40,6 +40,10 @@ extern void yyerror(char *); char *str_val; double double_val; symrec *sym; + struct { + char *name; + int line; + } syminfo; effaddr ea_val; immval im_val; bytecode bc; @@ -63,14 +67,14 @@ extern void yyerror(char *); %token 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 ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ /* @TYPES@ */ -%type line exp instr instrbase +%type line exp instr instrbase label %type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp @@ -79,6 +83,7 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type immexp imm imm8x imm16x imm32x imm8 imm16 imm32 +%type label_id %left '-' '+' %left '*' '/' @@ -90,6 +95,8 @@ input: /* empty */ 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; } ; @@ -97,6 +104,15 @@ line: '\n' { $$.len = 0; } 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); diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index 2ceff815..7aa6cc96 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.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 @@ -25,13 +25,15 @@ #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 @@ -88,14 +90,14 @@ WS [ \t\r] {WS}+ ; [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 ']'. */ [!-@a-z\\^-`{|}~]+ { - yylval.str_val = strdup(yytext); + yylval.str_val = y_strdup(yytext); if(!yylval.str_val) Fatal(FATAL_NOMEM); return DIRECTIVE_VAL; @@ -220,21 +222,33 @@ gs { yylval.int_val = 5; return REG_GS; } /* 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 */ @@ -242,19 +256,11 @@ gs { yylval.int_val = 5; return REG_GS; } /* 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; } ;.* ; diff --git a/src/bison.y.in b/src/bison.y.in index 6820f05d..bb0b71bb 100644 --- a/src/bison.y.in +++ b/src/bison.y.in @@ -1,7 +1,7 @@ -/* $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. * @@ -40,6 +40,10 @@ extern void yyerror(char *); char *str_val; double double_val; symrec *sym; + struct { + char *name; + int line; + } syminfo; effaddr ea_val; immval im_val; bytecode bc; @@ -63,14 +67,14 @@ extern void yyerror(char *); %token 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 ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ /* @TYPES@ */ -%type line exp instr instrbase +%type line exp instr instrbase label %type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp @@ -79,6 +83,7 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type immexp imm imm8x imm16x imm32x imm8 imm16 imm32 +%type label_id %left '-' '+' %left '*' '/' @@ -90,6 +95,8 @@ input: /* empty */ 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; } ; @@ -97,6 +104,15 @@ line: '\n' { $$.len = 0; } 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); diff --git a/src/errwarn.c b/src/errwarn.c index fb7b71d2..2c4983ee 100644 --- a/src/errwarn.c +++ b/src/errwarn.c @@ -1,4 +1,4 @@ -/* $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 @@ -51,7 +51,8 @@ static char *warn_msgs[] = { "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 diff --git a/src/errwarn.h b/src/errwarn.h index d46703a0..bad9abbd 100644 --- a/src/errwarn.h +++ b/src/errwarn.h @@ -1,4 +1,4 @@ -/* $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 @@ -49,7 +49,8 @@ typedef enum { 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 *, ...); diff --git a/src/globals.h b/src/globals.h index 8aee77cf..8e183374 100644 --- a/src/globals.h +++ b/src/globals.h @@ -1,4 +1,4 @@ -/* $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 @@ -24,5 +24,6 @@ extern unsigned int line_number; extern unsigned int mode_bits; +extern struct symrec_s *locallabel_base; #endif diff --git a/src/linemgr.h b/src/linemgr.h index ba42d109..81208ecb 100644 --- a/src/linemgr.h +++ b/src/linemgr.h @@ -1,4 +1,4 @@ -/* $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 @@ -24,5 +24,6 @@ extern unsigned int line_number; extern unsigned int mode_bits; +extern struct symrec_s *locallabel_base; #endif diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index 6820f05d..bb0b71bb 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -1,7 +1,7 @@ -/* $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. * @@ -40,6 +40,10 @@ extern void yyerror(char *); char *str_val; double double_val; symrec *sym; + struct { + char *name; + int line; + } syminfo; effaddr ea_val; immval im_val; bytecode bc; @@ -63,14 +67,14 @@ extern void yyerror(char *); %token 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 ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ /* @TYPES@ */ -%type line exp instr instrbase +%type line exp instr instrbase label %type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp @@ -79,6 +83,7 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type immexp imm imm8x imm16x imm32x imm8 imm16 imm32 +%type label_id %left '-' '+' %left '*' '/' @@ -90,6 +95,8 @@ input: /* empty */ 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; } ; @@ -97,6 +104,15 @@ line: '\n' { $$.len = 0; } 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); diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index 1c9cd278..ef594f2a 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -1,7 +1,7 @@ -/* $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. * @@ -40,6 +40,10 @@ extern void yyerror(char *); char *str_val; double double_val; symrec *sym; + struct { + char *name; + int line; + } syminfo; effaddr ea_val; immval im_val; bytecode bc; @@ -63,14 +67,14 @@ extern void yyerror(char *); %token 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 ID +%token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ /* @TOKENS@ */ /* @TYPES@ */ -%type line exp instr instrbase +%type line exp instr instrbase label %type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp @@ -79,6 +83,7 @@ extern void yyerror(char *); %type rm8x rm16x rm32x /*rm64x rm128x*/ %type rm8 rm16 rm32 rm64 rm128 %type immexp imm imm8x imm16x imm32x imm8 imm16 imm32 +%type label_id %left '-' '+' %left '*' '/' @@ -90,6 +95,8 @@ input: /* empty */ 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; } ; @@ -97,6 +104,15 @@ line: '\n' { $$.len = 0; } 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); diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index 2ceff815..7aa6cc96 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.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 @@ -25,13 +25,15 @@ #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 @@ -88,14 +90,14 @@ WS [ \t\r] {WS}+ ; [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 ']'. */ [!-@a-z\\^-`{|}~]+ { - yylval.str_val = strdup(yytext); + yylval.str_val = y_strdup(yytext); if(!yylval.str_val) Fatal(FATAL_NOMEM); return DIRECTIVE_VAL; @@ -220,21 +222,33 @@ gs { yylval.int_val = 5; return REG_GS; } /* 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 */ @@ -242,19 +256,11 @@ gs { yylval.int_val = 5; return REG_GS; } /* 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; } ;.* ; diff --git a/src/symrec.c b/src/symrec.c index aff2e6ea..12a7ba46 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -1,7 +1,7 @@ -/* $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. * @@ -22,10 +22,105 @@ #include #include #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; @@ -47,4 +142,4 @@ symrec *getsym(char *sym_name) return ptr; return 0; } - +#endif /* 0 */ diff --git a/src/symrec.h b/src/symrec.h index 0ad25246..525c4bd5 100644 --- a/src/symrec.h +++ b/src/symrec.h @@ -1,7 +1,7 @@ -/* $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. * @@ -22,19 +22,39 @@ #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 diff --git a/src/token.l.in b/src/token.l.in index 2ceff815..7aa6cc96 100644 --- a/src/token.l.in +++ b/src/token.l.in @@ -1,4 +1,4 @@ -/* $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 @@ -25,13 +25,15 @@ #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 @@ -88,14 +90,14 @@ WS [ \t\r] {WS}+ ; [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 ']'. */ [!-@a-z\\^-`{|}~]+ { - yylval.str_val = strdup(yytext); + yylval.str_val = y_strdup(yytext); if(!yylval.str_val) Fatal(FATAL_NOMEM); return DIRECTIVE_VAL; @@ -220,21 +222,33 @@ gs { yylval.int_val = 5; return REG_GS; } /* 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 */ @@ -242,19 +256,11 @@ gs { yylval.int_val = 5; return REG_GS; } /* 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; } ;.* ;