Beispiel #1
0
static void VPrintMsg (const FilePos* Pos, const char* Desc,
                       const char* Format, va_list ap)
/* Format and output an error/warning message. */
{
    StrBuf S = STATIC_STRBUF_INITIALIZER;

    /* Format the actual message */
    StrBuf Msg = STATIC_STRBUF_INITIALIZER;
    SB_VPrintf (&Msg, Format, ap);
    SB_Terminate (&Msg);

    /* Format the message header */
    SB_Printf (&S, "%s(%u): %s: ",
               SB_GetConstBuf (GetFileName (Pos->Name)),
               Pos->Line,
               Desc);

    /* Append the message to the message header */
    SB_Append (&S, &Msg);

    /* Delete the formatted message */
    SB_Done (&Msg);

    /* Add a new line and terminate the generated full message */
    SB_AppendChar (&S, '\n');
    SB_Terminate (&S);

    /* Output the full message */
    fputs (SB_GetConstBuf (&S), stderr);

    /* Delete the buffer for the full message */
    SB_Done (&S);
}
Beispiel #2
0
static void FuncConcat (void)
/* Handle the .CONCAT function */
{
    StrBuf      Buf = STATIC_STRBUF_INITIALIZER;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Concatenate any number of strings */
    while (1) {

        /* Next token must be a string */
        if (!LookAtStrCon ()) {
            SB_Done (&Buf);
            return;
        }

        /* Append the string */
        SB_Append (&Buf, &CurTok.SVal);

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

        /* Comma means another argument */
        if (CurTok.Tok == TOK_COMMA) {
            NextTok ();
        } else {
            /* Done */
            break;
        }
    }

    /* 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, &Buf);
        SB_Terminate (&CurTok.SVal);
    }

    /* Free the string buffer */
    SB_Done (&Buf);
}
Beispiel #3
0
SymEntry* ParseScopedSymName (SymFindAction Action)
/* Parse a (possibly scoped) symbol name, search for it in the symbol table
 * and return the symbol table entry.
 */
{
    StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
    StrBuf    Ident = STATIC_STRBUF_INITIALIZER;
    int       NoScope;
    SymEntry* Sym;

    /* Parse the scoped symbol name */
    SymTable* Scope = ParseScopedIdent (&Ident, &ScopeName);

    /* If ScopeName is empty, no scope was specified */
    NoScope = SB_IsEmpty (&ScopeName);

    /* We don't need ScopeName any longer */
    SB_Done (&ScopeName);

    /* Check if the scope is valid. Errors have already been diagnosed by
     * the routine, so just exit.
     */
    if (Scope) {
        /* Search for the symbol and return it. If no scope was specified,
         * search also in the upper levels.
         */
        if (NoScope && (Action & SYM_ALLOC_NEW) == 0) {
            Sym = SymFindAny (Scope, &Ident);
        } else {
            Sym = SymFind (Scope, &Ident, Action);
        }
    } else {
        /* No scope ==> no symbol. To avoid errors in the calling routine that
         * may not expect NULL to be returned if Action contains SYM_ALLOC_NEW,
         * create a new symbol.
         */
        if (Action & SYM_ALLOC_NEW) { 
            Sym = NewSymEntry (&Ident, SF_NONE);
        } else {
            Sym = 0;
        }
    }

    /* Deallocate memory for ident */
    SB_Done (&Ident);

    /* Return the symbol found */
    return Sym;
}
Beispiel #4
0
void IFDone (CharSource* S)
/* Close the current input file */
{
    /* We're at the end of an include file. Check if we have any
    ** open .IFs, or any open token lists in this file. This
    ** enforcement is artificial, using conditionals that start
    ** in one file and end in another are uncommon, and don't
    ** allowing these things will help finding errors.
    */
    CheckOpenIfs ();

    /* If we've added search paths for this file, remove them */
    if (S->V.File.IncSearchPath) {
        PopSearchPath (IncSearchPath);
    }
    if (S->V.File.BinSearchPath) {
        PopSearchPath (BinSearchPath);
    }

    /* Free the line buffer */
    SB_Done (&S->V.File.Line);

    /* Close the input file and decrement the file count. We will ignore
    ** errors here, since we were just reading from the file.
    */
    (void) fclose (S->V.File.F);
    --FCount;
}
Beispiel #5
0
static void DoInclude (void)
/* Open an include file. */
{
    char        RTerm;
    InputType   IT;
    StrBuf      Filename = STATIC_STRBUF_INITIALIZER;


    /* Preprocess the remainder of the line */
    PreprocessLine ();

    /* Skip blanks */
    SkipWhitespace (0);

    /* Get the next char and check for a valid file name terminator. Setup
     * the include directory spec (SYS/USR) by looking at the terminator.
     */
    switch (CurC) {

        case '\"':
            RTerm   = '\"';
            IT = IT_USRINC;
            break;

        case '<':
            RTerm   = '>';
            IT = IT_SYSINC;
            break;

        default:
            PPError ("`\"' or `<' expected");
            goto Done;
    }
    NextChar ();

    /* Get a copy of the filename */
    while (CurC != '\0' && CurC != RTerm) {
        SB_AppendChar (&Filename, CurC);
        NextChar ();
    }
    SB_Terminate (&Filename);

    /* Check if we got a terminator */
    if (CurC == RTerm) {
        /* Open the include file */
        OpenIncludeFile (SB_GetConstBuf (&Filename), IT);
    } else if (CurC == '\0') {
        /* No terminator found */
        PPError ("#include expects \"FILENAME\" or <FILENAME>");
    }

Done:
    /* Free the allocated filename data */
    SB_Done (&Filename);

    /* Clear the remaining line so the next input will come from the new
     * file (if open)
     */
    ClearLine ();
}
Beispiel #6
0
void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir)
/* Add a search path from an environment variable, adding a subdirectory to
** the environment variable value.
*/
{
    StrBuf Dir = AUTO_STRBUF_INITIALIZER;

    const char* EnvVal = getenv (EnvVar);
    if (EnvVal == 0) {
        /* Not found */
        return;
    }

    /* Copy the environment variable to the buffer */
    SB_CopyStr (&Dir, EnvVal);

    /* Add a path separator if necessary */
    if (SB_NotEmpty (&Dir)) {
        if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') {
            SB_AppendChar (&Dir, '/');
        }
    }

    /* Add the subdirectory and terminate the string */
    SB_AppendStr (&Dir, SubDir);
    SB_Terminate (&Dir);

    /* Add the search path */
    AddSearchPath (P, SB_GetConstBuf (&Dir));

    /* Free the temp buffer */
    SB_Done (&Dir);
}
Beispiel #7
0
char* SearchFile (const SearchPaths* P, const char* File)
/* Search for a file in a list of directories. Return a pointer to a malloced
** area that contains the complete path, if found, return 0 otherwise.
*/
{
    char* Name = 0;
    StrBuf PathName = AUTO_STRBUF_INITIALIZER;

    /* Start the search */
    unsigned I;
    for (I = 0; I < CollCount (P); ++I) {

        /* Copy the next path element into the buffer */
        SB_CopyStr (&PathName, CollConstAt (P, I));

        /* Add a path separator and the filename */
        if (SB_NotEmpty (&PathName)) {
            SB_AppendChar (&PathName, '/');
        }
        SB_AppendStr (&PathName, File);
        SB_Terminate (&PathName);

        /* Check if this file exists */
        if (access (SB_GetBuf (&PathName), 0) == 0) {
            /* The file exists, we're done */
            Name = xstrdup (SB_GetBuf (&PathName));
            break;
        }
    }

    /* Cleanup and return the result of the search */
    SB_Done (&PathName);
    return Name;
}
Beispiel #8
0
static IntStack* GetWarning (StrBuf* B)
/* Get a warning name from the string buffer. Returns a pointer to the intstack
 * that holds the state of the warning, and NULL in case of errors. The
 * function will output error messages in case of problems.
 */
{
    IntStack* S = 0;
    StrBuf W = AUTO_STRBUF_INITIALIZER;

    /* The warning name is a symbol but the '-' char is allowed within */
    if (SB_GetSym (B, &W, "-")) {

        /* Map the warning name to an IntStack that contains its state */
        S = FindWarning (SB_GetConstBuf (&W));

        /* Handle errors */
        if (S == 0) {
            Error ("Pragma expects a warning name as first argument");
        }
    }

    /* Deallocate the string */
    SB_Done (&W);

    /* Done */
    return S;
}
Beispiel #9
0
static void NewSymbol (const char* SymName, long Val)
/* Define a symbol with a fixed numeric value in the current scope */
{
    ExprNode* Expr;
    SymEntry* Sym;

    /* Convert the name to a string buffer */
    StrBuf SymBuf = STATIC_STRBUF_INITIALIZER;
    SB_CopyStr (&SymBuf, SymName);

    /* Search for the symbol, allocate a new one if it doesn't exist */
    Sym = SymFind (CurrentScope, &SymBuf, SYM_ALLOC_NEW);

    /* Check if have already a symbol with this name */
    if (SymIsDef (Sym)) {
        AbEnd ("`%s' is already defined", SymName);
    }

    /* Generate an expression for the symbol */
    Expr = GenLiteralExpr (Val);

    /* Mark the symbol as defined */
    SymDef (Sym, Expr, ADDR_SIZE_DEFAULT, SF_NONE);

    /* Free string buffer memory */
    SB_Done (&SymBuf);
}
Beispiel #10
0
void SplitAddAttr (Collection* C, const char* Combined, const char* Name)
/* Split a combined name/value pair and add it as an attribute to C. Some
 * attributes may not need a name. If the name is missing, use Name. If
 * Name is NULL, terminate with an error.
 */
{
    /* Name and value are separated by an equal sign */
    const char* Pos = strchr (Combined, '=');
    if (Pos == 0) {
        /* Combined is actually a value */
        if (Name == 0) {
            Error ("Command line attribute `%s' doesn't contain a name", Combined);
        }
        AddAttr (C, Name, Combined);
    } else {
        /* Must split name and value */
        StrBuf N = AUTO_STRBUF_INITIALIZER;
        SB_CopyBuf (&N, Combined, Pos - Combined);
        SB_Terminate (&N);

        /* Add the attribute */
        AddAttr (C, SB_GetConstBuf (&N), Pos+1);

        /* Release memory */
        SB_Done (&N);
    }
}
Beispiel #11
0
static void FreeIdDesc (IdDesc* ID)
/* Free an IdDesc */
{
    /* Free the name */
    SB_Done (&ID->Id);

    /* Free the structure itself */
    xfree (ID);
}
Beispiel #12
0
static void FreeLiteral (Literal* L)
/* Free a literal */
{
    /* Free the literal data */
    SB_Done (&L->Data);

    /* Free the structure itself */
    xfree (L);
}
Beispiel #13
0
static AFile* NewAFile (IFile* IF, FILE* F)
/* Create a new AFile, push it onto the stack, add the path of the file to
 * the path search list, and finally return a pointer to the new AFile struct.
 */
{
    StrBuf Path = AUTO_STRBUF_INITIALIZER;

    /* Allocate a AFile structure */
    AFile* AF = (AFile*) xmalloc (sizeof (AFile));

    /* Initialize the fields */
    AF->Line  = 0;
    AF->F     = F;
    AF->Input = IF;

    /* Increment the usage counter of the corresponding IFile. If this
     * is the first use, set the file data and output debug info if
     * requested.
     */
    if (IF->Usage++ == 0) {

 	/* Get file size and modification time. There a race condition here,
         * since we cannot use fileno() (non standard identifier in standard
         * header file), and therefore not fstat. When using stat with the
         * file name, there's a risk that the file was deleted and recreated
         * while it was open. Since mtime and size are only used to check
         * if a file has changed in the debugger, we will ignore this problem
         * here.
         */
     	struct stat Buf;
 	if (FileStat (IF->Name, &Buf) != 0) {
 	    /* Error */
 	    Fatal ("Cannot stat `%s': %s", IF->Name, strerror (errno));
 	}
       	IF->Size  = (unsigned long) Buf.st_size;
 	IF->MTime = (unsigned long) Buf.st_mtime;

 	/* Set the debug data */
 	g_fileinfo (IF->Name, IF->Size, IF->MTime);
    }

    /* Insert the new structure into the AFile collection */
    CollAppend (&AFiles, AF);

    /* Get the path of this file and add it as an extra search path.
     * To avoid file search overhead, we will add one path only once.
     * This is checked by the PushSearchPath function.
     */
    SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name);
    SB_Terminate (&Path);
    AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path));
    SB_Done (&Path);

    /* Return the new struct */
    return AF;
}
Beispiel #14
0
static void CreateLoadDefines (SegDesc* S, unsigned long SegAddr)
/* Create the defines for a LOAD segment */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    SB_Printf (&Buf, "__%s_LOAD__", GetString (S->Name));
    CreateMemoryExport (GetStrBufId (&Buf), S->Load, SegAddr - S->Load->Start);
    S->Flags |= SF_LOAD_DEF;
    SB_Done (&Buf);
}
Beispiel #15
0
static void StringConst (void)
/* Parse a quoted string */
{
    /* String buffer */
    StrBuf S = AUTO_STRBUF_INITIALIZER;

    /* Assume next token is a string constant */
    NextTok.Tok  = TOK_SCONST;

    /* Concatenate strings. If at least one of the concenated strings is a wide
    ** character literal, the whole string is a wide char literal, otherwise
    ** it's a normal string literal.
    */
    while (1) {

        /* Check if this is a normal or a wide char string */
        if (CurC == 'L' && NextC == '\"') {
            /* Wide character literal */
            NextTok.Tok = TOK_WCSCONST;
            NextChar ();
            NextChar ();
        } else if (CurC == '\"') {
            /* Skip the quote char */
            NextChar ();
        } else {
            /* No string */
            break;
        }

        /* Read until end of string */
        while (CurC != '\"') {
            if (CurC == '\0') {
                Error ("Unexpected newline");
                break;
            }
            SB_AppendChar (&S, ParseChar ());
        }

        /* Skip closing quote char if there was one */
        NextChar ();

        /* Skip white space, read new input */
        SkipWhite ();

    }

    /* Terminate the string */
    SB_AppendChar (&S, '\0');

    /* Add the whole string to the literal pool */
    NextTok.SVal = AddLiteralStr (&S);

    /* Free the buffer */
    SB_Done (&S);
}
Beispiel #16
0
static void CreateRunDefines (SegDesc* S, unsigned long SegAddr)
/* Create the defines for a RUN segment */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    SB_Printf (&Buf, "__%s_RUN__", GetString (S->Name));
    CreateMemoryExport (GetStrBufId (&Buf), S->Run, SegAddr - S->Run->Start);
    SB_Printf (&Buf, "__%s_SIZE__", GetString (S->Name));
    CreateConstExport (GetStrBufId (&Buf), S->Seg->Size);
    S->Flags |= SF_RUN_DEF;
    SB_Done (&Buf);
}
Beispiel #17
0
static void FuncString (void)
/* Handle the .STRING function */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    /* Skip it */
    NextTok ();

    /* Left paren expected */
    ConsumeLParen ();

    /* Accept identifiers or numeric expressions */
    if (CurTok.Tok == TOK_LOCAL_IDENT) {
        /* Save the identifier, then skip it */
        SB_Copy (&Buf, &CurTok.SVal);
        NextTok ();
    } else if (CurTok.Tok == TOK_NAMESPACE || CurTok.Tok == TOK_IDENT) {

        /* Parse a fully qualified symbol name. We cannot use
         * ParseScopedSymName here since the name may be invalid.
         */
        int NameSpace;
        do {
            NameSpace = (CurTok.Tok == TOK_NAMESPACE);
            if (NameSpace) {
                SB_AppendStr (&Buf, "::");
            } else {
                SB_Append (&Buf, &CurTok.SVal);
            }
            NextTok ();
        } while ((NameSpace != 0 && CurTok.Tok == TOK_IDENT) ||
                 (NameSpace == 0 && CurTok.Tok == TOK_NAMESPACE));

    } else {
        /* Numeric expression */
        long Val = ConstExpression ();
        SB_Printf (&Buf, "%ld", Val);
    }

    /* 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, &Buf);
        SB_Terminate (&CurTok.SVal);
    }

    /* Free string memory */
    SB_Done (&Buf);
}
Beispiel #18
0
static void DoneMacroExp (MacroExp* E)
/* Cleanup after use of a MacroExp structure */
{
    unsigned I;

    /* Delete the list with actual arguments */
    for (I = 0; I < CollCount (&E->ActualArgs); ++I) {
        FreeStrBuf (CollAtUnchecked (&E->ActualArgs, I));
    }
    DoneCollection (&E->ActualArgs);
    SB_Done (&E->Replacement);
}
Beispiel #19
0
SymTable* ParseScopedSymTable (void)
/* Parse a (possibly scoped) symbol table (scope) name, search for it in the
 * symbol space and return the symbol table struct.
 */
{
    StrBuf    ScopeName = STATIC_STRBUF_INITIALIZER;
    StrBuf    Name = STATIC_STRBUF_INITIALIZER;
    int       NoScope;


    /* Parse the scoped symbol name */
    SymTable* Scope = ParseScopedIdent (&Name, &ScopeName);

    /* If ScopeName is empty, no scope was specified */
    NoScope = SB_IsEmpty (&ScopeName);

    /* We don't need FullName any longer */
    SB_Done (&ScopeName);

    /* If we got no error, search for the child scope withint the enclosing one.
     * Beware: If no explicit parent scope was specified, search in all upper
     * levels.
     */
    if (Scope) {
        /* Search for the last scope */
        if (NoScope) {
            Scope = SymFindAnyScope (Scope, &Name);
        } else {
            Scope = SymFindScope (Scope, &Name, SYM_FIND_EXISTING);
        }
    }

    /* Free memory for name */
    SB_Done (&Name);

    /* Return the scope found */
    return Scope;
}
Beispiel #20
0
void CfgWarning (const FilePos* Pos, const char* Format, ...)
/* Print a warning message adding file name and line number of a given file */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;
    va_list ap;

    va_start (ap, Format);
    SB_VPrintf (&Buf, Format, ap);
    va_end (ap);

    Warning ("%s(%u): %s",
             GetString (Pos->Name), Pos->Line, SB_GetConstBuf (&Buf));
    SB_Done (&Buf);
}
Beispiel #21
0
static void StringPragma (StrBuf* B, void (*Func) (const char*))
/* Handle a pragma that expects a string parameter */
{
    StrBuf S = AUTO_STRBUF_INITIALIZER;

    /* We expect a string here */
    if (GetString (B, &S)) {
        /* Call the given function with the string argument */
        Func (SB_GetConstBuf (&S));
    }

    /* Call the string buf destructor */
    SB_Done (&S);
}
Beispiel #22
0
static void SetOptions (void)
/* Set the option for the translator */
{
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    /* Set the translator */
    SB_Printf (&Buf, "ca65 V%s", GetVersionAsString ());
    OptTranslator (&Buf);

    /* Set date and time */
    OptDateTime ((unsigned long) time(0));

    /* Release memory for the string */
    SB_Done (&Buf);
}
Beispiel #23
0
Collection* ParseAttrList (const char* List, const char** NameList, unsigned NameCount)
/* Parse a list containing name/value pairs into a sorted collection. Some
 * attributes may not need a name, so NameList contains these names. If there
 * were no errors, the function returns a alphabetically sorted collection
 * containing Attr entries.
 */
{
    const char* Name;

    /* Create a new collection */
    Collection* C = NewCollection ();

    /* Name/value pairs are separated by commas */
    const char* L = List;
    StrBuf B = AUTO_STRBUF_INITIALIZER;
    while (1) {
        if (*L == ',' || *L == ':' || *L == '\0') {

            /* Terminate the string */
            SB_Terminate (&B);

            /* Determine the default name */
            if (CollCount (C) >= NameCount) {
                Name = 0;
            } else {
                Name = NameList[CollCount (C)];
            }

            /* Split and add this attribute/value pair */
            SplitAddAttr (C, SB_GetConstBuf (&B), Name);

            /* Done, clear the buffer. */
            SB_Clear (&B);
            if (*L == '\0') {
                break;
            }
        } else {
            SB_AppendChar (&B, *L);
        }
        ++L;
    }

    /* Free memory */
    SB_Done (&B);

    /* Return the collection with the attributes */
    return C;
}
Beispiel #24
0
static void OpenDebugFile (const CodeSeg* S)
/* Open the debug file for the given segment if the flag is on */
{
    if (DebugOptOutput) {
        StrBuf Name = AUTO_STRBUF_INITIALIZER;
        if (S->Func) {
            SB_CopyStr (&Name, S->Func->Name);
        } else {
            SB_CopyStr (&Name, "global");
        }
        SB_AppendStr (&Name, ".opt");
        SB_Terminate (&Name);
        OpenDebugOutputFile (SB_GetConstBuf (&Name));
        SB_Done (&Name);
    }
}
Beispiel #25
0
static void DefineSymbol (const char* Def)
/* Define a symbol from the command line */
{
    const char* P;
    long Val;
    StrBuf SymName = AUTO_STRBUF_INITIALIZER;


    /* The symbol must start with a character or underline */
    if (!IsIdStart (Def [0])) {
        InvDef (Def);
    }
    P = Def;

    /* Copy the symbol, checking the rest */
    while (IsIdChar (*P)) {
        SB_AppendChar (&SymName, *P++);
    }
    SB_Terminate (&SymName);

    /* Do we have a value given? */
    if (*P != '=') {
        if (*P != '\0') {
            InvDef (Def);
        }
        Val = 0;
    } else {
        /* We have a value */
        ++P;
        if (*P == '$') {
            ++P;
            if (sscanf (P, "%lx", &Val) != 1) {
                InvDef (Def);
            }
        } else {
            if (sscanf (P, "%li", &Val) != 1) {
                InvDef (Def);
            }
        }
    }

    /* Define the new symbol */
    NewSymbol (SB_GetConstBuf (&SymName), Val);

    /* Release string memory */
    SB_Done (&SymName);
}
Beispiel #26
0
static void FlagPragma (StrBuf* B, IntStack* Stack)
/* Handle a pragma that expects a boolean paramater */
{
    StrBuf Ident = AUTO_STRBUF_INITIALIZER;
    long   Val;
    int    Push;


    /* Try to read an identifier */
    int IsIdent = SB_GetSym (B, &Ident, 0);

    /* Check if we have a first argument named "pop" */
    if (IsIdent && SB_CompareStr (&Ident, "pop") == 0) {
        PopInt (Stack);
        /* No other arguments allowed */
        return;
    }

    /* Check if we have a first argument named "push" */
    if (IsIdent && SB_CompareStr (&Ident, "push") == 0) {
        Push = 1;
        if (!GetComma (B)) {
            goto ExitPoint;
        }
        IsIdent = SB_GetSym (B, &Ident, 0);
    } else {
        Push = 0;
    }

    /* Boolean argument follows */
    if (IsIdent) {
        Val = BoolKeyword (&Ident);
    } else if (!GetNumber (B, &Val)) {
        goto ExitPoint;
    }

    /* Set/push the new value */
    if (Push) {
        PushInt (Stack, Val);
    } else {
        IS_Set (Stack, Val);
    }

ExitPoint:
    /* Free the identifier */
    SB_Done (&Ident);
}
Beispiel #27
0
void Internal (const char* Format, ...)
/* Print a message about an internal assembler error and die. */
{
    va_list ap;
    StrBuf S = STATIC_STRBUF_INITIALIZER;

    va_start (ap, Format);
    SB_VPrintf (&S, Format, ap);
    SB_Terminate (&S);
    va_end (ap);

    fprintf (stderr, "Internal assembler error: %s\n", SB_GetConstBuf (&S));

    SB_Done (&S);

    exit (EXIT_FAILURE);
}
Beispiel #28
0
void CS_AddVLine (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap)
/* Add a line to the given code segment */
{
    const char* L;
    CodeEntry*  E;
    char        Token[IDENTSIZE+10];

    /* Format the line */
    StrBuf Buf = STATIC_STRBUF_INITIALIZER;
    SB_VPrintf (&Buf, Format, ap);

    /* Skip whitespace */
    L = SkipSpace (SB_GetConstBuf (&Buf));

    /* Check which type of instruction we have */
    E = 0;  	/* Assume no insn created */
    switch (*L) {

    	case '\0':
	    /* Empty line, just ignore it */
	    break;

	case ';':
	    /* Comment or hint, ignore it for now */
     	    break;

	case '.':
	    /* Control instruction */
	    ReadToken (L, " \t", Token, sizeof (Token));
     	    Error ("ASM code error: Pseudo instruction `%s' not supported", Token);
	    break;

	default:
	    E = ParseInsn (S, LI, L);
	    break;
    }

    /* If we have a code entry, transfer the labels and insert it */
    if (E) {
	CS_AddEntry (S, E);
    }

    /* Cleanup the string buffer */
    SB_Done (&Buf);
}
Beispiel #29
0
static PushPopResult ParsePushPop (StrBuf* B)
/* Check for and parse the "push" and "pop" keywords. In case of "push", a
 * following comma is expected and skipped.
 */
{
    StrBuf Ident      = AUTO_STRBUF_INITIALIZER;
    PushPopResult Res = PP_NONE;

    /* Remember the current string index, so we can go back in case of errors */
    unsigned Index = SB_GetIndex (B);

    /* Try to read an identifier */
    if (SB_GetSym (B, &Ident, 0)) {

        /* Check if we have a first argument named "pop" */
        if (SB_CompareStr (&Ident, "pop") == 0) {

            Res = PP_POP;

        /* Check if we have a first argument named "push" */
        } else if (SB_CompareStr (&Ident, "push") == 0) {

            Res = PP_PUSH;

            /* Skip the following comma */
            if (!GetComma (B)) {
                /* Error already flagged by GetComma */
                Res = PP_ERROR;
            }

        } else {

            /* Unknown keyword, roll back */
            SB_SetIndex (B, Index);
        }
    }

    /* Free the string buffer and return the result */
    SB_Done (&Ident);
    return Res;
}
Beispiel #30
0
static void FreeMacro (Macro* M)
/* Free a macro entry which has already been removed from the macro table. */
{
    TokNode* T;

    /* Free locals */
    FreeIdDescList (M->Locals);

    /* Free identifiers of parameters */
    FreeIdDescList (M->Params);

    /* Free the token list for the macro */
    while ((T = M->TokRoot) != 0) {
        M->TokRoot = T->Next;
        FreeTokNode (T);
    }

    /* Free the macro name */
    SB_Done (&M->Name);

    /* Free the macro structure itself */
    xfree (M);
}