예제 #1
0
int mathWrapInt(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b, *c;
	int err;

	a = g->sp - 2;
	b = g->sp - 1;
	c = g->sp;

	if (IsSym(b)) {
		*a = *b;
	} else if (IsSym(c)) {
		*a = *c;
	} else if (IsInt(b) && IsInt(c)) {
		SetRaw(a, sc_mod((int)(slotRawInt(a) - slotRawInt(b)), (int)(slotRawInt(c) - slotRawInt(b) + 1)) + slotRawInt(b));
	} else {
		double x, lo, hi;
		x = slotRawInt(a);
		err = slotDoubleVal(b, &lo);
		if (err) return err;
		err = slotDoubleVal(c, &hi);
		if (err) return err;
		SetFloat(a, sc_mod(x - lo, hi - lo) + lo);
	}
	return errNone;
}
예제 #2
0
int mathFoldInt(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b, *c;
	int err;

	a = g->sp - 2;
	b = g->sp - 1;
	c = g->sp;

	if (IsSym(b)) {
		*a = *b;
	} else if (IsSym(c)) {
		*a = *c;
	} else if (IsInt(b) && IsInt(c)) {
		SetRaw(a, sc_fold(slotRawInt(a), slotRawInt(b), slotRawInt(c)));
	} else {
		double x, lo, hi;
		x = slotRawInt(a);
		err = slotDoubleVal(b, &lo);
		if (err) return err;
		err = slotDoubleVal(c, &hi);
		if (err) return err;
		SetFloat(a, sc_fold(x, lo, hi));
	}
	return errNone;
}
예제 #3
0
int mathFoldSignal(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b, *c;
	float lo, hi;
	int err;
	PyrObject *sig;

	a = g->sp - 2;
	b = g->sp - 1;
	c = g->sp;

	if (IsSym(b)) {
		*a = *b;
	} else if (IsSym(c)) {
		*a = *c;
	} else if (IsSignal(b) && IsSignal(c)) {
		sig = signal_fold_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
		SetObject(a, sig);
	} else {
		err = slotFloatVal(b, &lo);
		if (err) return err;
		err = slotFloatVal(c, &hi);
		if (err) return err;
		sig = signal_fold_f(g, slotRawObject(a), lo, hi);
		SetObject(a, sig);
	}
	return errNone;
}
예제 #4
0
파일: OSCData.cpp 프로젝트: scztt/sc-debug
int prArray_OSCBytes(VMGlobals *g, int numArgsPushed)
{
	PyrSlot* a = g->sp;
	PyrObject *array = a->uo;
	PyrSlot* args = array->slots;
	int numargs = array->size;
	if (numargs < 1) return errFailed;
	big_scpacket packet;

	if (IsFloat(args) || IsNil(args) || IsInt(args)) {
		makeSynthBundle(&packet, args, numargs, false);
	} else if (IsSym(args) || isKindOfSlot(args, class_string)) {
		makeSynthMsgWithTags(&packet, args, numargs);
	} else {
		return errWrongType;
	}

	int size = packet.size();
	PyrInt8Array* obj = newPyrInt8Array(g->gc, size, 0, true);
	obj->size = size;
	memcpy(obj->b, packet.data(), size);
	SetObject(a, (PyrObject*)obj);
	//for (int i=0; i<packet.size()/4; i++) post("%d %08X\n", i, packet.buf[i]);

	return errNone;
}
예제 #5
0
int prSymbolIsPrefix(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b;
	int length;

	a = g->sp - 1;
	b = g->sp;
	if (!IsSym(a) || !IsSym(b)) return errWrongType;
	int32 alen = slotRawSymbol(a)->length;
	int32 blen = slotRawSymbol(b)->length;
	length = sc_min(alen, blen);
	if (memcmp(slotRawSymbol(a)->name, slotRawSymbol(b)->name, length) == 0) {
		SetTrue(a);
	} else {
		SetFalse(a);
	}
	return errNone;
}
예제 #6
0
int prSymbol_matchOSCPattern(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b;
	int length;
	
	a = g->sp - 1;
	b = g->sp;
	if (!IsSym(a) || !IsSym(b)) return errWrongType;
//	int32 alen = slotRawSymbol(a)->length;
//	int32 blen = slotRawSymbol(b)->length;
//	length = sc_min(alen, blen);
	if (lo_pattern_match(slotRawSymbol(a)->name, slotRawSymbol(b)->name)) {
		SetTrue(a);
	} else {
		SetFalse(a);
	}
	return errNone;
}
예제 #7
0
int identDictPut(struct VMGlobals *g, PyrObject *dict, PyrSlot *key, PyrSlot *value)
{
	PyrSlot *slot, *newslot;
	int i, index, size;
	PyrObject *array;

	bool knows = IsTrue(dict->slots + ivxIdentDict_know);
	if (knows && IsSym(key)) {
		if (slotRawSymbol(key) == s_parent) {
			slotCopy(&dict->slots[ivxIdentDict_parent],value);
			g->gc->GCWrite(dict, value);
			return errNone;
		}
		if (slotRawSymbol(key) == s_proto) {
			slotCopy(&dict->slots[ivxIdentDict_proto],value);
			g->gc->GCWrite(dict, value);
			return errNone;
		}
	}
	array = slotRawObject(&dict->slots[ivxIdentDict_array]);
	if (array->IsImmutable()) return errImmutableObject;
	if (!isKindOf((PyrObject*)array, class_array)) return errFailed;

	index = arrayAtIdentityHashInPairs(array, key);
	slot = array->slots + index;
	slotCopy(&slot[1],value);
	g->gc->GCWrite(array, value);
	if (IsNil(slot)) {
		slotCopy(slot,key);
		g->gc->GCWrite(array, key);
		size = slotRawInt(&dict->slots[ivxIdentDict_size]) + 1;
		SetRaw(&dict->slots[ivxIdentDict_size], size);
		if (array->size < size*3) {
			PyrObject *newarray;
			newarray = newPyrArray(g->gc, size*3, 0, false);
			newarray->size = ARRAYMAXINDEXSIZE(newarray);
			nilSlots(newarray->slots, newarray->size);
			slot = array->slots;
			for (i=0; i<array->size; i+=2, slot+=2) {
				if (NotNil(slot)) {
					index = arrayAtIdentityHashInPairs(newarray, slot);
					newslot = newarray->slots + index;
					slotCopy(&newslot[0],&slot[0]);
					slotCopy(&newslot[1],&slot[1]);
				}
			}
			SetRaw(&dict->slots[ivxIdentDict_array], newarray);
			g->gc->GCWriteNew(dict, newarray); // we know newarray is white so we can use GCWriteNew
		}
	}
	return errNone;
}
예제 #8
0
파일: preproc.c 프로젝트: PanchoManera/cc65
static int MacName (char* Ident)
/* Get a macro symbol name into Ident.  If we have an error, print a
 * diagnostic message and clear the line.
 */
{
    if (IsSym (Ident) == 0) {
        PPError ("Identifier expected");
        ClearLine ();
        return 0;
    } else {
        return 1;
    }
}
예제 #9
0
int identDictPut(struct VMGlobals *g, PyrObject *dict, PyrSlot *key, PyrSlot *value)
{
	PyrSlot *slot, *newslot;
	int i, index, size;
	PyrObject *array;

	bool knows = IsTrue(dict->slots + ivxIdentDict_know);
	if (knows && IsSym(key)) {
		if (key->us == s_parent) {
			slotCopy(&dict->slots[ivxIdentDict_parent],value);
			g->gc->GCWrite(dict, value);
			return errNone;
		}
		if (key->us == s_proto) {
			slotCopy(&dict->slots[ivxIdentDict_proto],value);
			g->gc->GCWrite(dict, value);
			return errNone;
		}
	}
	array = dict->slots[ivxIdentDict_array].uo;
	if (!isKindOf((PyrObject*)array, class_array)) return errFailed;

	index = arrayAtIdentityHashInPairs(array, key);
	slot = array->slots + index;
	slotCopy(&slot[1],value);
	g->gc->GCWrite(array, value);
	if (IsNil(slot)) {
		slotCopy(slot,key);
		g->gc->GCWrite(array, key);
		size = ++dict->slots[ivxIdentDict_size].ui;
		if (array->size < size*3) {
			PyrObject *newarray;
			newarray = newPyrArray(g->gc, size*3, 0, false);
			newarray->size = ARRAYMAXINDEXSIZE(newarray);
			nilSlots(newarray->slots, newarray->size);
			slot = array->slots;
			for (i=0; i<array->size; i+=2, slot+=2) {
				if (NotNil(slot)) {
					index = arrayAtIdentityHashInPairs(newarray, slot);
					newslot = newarray->slots + index;
					slotCopy(&newslot[0],&slot[0]);
					slotCopy(&newslot[1],&slot[1]);
				}
			}
			dict->slots[ivxIdentDict_array].uo = newarray;
			g->gc->GCWrite(dict, newarray);
		}
	}
	return errNone;
}
예제 #10
0
int mathWrapFloat(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot *a, *b, *c;
	double lo, hi;
	int err;

	a = g->sp - 2;
	b = g->sp - 1;
	c = g->sp;

	if (IsSym(b)) {
		*a = *b;
	} else if (IsSym(c)) {
		*a = *c;
	} else {
		err = slotDoubleVal(b, &lo);
		if (err) return err;
		err = slotDoubleVal(c, &hi);
		if (err) return err;
		SetRaw(a, sc_mod(slotRawFloat(a) - lo, hi - lo) + lo);
	}
	return errNone;
}
예제 #11
0
int prIdentDict_At(struct VMGlobals *g, int numArgsPushed)
{
	PyrSlot* a = g->sp - 1;  // dict
	PyrSlot* key = g->sp;		// key
	PyrObject *dict = slotRawObject(a);

	bool knows = IsTrue(dict->slots + ivxIdentDict_know);
	if (knows && IsSym(key)) {
		if (slotRawSymbol(key) == s_parent) {
			slotCopy(a,&dict->slots[ivxIdentDict_parent]);
			return errNone;
		}
		if (slotRawSymbol(key) == s_proto) {
			slotCopy(a,&dict->slots[ivxIdentDict_proto]);
			return errNone;
		}
	}

	identDict_lookup(dict, key, calcHash(key), a);
	return errNone;
}
예제 #12
0
파일: preproc.c 프로젝트: PanchoManera/cc65
static void MacroReplacement (StrBuf* Source, StrBuf* Target)
/* Perform macro replacement. */
{
    ident       Ident;
    Macro*      M;

    /* Remember the current input and switch to Source */
    StrBuf* OldSource = InitLine (Source);

    /* Loop substituting macros */
    while (CurC != '\0') {
        /* If we have an identifier, check if it's a macro */
        if (IsSym (Ident)) {
            /* Check if it's a macro */
            if ((M = FindMacro (Ident)) != 0 && !M->Expanding) {
                /* It's a macro, expand it */
                ExpandMacro (Target, M);
            } else {
                /* An identifier, keep it */
                SB_AppendStr (Target, Ident);
            }
        } else if (IsQuote (CurC)) {
            CopyQuotedString (Target);
        } else if (IsSpace (CurC)) {
            if (!IsSpace (SB_LookAtLast (Target))) {
                SB_AppendChar (Target, CurC);
            }
            NextChar ();
        } else {
            SB_AppendChar (Target, CurC);
            NextChar ();
        }
    }

    /* Switch back the input */
    InitLine (OldSource);
}
예제 #13
0
파일: preproc.c 프로젝트: PanchoManera/cc65
void Preprocess (void)
/* Preprocess a line */
{
    int         Skip;
    ident       Directive;

    /* Create the output buffer if we don't already have one */
    if (MLine == 0) {
        MLine = NewStrBuf ();
    }

    /* Skip white space at the beginning of the line */
    SkipWhitespace (0);

    /* Check for stuff to skip */
    Skip = 0;
    while (CurC == '\0' || CurC == '#' || Skip) {

        /* Check for preprocessor lines lines */
        if (CurC == '#') {
            NextChar ();
            SkipWhitespace (0);
            if (CurC == '\0') {
                /* Ignore the empty preprocessor directive */
                continue;
            }
            if (!IsSym (Directive)) {
                PPError ("Preprocessor directive expected");
                ClearLine ();
            } else {
                switch (FindPPToken (Directive)) {

                    case PP_DEFINE:
                        if (!Skip) {
                            DefineMacro ();
                        }
                        break;

                    case PP_ELIF:
                        if (IfIndex >= 0) {
                            if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {

                                /* Handle as #else/#if combination */
                                if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
                                    Skip = !Skip;
                                }
                                IfStack[IfIndex] |= IFCOND_ELSE;
                                Skip = DoIf (Skip);

                                /* #elif doesn't need a terminator */
                                IfStack[IfIndex] &= ~IFCOND_NEEDTERM;
                            } else {
                                PPError ("Duplicate #else/#elif");
                            }
                        } else {
                            PPError ("Unexpected #elif");
                        }
                        break;

                    case PP_ELSE:
                        if (IfIndex >= 0) {
                            if ((IfStack[IfIndex] & IFCOND_ELSE) == 0) {
                                if ((IfStack[IfIndex] & IFCOND_SKIP) == 0) {
                                    Skip = !Skip;
                                }
                                IfStack[IfIndex] |= IFCOND_ELSE;
                            } else {
                                PPError ("Duplicate #else");
                            }
                        } else {
                            PPError ("Unexpected `#else'");
                        }
                        break;

                    case PP_ENDIF:
                        if (IfIndex >= 0) {
                            /* Remove any clauses on top of stack that do not
                             * need a terminating #endif.
                             */
                            while (IfIndex >= 0 && (IfStack[IfIndex] & IFCOND_NEEDTERM) == 0) {
                                --IfIndex;
                            }

                            /* Stack may not be empty here or something is wrong */
                            CHECK (IfIndex >= 0);

                            /* Remove the clause that needs a terminator */
                            Skip = (IfStack[IfIndex--] & IFCOND_SKIP) != 0;
                        } else {
                            PPError ("Unexpected `#endif'");
                        }
                        break;

                    case PP_ERROR:
                        if (!Skip) {
                            DoError ();
                        }
                        break;

                    case PP_IF:
                        Skip = DoIf (Skip);
                        break;

                    case PP_IFDEF:
                        Skip = DoIfDef (Skip, 1);
                        break;

                    case PP_IFNDEF:
                        Skip = DoIfDef (Skip, 0);
                        break;

                    case PP_INCLUDE:
                        if (!Skip) {
                            DoInclude ();
                        }
                        break;

                    case PP_LINE:
                        /* Should do something in C99 at least, but we ignore it */
                        if (!Skip) {
                            ClearLine ();
                        }
                        break;

                    case PP_PRAGMA:
                        if (!Skip) {
                            DoPragma ();
                            goto Done;
                        }
                        break;

                    case PP_UNDEF:
                        if (!Skip) {
                            DoUndef ();
                        }
                        break;

                    case PP_WARNING:
                        /* #warning is a non standard extension */
                        if (IS_Get (&Standard) > STD_C99) {
                            if (!Skip) {
                                DoWarning ();
                            }
                        } else {
                            if (!Skip) {
                                PPError ("Preprocessor directive expected");
                            }
                            ClearLine ();
                        }
                        break;

                    default:
                        if (!Skip) {
                            PPError ("Preprocessor directive expected");
                        }
                        ClearLine ();
                }
            }

        }
        if (NextLine () == 0) {
            if (IfIndex >= 0) {
                PPError ("`#endif' expected");
            }
            return;
        }
        SkipWhitespace (0);
    }

    PreprocessLine ();

Done:
    if (Verbosity > 1 && SB_NotEmpty (Line)) {
        printf ("%s(%u): %.*s\n", GetCurrentFile (), GetCurrentLine (),
                (int) SB_GetLen (Line), SB_GetConstBuf (Line));
    }
}
예제 #14
0
파일: scanner.c 프로젝트: pmprog/cc65
void NextToken (void)
/* Get next token from input stream */
{
    ident token;

    /* We have to skip white space here before shifting tokens, since the
    ** tokens and the current line info is invalid at startup and will get
    ** initialized by reading the first time from the file. Remember if
    ** we were at end of input and handle that later.
    */
    int GotEOF = (SkipWhite() == 0);

    /* Current token is the lookahead token */
    if (CurTok.LI) {
        ReleaseLineInfo (CurTok.LI);
    }
    CurTok = NextTok;

    /* When reading the first time from the file, the line info in NextTok,
    ** which was copied to CurTok is invalid. Since the information from
    ** the token is used for error messages, we must make it valid.
    */
    if (CurTok.LI == 0) {
        CurTok.LI = UseLineInfo (GetCurLineInfo ());
    }

    /* Remember the starting position of the next token */
    NextTok.LI = UseLineInfo (GetCurLineInfo ());

    /* Now handle end of input. */
    if (GotEOF) {
        /* End of file reached */
        NextTok.Tok = TOK_CEOF;
        return;
    }

    /* Determine the next token from the lookahead */
    if (IsDigit (CurC) || (CurC == '.' && IsDigit (NextC))) {
        /* A number */
        NumericConst ();
        return;
    }

    /* Check for wide character literals */
    if (CurC == 'L' && NextC == '\"') {
        StringConst ();
        return;
    }

    /* Check for keywords and identifiers */
    if (IsSym (token)) {

        /* Check for a keyword */
        if ((NextTok.Tok = FindKey (token)) != TOK_IDENT) {
            /* Reserved word found */
            return;
        }
        /* No reserved word, check for special symbols */
        if (token[0] == '_' && token[1] == '_') {
            /* Special symbols */
            if (strcmp (token+2, "FILE__") == 0) {
                NextTok.SVal = AddLiteral (GetCurrentFile());
                NextTok.Tok  = TOK_SCONST;
                return;
            } else if (strcmp (token+2, "LINE__") == 0) {
                NextTok.Tok  = TOK_ICONST;
                NextTok.IVal = GetCurrentLine();
                NextTok.Type = type_int;
                return;
            } else if (strcmp (token+2, "func__") == 0) {
                /* __func__ is only defined in functions */
                if (CurrentFunc) {
                    NextTok.SVal = AddLiteral (F_GetFuncName (CurrentFunc));
                    NextTok.Tok  = TOK_SCONST;
                    return;
                }
            }
        }

        /* No reserved word but identifier */
        strcpy (NextTok.Ident, token);
        NextTok.Tok = TOK_IDENT;
        return;
    }

    /* Monstrous switch statement ahead... */
    switch (CurC) {

        case '!':
            NextChar ();
            if (CurC == '=') {
                SetTok (TOK_NE);
            } else {
                NextTok.Tok = TOK_BOOL_NOT;
            }
            break;

        case '\"':
            StringConst ();
            break;

        case '%':
            NextChar ();
            if (CurC == '=') {
                SetTok (TOK_MOD_ASSIGN);
            } else {
                NextTok.Tok = TOK_MOD;
            }
            break;

        case '&':
            NextChar ();
            switch (CurC) {
                case '&':
                    SetTok (TOK_BOOL_AND);
                    break;
                case '=':
                    SetTok (TOK_AND_ASSIGN);
                    break;
                default:
                    NextTok.Tok = TOK_AND;
            }
            break;

        case '\'':
            CharConst ();
            break;

        case '(':
            SetTok (TOK_LPAREN);
            break;

        case ')':
            SetTok (TOK_RPAREN);
            break;

        case '*':
            NextChar ();
            if (CurC == '=') {
                SetTok (TOK_MUL_ASSIGN);
            } else {
                NextTok.Tok = TOK_STAR;
            }
            break;

        case '+':
            NextChar ();
            switch (CurC) {
                case '+':
                    SetTok (TOK_INC);
                    break;
                case '=':
                    SetTok (TOK_PLUS_ASSIGN);
                    break;
                default:
                    NextTok.Tok = TOK_PLUS;
            }
            break;

        case ',':
            SetTok (TOK_COMMA);
            break;

        case '-':
            NextChar ();
            switch (CurC) {
                case '-':
                    SetTok (TOK_DEC);
                    break;
                case '=':
                    SetTok (TOK_MINUS_ASSIGN);
                    break;
                case '>':
                    SetTok (TOK_PTR_REF);
                    break;
                default:
                    NextTok.Tok = TOK_MINUS;
            }
            break;

        case '.':
            NextChar ();
            if (CurC == '.') {
                NextChar ();
                if (CurC == '.') {
                    SetTok (TOK_ELLIPSIS);
                } else {
                    UnknownChar (CurC);
                }
            } else {
                NextTok.Tok = TOK_DOT;
            }
            break;

        case '/':
            NextChar ();
            if (CurC == '=') {
                SetTok (TOK_DIV_ASSIGN);
            } else {
                NextTok.Tok = TOK_DIV;
            }
            break;

        case ':':
            SetTok (TOK_COLON);
            break;

        case ';':
            SetTok (TOK_SEMI);
            break;

        case '<':
            NextChar ();
            switch (CurC) {
                case '=':
                    SetTok (TOK_LE);
                    break;
                case '<':
                    NextChar ();
                    if (CurC == '=') {
                        SetTok (TOK_SHL_ASSIGN);
                    } else {
                        NextTok.Tok = TOK_SHL;
                    }
                    break;
                default:
                    NextTok.Tok = TOK_LT;
            }
            break;

        case '=':
            NextChar ();
            if (CurC == '=') {
                SetTok (TOK_EQ);
            } else {
                NextTok.Tok = TOK_ASSIGN;
            }
            break;

        case '>':
            NextChar ();
            switch (CurC) {
                case '=':
                    SetTok (TOK_GE);
                    break;
                case '>':
                    NextChar ();
                    if (CurC == '=') {
                        SetTok (TOK_SHR_ASSIGN);
                    } else {
                        NextTok.Tok = TOK_SHR;
                    }
                    break;
                default:
                    NextTok.Tok = TOK_GT;
            }
            break;

        case '?':
            SetTok (TOK_QUEST);
            break;

        case '[':
            SetTok (TOK_LBRACK);
            break;

        case ']':
            SetTok (TOK_RBRACK);
            break;

        case '^':
            NextChar ();
            if (CurC == '=') {
                SetTok (TOK_XOR_ASSIGN);
            } else {
                NextTok.Tok = TOK_XOR;
            }
            break;

        case '{':
            SetTok (TOK_LCURLY);
            break;

        case '|':
            NextChar ();
            switch (CurC) {
                case '|':
                    SetTok (TOK_BOOL_OR);
                    break;
                case '=':
                    SetTok (TOK_OR_ASSIGN);
                    break;
                default:
                    NextTok.Tok = TOK_OR;
            }
            break;

        case '}':
            SetTok (TOK_RCURLY);
            break;

        case '~':
            SetTok (TOK_COMP);
            break;

        default:
            UnknownChar (CurC);

    }

}
예제 #15
0
파일: preproc.c 프로젝트: PanchoManera/cc65
static unsigned Pass1 (StrBuf* Source, StrBuf* Target)
/* Preprocessor pass 1. Remove whitespace. Handle old and new style comments
 * and the "defined" operator.
 */
{
    unsigned    IdentCount;
    ident       Ident;
    int         HaveParen;

    /* Switch to the new input source */
    StrBuf* OldSource = InitLine (Source);

    /* Loop removing ws and comments */
    IdentCount = 0;
    while (CurC != '\0') {
        if (SkipWhitespace (0)) {
            /* Squeeze runs of blanks */
            if (!IsSpace (SB_LookAtLast (Target))) {
                SB_AppendChar (Target, ' ');
            }
        } else if (IsSym (Ident)) {
            if (Preprocessing && strcmp (Ident, "defined") == 0) {
                /* Handle the "defined" operator */
                SkipWhitespace (0);
                HaveParen = 0;
                if (CurC == '(') {
                    HaveParen = 1;
                    NextChar ();
                    SkipWhitespace (0);
                }
                if (IsSym (Ident)) {
                    SB_AppendChar (Target, IsMacro (Ident)? '1' : '0');
                    if (HaveParen) {
                        SkipWhitespace (0);
                        if (CurC != ')') {
                            PPError ("`)' expected");
                        } else {
                            NextChar ();
                        }
                    }
                } else {
                    PPError ("Identifier expected");
                    SB_AppendChar (Target, '0');
                }
            } else {
                ++IdentCount;
                SB_AppendStr (Target, Ident);
            }
        } else if (IsQuote (CurC)) {
            CopyQuotedString (Target);
        } else if (CurC == '/' && NextC == '*') {
            if (!IsSpace (SB_LookAtLast (Target))) {
                SB_AppendChar (Target, ' ');
            }
            OldStyleComment ();
        } else if (IS_Get (&Standard) >= STD_C99 && CurC == '/' && NextC == '/') {
            if (!IsSpace (SB_LookAtLast (Target))) {
                SB_AppendChar (Target, ' ');
            }
            NewStyleComment ();
        } else {
            SB_AppendChar (Target, CurC);
            NextChar ();
        }
    }

    /* Switch back to the old source */
    InitLine (OldSource);

    /* Return the number of identifiers found in the line */
    return IdentCount;
}
예제 #16
0
파일: preproc.c 프로젝트: PanchoManera/cc65
static void MacroArgSubst (MacroExp* E)
/* Argument substitution according to ISO/IEC 9899:1999 (E), 6.10.3.1ff */
{
    ident       Ident;
    int         ArgIdx;
    StrBuf*     OldSource;
    StrBuf*     Arg;
    int         HaveSpace;


    /* Remember the current input and switch to the macro replacement. */
    int OldIndex = SB_GetIndex (&E->M->Replacement);
    SB_Reset (&E->M->Replacement);
    OldSource = InitLine (&E->M->Replacement);

    /* Argument handling loop */
    while (CurC != '\0') {

        /* If we have an identifier, check if it's a macro */
        if (IsSym (Ident)) {

            /* Check if it's a macro argument */
            if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) {

                /* A macro argument. Get the corresponding actual argument. */
                Arg = ME_GetActual (E, ArgIdx);

                /* Copy any following whitespace */
                HaveSpace = SkipWhitespace (0);

                /* If a ## operator follows, we have to insert the actual
                 * argument as is, otherwise it must be macro replaced.
                 */
                if (CurC == '#' && NextC == '#') {

                    /* ### Add placemarker if necessary */
                    SB_Append (&E->Replacement, Arg);

                } else {

                    /* Replace the formal argument by a macro replaced copy
                     * of the actual.
                     */
                    SB_Reset (Arg);
                    MacroReplacement (Arg, &E->Replacement);

                    /* If we skipped whitespace before, re-add it now */
                    if (HaveSpace) {
                        SB_AppendChar (&E->Replacement, ' ');
                    }
                }


            } else {

                /* An identifier, keep it */
                SB_AppendStr (&E->Replacement, Ident);

            }

        } else if (CurC == '#' && NextC == '#') {

            /* ## operator. */
            NextChar ();
            NextChar ();
            SkipWhitespace (0);

            /* Since we need to concatenate the token sequences, remove
             * any whitespace that was added to target, since it must come
             * from the input.
             */
            while (IsSpace (SB_LookAtLast (&E->Replacement))) {
                SB_Drop (&E->Replacement, 1);
            }

            /* If the next token is an identifier which is a macro argument,
             * replace it, otherwise do nothing.
             */
            if (IsSym (Ident)) {

                /* Check if it's a macro argument */
                if ((ArgIdx = FindMacroArg (E->M, Ident)) >= 0) {

                    /* Get the corresponding actual argument and add it. */
                    SB_Append (&E->Replacement, ME_GetActual (E, ArgIdx));

                } else {

                    /* Just an ordinary identifier - add as is */
                    SB_AppendStr (&E->Replacement, Ident);

                }
            }

        } else if (CurC == '#' && E->M->ArgCount >= 0) {

            /* A # operator within a macro expansion of a function like
             * macro. Read the following identifier and check if it's a
             * macro parameter.
             */
            NextChar ();
            SkipWhitespace (0);
            if (!IsSym (Ident) || (ArgIdx = FindMacroArg (E->M, Ident)) < 0) {
                PPError ("`#' is not followed by a macro parameter");
            } else {
                /* Make a valid string from Replacement */
                Arg = ME_GetActual (E, ArgIdx);
                SB_Reset (Arg);
                Stringize (Arg, &E->Replacement);
            }

        } else if (IsQuote (CurC)) {
            CopyQuotedString (&E->Replacement);
        } else {
            SB_AppendChar (&E->Replacement, CurC);
            NextChar ();
        }
    }

#if 0
    /* Remove whitespace from the end of the line */
    while (IsSpace (SB_LookAtLast (&E->Replacement))) {
        SB_Drop (&E->Replacement, 1);
    }
#endif

    /* Switch back the input */
    InitLine (OldSource);
    SB_SetIndex (&E->M->Replacement, OldIndex);
}
예제 #17
0
Token &
	TokenFactory::
	DoSymbol(unsigned char ch)
{
	// Get the position of the start of the symbol
	std::streampos
		pos = m_sCur->tellg();
	pos -= 1;
	// State of symbol determination
	E_STATE
		state = ES__NONE;
	// Current symbol type
	TokenType::E_TYPE
		type = TokenType::TT_SYMBOL;
	do
	{
		switch (state)
		{
			case ES__NONE: // ES_NONE
				switch (ch)
				{
					case 'A':
						if (CheckLetters("rray")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Array;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'B':
						if (CheckLetters("oolean")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Boolean;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'D':
						if (CheckLetters("ate")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Date;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'E':
						state = ES_E; // ES_E
						break;
					case 'F':
						if (CheckLetters("unction")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Function;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'M':
						if (CheckLetters("ath")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Math;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'N':
						if (CheckLetters("umber")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Number;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'O':
						if (CheckLetters("bject")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Object;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'R':
						state = ES_R; // ES_R
						break;
					case 'S':
						state = ES_S; // ES_S
						break;
					case 'T':
						if (CheckLetters("ypeError")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_TypeError;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'U':
						if (CheckLetters("RIError")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_URIError;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'a':
						if (CheckLetters("bstract")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_abstract;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'b':
						state = ES_b; // ES_b
						break;
					case 'c':
						state = ES_c; // ES_c
						break;
					case 'd':
						state = ES_d; // ES_d
						break;
					case 'e':
						state = ES_e; // ES_e
						break;
					case 'f':
						state = ES_f; // ES_f
						break;
					case 'g':
						if (CheckLetters("oto")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_goto;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'i':
						state = ES_i; // ES_i
						break;
					case 'l':
						if (CheckLetters("ong")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_long;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'n':
						state = ES_n; // ES_n
						break;
					case 'p':
						state = ES_p; // ES_p
						break;
					case 'r':
						if (CheckLetters("eturn")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_return;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 's':
						state = ES_s; // ES_s
						break;
					case 't':
						state = ES_t; // ES_t
						break;
					case 'u':
						if (CheckLetters("ndefined")) // Can only be this or unknown
						{
							// "undefined" is not a keyword but
							// is often used as one, we'll treat it
							// as one but warn them of the problems
							state = ES__DONE; // Mark as done
							type = TokenType::TK_undefined;
							Message::Send(Message::USED_UNDEFINED);
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'v':
						state = ES_v; // ES_v
						break;
					case 'w':
						state = ES_w; // ES_w
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_E: // ES_E
				switch (ch)
				{
					case 'r':
						if (CheckLetters("ror")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_Error;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'v':
						if (CheckLetters("alError")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_EvalError;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_R: // ES_R
				switch (ch)
				{
					case 'a':
						if (CheckLetters("ngeError")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_RangeError;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'e':
						state = ES_Re; // ES_Re
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_Re: // ES_Re
				switch (ch)
				{
					case 'f':
						if (CheckLetters("erenceError")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_ReferenceError;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'g':
						if (CheckLetters("Exp")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_RegExp;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_S: // ES_S
				switch (ch)
				{
					case 't':
						if (CheckLetters("ring")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_String;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'y':
						if (CheckLetters("ntaxError")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TG_SyntaxError;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_b: // ES_b
				switch (ch)
				{
					case 'o':
						if (CheckLetters("olean")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_boolean;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'r':
						if (CheckLetters("eak")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_break;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'y':
						if (CheckLetters("te")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_byte;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_c: // ES_c
				switch (ch)
				{
					case 'a':
						state = ES_ca; // ES_ca
						break;
					case 'h':
						if (CheckLetters("ar")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_char;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'l':
						if (CheckLetters("ass")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_class;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'o':
						if (CheckLetters("n")) // All possible symbols have these symbols
						{
							state = ES_con; // ES_con
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_ca: // ES_ca
				switch (ch)
				{
					case 's':
						if (CheckLetters("e")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_case;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 't':
						if (CheckLetters("ch")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_catch;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_con: // ES_con
				switch (ch)
				{
					case 's':
						if (CheckLetters("t")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_const;
							// SOME browsers implement this (at least FF)
							// but others don't (at least IE)
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 't':
						if (CheckLetters("inue")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_continue;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_d: // ES_d
				switch (ch)
				{
					case 'e':
						state = ES_de; // ES_de
						break;
					case 'o':
						state = ES_do; // ES_do
						type = TokenType::TK_do;
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_de: // ES_de
				switch (ch)
				{
					case 'b':
						if (CheckLetters("ugger")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_debugger;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'f':
						if (CheckLetters("ault")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_default;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'l':
						if (CheckLetters("ete")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_delete;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_do: // ES_do
				switch (ch)
				{
					case 'u':
						if (CheckLetters("ble")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_double;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_e: // ES_e
				switch (ch)
				{
					case 'l':
						if (CheckLetters("se")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_else;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'n':
						if (CheckLetters("um")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_enum;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'v':
						if (CheckLetters("al")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_eval;
							// Bad Bad Bad
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'x':
						state = ES_ex; // ES_ex
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_ex: // ES_ex
				switch (ch)
				{
					case 'p':
						if (CheckLetters("ort")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_export;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 't':
						if (CheckLetters("ends")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_extends;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_f: // ES_f
				switch (ch)
				{
					case 'a':
						if (CheckLetters("lse")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_false;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'i':
						if (CheckLetters("nal")) // All possible symbols have these symbols
						{
							state = ES_final; // ES_final
							type = TokenType::TR_final;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'l':
						if (CheckLetters("oat")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_float;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'o':
						if (CheckLetters("r")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_for;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'u':
						if (CheckLetters("nction")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_function;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_final: // ES_final
				switch (ch)
				{
					case 'l':
						if (CheckLetters("y")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_finally;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_i: // ES_i
				switch (ch)
				{
					case 'f':
						state = ES__DONE; // Mark as done
						type = TokenType::TK_if;
						break;
					case 'm':
						if (CheckLetters("p")) // All possible symbols have these symbols
						{
							state = ES_imp; // ES_imp
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'n':
						state = ES_in; // ES_in
						type = TokenType::TK_in;
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_imp: // ES_imp
				switch (ch)
				{
					case 'l':
						if (CheckLetters("ements")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_implements;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'o':
						if (CheckLetters("rt")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_import;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_in: // ES_in
				switch (ch)
				{
					case 's':
						if (CheckLetters("tanceof")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_instanceof;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 't':
						state = ES_int; // ES_int
						type = TokenType::TR_int;
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_int: // ES_int
				switch (ch)
				{
					case 'e':
						if (CheckLetters("rface")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_interface;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_n: // ES_n
				switch (ch)
				{
					case 'a':
						if (CheckLetters("tive")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_native;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'e':
						if (CheckLetters("w")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_new;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'u':
						if (CheckLetters("ll")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_null;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_p: // ES_p
				switch (ch)
				{
					case 'a':
						if (CheckLetters("ckage")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_package;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'r':
						state = ES_pr; // ES_pr
						break;
					case 'u':
						if (CheckLetters("blic")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_public;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_pr: // ES_pr
				switch (ch)
				{
					case 'i':
						if (CheckLetters("vate")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_private;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'o':
						if (CheckLetters("tected")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_protected;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_s: // ES_s
				switch (ch)
				{
					case 'h':
						if (CheckLetters("ort")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_short;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 't':
						if (CheckLetters("atic")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_static;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'u':
						if (CheckLetters("per")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_super;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'w':
						if (CheckLetters("itch")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_switch;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'y':
						if (CheckLetters("nchronized")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_synchronized;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_t: // ES_t
				switch (ch)
				{
					case 'h':
						state = ES_th; // ES_th
						break;
					case 'r':
						state = ES_tr; // ES_tr
						break;
					case 'y':
						if (CheckLetters("peof")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_typeof;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_th: // ES_th
				switch (ch)
				{
					case 'i':
						if (CheckLetters("s")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							//type = TokenType::TT_THIS; // Special case, "this" keyword
							//value.keyword = SymbolType::EK_this; // Only needed for the check below
							type = TokenType::TK_this;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'r':
						if (CheckLetters("ow")) // All possible symbols have these symbols
						{
							state = ES_throw; // ES_throw
							type = TokenType::TK_throw;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_throw: // ES_throw
				switch (ch)
				{
					case 's':
						state = ES__DONE; // Mark as done
						type = TokenType::TR_throws;
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_tr: // ES_tr
				switch (ch)
				{
					case 'a':
						if (CheckLetters("nsient")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_transient;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'u':
						if (CheckLetters("e")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_true;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'y':
						state = ES__DONE; // Mark as done
						type = TokenType::TK_try;
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_v: // ES_v
				switch (ch)
				{
					case 'a':
						if (CheckLetters("r")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_var;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'o':
						state = ES_vo; // ES_vo
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_vo: // ES_vo
				switch (ch)
				{
					case 'i':
						if (CheckLetters("d")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_void;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'l':
						if (CheckLetters("atile")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TR_volatile;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES_w: // ES_w
				switch (ch)
				{
					case 'h':
						if (CheckLetters("ile")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_while;
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					case 'i':
						if (CheckLetters("th")) // Can only be this or unknown
						{
							state = ES__DONE; // Mark as done
							type = TokenType::TK_with;
							// Bad Bad Bad
						}
						else
						{
							state = ES__UNKNOWN; // Mark as unknown
						}
						break;
					default:
						state = ES__UNKNOWN; // Mark as unknown
						break;
				}
				break;
			case ES__DONE:
				// If it's done that means there's no longer known
				// word that it can be, so if we get another char
				// then it's a custom symbol that starts out the
				// same as a regular symbol
				Message::Send(Message::POSSIBLY_AMBIGUOUS);
				state = ES__UNKNOWN;
				break;
			case ES__UNKNOWN:
				// Do nothing, we're just collecting data
				break;
			default:
				Message::Send(Message::UNKNOWN_STATE);
				state = ES__UNKNOWN;
				break;
		}
		ch = Read();
		// Check IsSym and IsDec as now they're both
		// valid symbol characters
	}
	while (IsSym(ch) || IsDec(ch));
	if (state == ES__UNKNOWN || type == TokenType::TT_SYMBOL)
	{
		// Technically not "unknown"
		// Just a new custom symbol
		// Found a new token
		std::streampos
			len;
		if (!ch)
		{
			// At the end of the file
			m_sCur->clear();
			len = 1;
		}
		else
		{
			len = 0;
		}
		len += m_sCur->tellg();
		len -= pos;
		// Include NULL in allocation
		// Use alloca because we only need this
		// temporarilly and it's easy to handle
		// no need to remember to delete the
		// memory on function exit or exception
		char *
			c = (char *)alloca(len);
		if (c)
		{
			// Get the start of the symbol and read
			m_sCur->seekg(pos);
			len -= 1;
			m_sCur->read(c, len);
			c[len] = '\0';
			Preprocessor &
				pp = Compiler::Get().GetPreprocessor();
			// Check if this is a macro
			if (pp.Defined(c))
			{
				// Yes
				m_altIn.push(pp.Get(c));
				return GetNext();
			}
			if (m_sCur->bad())
			{
				// Error reading
				Message::Send(Message::INPUT_STREAM_ERROR);
			}
			else
			{
				// Read, save token
				return Create(c, TokenType::TT_SYMBOL);
			}
		}
		else
		{
			m_sCur->unget();
			Message::Send(Message::OUT_OF_MEMORY);
		}
		// Something went wrong
		// Compile should fail
		return Create(TokenType::TT__NONE);
	}
	else
	{
		// Found an existing known token
		if (TokenType::IsReserved(type) && type != TokenType::TK_undefined)
		{
			// Using a reserved word, may conflict in future
			Message::Send(Message::USED_RESERVE, SC::L(type));
		}
		// Return a character to the stream
		m_sCur->unget();
		return Create(type);
	}
}