Implement .RAD50 <CHR> syntax, and tests.

This commit is contained in:
Olaf Seibert
2015-11-09 21:17:57 +01:00
parent fda852a3f1
commit 82f68e0d60
6 changed files with 173 additions and 21 deletions

View File

@@ -1154,33 +1154,60 @@ static int assemble(
report(stack->top, ".RAD50 on odd " "boundary\n");
DOT++; /* Fix it */
}
while (!EOL(*cp)) {
char endstr[6];
int len;
{
char *radstr;
char *radp;
int i, len;
endstr[0] = *cp++;
endstr[1] = '\n';
endstr[2] = 0;
/*
* Allocate storage sufficient for the rest of
* the line.
*/
radstr = memcheck(malloc(strlen(cp)));
len = 0;
len = strcspn(cp, endstr);
radstr = memcheck(malloc(len + 1));
memcpy(radstr, cp, len);
radstr[len] = 0;
cp += len;
if (*cp && *cp != '\n')
cp++;
for (radp = radstr; *radp;) {
unsigned rad;
do {
cp = skipwhite(cp);
if (*cp == '<') {
EX_TREE *value;
/* A byte value */
value = parse_unary_expr(cp, 0);
cp = value->cp;
if (value->type != EX_LIT) {
report(stack->top, "expression must be constant\n");
radstr[len++] = 0;
} else if (value->data.lit >= 050) {
report(stack->top, "invalid character value %o\n", value->data.lit);
radstr[len++] = 0;
} else {
radstr[len++] = value->data.lit;
}
free_tree(value);
} else {
char quote = *cp++;
rad = rad50(radp, &radp);
store_word(stack->top, tr, 2, rad);
while (*cp && *cp != '\n' && *cp != quote) {
int ch = ascii2rad50(*cp++);
if (ch == -1) {
report(stack->top, "invalid character '%c'\n", cp[-1]);
radstr[len++] = 0;
} else {
radstr[len++] = ch;
}
}
cp++; /* Skip closing quote */
}
cp = skipwhite(cp);
} while (!EOL(*cp));
for (i = 0; i < len; i += 3) {
int word = packrad50word(radstr + i, len - i);
store_word(stack->top, tr, 2, word);
}
free(radstr);
cp = skipwhite(cp);
free(radstr);
}
return 1;

40
rad50.c
View File

@@ -118,3 +118,43 @@ void unrad50(
} else
cp[0] = cp[1] = cp[2] = ' ';
}
/* ascii2rad50 - convert a single character to a RAD50 character */
int ascii2rad50(
char c)
{
char *rp;
if (c == '\0') /* Not a RAD50 character */
return -1;
rp = strchr(radtbl, toupper((unsigned char)c));
if (rp == NULL) /* Not a RAD50 character */
return -1;
return (int) (rp - radtbl); /* Convert */
}
/* packrad50word - packs up to 3 characters into a RAD50 word.
*
* The characters should be in the range [0, 050),
* such as having been converted by ascii2rad50().
*/
unsigned packrad50word(
char *cp,
int len)
{
unsigned long acc = 0;
if (len >= 1) {
acc += (cp[0] % 050) * 050 * 050;
}
if (len >= 2) {
acc += (cp[1] % 050) * 050;
}
if (len >= 3) {
acc += cp[2] % 050;
}
return acc;
}

View File

@@ -46,4 +46,11 @@ extern void unrad50(
unsigned word,
char *cp);
int ascii2rad50(
char c);
unsigned packrad50word(
char *cp,
int len);
#endif /* RAD50_H */

View File

@@ -17,6 +17,7 @@ TESTS="test-asciz \
test-locals \
test-macro-comma \
test-psect \
test-rad50 \
test-undef \
test-word-comma"

47
tests/test-rad50.lst.ok Normal file
View File

@@ -0,0 +1,47 @@
1 ;;;;;
2 ;
3 ; Test .rad50 directive
4 ;
5 ;
6 ; 0 space
7 ; 01-32 A-Z
8 ; 33 $
9 ; 34 .
10 ; 35 (undefined)
11 ; 36-47 0-9
12 ;
13 ; radix-50 value: ((C1 * 50) + C2) * 50) + C3 ; everything octal of course
14 ; example: ABC => ((1*50)+2)*50+3 = 3223
15
16 000000 003223 .rad50 /ABC/ ; Packs ABC into one word
17 000002 003223 .rad50 ^ABC^ ; Packs ABC into one word
18 000004 003220 .rad50 /AB/ ; Packs AB (SPACE) into one word
19 000006 003223 014400 .rad50 /ABCD/ ; Packs ABC into first word and
20 ; D (SPACE) (SPACE) into second word.
21 000012 003223 014716 .rad50 /ABCDEF/ ; Packs ABC into first word, DEF into
22 ; second word.
23 000016 003255 .rad50 /AB/<35> ; stores 3255 in one word
test-rad50.mac:24: ***ERROR invalid character '?'
test-rad50.mac:24: ***ERROR invalid character '!'
test-rad50.mac:24: ***ERROR invalid character '='
24 000020 000000 .rad50 /?!=/ ; invalid characters
test-rad50.mac:25: ***ERROR invalid character value 50
test-rad50.mac:25: ***ERROR invalid character value 37777777777
25 000022 000000 .rad50 <0><50><-1> ; invalid characters
26 000001 CHR1=1
27 000002 CHR2=2
28 000003 CHR3=3
29 000024 003223 .RAD50 <1><2><3> ; Equivalent to .RAD50 /ABC/
30 000026 003223 .RAD50 <CHR1><CHR2><CHR3> ; Equivalent to .RAD50 /ABC/
30
Symbol table
. ******R 001 CHR1 =000001 CHR2 =000002 CHR3 =000003
Program sections:
. ABS. 000000 000 (RW,I,GBL,ABS,OVR,NOSAV)
000030 001 (RW,I,LCL,REL,CON,NOSAV)

30
tests/test-rad50.mac Normal file
View File

@@ -0,0 +1,30 @@
;;;;;
;
; Test .rad50 directive
;
;
; 0 space
; 01-32 A-Z
; 33 $
; 34 .
; 35 (undefined)
; 36-47 0-9
;
; radix-50 value: ((C1 * 50) + C2) * 50) + C3 ; everything octal of course
; example: ABC => ((1*50)+2)*50+3 = 3223
.rad50 /ABC/ ; Packs ABC into one word
.rad50 ^ABC^ ; Packs ABC into one word
.rad50 /AB/ ; Packs AB (SPACE) into one word
.rad50 /ABCD/ ; Packs ABC into first word and
; D (SPACE) (SPACE) into second word.
.rad50 /ABCDEF/ ; Packs ABC into first word, DEF into
; second word.
.rad50 /AB/<35> ; stores 3255 in one word
.rad50 /?!=/ ; invalid characters
.rad50 <0><50><-1> ; invalid characters
CHR1=1
CHR2=2
CHR3=3
.RAD50 <1><2><3> ; Equivalent to .RAD50 /ABC/
.RAD50 <CHR1><CHR2><CHR3> ; Equivalent to .RAD50 /ABC/