1 /*****************************************************************************/
5 /* Pseudo instructions for the ca65 macroassembler */
9 /* (C) 1998-2002 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
69 /*****************************************************************************/
71 /*****************************************************************************/
75 /* Keyword we're about to handle */
76 static char Keyword [sizeof (SVal)+1] = ".";
80 /*****************************************************************************/
82 /*****************************************************************************/
86 static void DoUnexpected (void);
87 /* Got an unexpected keyword */
89 static void DoInvalid (void);
90 /* Handle a token that is invalid here, since it should have been handled on
91 * a much lower level of the expression hierarchy. Getting this sort of token
92 * means that the lower level code has bugs.
93 * This function differs to DoUnexpected in that the latter may be triggered
94 * by the user by using keywords in the wrong location. DoUnexpected is not
95 * an error in the assembler itself, while DoInvalid is.
100 /*****************************************************************************/
101 /* Helper functions */
102 /*****************************************************************************/
106 static void SetBoolOption (unsigned char* Flag)
107 /* Read a on/off/+/- option and set flag accordingly */
109 static const char* Keys[] = {
114 if (Tok == TOK_PLUS) {
117 } else if (Tok == TOK_MINUS) {
120 } else if (Tok == TOK_IDENT) {
121 /* Map the keyword to a number */
122 switch (GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]))) {
123 case 0: *Flag = 0; NextTok (); break;
124 case 1: *Flag = 1; NextTok (); break;
125 default: ErrorSkip (ERR_ONOFF_EXPECTED); break;
127 } else if (Tok == TOK_SEP || Tok == TOK_EOF) {
128 /* Without anything assume switch on */
131 ErrorSkip (ERR_ONOFF_EXPECTED);
137 static void ExportImport (void (*SymFunc) (const char*, int), int ZP)
138 /* Export or import symbols */
141 if (Tok != TOK_IDENT) {
142 ErrorSkip (ERR_IDENT_EXPECTED);
147 if (Tok == TOK_COMMA) {
157 static long IntArg (long Min, long Max)
158 /* Read an integer argument and check a range. Accept the token "unlimited"
159 * and return -1 in this case.
162 if (Tok == TOK_IDENT && strcmp (SVal, "unlimited") == 0) {
166 long Val = ConstExpression ();
167 if (Val < Min || Val > Max) {
177 static void ConDes (const char* Name, unsigned Type)
178 /* Parse remaining line for constructor/destructor of the remaining type */
182 /* Optional constructor priority */
183 if (Tok == TOK_COMMA) {
184 /* Priority value follows */
186 Prio = ConstExpression ();
187 if (Prio < CD_PRIO_MIN || Prio > CD_PRIO_MAX) {
188 /* Value out of range */
193 /* Use the default priority value */
197 /* Define the symbol */
198 SymConDes (Name, Type, (unsigned) Prio);
203 /*****************************************************************************/
204 /* Handler functions */
205 /*****************************************************************************/
209 static void DoA16 (void)
210 /* Switch the accu to 16 bit mode (assembler only) */
212 if (GetCPU() != CPU_65816) {
213 Error (ERR_816_MODE_ONLY);
215 /* Immidiate mode has two extension bytes */
216 ExtBytes [AMI_IMM_ACCU] = 2;
222 static void DoA8 (void)
223 /* Switch the accu to 8 bit mode (assembler only) */
225 if (GetCPU() != CPU_65816) {
226 Error (ERR_816_MODE_ONLY);
228 /* Immidiate mode has one extension byte */
229 ExtBytes [AMI_IMM_ACCU] = 1;
235 static void DoAddr (void)
236 /* Define addresses */
239 if (GetCPU() == CPU_65816) {
240 EmitWord (ForceWordExpr (Expression ()));
242 /* Do a range check */
243 EmitWord (Expression ());
245 if (Tok != TOK_COMMA) {
255 static void DoAlign (void)
256 /* Align the PC to some boundary */
262 /* Read the alignment value */
263 Align = ConstExpression ();
264 if (Align <= 0 || Align > 0x10000) {
265 ErrorSkip (ERR_RANGE);
269 /* Optional value follows */
270 if (Tok == TOK_COMMA) {
272 Val = ConstExpression ();
273 /* We need a byte value here */
274 if (!IsByteRange (Val)) {
275 ErrorSkip (ERR_RANGE);
282 /* Check if the alignment is a power of two */
283 Bit = BitFind (Align);
284 if (Align != (0x01L << Bit)) {
287 SegAlign (Bit, (int) Val);
293 static void DoASCIIZ (void)
294 /* Define text with a zero terminator */
299 /* Must have a string constant */
300 if (Tok != TOK_STRCON) {
301 ErrorSkip (ERR_STRCON_EXPECTED);
305 /* Get the length of the string constant */
308 /* Translate into target charset and emit */
309 TgtTranslateBuf (SVal, Len);
310 EmitData ((unsigned char*) SVal, Len);
312 if (Tok == TOK_COMMA) {
323 static void DoAutoImport (void)
324 /* Mark unresolved symbols as imported */
326 SetBoolOption (&AutoImport);
331 static void DoBss (void)
332 /* Switch to the BSS segment */
339 static void DoByte (void)
343 if (Tok == TOK_STRCON) {
344 /* A string, translate into target charset and emit */
345 unsigned Len = strlen (SVal);
346 TgtTranslateBuf (SVal, Len);
347 EmitData ((unsigned char*) SVal, Len);
350 EmitByte (Expression ());
352 if (Tok != TOK_COMMA) {
356 /* Do smart handling of dangling comma */
357 if (Tok == TOK_SEP) {
358 Error (ERR_UNEXPECTED_EOL);
367 static void DoCase (void)
368 /* Switch the IgnoreCase option */
370 SetBoolOption (&IgnoreCase);
371 IgnoreCase = !IgnoreCase;
376 static void DoCharMap (void)
377 /* Allow custome character mappings */
382 /* Read the index as numerical value */
383 Index = ConstExpression ();
384 if (Index < 1 || Index > 255) {
385 /* Value out of range */
386 ErrorSkip (ERR_RANGE);
393 /* Read the character code */
394 Code = ConstExpression ();
395 if (Code < 1 || Code > 255) {
396 /* Value out of range */
397 ErrorSkip (ERR_RANGE);
401 /* Set the character translation */
402 TgtTranslateSet ((unsigned) Index, (unsigned char) Code);
407 static void DoCode (void)
408 /* Switch to the code segment */
415 static void DoConDes (void)
416 /* Export a symbol as constructor/destructor */
418 static const char* Keys[] = {
422 char Name [sizeof (SVal)];
425 /* Symbol name follows */
426 if (Tok != TOK_IDENT) {
427 ErrorSkip (ERR_IDENT_EXPECTED);
433 /* Type follows. May be encoded as identifier or numerical */
435 if (Tok == TOK_IDENT) {
437 /* Map the following keyword to a number, then skip it */
438 Type = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
441 /* Check if we got a valid keyword */
450 /* Read the type as numerical value */
451 Type = ConstExpression ();
452 if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
453 /* Value out of range */
460 /* Parse the remainder of the line and export the symbol */
461 ConDes (Name, (unsigned) Type);
466 static void DoConstructor (void)
467 /* Export a symbol as constructor */
469 char Name [sizeof (SVal)];
471 /* Symbol name follows */
472 if (Tok != TOK_IDENT) {
473 ErrorSkip (ERR_IDENT_EXPECTED);
479 /* Parse the remainder of the line and export the symbol */
480 ConDes (Name, CD_TYPE_CON);
485 static void DoData (void)
486 /* Switch to the data segment */
493 static void DoDbg (void)
494 /* Add debug information from high level code */
496 static const char* Keys[] = {
504 /* We expect a subkey */
505 if (Tok != TOK_IDENT) {
506 ErrorSkip (ERR_IDENT_EXPECTED);
510 /* Map the following keyword to a number */
511 Key = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
513 /* Skip the subkey */
516 /* Check the key and dispatch to a handler */
518 case 0: DbgInfoFile (); break;
519 case 1: DbgInfoLine (); break;
520 case 2: DbgInfoSym (); break;
521 default: ErrorSkip (ERR_SYNTAX); break;
527 static void DoDByt (void)
528 /* Output double bytes */
531 EmitWord (SwapExpr (Expression ()));
532 if (Tok != TOK_COMMA) {
542 static void DoDebugInfo (void)
543 /* Switch debug info on or off */
545 SetBoolOption (&DbgSyms);
550 static void DoDefine (void)
551 /* Define a one line macro */
553 MacDef (MAC_STYLE_DEFINE);
558 static void DoDestructor (void)
559 /* Export a symbol as destructor */
561 char Name [sizeof (SVal)];
563 /* Symbol name follows */
564 if (Tok != TOK_IDENT) {
565 ErrorSkip (ERR_IDENT_EXPECTED);
571 /* Parse the remainder of the line and export the symbol */
572 ConDes (Name, CD_TYPE_DES);
577 static void DoDWord (void)
581 EmitDWord (Expression ());
582 if (Tok != TOK_COMMA) {
592 static void DoEnd (void)
593 /* End of assembly */
600 static void DoEndProc (void)
601 /* Leave a lexical level */
608 static void DoError (void)
611 if (Tok != TOK_STRCON) {
612 ErrorSkip (ERR_STRCON_EXPECTED);
614 Error (ERR_USER, SVal);
621 static void DoExitMacro (void)
622 /* Exit a macro expansion */
624 if (!InMacExpansion ()) {
625 /* We aren't expanding a macro currently */
634 static void DoExport (void)
635 /* Export a symbol */
637 ExportImport (SymExport, 0);
642 static void DoExportZP (void)
643 /* Export a zeropage symbol */
645 ExportImport (SymExport, 1);
650 static void DoFarAddr (void)
651 /* Define far addresses (24 bit) */
654 EmitFarAddr (Expression ());
655 if (Tok != TOK_COMMA) {
665 static void DoFeature (void)
666 /* Switch the Feature option */
668 /* Allow a list of comma separated keywords */
671 /* We expect an identifier */
672 if (Tok != TOK_IDENT) {
673 ErrorSkip (ERR_IDENT_EXPECTED);
677 /* Make the string attribute lower case */
680 /* Set the feature and check for errors */
681 if (SetFeature (SVal) == FEAT_UNKNOWN) {
683 ErrorSkip (ERR_ILLEGAL_FEATURE);
686 /* Skip the keyword */
690 /* Allow more than one keyword */
691 if (Tok == TOK_COMMA) {
701 static void DoFileOpt (void)
702 /* Insert a file option */
706 /* The option type may be given as a keyword or as a number. */
707 if (Tok == TOK_IDENT) {
709 /* Option given as keyword */
710 static const char* Keys [] = {
711 "AUTHOR", "COMMENT", "COMPILER"
714 /* Map the option to a number */
715 OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
718 ErrorSkip (ERR_OPTION_KEY_EXPECTED);
722 /* Skip the keyword */
725 /* Must be followed by a comma */
728 /* We accept only string options for now */
729 if (Tok != TOK_STRCON) {
730 ErrorSkip (ERR_STRCON_EXPECTED);
734 /* Insert the option */
753 Internal ("Invalid OptNum: %l", OptNum);
762 /* Option given as number */
763 OptNum = ConstExpression ();
764 if (!IsByteRange (OptNum)) {
765 ErrorSkip (ERR_RANGE);
769 /* Must be followed by a comma */
772 /* We accept only string options for now */
773 if (Tok != TOK_STRCON) {
774 ErrorSkip (ERR_STRCON_EXPECTED);
778 /* Insert the option */
779 OptStr ((unsigned char) OptNum, SVal);
788 static void DoGlobal (void)
789 /* Declare a global symbol */
791 ExportImport (SymGlobal, 0);
796 static void DoGlobalZP (void)
797 /* Declare a global zeropage symbol */
799 ExportImport (SymGlobal, 1);
804 static void DoI16 (void)
805 /* Switch the index registers to 16 bit mode (assembler only) */
807 if (GetCPU() != CPU_65816) {
808 Error (ERR_816_MODE_ONLY);
810 /* Immidiate mode has two extension bytes */
811 ExtBytes [AMI_IMM_INDEX] = 2;
817 static void DoI8 (void)
818 /* Switch the index registers to 16 bit mode (assembler only) */
820 if (GetCPU() != CPU_65816) {
821 Error (ERR_816_MODE_ONLY);
823 /* Immidiate mode has one extension byte */
824 ExtBytes [AMI_IMM_INDEX] = 1;
830 static void DoImport (void)
831 /* Import a symbol */
833 ExportImport (SymImport, 0);
838 static void DoImportZP (void)
839 /* Import a zero page symbol */
841 ExportImport (SymImport, 1);
846 static void DoIncBin (void)
847 /* Include a binary file */
849 char Name [sizeof (SVal)];
855 /* Name must follow */
856 if (Tok != TOK_STRCON) {
857 ErrorSkip (ERR_STRCON_EXPECTED);
863 /* A starting offset may follow */
864 if (Tok == TOK_COMMA) {
866 Start = ConstExpression ();
868 /* And a length may follow */
869 if (Tok == TOK_COMMA) {
871 Count = ConstExpression ();
876 /* Try to open the file */
877 F = fopen (Name, "rb");
879 ErrorSkip (ERR_CANNOT_OPEN_INCLUDE, Name, strerror (errno));
883 /* Get the size of the file */
884 fseek (F, 0, SEEK_END);
887 /* If a count was not given, calculate it now */
889 Count = Size - Start;
891 /* Nothing to read - flag this as a range error */
892 ErrorSkip (ERR_RANGE);
896 /* Count was given, check if it is valid */
897 if (Start + Count > Size) {
898 ErrorSkip (ERR_RANGE);
903 /* Seek to the start position */
904 fseek (F, Start, SEEK_SET);
906 /* Read chunks and insert them into the output */
909 unsigned char Buf [1024];
911 /* Calculate the number of bytes to read */
912 size_t BytesToRead = (Count > (long)sizeof(Buf))? sizeof(Buf) : (size_t) Count;
915 size_t BytesRead = fread (Buf, 1, BytesToRead, F);
916 if (BytesToRead != BytesRead) {
917 /* Some sort of error */
918 ErrorSkip (ERR_CANNOT_READ_INCLUDE, Name, strerror (errno));
922 /* Insert it into the output */
923 EmitData (Buf, BytesRead);
925 /* Keep the counters current */
930 /* Close the file, ignore errors since it's r/o */
936 static void DoInclude (void)
937 /* Include another file */
939 char Name [MAX_STR_LEN+1];
941 /* Name must follow */
942 if (Tok != TOK_STRCON) {
943 ErrorSkip (ERR_STRCON_EXPECTED);
953 static void DoInvalid (void)
954 /* Handle a token that is invalid here, since it should have been handled on
955 * a much lower level of the expression hierarchy. Getting this sort of token
956 * means that the lower level code has bugs.
957 * This function differs to DoUnexpected in that the latter may be triggered
958 * by the user by using keywords in the wrong location. DoUnexpected is not
959 * an error in the assembler itself, while DoInvalid is.
962 Internal ("Unexpected token: %s", Keyword);
967 static void DoLineCont (void)
968 /* Switch the use of line continuations */
970 SetBoolOption (&LineCont);
975 static void DoList (void)
976 /* Enable/disable the listing */
978 /* Get the setting */
980 SetBoolOption (&List);
982 /* Manage the counter */
992 static void DoListBytes (void)
993 /* Set maximum number of bytes to list for one line */
995 SetListBytes (IntArg (MIN_LIST_BYTES, MAX_LIST_BYTES));
1000 static void DoLocalChar (void)
1001 /* Define the character that starts local labels */
1003 if (Tok != TOK_CHARCON) {
1004 ErrorSkip (ERR_CHARCON_EXPECTED);
1006 if (IVal != '@' && IVal != '?') {
1007 Error (ERR_ILLEGAL_LOCALSTART);
1009 LocalStart = (char) IVal;
1017 static void DoMacPack (void)
1018 /* Insert a macro package */
1020 /* Macro package names */
1021 static const char* Keys [] = {
1028 /* We expect an identifier */
1029 if (Tok != TOK_IDENT) {
1030 ErrorSkip (ERR_IDENT_EXPECTED);
1034 /* Map the keyword to a number */
1035 Package = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
1038 ErrorSkip (ERR_ILLEGAL_MACPACK);
1042 /* Skip the package name */
1045 /* Insert the package */
1046 InsertMacPack (Package);
1051 static void DoMacro (void)
1052 /* Start a macro definition */
1054 MacDef (MAC_STYLE_CLASSIC);
1059 static void DoNull (void)
1060 /* Switch to the NULL segment */
1067 static void DoOrg (void)
1068 /* Start absolute code */
1070 long PC = ConstExpression ();
1071 if (PC < 0 || PC > 0xFFFFFF) {
1080 static void DoOut (void)
1081 /* Output a string */
1083 if (Tok != TOK_STRCON) {
1084 ErrorSkip (ERR_STRCON_EXPECTED);
1086 /* Output the string and be sure to flush the output to keep it in
1087 * sync with any error messages if the output is redirected to a file.
1089 printf ("%s\n", SVal);
1097 static void DoP02 (void)
1098 /* Switch to 6502 CPU */
1105 static void DoPC02 (void)
1106 /* Switch to 65C02 CPU */
1113 static void DoP816 (void)
1114 /* Switch to 65816 CPU */
1121 static void DoPageLength (void)
1122 /* Set the page length for the listing */
1124 PageLength = IntArg (MIN_PAGE_LEN, MAX_PAGE_LEN);
1129 static void DoProc (void)
1130 /* Start a new lexical scope */
1132 if (Tok == TOK_IDENT) {
1133 /* The new scope has a name */
1134 SymDef (SVal, CurrentPC (), IsZPSeg (), 1);
1142 static void DoReloc (void)
1143 /* Enter relocatable mode */
1150 static void DoRepeat (void)
1151 /* Repeat some instruction block */
1158 static void DoRes (void)
1159 /* Reserve some number of storage bytes */
1164 Count = ConstExpression ();
1165 if (Count > 0xFFFF || Count < 0) {
1166 ErrorSkip (ERR_RANGE);
1169 if (Tok == TOK_COMMA) {
1171 Val = ConstExpression ();
1172 /* We need a byte value here */
1173 if (!IsByteRange (Val)) {
1174 ErrorSkip (ERR_RANGE);
1178 /* Emit constant values */
1180 Emit0 ((unsigned char) Val);
1184 /* Emit fill fragments */
1191 static void DoROData (void)
1192 /* Switch to the r/o data segment */
1199 static void DoSegment (void)
1200 /* Switch to another segment */
1202 static const char* AttrTab [] = {
1203 "ZEROPAGE", "DIRECT",
1207 char Name [sizeof (SVal)];
1210 if (Tok != TOK_STRCON) {
1211 ErrorSkip (ERR_STRCON_EXPECTED);
1214 /* Save the name of the segment and skip it */
1215 strcpy (Name, SVal);
1218 /* Check for an optional segment attribute */
1219 SegType = SEGTYPE_DEFAULT;
1220 if (Tok == TOK_COMMA) {
1222 if (Tok != TOK_IDENT) {
1223 ErrorSkip (ERR_IDENT_EXPECTED);
1225 int Attr = GetSubKey (AttrTab, sizeof (AttrTab) / sizeof (AttrTab [0]));
1231 SegType = SEGTYPE_ZP;
1236 SegType = SEGTYPE_ABS;
1242 SegType = SEGTYPE_FAR;
1246 Error (ERR_ILLEGAL_SEG_ATTR);
1252 /* Set the segment */
1253 UseSeg (Name, SegType);
1259 static void DoSmart (void)
1260 /* Smart mode on/off */
1262 SetBoolOption (&SmartMode);
1267 static void DoSunPlus (void)
1268 /* Switch to the SUNPLUS CPU */
1270 SetCPU (CPU_SUNPLUS);
1275 static void DoUnexpected (void)
1276 /* Got an unexpected keyword */
1278 Error (ERR_UNEXPECTED, Keyword);
1284 static void DoWarning (void)
1287 if (Tok != TOK_STRCON) {
1288 ErrorSkip (ERR_STRCON_EXPECTED);
1290 Warning (WARN_USER, SVal);
1297 static void DoWord (void)
1301 EmitWord (Expression ());
1302 if (Tok != TOK_COMMA) {
1312 static void DoZeropage (void)
1313 /* Switch to the zeropage segment */
1320 /*****************************************************************************/
1322 /*****************************************************************************/
1326 /* Control commands flags */
1328 ccNone = 0x0000, /* No special flags */
1329 ccKeepToken = 0x0001 /* Do not skip the current token */
1332 /* Control command table */
1334 unsigned Flags; /* Flags for this directive */
1335 void (*Handler) (void); /* Command handler */
1337 typedef struct CtrlDesc_ CtrlDesc;
1339 #define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0]))
1340 static CtrlDesc CtrlCmdTab [] = {
1343 { ccNone, DoAddr }, /* .ADDR */
1344 { ccNone, DoAlign },
1345 { ccNone, DoASCIIZ },
1346 { ccNone, DoAutoImport },
1347 { ccNone, DoUnexpected }, /* .BLANK */
1351 { ccNone, DoCharMap },
1353 { ccNone, DoUnexpected, }, /* .CONCAT */
1354 { ccNone, DoConDes },
1355 { ccNone, DoUnexpected }, /* .CONST */
1356 { ccNone, DoConstructor },
1357 { ccNone, DoUnexpected }, /* .CPU */
1361 { ccNone, DoDebugInfo },
1362 { ccNone, DoDefine },
1363 { ccNone, DoUnexpected }, /* .DEFINED */
1364 { ccNone, DoDestructor },
1365 { ccNone, DoDWord },
1366 { ccKeepToken, DoConditionals }, /* .ELSE */
1367 { ccKeepToken, DoConditionals }, /* .ELSEIF */
1369 { ccKeepToken, DoConditionals }, /* .ENDIF */
1370 { ccNone, DoUnexpected }, /* .ENDMACRO */
1371 { ccNone, DoEndProc },
1372 { ccNone, DoUnexpected }, /* .ENDREPEAT */
1373 { ccNone, DoError },
1374 { ccNone, DoExitMacro },
1375 { ccNone, DoExport },
1376 { ccNone, DoExportZP },
1377 { ccNone, DoFarAddr },
1378 { ccNone, DoFeature },
1379 { ccNone, DoFileOpt },
1380 { ccNone, DoUnexpected }, /* .FORCEWORD */
1381 { ccNone, DoGlobal },
1382 { ccNone, DoGlobalZP },
1385 { ccKeepToken, DoConditionals }, /* .IF */
1386 { ccKeepToken, DoConditionals }, /* .IFBLANK */
1387 { ccKeepToken, DoConditionals }, /* .IFCONST */
1388 { ccKeepToken, DoConditionals }, /* .IFDEF */
1389 { ccKeepToken, DoConditionals }, /* .IFNBLANK */
1390 { ccKeepToken, DoConditionals }, /* .IFNCONST */
1391 { ccKeepToken, DoConditionals }, /* .IFNDEF */
1392 { ccKeepToken, DoConditionals }, /* .IFNREF */
1393 { ccKeepToken, DoConditionals }, /* .IFP02 */
1394 { ccKeepToken, DoConditionals }, /* .IFP816 */
1395 { ccKeepToken, DoConditionals }, /* .IFPC02 */
1396 { ccKeepToken, DoConditionals }, /* .IFREF */
1397 { ccNone, DoImport },
1398 { ccNone, DoImportZP },
1399 { ccNone, DoIncBin },
1400 { ccNone, DoInclude },
1401 { ccNone, DoInvalid }, /* .LEFT */
1402 { ccNone, DoLineCont },
1404 { ccNone, DoListBytes },
1405 { ccNone, DoUnexpected }, /* .LOCAL */
1406 { ccNone, DoLocalChar },
1407 { ccNone, DoMacPack },
1408 { ccNone, DoMacro },
1409 { ccNone, DoUnexpected }, /* .MATCH */
1410 { ccNone, DoInvalid }, /* .MID */
1416 { ccNone, DoPageLength },
1417 { ccNone, DoUnexpected }, /* .PARAMCOUNT */
1420 { ccNone, DoUnexpected }, /* .REFERENCED */
1421 { ccNone, DoReloc },
1422 { ccNone, DoRepeat },
1424 { ccNone, DoInvalid }, /* .RIGHT */
1425 { ccNone, DoROData },
1426 { ccNone, DoSegment },
1427 { ccNone, DoSmart },
1428 { ccNone, DoUnexpected }, /* .STRAT */
1429 { ccNone, DoUnexpected }, /* .STRING */
1430 { ccNone, DoUnexpected }, /* .STRLEN */
1431 { ccNone, DoSunPlus },
1432 { ccNone, DoUnexpected }, /* .TCOUNT */
1433 { ccNone, DoWarning },
1435 { ccNone, DoUnexpected }, /* .XMATCH */
1436 { ccNone, DoZeropage },
1441 /*****************************************************************************/
1443 /*****************************************************************************/
1447 int TokIsPseudo (unsigned Tok)
1448 /* Return true if the given token is a pseudo instruction token */
1450 return (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO);
1455 void HandlePseudo (void)
1456 /* Handle a pseudo instruction */
1460 /* Calculate the index into the table */
1461 unsigned Index = Tok - TOK_FIRSTPSEUDO;
1464 if (PSEUDO_COUNT != (TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1)) {
1465 Internal ("Pseudo mismatch: PSEUDO_COUNT = %u, actual count = %u\n",
1466 PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
1468 CHECK (Index < PSEUDO_COUNT);
1470 /* Get the pseudo intruction descriptor */
1471 D = &CtrlCmdTab [Index];
1473 /* Remember the instruction, then skip it if needed */
1474 if ((D->Flags & ccKeepToken) == 0) {
1475 strcpy (Keyword+1, SVal);
1479 /* Call the handler */