Esempio n. 1
0
int SB_GetString (StrBuf* B, StrBuf* S)
/* Get a string from the string buffer. Returns 1 if a string was found and 0
** otherwise. Errors are only output in case of invalid strings (missing end
** of string).
*/
{
    char C;

    /* Clear S */
    SB_Clear (S);

    /* A string starts with quote marks */
    if (SB_Peek (B) == '\"') {

        /* String follows, be sure to concatenate strings */
        while (SB_Peek (B) == '\"') {

            /* Skip the quote char */
            SB_Skip (B);

            /* Read the actual string contents */
            while ((C = SB_Peek (B)) != '\"') {
                if (C == '\0') {
                    Error ("Unexpected end of string");
                    break;
                }
                SB_AppendChar (S, ParseChar (B));
            }

            /* Skip the closing quote char if there was one */
            SB_Skip (B);

            /* Skip white space, read new input */
            SB_SkipWhite (B);
        }

        /* Terminate the string */
        SB_Terminate (S);

        /* Success */
        return 1;

    } else {

        /* Not a string */
        SB_Terminate (S);
        return 0;
    }
}
Esempio n. 2
0
int SB_GetSym (StrBuf* B, StrBuf* Ident, const char* SpecialChars)
/* Get a symbol from the string buffer. If SpecialChars is not NULL, it
** points to a string that contains characters allowed within the string in
** addition to letters, digits and the underline. Note: The identifier must
** still begin with a letter.
** Returns 1 if a symbol was found and 0 otherwise but doesn't output any
** errors.
*/
{
    /* Handle a NULL argument for SpecialChars transparently */
    if (SpecialChars == 0) {
        SpecialChars = "";
    }

    /* Clear Ident */
    SB_Clear (Ident);

    if (IsIdent (SB_Peek (B))) {
        char C = SB_Peek (B);
        do {
            SB_AppendChar (Ident, C);
            SB_Skip (B);
            C = SB_Peek (B);
        } while (IsIdent (C) || IsDigit (C) || 
                 (C != '\0' && strchr (SpecialChars, C) != 0));
        SB_Terminate (Ident);
        return 1;
    } else {
        return 0;
    }
}
Esempio n. 3
0
void SB_SkipWhite (StrBuf* B)
/* Skip whitespace in the string buffer */
{
    while (IsBlank (SB_Peek (B))) {
        SB_Skip (B);
    }
}
Esempio n. 4
0
void NextChar (void)
/* Skip the current input character and read the next one from the input
 * stream. CurC and NextC are valid after the call. If end of line is
 * reached, both are set to NUL, no more lines are read by this function.
 */
{
    /* Skip the last character read */
    SB_Skip (Line);

    /* Read the next one */
    GetInputChar ();
}
Esempio n. 5
0
static void FuncSPrintF (void)
/* Handle the .SPRINTF function */
{
    StrBuf      Format = STATIC_STRBUF_INITIALIZER; /* User supplied format */
    StrBuf      R = STATIC_STRBUF_INITIALIZER;      /* Result string */
    StrBuf      F1 = STATIC_STRBUF_INITIALIZER;     /* One format spec from F */
    StrBuf      R1 = STATIC_STRBUF_INITIALIZER;     /* One result */
    char        C;
    int         Done;
    long        IVal;                               /* Integer value */



    /* Skip the .SPRINTF token */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* First argument is a format string. Remember and skip it */
    if (!LookAtStrCon ()) {
        return;
    }
    SB_Copy (&Format, &CurTok.SVal);
    NextTok ();

    /* Walk over the format string, generating the function result in R */
    while (1) {

        /* Get the next char from the format string and check for EOS */
        if (SB_Peek (&Format) == '\0') {
            break;
        }

        /* Check for a format specifier */
        if (SB_Peek (&Format) != '%') {
            /* No format specifier, just copy */
            SB_AppendChar (&R, SB_Get (&Format));
            continue;
        }
        SB_Skip (&Format);
        if (SB_Peek (&Format) == '%') {
            /* %% */
            SB_AppendChar (&R, '%');
            SB_Skip (&Format);
            continue;
        }
        if (SB_Peek (&Format) == '\0') {
            InvalidFormatString ();
            break;
        }

        /* Since a format specifier follows, we do expect anotehr argument for
         * the .sprintf function.
         */
        ConsumeComma ();

        /* We will copy the format spec into F1 checking for the things we
         * support, and later use xsprintf to do the actual formatting. This
         * is easier than adding another printf implementation...
         */
        SB_Clear (&F1);
        SB_AppendChar (&F1, '%');

        /* Check for flags */
        Done = 0;
        while ((C = SB_Peek (&Format)) != '\0' && !Done) {
            switch (C) {
                case '-': /* FALLTHROUGH */
                case '+': /* FALLTHROUGH */
                case ' ': /* FALLTHROUGH */
                case '#': /* FALLTHROUGH */
                case '0': SB_AppendChar (&F1, SB_Get (&Format));  break;
                default:  Done = 1;                               break;
            }
        }

        /* We do only support a numerical width field */
        while (IsDigit (SB_Peek (&Format))) {
            SB_AppendChar (&F1, SB_Get (&Format));
        }

        /* Precision - only positive numerical fields supported */
        if (SB_Peek (&Format) == '.') {
            SB_AppendChar (&F1, SB_Get (&Format));
            while (IsDigit (SB_Peek (&Format))) {
                SB_AppendChar (&F1, SB_Get (&Format));
            }
        }

        /* Length modifiers aren't supported, so read the conversion specs */
        switch (SB_Peek (&Format)) {

            case 'd':
            case 'i':
            case 'o':
            case 'u':
            case 'X':
            case 'x':
                /* Our ints are actually longs, so we use the 'l' modifier when
                 * calling xsprintf later. Terminate the format string.
                 */
                SB_AppendChar (&F1, 'l');
                SB_AppendChar (&F1, SB_Get (&Format));
                SB_Terminate (&F1);

                /* The argument must be a constant expression */
                IVal = ConstExpression ();

                /* Format this argument according to the spec */
                SB_Printf (&R1, SB_GetConstBuf (&F1), IVal);

                /* Append the formatted argument to the result */
                SB_Append (&R, &R1);

                break;

            case 's':
                /* Add the format spec and terminate the format */
                SB_AppendChar (&F1, SB_Get (&Format));
                SB_Terminate (&F1);

                /* The argument must be a string constant */
                if (!LookAtStrCon ()) {
                    /* Make it one */
                    SB_CopyStr (&CurTok.SVal, "**undefined**");
                }

                /* Format this argument according to the spec */
                SB_Printf (&R1, SB_GetConstBuf (&F1), SB_GetConstBuf (&CurTok.SVal));

                /* Skip the string constant */
                NextTok ();

                /* Append the formatted argument to the result */
                SB_Append (&R, &R1);

                break;

            case 'c':
                /* Add the format spec and terminate the format */
                SB_AppendChar (&F1, SB_Get (&Format));
                SB_Terminate (&F1);

                /* The argument must be a constant expression */
                IVal = ConstExpression ();

                /* Check for a valid character range */
                if (IVal <= 0 || IVal > 255) {
                    Error ("Char argument out of range");
                    IVal = ' ';
                }

                /* Format this argument according to the spec. Be sure to pass
                 * an int as the char value.
                 */
                SB_Printf (&R1, SB_GetConstBuf (&F1), (int) IVal);

                /* Append the formatted argument to the result */
                SB_Append (&R, &R1);

                break;

            default:
                Error ("Invalid format string");
                SB_Skip (&Format);
                break;
        }

    }

    /* Terminate the result string */
    SB_Terminate (&R);

    /* We expect a closing parenthesis, but will not skip it but replace it
     * by the string token just created.
     */
    if (CurTok.Tok != TOK_RPAREN) {
        Error ("`)' expected");
    } else {
        CurTok.Tok = TOK_STRCON;
        SB_Copy (&CurTok.SVal, &R);
        SB_Terminate (&CurTok.SVal);
    }


    /* Delete the string buffers */
    SB_Done (&Format);
    SB_Done (&R);
    SB_Done (&F1);
    SB_Done (&R1);
}
Esempio n. 6
0
static void FuncIdent (void)
/* Handle the .IDENT function */
{
    StrBuf    Buf = STATIC_STRBUF_INITIALIZER;
    token_t   Id;
    unsigned  I;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* The function expects a string argument */
    if (!LookAtStrCon ()) {
        return;
    }

    /* Check that the string contains a valid identifier. While doing so,
     * determine if it is a cheap local, or global one.
     */
    SB_Reset (&CurTok.SVal);

    /* Check for a cheap local symbol */
    if (SB_Peek (&CurTok.SVal) == LocalStart) {
        SB_Skip (&CurTok.SVal);
        Id = TOK_LOCAL_IDENT;
    } else {
        Id = TOK_IDENT;
    }

    /* Next character must be a valid identifier start */
    if (!IsIdStart (SB_Get (&CurTok.SVal))) {
        NoIdent ();
        return;
    }
    for (I = SB_GetIndex (&CurTok.SVal); I < SB_GetLen (&CurTok.SVal); ++I) {
        if (!IsIdChar (SB_AtUnchecked (&CurTok.SVal, I))) {
            NoIdent ();
            return;
        }
    }
    if (IgnoreCase) {
        UpcaseSVal ();
    }

    /* If anything is ok, save and skip the string. Check that the next token
     * is a right paren, then replace the token by an identifier token.
     */
    SB_Copy (&Buf, &CurTok.SVal);
    NextTok ();
    if (CurTok.Tok != TOK_RPAREN) {
        Error ("`)' expected");
    } else {
        CurTok.Tok = Id;
        SB_Copy (&CurTok.SVal, &Buf);
        SB_Terminate (&CurTok.SVal);
    }

    /* Free buffer memory */
    SB_Done (&Buf);
}
Esempio n. 7
0
static void ParsePragma (void)
/* Parse the contents of the _Pragma statement */
{
    pragma_t Pragma;
    StrBuf   Ident = AUTO_STRBUF_INITIALIZER;

    /* Create a string buffer from the string literal */
    StrBuf B = AUTO_STRBUF_INITIALIZER;
    SB_Append (&B, GetLiteralStrBuf (CurTok.SVal));

    /* Skip the string token */
    NextToken ();

    /* Get the pragma name from the string */
    SB_SkipWhite (&B);
    if (!SB_GetSym (&B, &Ident, "-")) {
        Error ("Invalid pragma");
        goto ExitPoint;
    }

    /* Search for the name */
    Pragma = FindPragma (&Ident);

    /* Do we know this pragma? */
    if (Pragma == PRAGMA_ILLEGAL) {
        /* According to the ANSI standard, we're not allowed to generate errors
         * for unknown pragmas, but warn about them if enabled (the default).
         */
        if (IS_Get (&WarnUnknownPragma)) {
            Warning ("Unknown pragma `%s'", SB_GetConstBuf (&Ident));
        }
        goto ExitPoint;
    }

    /* Check for an open paren */
    SB_SkipWhite (&B);
    if (SB_Get (&B) != '(') {
        Error ("'(' expected");
        goto ExitPoint;
    }

    /* Skip white space before the argument */
    SB_SkipWhite (&B);

    /* Switch for the different pragmas */
    switch (Pragma) {

        case PRAGMA_ALIGN:
            IntPragma (&B, &DataAlignment, 1, 4096);
            break;

        case PRAGMA_BSSSEG:
            Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead");
            /* FALLTHROUGH */
        case PRAGMA_BSS_NAME:
            SegNamePragma (&B, SEG_BSS);
            break;

        case PRAGMA_CHARMAP:
            CharMapPragma (&B);
            break;

        case PRAGMA_CHECKSTACK:
            Warning ("#pragma checkstack is obsolete, please use #pragma check-stack instead");
            /* FALLTHROUGH */
        case PRAGMA_CHECK_STACK:
            FlagPragma (&B, &CheckStack);
            break;

        case PRAGMA_CODESEG:
            Warning ("#pragma codeseg is obsolete, please use #pragma code-name instead");
            /* FALLTHROUGH */
        case PRAGMA_CODE_NAME:
            SegNamePragma (&B, SEG_CODE);
            break;

        case PRAGMA_CODESIZE:
            IntPragma (&B, &CodeSizeFactor, 10, 1000);
            break;

        case PRAGMA_DATASEG:
            Warning ("#pragma dataseg is obsolete, please use #pragma data-name instead");
            /* FALLTHROUGH */
        case PRAGMA_DATA_NAME:
            SegNamePragma (&B, SEG_DATA);
            break;

        case PRAGMA_LOCAL_STRINGS:
            FlagPragma (&B, &LocalStrings);
            break;

        case PRAGMA_OPTIMIZE:
            FlagPragma (&B, &Optimize);
            break;

        case PRAGMA_REGVARADDR:
            FlagPragma (&B, &AllowRegVarAddr);
            break;

        case PRAGMA_REGVARS:
            Warning ("#pragma regvars is obsolete, please use #pragma register-vars instead");
            /* FALLTHROUGH */
        case PRAGMA_REGISTER_VARS:
            FlagPragma (&B, &EnableRegVars);
            break;

        case PRAGMA_RODATASEG:
            Warning ("#pragma rodataseg is obsolete, please use #pragma rodata-name instead");
            /* FALLTHROUGH */
        case PRAGMA_RODATA_NAME:
            SegNamePragma (&B, SEG_RODATA);
            break;

        case PRAGMA_SIGNEDCHARS:
            Warning ("#pragma signedchars is obsolete, please use #pragma signed-chars instead");
            /* FALLTHROUGH */
        case PRAGMA_SIGNED_CHARS:
            FlagPragma (&B, &SignedChars);
            break;

        case PRAGMA_STATICLOCALS:
            Warning ("#pragma staticlocals is obsolete, please use #pragma static-locals instead");
            /* FALLTHROUGH */
        case PRAGMA_STATIC_LOCALS:
            FlagPragma (&B, &StaticLocals);
            break;

        case PRAGMA_WARN:
            WarnPragma (&B);
            break;

        case PRAGMA_WRITABLE_STRINGS:
            FlagPragma (&B, &WritableStrings);
            break;

        case PRAGMA_ZPSYM:
            StringPragma (&B, MakeZPSym);
            break;

        default:
            Internal ("Invalid pragma");
    }

    /* Closing paren expected */
    SB_SkipWhite (&B);
    if (SB_Get (&B) != ')') {
        Error ("')' expected");
        goto ExitPoint;
    }
    SB_SkipWhite (&B);

    /* Allow an optional semicolon to be compatible with the old syntax */
    if (SB_Peek (&B) == ';') {
        SB_Skip (&B);
        SB_SkipWhite (&B);
    }

    /* Make sure nothing follows */
    if (SB_Peek (&B) != '\0') {
        Error ("Unexpected input following pragma directive");
    }

ExitPoint:
    /* Release the string buffers */
    SB_Done (&B);
    SB_Done (&Ident);
}
Esempio n. 8
0
static int ParseChar (StrBuf* B)
/* Parse a character. Converts \n into EOL, etc. */
{
    unsigned I;
    unsigned Val;
    int C;

    /* Check for escape chars */
    if ((C = SB_Get (B)) == '\\') {
        switch (SB_Peek (B)) {
            case '?':
                C = '?';
                SB_Skip (B);
                break;
            case 'a':
                C = '\a';
                SB_Skip (B);
                break;
            case 'b':
                C = '\b';
                SB_Skip (B);
                break;
            case 'f':
                C = '\f';
                SB_Skip (B);
                break;
            case 'r':
                C = '\r';
                SB_Skip (B);
                break;
            case 'n':
                C = '\n';
                SB_Skip (B);
                break;
            case 't':
                C = '\t';
                SB_Skip (B);
                break;
            case 'v':
                C = '\v';
                SB_Skip (B);
                break;
            case '\"':
                C = '\"';
                SB_Skip (B);
                break;
            case '\'':
                C = '\'';
                SB_Skip (B);
                break;
            case '\\':
                C = '\\';
                SB_Skip (B);
                break;
            case 'x':
            case 'X':
                /* Hex character constant */
                SB_Skip (B);
                C = HexVal (SB_Get (B)) << 4;
                C |= HexVal (SB_Get (B));
                break;
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
                /* Octal constant */
                I = 0;
                Val = SB_Get (B) - '0';
                while (SB_Peek (B) >= '0' && SB_Peek (B) <= '7' && ++I <= 3) {
                    Val = (Val << 3) | (SB_Get (B) - '0');
                }
                C = (int) Val;
                if (Val > 256) {
                    Error ("Character constant out of range");
                    C = ' ';
                }
                break;
            default:
                Error ("Illegal character constant 0x%02X", SB_Get (B));
                C = ' ';
                break;
        }
    }

    /* Return the character */
    return C;
}
Esempio n. 9
0
int SB_GetNumber (StrBuf* B, long* Val)
/* Get a number from the string buffer. Accepted formats are decimal, octal,
** hex and character constants. Numeric constants may be preceeded by a
** minus or plus sign. The function returns 1 if a number was found and
** zero otherwise. Errors are only output for invalid numbers.
*/
{
    int      Sign;
    char     C;
    unsigned Base;
    unsigned DigitVal;


    /* Initialize Val */
    *Val = 0;

    /* Handle character constants */
    if (SB_Peek (B) == '\'') {

        /* Character constant */
        SB_Skip (B);
        *Val = SignExtendChar (TgtTranslateChar (ParseChar (B)));
        if (SB_Peek (B) != '\'') {
            Error ("`\'' expected");
            return 0;
        } else {
            /* Skip the quote */
            SB_Skip (B);
            return 1;
        }
    }

    /* Check for a sign. A sign must be followed by a digit, otherwise it's
    ** not a number
    */
    Sign = 1;
    switch (SB_Peek (B)) {
        case '-':
            Sign = -1;
            /* FALLTHROUGH */
        case '+':
            if (!IsDigit (SB_LookAt (B, SB_GetIndex (B) + 1))) {
                return 0;
            }
            SB_Skip (B);
            break;
    }

    /* We must have a digit now, otherwise its not a number */
    C = SB_Peek (B);
    if (!IsDigit (C)) {
        return 0;
    }

    /* Determine the base */
    if (C == '0') {
        /* Hex or octal */
        SB_Skip (B);
        if (tolower (SB_Peek (B)) == 'x') {
            SB_Skip (B);
            Base = 16;
            if (!IsXDigit (SB_Peek (B))) {
                Error ("Invalid hexadecimal number");
                return 0;
            }
        } else {
            Base = 8;
        }
    } else {
        Base = 10;
    }

    /* Read the number */
    while (IsXDigit (C = SB_Peek (B)) && (DigitVal = HexVal (C)) < Base) {
        *Val = (*Val * Base) + DigitVal;
        SB_Skip (B);
    }

    /* Allow optional 'U' and 'L' modifiers */
    C = SB_Peek (B);
    if (C == 'u' || C == 'U') {
        SB_Skip (B);
        C = SB_Peek (B);
        if (C == 'l' || C == 'L') {
            SB_Skip (B);
        }
    } else if (C == 'l' || C == 'L') {
        SB_Skip (B);
        C = SB_Peek (B);
        if (C == 'u' || C == 'U') {
            SB_Skip (B);
        }
    }

    /* Success, value read is in Val */
    *Val *= Sign;
    return 1;
}