From 18205c74c571af97f8f8106698fc9b70ce0c1c0f Mon Sep 17 00:00:00 2001 From: Rangi Date: Sat, 23 Jan 2021 22:20:35 -0500 Subject: [PATCH] Implement [[ inline code blocks ]] Fixes #500 --- include/asm/section.h | 1 + src/asm/lexer.c | 16 +++++++++++---- src/asm/parser.y | 45 +++++++++++++++++++++++++++++++++++++++++-- src/asm/section.c | 5 +++++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/include/asm/section.h b/include/asm/section.h index d8c7855a44..74700f4451 100644 --- a/include/asm/section.h +++ b/include/asm/section.h @@ -46,6 +46,7 @@ void out_SetLoadSection(char const *name, uint32_t secttype, uint32_t org, struct SectionSpec const *attributes); void out_EndLoadSection(void); +struct Section *sect_GetCurrentSection(void); struct Section *sect_GetSymbolSection(void); uint32_t sect_GetSymbolOffset(void); uint32_t sect_GetOutputOffset(void); diff --git a/src/asm/lexer.c b/src/asm/lexer.c index 706363f619..7d44da2a86 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -1650,10 +1650,6 @@ static int yylex_NORMAL(void) yylval.tzSym[1] = '\0'; return T_ID; - case '[': - return T_LBRACK; - case ']': - return T_RBRACK; case '(': return T_LPAREN; case ')': @@ -1663,6 +1659,18 @@ static int yylex_NORMAL(void) /* Handle ambiguous 1- or 2-char tokens */ + case '[': /* Either [ or [[ */ + if (peek(0) == '[') { + shiftChars(1); + return T_2LBRACK; + } + return T_LBRACK; + case ']': /* Either ] or ]] */ + if (peek(0) == ']') { + shiftChars(1); + return T_2RBRACK; + } + return T_RBRACK; case '*': /* Either MUL or EXP */ if (peek(0) == '*') { shiftChars(1); diff --git a/src/asm/parser.y b/src/asm/parser.y index 0ae82123c6..5cc8aacacc 100644 --- a/src/asm/parser.y +++ b/src/asm/parser.y @@ -41,6 +41,7 @@ int32_t nPCOffset; /* Read by rpn_Symbol */ static uint32_t nListCountEmpty; static bool executeElseBlock; /* If this is set, ELIFs cannot be executed anymore */ static struct CaptureBody captureBody; /* Captures a REPT/FOR or MACRO */ +static uint32_t inlineBlockID = 0; /* Incrementing unique ID for inline block labels */ static void upperstring(char *dest, char const *src) { @@ -406,6 +407,12 @@ enum { int32_t step; } forArgs; struct StrFmtArgList strfmtArgs; + struct { + int32_t nPCOffset; + uint32_t nListCountEmpty; + struct Section *sect; + char name[24]; // space for "inline_block$4294967295" + '\0' + } inlineBlock; } %type relocexpr @@ -429,12 +436,15 @@ enum { %type sectorg %type sectattrs +%type inline_block + %token T_NUMBER "number" %token T_STRING "string" %token T_COMMA "," %token T_COLON ":" %token T_LBRACK "[" T_RBRACK "]" +%token T_2LBRACK "[[" T_2RBRACK "]]" %token T_LPAREN "(" T_RPAREN ")" %token T_NEWLINE "newline" @@ -1179,7 +1189,8 @@ reloc_8bit_no_str : relocexpr_no_str { } ; -reloc_16bit : relocexpr { +reloc_16bit : inline_block { rpn_Symbol(&$$, $1.name); } + | relocexpr { if (rpn_isKnown(&$1) && ($1.nVal < -32768 || $1.nVal > 65535)) warning(WARNING_TRUNCATION, "Expression must be 16-bit\n"); @@ -1187,7 +1198,8 @@ reloc_16bit : relocexpr { } ; -reloc_16bit_no_str : relocexpr_no_str { +reloc_16bit_no_str : inline_block { rpn_Symbol(&$$, $1.name); } + | relocexpr_no_str { if (rpn_isKnown(&$1) && ($1.nVal < -32768 || $1.nVal > 65535)) warning(WARNING_TRUNCATION, "Expression must be 16-bit\n"); @@ -1195,6 +1207,35 @@ reloc_16bit_no_str : relocexpr_no_str { } ; +inline_block : T_2LBRACK T_NEWLINE { + struct Section *sect = sect_GetCurrentSection(); + struct SectionSpec attrs; + + attrs.bank = sect->bank == 0 ? -1 : sect->bank; // BANK[0] not allowed + attrs.alignment = sect->align; + attrs.alignOfs = sect->alignOfs; + sect->modifier = SECTION_FRAGMENT; + $$.nPCOffset = nPCOffset; + $$.nListCountEmpty = nListCountEmpty; + out_PushSection(); + sprintf($$.name, "inline_block$%" PRIu32, inlineBlockID++); + out_NewSection($$.name, sect->type, sect->org, &attrs, sect->modifier); + sym_AddLabel($$.name); + $$.sect = sect_GetCurrentSection(); + } lines T_2RBRACK { + out_PopSection(); + struct Section *sect = sect_GetCurrentSection(); + + free($3.sect->name); + $3.sect->name = strdup(sect->name); + if ($3.sect->name == NULL) + fatalerror("Not enough memory for section name: %s\n", strerror(errno)); + nPCOffset = $3.nPCOffset; + nListCountEmpty = $3.nListCountEmpty; + $$.sect = $3.sect; + strcpy($$.name, $3.name); + } +; relocexpr : relocexpr_no_str | string { diff --git a/src/asm/section.c b/src/asm/section.c index f96de32a59..4ba0d623a7 100644 --- a/src/asm/section.c +++ b/src/asm/section.c @@ -364,6 +364,11 @@ void out_EndLoadSection(void) loadOffset = 0; } +struct Section *sect_GetCurrentSection(void) +{ + return pCurrentSection; +} + struct Section *sect_GetSymbolSection(void) { return currentLoadSection ? currentLoadSection : pCurrentSection;