1 /*****************************************************************************/
5 /* Pseudo instructions for the ca65 macroassembler */
9 /* (C) 1998-2000 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 DoCode (void)
377 /* Switch to the code segment */
384 static void DoConDes (void)
385 /* Export a symbol as constructor/destructor */
387 static const char* Keys[] = {
391 char Name [sizeof (SVal)];
394 /* Symbol name follows */
395 if (Tok != TOK_IDENT) {
396 ErrorSkip (ERR_IDENT_EXPECTED);
402 /* Type follows. May be encoded as identifier or numerical */
404 if (Tok == TOK_IDENT) {
406 /* Map the following keyword to a number, then skip it */
407 Type = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
410 /* Check if we got a valid keyword */
419 /* Read the type as numerical value */
420 Type = ConstExpression ();
421 if (Type < CD_TYPE_MIN || Type > CD_TYPE_MAX) {
422 /* Value out of range */
429 /* Parse the remainder of the line and export the symbol */
430 ConDes (Name, (unsigned) Type);
435 static void DoConstructor (void)
436 /* Export a symbol as constructor */
438 char Name [sizeof (SVal)];
440 /* Symbol name follows */
441 if (Tok != TOK_IDENT) {
442 ErrorSkip (ERR_IDENT_EXPECTED);
448 /* Parse the remainder of the line and export the symbol */
449 ConDes (Name, CD_TYPE_CON);
454 static void DoData (void)
455 /* Switch to the data segment */
462 static void DoDbg (void)
463 /* Add debug information from high level code */
465 static const char* Keys[] = {
473 /* We expect a subkey */
474 if (Tok != TOK_IDENT) {
475 ErrorSkip (ERR_IDENT_EXPECTED);
479 /* Map the following keyword to a number */
480 Key = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
482 /* Skip the subkey */
485 /* Parameters are separated by a comma */
488 /* Check the key and dispatch to a handler */
490 case 0: DbgInfoFile (); break;
491 case 1: DbgInfoLine (); break;
492 case 2: DbgInfoSym (); break;
493 default: ErrorSkip (ERR_SYNTAX); break;
499 static void DoDByt (void)
500 /* Output double bytes */
503 EmitWord (SwapExpr (Expression ()));
504 if (Tok != TOK_COMMA) {
514 static void DoDebugInfo (void)
515 /* Switch debug info on or off */
517 SetBoolOption (&DbgSyms);
522 static void DoDefine (void)
523 /* Define a one line macro */
525 MacDef (MAC_STYLE_DEFINE);
530 static void DoDestructor (void)
531 /* Export a symbol as destructor */
533 char Name [sizeof (SVal)];
535 /* Symbol name follows */
536 if (Tok != TOK_IDENT) {
537 ErrorSkip (ERR_IDENT_EXPECTED);
543 /* Parse the remainder of the line and export the symbol */
544 ConDes (Name, CD_TYPE_DES);
549 static void DoDWord (void)
553 EmitDWord (Expression ());
554 if (Tok != TOK_COMMA) {
564 static void DoEnd (void)
565 /* End of assembly */
572 static void DoEndProc (void)
573 /* Leave a lexical level */
580 static void DoError (void)
583 if (Tok != TOK_STRCON) {
584 ErrorSkip (ERR_STRCON_EXPECTED);
586 Error (ERR_USER, SVal);
593 static void DoExitMacro (void)
594 /* Exit a macro expansion */
596 if (!InMacExpansion ()) {
597 /* We aren't expanding a macro currently */
606 static void DoExport (void)
607 /* Export a symbol */
609 ExportImport (SymExport, 0);
614 static void DoExportZP (void)
615 /* Export a zeropage symbol */
617 ExportImport (SymExport, 1);
622 static void DoFarAddr (void)
623 /* Define far addresses (24 bit) */
626 EmitFarAddr (Expression ());
627 if (Tok != TOK_COMMA) {
637 static void DoFeature (void)
638 /* Switch the Feature option */
640 /* Allow a list of comma separated keywords */
643 /* We expect an identifier */
644 if (Tok != TOK_IDENT) {
645 ErrorSkip (ERR_IDENT_EXPECTED);
649 /* Make the string attribute lower case */
652 /* Set the feature and check for errors */
653 if (SetFeature (SVal) == FEAT_UNKNOWN) {
655 ErrorSkip (ERR_ILLEGAL_FEATURE);
658 /* Skip the keyword */
662 /* Allow more than one keyword */
663 if (Tok == TOK_COMMA) {
673 static void DoFileOpt (void)
674 /* Insert a file option */
678 /* The option type may be given as a keyword or as a number. */
679 if (Tok == TOK_IDENT) {
681 /* Option given as keyword */
682 static const char* Keys [] = {
683 "AUTHOR", "COMMENT", "COMPILER"
686 /* Map the option to a number */
687 OptNum = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
690 ErrorSkip (ERR_OPTION_KEY_EXPECTED);
694 /* Skip the keyword */
697 /* Must be followed by a comma */
700 /* We accept only string options for now */
701 if (Tok != TOK_STRCON) {
702 ErrorSkip (ERR_STRCON_EXPECTED);
706 /* Insert the option */
725 Internal ("Invalid OptNum: %l", OptNum);
734 /* Option given as number */
735 OptNum = ConstExpression ();
736 if (!IsByteRange (OptNum)) {
737 ErrorSkip (ERR_RANGE);
741 /* Must be followed by a comma */
744 /* We accept only string options for now */
745 if (Tok != TOK_STRCON) {
746 ErrorSkip (ERR_STRCON_EXPECTED);
750 /* Insert the option */
751 OptStr ((unsigned char) OptNum, SVal);
760 static void DoGlobal (void)
761 /* Declare a global symbol */
763 ExportImport (SymGlobal, 0);
768 static void DoGlobalZP (void)
769 /* Declare a global zeropage symbol */
771 ExportImport (SymGlobal, 1);
776 static void DoI16 (void)
777 /* Switch the index registers to 16 bit mode (assembler only) */
779 if (GetCPU() != CPU_65816) {
780 Error (ERR_816_MODE_ONLY);
782 /* Immidiate mode has two extension bytes */
783 ExtBytes [AMI_IMM_INDEX] = 2;
789 static void DoI8 (void)
790 /* Switch the index registers to 16 bit mode (assembler only) */
792 if (GetCPU() != CPU_65816) {
793 Error (ERR_816_MODE_ONLY);
795 /* Immidiate mode has one extension byte */
796 ExtBytes [AMI_IMM_INDEX] = 1;
802 static void DoImport (void)
803 /* Import a symbol */
805 ExportImport (SymImport, 0);
810 static void DoImportZP (void)
811 /* Import a zero page symbol */
813 ExportImport (SymImport, 1);
818 static void DoIncBin (void)
819 /* Include a binary file */
821 char Name [sizeof (SVal)];
827 /* Name must follow */
828 if (Tok != TOK_STRCON) {
829 ErrorSkip (ERR_STRCON_EXPECTED);
835 /* A starting offset may follow */
836 if (Tok == TOK_COMMA) {
838 Start = ConstExpression ();
840 /* And a length may follow */
841 if (Tok == TOK_COMMA) {
843 Count = ConstExpression ();
848 /* Try to open the file */
849 F = fopen (Name, "rb");
851 ErrorSkip (ERR_CANNOT_OPEN_INCLUDE, Name, strerror (errno));
855 /* Get the size of the file */
856 fseek (F, 0, SEEK_END);
859 /* If a count was not given, calculate it now */
861 Count = Size - Start;
863 /* Nothing to read - flag this as a range error */
864 ErrorSkip (ERR_RANGE);
868 /* Count was given, check if it is valid */
869 if (Start + Count > Size) {
870 ErrorSkip (ERR_RANGE);
875 /* Seek to the start position */
876 fseek (F, Start, SEEK_SET);
878 /* Read chunks and insert them into the output */
881 unsigned char Buf [1024];
883 /* Calculate the number of bytes to read */
884 size_t BytesToRead = (Count > (long)sizeof(Buf))? sizeof(Buf) : (size_t) Count;
887 size_t BytesRead = fread (Buf, 1, BytesToRead, F);
888 if (BytesToRead != BytesRead) {
889 /* Some sort of error */
890 ErrorSkip (ERR_CANNOT_READ_INCLUDE, Name, strerror (errno));
894 /* Insert it into the output */
895 EmitData (Buf, Count);
897 /* Keep the counters current */
902 /* Close the file, ignore errors since it's r/o */
908 static void DoInclude (void)
909 /* Include another file */
911 char Name [MAX_STR_LEN+1];
913 /* Name must follow */
914 if (Tok != TOK_STRCON) {
915 ErrorSkip (ERR_STRCON_EXPECTED);
925 static void DoInvalid (void)
926 /* Handle a token that is invalid here, since it should have been handled on
927 * a much lower level of the expression hierarchy. Getting this sort of token
928 * means that the lower level code has bugs.
929 * This function differs to DoUnexpected in that the latter may be triggered
930 * by the user by using keywords in the wrong location. DoUnexpected is not
931 * an error in the assembler itself, while DoInvalid is.
934 Internal ("Unexpected token: %s", Keyword);
939 static void DoLineCont (void)
940 /* Switch the use of line continuations */
942 SetBoolOption (&LineCont);
947 static void DoList (void)
948 /* Enable/disable the listing */
950 /* Get the setting */
952 SetBoolOption (&List);
954 /* Manage the counter */
964 static void DoListBytes (void)
965 /* Set maximum number of bytes to list for one line */
967 SetListBytes (IntArg (MIN_LIST_BYTES, MAX_LIST_BYTES));
972 static void DoLocalChar (void)
973 /* Define the character that starts local labels */
975 if (Tok != TOK_CHARCON) {
976 ErrorSkip (ERR_CHARCON_EXPECTED);
978 if (IVal != '@' && IVal != '?') {
979 Error (ERR_ILLEGAL_LOCALSTART);
981 LocalStart = (char) IVal;
989 static void DoMacPack (void)
990 /* Insert a macro package */
992 /* Macro package names */
993 static const char* Keys [] = {
1000 /* We expect an identifier */
1001 if (Tok != TOK_IDENT) {
1002 ErrorSkip (ERR_IDENT_EXPECTED);
1006 /* Map the keyword to a number */
1007 Package = GetSubKey (Keys, sizeof (Keys) / sizeof (Keys [0]));
1010 ErrorSkip (ERR_ILLEGAL_MACPACK);
1014 /* Skip the package name */
1017 /* Insert the package */
1018 InsertMacPack (Package);
1023 static void DoMacro (void)
1024 /* Start a macro definition */
1026 MacDef (MAC_STYLE_CLASSIC);
1031 static void DoNull (void)
1032 /* Switch to the NULL segment */
1039 static void DoOrg (void)
1040 /* Start absolute code */
1042 long PC = ConstExpression ();
1043 if (PC < 0 || PC > 0xFFFFFF) {
1052 static void DoOut (void)
1053 /* Output a string */
1055 if (Tok != TOK_STRCON) {
1056 ErrorSkip (ERR_STRCON_EXPECTED);
1058 /* Output the string and be sure to flush the output to keep it in
1059 * sync with any error messages if the output is redirected to a file.
1061 printf ("%s\n", SVal);
1069 static void DoP02 (void)
1070 /* Switch to 6502 CPU */
1077 static void DoPC02 (void)
1078 /* Switch to 65C02 CPU */
1085 static void DoP816 (void)
1086 /* Switch to 65816 CPU */
1093 static void DoPageLength (void)
1094 /* Set the page length for the listing */
1096 PageLength = IntArg (MIN_PAGE_LEN, MAX_PAGE_LEN);
1101 static void DoProc (void)
1102 /* Start a new lexical scope */
1104 if (Tok == TOK_IDENT) {
1105 /* The new scope has a name */
1106 SymDef (SVal, CurrentPC (), IsZPSeg ());
1114 static void DoReloc (void)
1115 /* Enter relocatable mode */
1122 static void DoRepeat (void)
1123 /* Repeat some instruction block */
1130 static void DoRes (void)
1131 /* Reserve some number of storage bytes */
1136 Count = ConstExpression ();
1137 if (Count > 0xFFFF || Count < 0) {
1138 ErrorSkip (ERR_RANGE);
1141 if (Tok == TOK_COMMA) {
1143 Val = ConstExpression ();
1144 /* We need a byte value here */
1145 if (!IsByteRange (Val)) {
1146 ErrorSkip (ERR_RANGE);
1150 /* Emit constant values */
1152 Emit0 ((unsigned char) Val);
1156 /* Emit fill fragments */
1163 static void DoROData (void)
1164 /* Switch to the r/o data segment */
1171 static void DoSegment (void)
1172 /* Switch to another segment */
1174 static const char* AttrTab [] = {
1175 "ZEROPAGE", "DIRECT",
1179 char Name [sizeof (SVal)];
1182 if (Tok != TOK_STRCON) {
1183 ErrorSkip (ERR_STRCON_EXPECTED);
1186 /* Save the name of the segment and skip it */
1187 strcpy (Name, SVal);
1190 /* Check for an optional segment attribute */
1191 SegType = SEGTYPE_DEFAULT;
1192 if (Tok == TOK_COMMA) {
1194 if (Tok != TOK_IDENT) {
1195 ErrorSkip (ERR_IDENT_EXPECTED);
1197 int Attr = GetSubKey (AttrTab, sizeof (AttrTab) / sizeof (AttrTab [0]));
1203 SegType = SEGTYPE_ZP;
1208 SegType = SEGTYPE_ABS;
1214 SegType = SEGTYPE_FAR;
1218 Error (ERR_ILLEGAL_SEG_ATTR);
1224 /* Set the segment */
1225 UseSeg (Name, SegType);
1231 static void DoSmart (void)
1232 /* Smart mode on/off */
1234 SetBoolOption (&SmartMode);
1239 static void DoSunPlus (void)
1240 /* Switch to the SUNPLUS CPU */
1242 SetCPU (CPU_SUNPLUS);
1247 static void DoUnexpected (void)
1248 /* Got an unexpected keyword */
1250 Error (ERR_UNEXPECTED, Keyword);
1256 static void DoWarning (void)
1259 if (Tok != TOK_STRCON) {
1260 ErrorSkip (ERR_STRCON_EXPECTED);
1262 Warning (WARN_USER, SVal);
1269 static void DoWord (void)
1273 EmitWord (Expression ());
1274 if (Tok != TOK_COMMA) {
1284 static void DoZeropage (void)
1285 /* Switch to the zeropage segment */
1292 /*****************************************************************************/
1294 /*****************************************************************************/
1298 /* Control commands flags */
1300 ccNone = 0x0000, /* No special flags */
1301 ccKeepToken = 0x0001 /* Do not skip the current token */
1304 /* Control command table */
1306 unsigned Flags; /* Flags for this directive */
1307 void (*Handler) (void); /* Command handler */
1309 typedef struct CtrlDesc_ CtrlDesc;
1311 #define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0]))
1312 static CtrlDesc CtrlCmdTab [] = {
1315 { ccNone, DoAddr }, /* .ADDR */
1316 { ccNone, DoAlign },
1317 { ccNone, DoASCIIZ },
1318 { ccNone, DoAutoImport },
1319 { ccNone, DoUnexpected }, /* .BLANK */
1324 { ccNone, DoUnexpected, }, /* .CONCAT */
1325 { ccNone, DoConDes },
1326 { ccNone, DoUnexpected }, /* .CONST */
1327 { ccNone, DoConstructor },
1328 { ccNone, DoUnexpected }, /* .CPU */
1332 { ccNone, DoDebugInfo },
1333 { ccNone, DoDefine },
1334 { ccNone, DoUnexpected }, /* .DEFINED */
1335 { ccNone, DoDestructor },
1336 { ccNone, DoDWord },
1337 { ccKeepToken, DoConditionals }, /* .ELSE */
1338 { ccKeepToken, DoConditionals }, /* .ELSEIF */
1340 { ccKeepToken, DoConditionals }, /* .ENDIF */
1341 { ccNone, DoUnexpected }, /* .ENDMACRO */
1342 { ccNone, DoEndProc },
1343 { ccNone, DoUnexpected }, /* .ENDREPEAT */
1344 { ccNone, DoError },
1345 { ccNone, DoExitMacro },
1346 { ccNone, DoExport },
1347 { ccNone, DoExportZP },
1348 { ccNone, DoFarAddr },
1349 { ccNone, DoFeature },
1350 { ccNone, DoFileOpt },
1351 { ccNone, DoUnexpected }, /* .FORCEWORD */
1352 { ccNone, DoGlobal },
1353 { ccNone, DoGlobalZP },
1356 { ccKeepToken, DoConditionals }, /* .IF */
1357 { ccKeepToken, DoConditionals }, /* .IFBLANK */
1358 { ccKeepToken, DoConditionals }, /* .IFCONST */
1359 { ccKeepToken, DoConditionals }, /* .IFDEF */
1360 { ccKeepToken, DoConditionals }, /* .IFNBLANK */
1361 { ccKeepToken, DoConditionals }, /* .IFNCONST */
1362 { ccKeepToken, DoConditionals }, /* .IFNDEF */
1363 { ccKeepToken, DoConditionals }, /* .IFNREF */
1364 { ccKeepToken, DoConditionals }, /* .IFP02 */
1365 { ccKeepToken, DoConditionals }, /* .IFP816 */
1366 { ccKeepToken, DoConditionals }, /* .IFPC02 */
1367 { ccKeepToken, DoConditionals }, /* .IFREF */
1368 { ccNone, DoImport },
1369 { ccNone, DoImportZP },
1370 { ccNone, DoIncBin },
1371 { ccNone, DoInclude },
1372 { ccNone, DoInvalid }, /* .LEFT */
1373 { ccNone, DoLineCont },
1375 { ccNone, DoListBytes },
1376 { ccNone, DoUnexpected }, /* .LOCAL */
1377 { ccNone, DoLocalChar },
1378 { ccNone, DoMacPack },
1379 { ccNone, DoMacro },
1380 { ccNone, DoUnexpected }, /* .MATCH */
1381 { ccNone, DoInvalid }, /* .MID */
1387 { ccNone, DoPageLength },
1388 { ccNone, DoUnexpected }, /* .PARAMCOUNT */
1391 { ccNone, DoUnexpected }, /* .REFERENCED */
1392 { ccNone, DoReloc },
1393 { ccNone, DoRepeat },
1395 { ccNone, DoInvalid }, /* .RIGHT */
1396 { ccNone, DoROData },
1397 { ccNone, DoSegment },
1398 { ccNone, DoSmart },
1399 { ccNone, DoUnexpected }, /* .STRAT */
1400 { ccNone, DoUnexpected }, /* .STRING */
1401 { ccNone, DoUnexpected }, /* .STRLEN */
1402 { ccNone, DoSunPlus },
1403 { ccNone, DoUnexpected }, /* .TCOUNT */
1404 { ccNone, DoWarning },
1406 { ccNone, DoUnexpected }, /* .XMATCH */
1407 { ccNone, DoZeropage },
1412 /*****************************************************************************/
1414 /*****************************************************************************/
1418 int TokIsPseudo (unsigned Tok)
1419 /* Return true if the given token is a pseudo instruction token */
1421 return (Tok >= TOK_FIRSTPSEUDO && Tok <= TOK_LASTPSEUDO);
1426 void HandlePseudo (void)
1427 /* Handle a pseudo instruction */
1431 /* Calculate the index into the table */
1432 unsigned Index = Tok - TOK_FIRSTPSEUDO;
1435 if (PSEUDO_COUNT != (TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1)) {
1436 Internal ("Pseudo mismatch: PSEUDO_COUNT = %u, actual count = %u\n",
1437 PSEUDO_COUNT, TOK_LASTPSEUDO - TOK_FIRSTPSEUDO + 1);
1439 CHECK (Index < PSEUDO_COUNT);
1441 /* Get the pseudo intruction descriptor */
1442 D = &CtrlCmdTab [Index];
1444 /* Remember the instruction, then skip it if needed */
1445 if ((D->Flags & ccKeepToken) == 0) {
1446 strcpy (Keyword+1, SVal);
1450 /* Call the handler */