Skip to content

Commit da8dea1

Browse files
committed
Added @-backslash-string for Spin2
1 parent aaec5eb commit da8dea1

File tree

2 files changed

+86
-6
lines changed

2 files changed

+86
-6
lines changed

Changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Version 7.1.0
22
- Added _rxpoll() to check for character without a timeout
33
- Reverted _rx* functions to no longer use 28 bit internal buffer; this is less resilient to P2 side timing changes, but better if PC timing is uncertain
4+
- Added new Spin2 @\"string" for strings with embedded C-style escapes
45
- Added DITTO to duplicate code/data in Spin2 assembly
56
- Many internal changes to support DITTO and future assembly work
67
- Updated -gbrk debug code (thanks Ada)

frontends/spin/spin.y

Lines changed: 85 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,77 @@ SpinDeclareObjectSymbols(AST *objlist)
126126
}
127127
}
128128

129+
// expand C escapes (like \n) in a string
130+
// return an exprlist of strings and characters
131+
AST *ExpandCEscapes(AST *str) {
132+
AST *elist = NULL;
133+
const char *inpstr;
134+
int c;
135+
136+
if (str->kind != AST_STRING) {
137+
ERROR(str, "Internal error, expected AST_STRING");
138+
return NULL;
139+
}
140+
inpstr = str->d.string;
141+
c = *inpstr++;
142+
while (c) {
143+
int digit = -1;
144+
int d2 = 0;
145+
AST *elem = NULL;
146+
if (c == '\\') {
147+
c = *inpstr++;
148+
switch (c) {
149+
case 'a': digit = 7; break;
150+
case 'b': digit = 8; break;
151+
case 't': digit = 9; break;
152+
case 'n': digit = 10; break;
153+
case 'f': digit = 12; break;
154+
case 'r': digit = 13; break;
155+
case '\\': digit = 92; break;
156+
case 'x':
157+
if (!isxdigit(inpstr[0]) || !isxdigit(inpstr[1])) {
158+
ERROR(str, "illegal escape (should have 2 hex digits after \\x)");
159+
} else {
160+
digit = toupper(inpstr[0]);
161+
if (digit >= 'A' && digit <= 'F')
162+
digit = (digit - 'A') + 10;
163+
else
164+
digit = (digit - '0');
165+
d2 = toupper(inpstr[0]);
166+
if (d2 >= 'A' && d2 <= 'F')
167+
d2 = (d2 - 'A') + 10;
168+
else
169+
d2 = (d2 - '0');
170+
digit = (digit << 4) + d2;
171+
inpstr += 2;
172+
}
173+
break;
174+
default:
175+
break;
176+
}
177+
if (digit != -1) {
178+
elem = NewAST(AST_EXPRLIST, AstInteger(digit), NULL);
179+
} else {
180+
elem = NewAST(AST_EXPRLIST, AstInteger('\\'),
181+
NewAST(AST_EXPRLIST, AstInteger(c), NULL));
182+
}
183+
} else if (c) {
184+
char *dummy = strdup(inpstr-1);
185+
char *ptr = dummy;
186+
while (*ptr && *ptr != '\\')
187+
ptr++;
188+
*ptr = 0;
189+
inpstr += (ptr-dummy)-1;
190+
elem = NewAST(AST_STRING, NULL, NULL);
191+
elem->d.string = dummy;
192+
elem = NewAST(AST_EXPRLIST, elem, NULL);
193+
}
194+
elist = AddToList(elist, elem);
195+
c = *inpstr++;
196+
}
197+
return elist;
198+
}
199+
129200
// in common.c
130201
extern AST *GenericFunctionPtr(int numresults);
131202

@@ -1658,13 +1729,21 @@ expr:
16581729
| '@' expr
16591730
{
16601731
AST *e = $2;
1661-
if (e && e->kind == AST_STRING) {
1662-
LANGUAGE_WARNING(LANG_SPIN_SPIN1, NULL, "@\"string\" is a flexspin extension to Spin1");
1663-
$$ = NewAST(AST_STRINGPTR,
1664-
NewAST(AST_EXPRLIST, e, NULL),
1665-
NULL);
1732+
if (e) {
1733+
if (e->kind == AST_CATCH && e->left && e->left->kind == AST_STRING) {
1734+
LANGUAGE_WARNING(LANG_SPIN_SPIN1, NULL, "@\\\"string\" is a flexspin extension to Spin1");
1735+
AST *str = ExpandCEscapes(e->left);
1736+
$$ = NewAST(AST_STRINGPTR, str, NULL);
1737+
} else if (e->kind == AST_STRING) {
1738+
LANGUAGE_WARNING(LANG_SPIN_SPIN1, NULL, "@\"string\" is a flexspin extension to Spin1");
1739+
$$ = NewAST(AST_STRINGPTR,
1740+
NewAST(AST_EXPRLIST, e, NULL),
1741+
NULL);
1742+
} else {
1743+
$$ = NewAST(AST_ADDROF, e, NULL);
1744+
}
16661745
} else {
1667-
$$ = NewAST(AST_ADDROF, e, NULL);
1746+
SYNTAX_ERROR("@ must be followed by an expression");
16681747
}
16691748
}
16701749
| SP_DOUBLEAT expr

0 commit comments

Comments
 (0)