1#!/usr/bin/perl
2
3# Z88DK Z80 Macro Assembler
4#
5# Copyright (C) Gunther Strube, InterLogic 1993-99
6# Copyright (C) Paulo Custodio, 2011-2020
7# License: The Artistic License 2.0, http://www.perlfoundation.org/artistic_license_2_0
8# Repository: https://github.com/z88dk/z88dk
9#
10# Test scan.rl
11
12use Modern::Perl;
13use Test::More;
14use File::Slurp;
15use Test::Differences;
16require './t/test_utils.pl';
17
18my $objs = "scan.o errors.o error_func.o model.o module.o codearea.o listfile.o ".
19		   "options.o hist.o sym.o symtab.o expr.o ".
20		   "lib/str.o lib/strhash.o  ../common/fileutil.o ../common/strutil.o ../common/die.o ../common/objfile.o ../../ext/regex/regcomp.o ../../ext/regex/regerror.o ../../ext/regex/regexec.o ../../ext/regex/regfree.o modlink.o zobjfile.o libfile.o ".
21		   "lib/srcfile.o macros.o lib/class.o ".
22		   "lib/list.o lib/array.o lib/dbg.o ../common/zutils.o z80asm.o z80pass.o directives.o parse.o opcodes.o ";
23if ($^O eq 'MSWin32' || $^O eq 'msys') {
24	  $objs .= "../../ext/UNIXem/src/glob.o ../../ext/UNIXem/src/dirent.o ";
25}
26
27my $init = <<'END';
28#include "macros.h"
29#include "scan.h"
30#include "strutil.h"
31#include "symbol.h"
32#include "utstring.h"
33#include <assert.h>
34
35char *GetLibfile( char *filename ) {return NULL;}
36
37#define T_GET_N( exp_token, exp_text, exp_len ) \
38	token = GetSym(); \
39	assert( token   == exp_token ); \
40	assert( sym.tok == exp_token ); \
41	assert( sym.tlen == exp_len ); \
42	assert( strncmp( sym.tstart, exp_text, sym.tlen ) == 0 );
43
44#define T_GET( exp_token, exp_text ) \
45	T_GET_N( exp_token, exp_text, strlen(exp_text) )
46
47#define T_NAME_LABEL( exp_token, exp_text ) \
48	T_GET( exp_token, exp_text );
49
50#define T_NAME(  exp_text ) 		T_NAME_LABEL( TK_NAME,  exp_text );
51#define T_LABEL( exp_text ) 		T_NAME_LABEL( TK_LABEL, exp_text );
52
53#define T_NUMBER( exp_value ) \
54	T_GET( TK_NUMBER, "" ); \
55	assert( sym.number == exp_value );
56
57#define T_STRING_N( exp_string, n ) \
58	T_GET_N( TK_STRING, exp_string, n ); \
59	assert( sym.tlen == n); \
60	assert( strncmp( sym.tstart, exp_string, sym.tlen ) == 0 );
61
62#define T_STRING( exp_string ) \
63	T_STRING_N( exp_string, strlen(exp_string) );
64
65#define T_NEWLINE() \
66	T_GET( TK_NEWLINE, "\n" ); assert( EOL ); \
67	T_GET( TK_NEWLINE, "\n" ); assert( EOL ); \
68	T_GET( TK_NEWLINE, "\n" ); assert( EOL ); \
69	EOL = false;
70
71#define T_NIL()				T_GET( TK_NIL,			"" );
72#define T_EXCLAM()			T_GET( TK_LOG_NOT,		"!" );
73#define T_HASH()			T_GET( TK_CONST_EXPR,	"#" );
74#define T_PERCENT()			T_GET( TK_MOD,			"%" );
75
76#define T_AND()				T_GET( TK_BIN_AND,		"&" );
77
78#define T_AND_AND()			T_GET( TK_LOG_AND,		"&&" );
79#define T_LPAREN()			T_GET( TK_LPAREN,		"(" );
80#define T_RPAREN()			T_GET( TK_RPAREN,		")" );
81#define T_STAR() 			T_GET( TK_MULTIPLY,		"*" );
82#define T_PLUS() 			T_GET( TK_PLUS,			"+" );
83#define T_COMMA()			T_GET( TK_COMMA,		"," );
84#define T_MINUS()			T_GET( TK_MINUS,		"-" );
85#define T_DOT()				T_GET( TK_DOT, 			"." );
86#define T_SLASH()			T_GET( TK_DIVIDE, 		"/" );
87
88#define T_COLON()			T_GET( TK_COLON,		":" );
89
90#define T_LT()				T_GET( TK_LESS, 		"<" );
91#define T_LT_LT()			T_GET( TK_LEFT_SHIFT,	"<<" );
92#define T_LT_EQ()			T_GET( TK_LESS_EQ,		"<=" );
93#define T_LT_GT()			T_GET( TK_NOT_EQ,		"<>" );
94#define T_EXCLAM_EQ()		T_GET( TK_NOT_EQ,		"!=" );
95#define T_EQ()				T_GET( TK_EQUAL, 		"=" );
96#define T_EQ_EQ()			T_GET( TK_EQUAL, 		"==" );
97#define T_GT()				T_GET( TK_GREATER, 		">" );
98#define T_GT_GT()			T_GET( TK_RIGHT_SHIFT,	">>" );
99#define T_GT_EQ()			T_GET( TK_GREATER_EQ,	">=" );
100
101#define TEXT_QUESTION()		" ? "
102#define T_QUESTION()		T_GET( TK_QUESTION,		"?" );
103
104#define T_LSQUARE()			T_GET( TK_LSQUARE, 		"[" );
105#define T_RSQUARE()			T_GET( TK_RSQUARE, 		"]" );
106
107#define T_CARET()			T_GET( TK_BIN_XOR, 		"^" );
108
109#define T_STAR_STAR()		T_GET( TK_POWER, 		"**" );
110
111#define T_LCURLY()			T_GET( TK_LCURLY, 		"{" );
112#define T_VBAR()			T_GET( TK_BIN_OR, 		"|" );
113#define T_VBAR_VBAR()		T_GET( TK_LOG_OR, 		"||" );
114#define T_RCURLY()			T_GET( TK_RCURLY, 		"}" );
115
116#define T_TILDE()			T_GET( TK_BIN_NOT, 		"~" );
117
118#define T_END() \
119	T_GET( TK_END, "" ); \
120	T_GET( TK_END, "" ); \
121	T_GET( TK_END, "" );
122
123#define T_Z80		1
124#define T_RABBIT	2
125#define T_ALL		3
126
127#define T_OPCODE1(opcode, opcode_cmp) \
128			SetTemporaryLine(string); \
129			scan_expect_opcode(); \
130			T_GET(TK_##opcode, opcode_cmp); \
131			T_NAME(opcode_cmp); \
132			T_END(); \
133			SetTemporaryLine(string); \
134			scan_expect_operands(); \
135			T_NAME(opcode_cmp); \
136			T_NAME(opcode_cmp); \
137			T_END();
138
139#define T_OPCODE2(opcode, opcode_cmp, _cpu) \
140		if (_cpu & CPU_Z80) { \
141			opts.cpu &= ~CPU_RABBIT; \
142			T_OPCODE1(opcode, opcode_cmp); \
143		} \
144		if (_cpu & CPU_RABBIT) { \
145			opts.cpu |= CPU_RABBIT; \
146			T_OPCODE1(opcode, opcode_cmp); \
147		}
148
149#define T_OPCODE(opcode, _cpu)	\
150		strcpy(opcode_lcase, #opcode); \
151		strtolower(opcode_lcase); \
152		strcpy(string, #opcode " " #opcode); \
153		strtolower(string); \
154		T_OPCODE2(opcode, opcode_lcase, _cpu); \
155		strtoupper(string); \
156		T_OPCODE2(opcode, #opcode, _cpu);
157
158END
159
160t_compile_module($init, <<'END', $objs);
161	tokid_t token;
162	char string[MAXLINE];
163	char opcode_lcase[MAXLINE];
164
165	init_macros();
166	SetTemporaryLine("");
167	T_END();
168
169
170	/* invalid chars */
171	SetTemporaryLine(" \\ hello \n . ");
172	T_NIL();
173	T_NEWLINE();
174	T_DOT();
175	T_END();
176
177
178	/* at_bol = true */
179	SetTemporaryLine("\n \t start \t : \t . start : \n");
180	T_NEWLINE();
181	T_LABEL("start");
182	T_DOT();
183	T_NAME("start");
184	T_COLON();
185	T_NEWLINE();
186	T_END();
187
188	SetTemporaryLine("\n \t . \t start \t : \t . start : \n");
189	T_NEWLINE();
190	T_LABEL("start");
191	T_COLON();
192	T_DOT();
193	T_NAME("start");
194	T_COLON();
195	T_NEWLINE();
196	T_END();
197
198	SetTemporaryLine("\n \t . \t start \t . start : \n");
199	T_NEWLINE();
200	T_LABEL("start");
201	T_DOT();
202	T_NAME("start");
203	T_COLON();
204	T_NEWLINE();
205	T_END();
206
207	SetTemporaryLine("\n \t . \t : \t . start : \n");
208	T_NEWLINE();
209	T_DOT();
210	T_COLON();
211	T_DOT();
212	T_NAME("start");
213	T_COLON();
214	T_NEWLINE();
215	T_END();
216
217
218	/* at_bol = false */
219	SetTemporaryLine(" \t start \t : \t . start : \n");
220	T_NAME("start");
221	T_COLON();
222	T_DOT();
223	T_NAME("start");
224	T_COLON();
225	T_NEWLINE();
226	T_END();
227
228	SetTemporaryLine(" \t . \t start \t : \t . start : \n");
229	T_DOT();
230	T_NAME("start");
231	T_COLON();
232	T_DOT();
233	T_NAME("start");
234	T_COLON();
235	T_NEWLINE();
236	T_END();
237
238	SetTemporaryLine(" \t . \t start \t . start : \n");
239	T_DOT();
240	T_NAME("start");
241	T_DOT();
242	T_NAME("start");
243	T_COLON();
244	T_NEWLINE();
245	T_END();
246
247	SetTemporaryLine(" \t . \t : \t . start : \n");
248	T_DOT();
249	T_COLON();
250	T_DOT();
251	T_NAME("start");
252	T_COLON();
253	T_NEWLINE();
254	T_END();
255
256
257	/* symbols */
258	SetTemporaryLine(" \r\f\v\t ; comment \n ! # % & && ( ) * + , - . / : ; comment ");
259	T_NEWLINE();
260	T_EXCLAM();
261	T_HASH();
262	T_PERCENT();
263	T_AND();
264	T_AND_AND();
265	T_LPAREN();
266	T_RPAREN();
267	T_STAR();
268	T_PLUS();
269	T_COMMA();
270	T_MINUS();
271	T_DOT();
272	T_SLASH();
273	T_COLON();
274	T_END();
275
276	SetTemporaryLine(" < << <= <> != = == > >> >= ; comment ");
277	T_LT();
278	T_LT_LT();
279	T_LT_EQ();
280	T_LT_GT();
281	T_EXCLAM_EQ();
282	T_EQ();
283	T_EQ_EQ();
284	T_GT();
285	T_GT_GT();
286	T_GT_EQ();
287	T_END();
288
289	SetTemporaryLine( TEXT_QUESTION() " [ ] ^ ** { | || } ~ ; comment ");
290	T_QUESTION();
291	T_LSQUARE();
292	T_RSQUARE();
293	T_CARET();
294	T_STAR_STAR();
295	T_LCURLY();
296	T_VBAR();
297	T_VBAR_VBAR();
298	T_RCURLY();
299	T_TILDE();
300	T_END();
301
302	/* names */
303	SetTemporaryLine(" _Abc_123 Abc_123 123_Abc_0 0 ");
304	T_NAME("_Abc_123");
305	T_NAME("Abc_123");
306	T_NUMBER(123);
307	T_NAME("_Abc_0");
308	T_NUMBER(0);
309	T_END();
310
311	/* labels */
312	SetTemporaryLine(  "\n . abc   . def ghi : . jkl : "
313					   "\n   abc : . def ghi : . jkl : "
314					   "\n . abc : . def ghi : . jkl : "
315					   "\n");
316	T_NEWLINE();
317	T_LABEL("abc");
318	T_DOT();
319	T_NAME("def");
320	T_NAME("ghi");
321	T_COLON();
322	T_DOT();
323	T_NAME("jkl");
324	T_COLON();
325
326	T_NEWLINE();
327	T_LABEL("abc");
328	T_DOT();
329	T_NAME("def");
330	T_NAME("ghi");
331	T_COLON();
332	T_DOT();
333	T_NAME("jkl");
334	T_COLON();
335
336	T_NEWLINE();
337	T_LABEL("abc");
338	T_COLON();
339	T_DOT();
340	T_NAME("def");
341	T_NAME("ghi");
342	T_COLON();
343	T_DOT();
344	T_NAME("jkl");
345	T_COLON();
346
347	T_NEWLINE();
348	T_END();
349
350	/* numbers - decimal */
351	SetTemporaryLine("2147483647 2147483648 0 1");
352	T_NUMBER(0x7FFFFFFF);
353	T_NUMBER(0x80000000);
354	T_NUMBER(0);
355	T_NUMBER(1);
356	T_END();
357
358	/* numbers - binary */
359	SetTemporaryLine  ("   0000b     0011b      1111111111111111111111111111111b	"
360					   "  @0000     @0011      @1111111111111111111111111111111		"
361					   "  %0000     %0011      %1111111111111111111111111111111		"
362					   " 0b0000    0b0011     0b1111111111111111111111111111111		"
363					   "@\"----\" @\"--##\"  @\"###############################\"	"
364					   "%\"----\" %\"--##\"  %\"###############################\"	"
365					   "@\"#\" 														"
366					   "@\"#---\"													"
367					   "@\"#-------\"												"
368					   "@\"#-----------\" 											"
369					   "@\"#---------------\" 										"
370					   "@\"#-------------------\"									"
371					   "@\"#-----------------------\" 								"
372					   "@\"#---------------------------\" 							"
373					   "@\"#-------------------------------\"						");
374	T_NUMBER(0x00000000);
375	T_NUMBER(0x00000003);
376	T_NUMBER(0x7FFFFFFF);
377
378	T_NUMBER(0x00000000);
379	T_NUMBER(0x00000003);
380	T_NUMBER(0x7FFFFFFF);
381
382	T_NUMBER(0x00000000);
383	T_NUMBER(0x00000003);
384	T_NUMBER(0x7FFFFFFF);
385
386	T_NUMBER(0x00000000);
387	T_NUMBER(0x00000003);
388	T_NUMBER(0x7FFFFFFF);
389
390	T_NUMBER(0x00000000);
391	T_NUMBER(0x00000003);
392	T_NUMBER(0x7FFFFFFF);
393
394	T_NUMBER(0x00000000);
395	T_NUMBER(0x00000003);
396	T_NUMBER(0x7FFFFFFF);
397
398	T_NUMBER(0x00000001);
399	T_NUMBER(0x00000008);
400	T_NUMBER(0x00000080);
401	T_NUMBER(0x00000800);
402	T_NUMBER(0x00008000);
403	T_NUMBER(0x00080000);
404	T_NUMBER(0x00800000);
405	T_NUMBER(0x08000000);
406	T_NUMBER(0x80000000);
407	T_END();
408
409	/* numbers - hexadecimal */
410	SetTemporaryLine(  "  0h  0ah 0FH  7FFFFFFFh	"
411					   " $0   $a  $F  $7FFFFFFF 	"
412					   "0x0  0xa 0xF 0x7FFFFFFF		"
413					   "0");
414	T_NUMBER(0x00000000);
415	T_NUMBER(0x0000000A);
416	T_NUMBER(0x0000000F);
417	T_NUMBER(0x7FFFFFFF);
418
419	T_NUMBER(0x00000000);
420	T_NUMBER(0x0000000A);
421	T_NUMBER(0x0000000F);
422	T_NUMBER(0x7FFFFFFF);
423
424	T_NUMBER(0x00000000);
425	T_NUMBER(0x0000000A);
426	T_NUMBER(0x0000000F);
427	T_NUMBER(0x7FFFFFFF);
428
429	T_NUMBER(0);
430	T_END();
431
432	/* very long number > MAXLINE = 1024 --> truncates to 0 */
433	SetTemporaryLine(  "0000000000000000000000000000000000000000"
434					   "0000000000000000000000000000000000000000"
435					   "0000000000000000000000000000000000000000"
436					   "0000000000000000000000000000000000000000"
437					   "0000000000000000000000000000000000000000"
438					   "0000000000000000000000000000000000000000"
439					   "0000000000000000000000000000000000000000"
440					   "0000000000000000000000000000000000000000"
441					   "0000000000000000000000000000000000000000"
442					   "0000000000000000000000000000000000000000"
443					   "0000000000000000000000000000000000000000"
444					   "0000000000000000000000000000000000000000"
445					   "0000000000000000000000000000000000000000"
446					   "0000000000000000000000000000000000000000"
447					   "0000000000000000000000000000000000000000"
448					   "0000000000000000000000000000000000000000"
449					   "0000000000000000000000000000000000000000"
450					   "0000000000000000000000000000000000000000"
451					   "0000000000000000000000000000000000000000"
452					   "0000000000000000000000000000000000000000"
453					   "0000000000000000000000000000000000000000"
454					   "0000000000000000000000000000000000000000"
455					   "0000000000000000000000000000000000000000"
456					   "0000000000000000000000000000000000000000"
457					   "0000000000000000000000000000000000000000"
458					   "0000000000000000000000000000000000000000"
459					   "0000000000000000000000000000000000000000"
460					   "0000000000000000000000000000000000000000"
461					   "0000000000000000000000000000000000000000"
462					   "0000000000000000000000000000000000000000"
463					   "0000000000000000000000000000000000000000"
464					   "0000000000000000000000000000000000000000"
465					   "0000000000000000000000000000000000000000"
466					   "0000000000000000000000000000000000000000"
467					   "0000000000000000000000000000000000000000"
468					   "0000000000000000000000000000000000000000"
469					   "0000000000000000000000000000000000000000"
470					   "0000000000000000000000000000000000000000"
471					   "0000000000000000000000000000000000000000"
472					   "0000000000000000000000000000000000000000"
473					   "0000000000000000000000000000000000000000"
474					   "0000000000000000000000000000000000000000"
475					   "0000000000000000000000000000000000000000"
476					   "0000000000000000000000000000000000000000"
477					   "0000000000000000000000000000000000000000"
478					   "0000000000000000000000000000000000000000"
479					   "0000000000000000000000000000000000000000"
480					   "0000000000000000000000000000000000000000"
481					   "0000000000000000000000000000000000000000"
482					   "0000000000000000000000000000000000000000"
483					   "0000000000000000000000000000000000000000"
484					   "0000000000000000000000000000000000000000"
485					   "0000000000000000000000000000000000000000"
486					   "0000000000000000000000000000000000000000"
487					   "0000000000000000000000000000000000000000"
488					   "0000000000000000000000000000000000000000"
489					   "0000000000000000000000000000000000000000"
490					   "0000000000000000000000000000000000000000"
491					   "0000000000000000000000000000000000000000"
492					   "0000000000000000000000000000000000000000"
493					   "0000000000000000000000000000000000000000"
494					   "0000000000000000000000000000000000000000"
495					   "0000000000000000000000000000000000000000"
496					   "0000000000000000000000000000000000000000"
497					   "1");
498	T_NUMBER(1);
499	T_END();
500
501	/* strings - single-quote */
502	SetTemporaryLine(  "'\n"
503					   "'a\n"
504					   "''\n"
505					   "'a'\n"
506					   "'aa'\n"
507					   "'\\a''\\b''\\f''\\n''\\r''\\t''\\v'"
508					   "'\\\\''\\'''\\0''\\377''\\xff'\n"
509					   "0");
510	T_NUMBER(0);
511	T_NEWLINE();
512
513	T_NUMBER(0);
514	T_NEWLINE();
515
516	T_NUMBER(0);
517	T_NEWLINE();
518
519	T_NUMBER('a');
520	T_NEWLINE();
521
522	T_NUMBER(0);
523	T_NEWLINE();
524
525	T_NUMBER(7);
526	T_NUMBER(8);
527	T_NUMBER(12);
528	T_NUMBER(10);
529	T_NUMBER(13);
530	T_NUMBER(9);
531	T_NUMBER(11);
532	T_NUMBER('\\');
533	T_NUMBER('\'');
534	T_NUMBER(0);
535	T_NUMBER(-1);
536	T_NUMBER(-1);
537	T_NEWLINE();
538
539	T_NUMBER(0);
540	T_END();
541
542	/* strings - double-quote */
543	SetTemporaryLine(  "\"\n"
544					   "\"a\n"
545					   "\"\"\n"
546					   "\"a\"\n"
547					   "\"aa\"\n"
548					   "\"\"\n"
549					   "0");
550	T_STRING("");
551	T_NEWLINE();
552
553	T_STRING("");
554	T_NEWLINE();
555
556	T_STRING("");
557	T_NEWLINE();
558
559	T_STRING("a");
560	T_NEWLINE();
561
562	T_STRING("aa");
563	T_NEWLINE();
564
565	T_STRING("");
566	T_NEWLINE();
567
568	T_NUMBER(0);
569	T_END();
570
571	/* keywords */
572	SetTemporaryLine("nz z nc c po pe p m "
573					 "NZ Z NC C PO PE P M ");
574	T_GET(TK_NZ, "nz");
575	T_GET(TK_Z,  "z");
576	T_GET(TK_NC, "nc");
577	T_GET(TK_C,  "c");
578	T_GET(TK_PO, "po");
579	T_GET(TK_PE, "pe");
580	T_GET(TK_P,  "p");
581	T_GET(TK_M,  "m");
582
583	T_GET(TK_NZ, "NZ");
584	T_GET(TK_Z,  "Z");
585	T_GET(TK_NC, "NC");
586	T_GET(TK_C,  "C");
587	T_GET(TK_PO, "PO");
588	T_GET(TK_PE, "PE");
589	T_GET(TK_P,  "P");
590	T_GET(TK_M,  "M");
591	T_END();
592
593	SetTemporaryLine("b c d e h l a ixh ixl iyh iyl "
594					 "B C D E H L A IXH IXL IYH IYL ");
595	T_GET(TK_B,   "b");
596	T_GET(TK_C,   "c");
597	T_GET(TK_D,   "d");
598	T_GET(TK_E,   "e");
599	T_GET(TK_H,   "h");
600	T_GET(TK_L,   "l");
601	T_GET(TK_A,   "a");
602	T_GET(TK_IXH, "ixh");
603	T_GET(TK_IXL, "ixl");
604	T_GET(TK_IYH, "iyh");
605	T_GET(TK_IYL, "iyl");
606
607	T_GET(TK_B,   "B");
608	T_GET(TK_C,   "C");
609	T_GET(TK_D,   "D");
610	T_GET(TK_E,   "E");
611	T_GET(TK_H,   "H");
612	T_GET(TK_L,   "L");
613	T_GET(TK_A,   "A");
614	T_GET(TK_IXH, "IXH");
615	T_GET(TK_IXL, "IXL");
616	T_GET(TK_IYH, "IYH");
617	T_GET(TK_IYL, "IYL");
618	T_END();
619
620	SetTemporaryLine("f (c) (\t c \t) "
621					 "F (C) (\t C \t) "
622					 "(cur)");		// (c is not interpreted as TK_IND_C
623	T_GET(TK_F,     "f");
624	T_GET(TK_IND_C, "(c");
625	T_RPAREN();
626	T_GET(TK_IND_C, "(\t c \t");
627	T_RPAREN();
628
629	T_GET(TK_F,     "F");
630	T_GET(TK_IND_C, "(C");
631	T_RPAREN();
632	T_GET(TK_IND_C, "(\t C \t");
633	T_RPAREN();
634	T_LPAREN();
635	T_NAME("cur");
636	T_RPAREN();
637	T_END();
638
639	SetTemporaryLine("bc bc' de de' hl hl' af af' sp ix iy "
640					 "BC BC' DE DE' HL HL' AF AF' SP IX IY ");
641	T_GET(TK_BC,  "bc");
642	T_GET(TK_BC1, "bc'");
643	T_GET(TK_DE,  "de");
644	T_GET(TK_DE1, "de'");
645	T_GET(TK_HL,  "hl");
646	T_GET(TK_HL1, "hl'");
647	T_GET(TK_AF,  "af");
648	T_GET(TK_AF1, "af'");
649	T_GET(TK_SP,  "sp");
650	T_GET(TK_IX,  "ix");
651	T_GET(TK_IY,  "iy");
652
653	T_GET(TK_BC,  "BC");
654	T_GET(TK_BC1, "BC'");
655	T_GET(TK_DE,  "DE");
656	T_GET(TK_DE1, "DE'");
657	T_GET(TK_HL,  "HL");
658	T_GET(TK_HL1, "HL'");
659	T_GET(TK_AF,  "AF");
660	T_GET(TK_AF1, "AF'");
661	T_GET(TK_SP,  "SP");
662	T_GET(TK_IX,  "IX");
663	T_GET(TK_IY,  "IY");
664	T_END();
665
666	SetTemporaryLine("(bc) (de) (hl) (sp) (\t bc \t) (\t de \t) (\t hl \t) (\t sp \t) "
667					 "(BC) (DE) (HL) (SP) (\t BC \t) (\t DE \t) (\t HL \t) (\t SP \t) ");
668	T_GET(TK_IND_BC, "(bc"); T_RPAREN();
669	T_GET(TK_IND_DE, "(de"); T_RPAREN();
670	T_GET(TK_IND_HL, "(hl"); T_RPAREN();
671	T_GET(TK_IND_SP, "(sp"); T_RPAREN();
672
673	T_GET(TK_IND_BC, "(\t bc \t"); T_RPAREN();
674	T_GET(TK_IND_DE, "(\t de \t"); T_RPAREN();
675	T_GET(TK_IND_HL, "(\t hl \t"); T_RPAREN();
676	T_GET(TK_IND_SP, "(\t sp \t"); T_RPAREN();
677
678	T_GET(TK_IND_BC, "(BC"); T_RPAREN();
679	T_GET(TK_IND_DE, "(DE"); T_RPAREN();
680	T_GET(TK_IND_HL, "(HL"); T_RPAREN();
681	T_GET(TK_IND_SP, "(SP"); T_RPAREN();
682
683	T_GET(TK_IND_BC, "(\t BC \t"); T_RPAREN();
684	T_GET(TK_IND_DE, "(\t DE \t"); T_RPAREN();
685	T_GET(TK_IND_HL, "(\t HL \t"); T_RPAREN();
686	T_GET(TK_IND_SP, "(\t SP \t"); T_RPAREN();
687	T_END();
688
689	SetTemporaryLine("(ix) (iy) (\t ix \t) (\t iy \t) "
690					 "(IX) (IY) (\t IX \t) (\t IY \t) ");
691	T_GET(TK_IND_IX, "(ix");
692	T_RPAREN();
693	T_GET(TK_IND_IY, "(iy");
694	T_RPAREN();
695	T_GET(TK_IND_IX, "(\t ix \t");
696	T_RPAREN();
697	T_GET(TK_IND_IY, "(\t iy \t");
698	T_RPAREN();
699
700	T_GET(TK_IND_IX, "(IX");
701	T_RPAREN();
702	T_GET(TK_IND_IY, "(IY");
703	T_RPAREN();
704	T_GET(TK_IND_IX, "(\t IX \t");
705	T_RPAREN();
706	T_GET(TK_IND_IY, "(\t IY \t");
707	T_RPAREN();
708	T_END();
709
710	SetTemporaryLine("( \t ix \t ) ( \t ix \t + \t 0 \t ) ( \t ix \t - \t 0 \t ) "
711					 "( \t iy \t ) ( \t iy \t + \t 0 \t ) ( \t iy \t - \t 0 \t ) "
712					 "( \t IX \t ) ( \t IX \t + \t 0 \t ) ( \t IX \t - \t 0 \t ) "
713					 "( \t IY \t ) ( \t IY \t + \t 0 \t ) ( \t IY \t - \t 0 \t ) "
714					 );
715	T_GET(TK_IND_IX, "( \t ix \t ");
716	T_RPAREN();
717	T_GET(TK_IND_IX, "( \t ix \t ");
718	T_PLUS();
719	T_NUMBER(0);
720	T_RPAREN();
721	T_GET(TK_IND_IX, "( \t ix \t ");
722	T_MINUS();
723	T_NUMBER(0);
724	T_RPAREN();
725
726	T_GET(TK_IND_IY, "( \t iy \t ");
727	T_RPAREN();
728	T_GET(TK_IND_IY, "( \t iy \t ");
729	T_PLUS();
730	T_NUMBER(0);
731	T_RPAREN();
732	T_GET(TK_IND_IY, "( \t iy \t ");
733	T_MINUS();
734	T_NUMBER(0);
735	T_RPAREN();
736
737	T_GET(TK_IND_IX, "( \t IX \t ");
738	T_RPAREN();
739	T_GET(TK_IND_IX, "( \t IX \t ");
740	T_PLUS();
741	T_NUMBER(0);
742	T_RPAREN();
743	T_GET(TK_IND_IX, "( \t IX \t ");
744	T_MINUS();
745	T_NUMBER(0);
746	T_RPAREN();
747
748	T_GET(TK_IND_IY, "( \t IY \t ");
749	T_RPAREN();
750	T_GET(TK_IND_IY, "( \t IY \t ");
751	T_PLUS();
752	T_NUMBER(0);
753	T_RPAREN();
754	T_GET(TK_IND_IY, "( \t IY \t ");
755	T_MINUS();
756	T_NUMBER(0);
757	T_RPAREN();
758	T_END();
759
760	SetTemporaryLine("ds.b ds.w ds.p ds.q "
761					 "DS.B DS.W DS.P DS.Q ");
762	T_GET(TK_DS_B, "ds.b");
763	T_GET(TK_DS_W, "ds.w");
764	T_GET(TK_DS_P, "ds.p");
765	T_GET(TK_DS_Q, "ds.q");
766
767	T_GET(TK_DS_B, "DS.B");
768	T_GET(TK_DS_W, "DS.W");
769	T_GET(TK_DS_P, "DS.P");
770	T_GET(TK_DS_Q, "DS.Q");
771	T_END();
772
773
774	/* assembly operands */
775	SetTemporaryLine("i r I R iir eir IIR EIR xpc XPC");
776	scan_expect_operands();
777	T_GET(TK_I,    "i");
778	T_GET(TK_R,    "r");
779	T_GET(TK_I,    "I");
780	T_GET(TK_R,    "R");
781	T_GET(TK_IIR,   "iir");
782	T_GET(TK_EIR,   "eir");
783	T_GET(TK_IIR,   "IIR");
784	T_GET(TK_EIR,   "EIR");
785	T_GET(TK_XPC,   "xpc");
786	T_GET(TK_XPC,   "XPC");
787	T_END();
788
789
790	/* assembly directives */
791	T_OPCODE(BINARY,	T_ALL);
792	T_OPCODE(DEFB,		T_ALL);
793	T_OPCODE(DEFC,		T_ALL);
794	T_OPCODE(DEFGROUP,	T_ALL);
795	T_OPCODE(DEFINE,	T_ALL);
796	T_OPCODE(DEFQ,		T_ALL);
797	T_OPCODE(DEFM,		T_ALL);
798	T_OPCODE(DEFS,		T_ALL);
799	T_OPCODE(DEFVARS,	T_ALL);
800	T_OPCODE(DEFW,		T_ALL);
801	T_OPCODE(ELSE,		T_ALL);
802	T_OPCODE(ENDIF,		T_ALL);
803	T_OPCODE(EXTERN,	T_ALL);
804	T_OPCODE(GLOBAL,	T_ALL);
805	T_OPCODE(IF,		T_ALL);
806	T_OPCODE(IFDEF,		T_ALL);
807	T_OPCODE(IFNDEF,	T_ALL);
808	T_OPCODE(INCLUDE,	T_ALL);
809	T_OPCODE(LINE,		T_ALL);
810	T_OPCODE(LSTOFF,	T_ALL);
811	T_OPCODE(LSTON,		T_ALL);
812	T_OPCODE(MODULE,	T_ALL);
813	T_OPCODE(ORG,		T_ALL);
814	T_OPCODE(PUBLIC,	T_ALL);
815	T_OPCODE(SECTION,	T_ALL);
816	T_OPCODE(UNDEFINE,	T_ALL);
817
818	/* assembly opcodes */
819	T_OPCODE(ADC,	T_ALL);
820	T_OPCODE(ADD,	T_ALL);
821	T_OPCODE(AND,	T_ALL);
822	T_OPCODE(BIT,  	T_ALL)
823	T_OPCODE(CALL,	T_ALL);
824	T_OPCODE(CCF,	T_ALL);
825	T_OPCODE(CP,	T_ALL);
826	T_OPCODE(CPD,	T_ALL);
827	T_OPCODE(CPDR,	T_ALL);
828	T_OPCODE(CPI,	T_ALL);
829	T_OPCODE(CPIR,	T_ALL);
830	T_OPCODE(CPL,	T_ALL);
831	T_OPCODE(DAA,	T_Z80);
832	T_OPCODE(DEC,	T_ALL);
833	T_OPCODE(DI,	T_Z80);
834	T_OPCODE(DJNZ,	T_ALL);
835	T_OPCODE(EI,	T_Z80);
836	T_OPCODE(EX,	T_ALL);
837	T_OPCODE(EXX,	T_ALL);
838	T_OPCODE(HALT,	T_Z80);
839	T_OPCODE(IM,	T_Z80);
840	T_OPCODE(IN,	T_Z80);
841	T_OPCODE(INC,	T_ALL);
842	T_OPCODE(IND,	T_Z80);
843	T_OPCODE(INDR,	T_Z80);
844	T_OPCODE(INI,	T_Z80);
845	T_OPCODE(INIR,	T_Z80);
846	T_OPCODE(JP,	T_ALL);
847	T_OPCODE(JR,	T_ALL);
848	T_OPCODE(LD,	T_ALL);
849	T_OPCODE(LDD,	T_ALL);
850	T_OPCODE(LDDR,	T_ALL);
851	T_OPCODE(LDI,	T_ALL);
852	T_OPCODE(LDIR,	T_ALL);
853	T_OPCODE(NEG,	T_ALL);
854	T_OPCODE(NOP,	T_ALL);
855	T_OPCODE(OR,	T_ALL);
856	T_OPCODE(OTDR,	T_Z80);
857	T_OPCODE(OTIR,	T_Z80);
858	T_OPCODE(OUT,	T_Z80);
859	T_OPCODE(OUTD,	T_Z80);
860	T_OPCODE(OUTI,	T_Z80);
861	T_OPCODE(POP,	T_ALL);
862	T_OPCODE(PUSH,	T_ALL);
863	T_OPCODE(RES,  	T_ALL)
864	T_OPCODE(RET,	T_ALL);
865	T_OPCODE(RETI,	T_ALL);
866	T_OPCODE(RETN,	T_Z80);
867	T_OPCODE(RL,   	T_ALL)
868	T_OPCODE(RLA,  	T_ALL);
869	T_OPCODE(RLC,  	T_ALL)
870	T_OPCODE(RLCA, 	T_ALL);
871	T_OPCODE(RLD,	T_ALL);
872	T_OPCODE(RR,   	T_ALL)
873	T_OPCODE(RRA,  	T_ALL);
874	T_OPCODE(RRC,  	T_ALL)
875	T_OPCODE(RRCA, 	T_ALL);
876	T_OPCODE(RRD,	T_ALL);
877	T_OPCODE(RST,	T_ALL);
878	T_OPCODE(SBC,	T_ALL);
879	T_OPCODE(SCF,	T_ALL);
880	T_OPCODE(SET,  	T_ALL)
881	T_OPCODE(SLA,  	T_ALL)
882	T_OPCODE(SLL,  	T_Z80)
883	T_OPCODE(SLI,  	T_Z80)
884	T_OPCODE(SRA,  	T_ALL)
885	T_OPCODE(SRL,  	T_ALL)
886	T_OPCODE(SUB,	T_ALL);
887	T_OPCODE(XOR,	T_ALL);
888
889	/* Z88DK specific opcodes */
890	T_OPCODE(CALL_OZ,	T_ALL);
891	T_OPCODE(CALL_PKG,	T_ALL);
892	T_OPCODE(FPP,		T_ALL);
893	T_OPCODE(INVOKE,	T_ALL);
894
895	/* check limit cases */
896	SetTemporaryLine("ld(ix_save+2),ix "
897					 "ld ( ix_save + 2 ) , ix ");
898	T_NAME("ld");
899	T_LPAREN();
900	T_NAME("ix_save");
901	T_PLUS();
902	T_NUMBER(2);
903	T_RPAREN();
904	T_COMMA();
905	T_GET(TK_IX, "ix");
906
907	T_NAME("ld");
908	T_LPAREN();
909	T_NAME("ix_save");
910	T_PLUS();
911	T_NUMBER(2);
912	T_RPAREN();
913	T_COMMA();
914	T_GET(TK_IX, "ix");
915	T_END();
916
917	free_macros();
918
919	return 0;
920
921END
922
923t_run_module([], '', <<'ERR', 0);
924Error: invalid single quoted character
925Error: invalid single quoted character
926Error: invalid single quoted character
927Error: invalid single quoted character
928Error: unclosed quoted string
929Error: unclosed quoted string
930ERR
931
932unlink_testfiles();
933done_testing;
934