Example #1
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);
}
Example #2
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);
}
Example #3
0
StrBuf* AnonName (StrBuf* Buf, const char* Spec)
/* Get a name for an anonymous scope, variable or type. Size is the size of
 * the buffer passed to the function, Spec will be used as part of the
 * identifier if given. A pointer to the buffer is returned.
 */
{
    static unsigned ACount = 0;
    SB_Printf (Buf, "%s-%s-%04X", AnonTag, Spec, ++ACount);
    return Buf;
}
Example #4
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);
}
Example #5
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);
}
Example #6
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);
}
Example #7
0
const char* ED_GetLabelName (const ExprDesc* Expr, long Offs)
/* Return the assembler label name of the given expression. Beware: This
 * function may use a static buffer, so the name may get "lost" on the second
 * call to the function.
 */
{
    static StrBuf Buf = STATIC_STRBUF_INITIALIZER;

    /* Expr may have it's own offset, adjust Offs accordingly */
    Offs += Expr->IVal;

    /* Generate a label depending on the location */
    switch (ED_GetLoc (Expr)) {

        case E_LOC_ABS:
            /* Absolute: numeric address or const */
            SB_Printf (&Buf, "$%04X", (int)(Offs & 0xFFFF));
            break;

        case E_LOC_GLOBAL:
        case E_LOC_STATIC:
            /* Global or static variable */
            if (Offs) {
                SB_Printf (&Buf, "%s%+ld", SymGetAsmName (Expr->Sym), Offs);
            } else {
                SB_Printf (&Buf, "%s", SymGetAsmName (Expr->Sym));
            }
            break;

        case E_LOC_REGISTER:
            /* Register variable */
            SB_Printf (&Buf, "regbank+%u", (unsigned)((Offs + Expr->Name) & 0xFFFFU));
            break;

        case E_LOC_LITERAL:
            /* Literal in the literal pool */
            if (Offs) {
                SB_Printf (&Buf, "%s%+ld", LocalLabelName (Expr->Name), Offs);
            } else {
                SB_Printf (&Buf, "%s", LocalLabelName (Expr->Name));
            }
            break;

        default:
            Internal ("Invalid location in ED_GetLabelName: 0x%04X", ED_GetLoc (Expr));
    }

    /* Return a pointer to the static buffer */
    return SB_GetConstBuf (&Buf);
}
Example #8
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);
}
Example #9
0
static void CheckSymType (const Export* E)
/* Check the types for one export */
{
    /* External with matching imports */
    Import* I = E->ImpList;
    while (I) {
        if (E->AddrSize != I->AddrSize) {
            /* Export and import address sizes do not match */
            StrBuf ExportLoc = STATIC_STRBUF_INITIALIZER;
            StrBuf ImportLoc = STATIC_STRBUF_INITIALIZER;
            const char* ExpAddrSize = AddrSizeToStr ((unsigned char) E->AddrSize);
            const char* ImpAddrSize = AddrSizeToStr ((unsigned char) I->AddrSize);
            const LineInfo* ExportLI = GetExportPos (E);
            const LineInfo* ImportLI = GetImportPos (I);

            /* Generate strings that describe the location of the im- and
            ** exports. This depends on the place from where they come:
            ** Object file or linker config.
            */
            if (E->Obj) {
                /* The export comes from an object file */
                SB_Printf (&ExportLoc, "%s, %s(%u)",
                           GetString (E->Obj->Name),
                           GetSourceName (ExportLI),
                           GetSourceLine (ExportLI));
            } else {
                SB_Printf (&ExportLoc, "%s(%u)",
                           GetSourceName (ExportLI),
                           GetSourceLine (ExportLI));
            }
            if (I->Obj) {
                /* The import comes from an object file */
                SB_Printf (&ImportLoc, "%s, %s(%u)",
                           GetString (I->Obj->Name),
                           GetSourceName (ImportLI),
                           GetSourceLine (ImportLI));
            } else if (ImportLI) {
                /* The import is linker generated and we have line
                ** information
                */
                SB_Printf (&ImportLoc, "%s(%u)",
                           GetSourceName (ImportLI),
                           GetSourceLine (ImportLI));
            } else {
                /* The import is linker generated and we don't have line
                ** information
                */
                SB_Printf (&ImportLoc, "%s", GetObjFileName (I->Obj));
            }

            /* Output the diagnostic */
            Warning ("Address size mismatch for `%s': "
                     "Exported from %s as `%s', "
                     "import in %s as `%s'",
                     GetString (E->Name),
                     SB_GetConstBuf (&ExportLoc),
                     ExpAddrSize,
                     SB_GetConstBuf (&ImportLoc),
                     ImpAddrSize);

            /* Free the temporary strings */
            SB_Done (&ExportLoc);
            SB_Done (&ImportLoc);
        }
        I = I->Next;
    }
}
Example #10
0
static int MacExpand (void* Data)
/* If we're currently expanding a macro, set the the scanner token and
 * attribute to the next value and return true. If we are not expanding
 * a macro, return false.
 */
{
    /* Cast the Data pointer to the actual data structure */
    MacExp* Mac = (MacExp*) Data;

    /* Check if we should abort this macro */
    if (DoMacAbort) {

        /* Reset the flag */
        DoMacAbort = 0;

        /* Abort any open .IF statements in this macro expansion */
        CleanupIfStack (Mac->IfSP);

        /* Terminate macro expansion */
        goto MacEnd;
    }

    /* We're expanding a macro. Check if we are expanding one of the
     * macro parameters.
     */
ExpandParam:
    if (Mac->ParamExp) {

        /* Ok, use token from parameter list */
        TokSet (Mac->ParamExp);

        /* Create new line info for this parameter token */
        if (Mac->ParamLI) {
            EndLine (Mac->ParamLI);
        }
        Mac->ParamLI = StartLine (&CurTok.Pos, LI_TYPE_MACPARAM, Mac->MacExpansions);

        /* Set pointer to next token */
        Mac->ParamExp = Mac->ParamExp->Next;

        /* Done */
        return 1;

    } else if (Mac->ParamLI) {

        /* There's still line info open from the parameter expansion - end it */
        EndLine (Mac->ParamLI);
        Mac->ParamLI = 0;

    }

    /* We're not expanding macro parameters. Check if we have tokens left from
     * the macro itself.
     */
    if (Mac->Exp) {

        /* Use next macro token */
        TokSet (Mac->Exp);

        /* Create new line info for this token */
        if (Mac->LI) {
            EndLine (Mac->LI);
        }
        Mac->LI = StartLine (&CurTok.Pos, LI_TYPE_MACRO, Mac->MacExpansions);

        /* Set pointer to next token */
        Mac->Exp = Mac->Exp->Next;

        /* Is it a request for actual parameter count? */
        if (CurTok.Tok == TOK_PARAMCOUNT) {
            CurTok.Tok  = TOK_INTCON;
            CurTok.IVal = Mac->ParamCount;
            return 1;
        }

        /* Is it the name of a macro parameter? */
        if (CurTok.Tok == TOK_MACPARAM) {

            /* Start to expand the parameter token list */
            Mac->ParamExp = Mac->Params[CurTok.IVal];

            /* Go back and expand the parameter */
            goto ExpandParam;
        }

        /* If it's an identifier, it may in fact be a local symbol */
        if ((CurTok.Tok == TOK_IDENT || CurTok.Tok == TOK_LOCAL_IDENT) &&
            Mac->M->LocalCount) {
            /* Search for the local symbol in the list */
            unsigned Index = 0;
            IdDesc* I = Mac->M->Locals;
            while (I) {
                if (SB_Compare (&CurTok.SVal, &I->Id) == 0) {
                    /* This is in fact a local symbol, change the name. Be sure
                     * to generate a local label name if the original name was
                     * a local label, and also generate a name that cannot be
                     * generated by a user.
                     */
                    if (SB_At (&I->Id, 0) == LocalStart) {
                        /* Must generate a local symbol */
                        SB_Printf (&CurTok.SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
                                   LocalStart, Mac->LocalStart + Index);
                    } else {
                        /* Global symbol */
                        SB_Printf (&CurTok.SVal, "LOCAL-MACRO_SYMBOL-%04X",
                                   Mac->LocalStart + Index);
                    }
                    break;
                }
                /* Next symbol */
                ++Index;
                I = I->Next;
            }

            /* Done */
            return 1;
        }

        /* The token was successfully set */
        return 1;
    }

    /* No more macro tokens. Do we have a final token? */
    if (Mac->Final) {

        /* Set the final token and remove it */
        TokSet (Mac->Final);
        FreeTokNode (Mac->Final);
        Mac->Final = 0;

        /* Problem: When a .define style macro is expanded within the call
         * of a classic one, the latter may be terminated and removed while
         * the expansion of the .define style macro is still active. Because
         * line info slots are "stacked", this runs into a CHECK FAILED. For
         * now, we will fix that by removing the .define style macro expansion
         * immediately, once the final token is placed. The better solution
         * would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
         * to be called in FIFO order, but this is a bigger change.
         */
        /* End of macro expansion and pop the input function */
        FreeMacExp (Mac);
        PopInput ();

        /* The token was successfully set */
        return 1;
    }

MacEnd:
    /* End of macro expansion */
    FreeMacExp (Mac);

    /* Pop the input function */
    PopInput ();

    /* No token available */
    return 0;
}
Example #11
0
static int MacExpand (void* Data)
/* If we're currently expanding a macro, set the the scanner token and
 * attribute to the next value and return true. If we are not expanding
 * a macro, return false.
 */
{
    /* Cast the Data pointer to the actual data structure */
    MacExp* Mac = (MacExp*) Data;

    /* Check if we should abort this macro */
    if (DoMacAbort) {

	/* Reset the flag */
	DoMacAbort = 0;

	/* Abort any open .IF statements in this macro expansion */
	CleanupIfStack (Mac->IfSP);

	/* Terminate macro expansion */
	goto MacEnd;
    }

    /* We're expanding a macro. Check if we are expanding one of the
     * macro parameters.
     */
    if (Mac->ParamExp) {

       	/* Ok, use token from parameter list */
       	TokSet (Mac->ParamExp);

       	/* Set pointer to next token */
       	Mac->ParamExp = Mac->ParamExp->Next;

       	/* Done */
       	return 1;

    }

    /* We're not expanding macro parameters. Check if we have tokens left from
     * the macro itself.
     */
    if (Mac->Exp) {

       	/* Use next macro token */
       	TokSet (Mac->Exp);

       	/* Set pointer to next token */
       	Mac->Exp = Mac->Exp->Next;

       	/* Is it a request for actual parameter count? */
       	if (Tok == TOK_PARAMCOUNT) {
       	    Tok  = TOK_INTCON;
       	    IVal = Mac->ParamCount;
       	    return 1;
       	}

       	/* Is it the name of a macro parameter? */
       	if (Tok == TOK_MACPARAM) {

       	    /* Start to expand the parameter token list */
       	    Mac->ParamExp = Mac->Params [IVal];

       	    /* Recursive call to expand the parameter */
       	    return MacExpand (Mac);
       	}

       	/* If it's an identifier, it may in fact be a local symbol */
       	if ((Tok == TOK_IDENT || Tok == TOK_LOCAL_IDENT) && Mac->M->LocalCount) {
       	    /* Search for the local symbol in the list */
       	    unsigned Index = 0;
       	    IdDesc* I = Mac->M->Locals;
       	    while (I) {
       	       	if (SB_Compare (&SVal, &I->Id) == 0) {
       	       	    /* This is in fact a local symbol, change the name. Be sure
                     * to generate a local label name if the original name was
                     * a local label, and also generate a name that cannot be
                     * generated by a user.
                     */
                    if (SB_At (&I->Id, 0) == LocalStart) {
                        /* Must generate a local symbol */
                        SB_Printf (&SVal, "%cLOCAL-MACRO_SYMBOL-%04X",
                                   LocalStart, Mac->LocalStart + Index);
                    } else {
                        /* Global symbol */
                        SB_Printf (&SVal, "LOCAL-MACRO_SYMBOL-%04X",
                                   Mac->LocalStart + Index);
                    }
       	       	    break;
       	       	}
       	       	/* Next symbol */
       	       	++Index;
       	       	I = I->Next;
       	    }

       	    /* Done */
       	    return 1;
       	}

       	/* The token was successfully set */
       	return 1;

    }

    /* No more macro tokens. Do we have a final token? */
    if (Mac->Final) {

      	/* Set the final token and remove it */
      	TokSet (Mac->Final);
      	FreeTokNode (Mac->Final);
      	Mac->Final = 0;

       	/* The token was successfully set */
       	return 1;

    }

MacEnd:
    /* End of macro expansion */
    FreeMacExp (Mac);

    /* Pop the input function */
    PopInput ();

    /* No token available */
    return 0;
}
Example #12
0
unsigned CfgAssignSegments (void)
/* Assign segments, define linker symbols where requested. The function will
 * return the number of memory area overflows (so zero means anything went ok).
 * In case of overflows, a short mapfile can be generated later, to ease the
 * task of rearranging segments for the user.
 */
{
    unsigned Overflows = 0;

    /* Walk through each of the memory sections. Add up the sizes and check
     * for an overflow of the section. Assign the start addresses of the
     * segments while doing this.
     */
    Memory* M = MemoryList;
    while (M) {

        MemListNode* N;

     	/* Get the start address of this memory area */
     	unsigned long Addr = M->Start;

        /* Remember if this is a relocatable memory area */
        M->Relocatable = RelocatableBinFmt (M->F->Format);

     	/* Walk through the segments in this memory area */
     	N = M->SegList;
     	while (N) {

     	    /* Get the segment from the node */
     	    SegDesc* S = N->Seg;

            /* Some actions depend on wether this is the load or run memory
             * area.
             */
            if (S->Run == M) {

                /* This is the run (and maybe load) memory area. Handle
                 * alignment and explict start address and offset.
                 */
                if (S->Flags & SF_ALIGN) {
                    /* Align the address */
                    unsigned long Val = (0x01UL << S->Align) - 1;
                    Addr = (Addr + Val) & ~Val;
                } else if (S->Flags & (SF_OFFSET | SF_START)) {
                    /* Give the segment a fixed starting address */
                    unsigned long NewAddr = S->Addr;
                    if (S->Flags & SF_OFFSET) {
                        /* An offset was given, no address, make an address */
                        NewAddr += M->Start;
                    }
                    if (Addr > NewAddr) {
                        /* Offset already too large */
                        if (S->Flags & SF_OFFSET) {
                            Error ("Offset too small in `%s', segment `%s'",
                                   GetString (M->Name), GetString (S->Name));
                        } else {
                            Error ("Start address too low in `%s', segment `%s'",
                                   GetString (M->Name), GetString (S->Name));
                        }
                    }
                    Addr = NewAddr;
                }

                /* Set the start address of this segment, set the readonly flag
                 * in the segment and and remember if the segment is in a
                 * relocatable file or not.
                 */
                S->Seg->PC = Addr;
                S->Seg->ReadOnly = (S->Flags & SF_RO) != 0;
                S->Seg->Relocatable = M->Relocatable;

            } else if (S->Load == M) {

                /* This is the load memory area, *and* run and load are
                 * different (because of the "else" above). Handle alignment.
                 */
                if (S->Flags & SF_ALIGN_LOAD) {
                    /* Align the address */
                    unsigned long Val = (0x01UL << S->AlignLoad) - 1;
                    Addr = (Addr + Val) & ~Val;
                }

            }

     	    /* Increment the fill level of the memory area and check for an
     	     * overflow.
     	     */
     	    M->FillLevel = Addr + S->Seg->Size - M->Start;
       	    if (M->FillLevel > M->Size && (M->Flags & MF_OVERFLOW) == 0) {
                ++Overflows;
                M->Flags |= MF_OVERFLOW;
                Warning ("Memory area overflow in `%s', segment `%s' (%lu bytes)",
                         GetString (M->Name), GetString (S->Name),
                         M->FillLevel - M->Size);
     	    }

     	    /* If requested, define symbols for the start and size of the
     	     * segment.
     	     */
     	    if (S->Flags & SF_DEFINE) {
                if (S->Run == M && (S->Flags & SF_RUN_DEF) == 0) {
                    CreateRunDefines (S, Addr);
                }
                if (S->Load == M && (S->Flags & SF_LOAD_DEF) == 0) {
                    CreateLoadDefines (S, Addr);
                }
     	    }

     	    /* Calculate the new address */
     	    Addr += S->Seg->Size;

	    /* Next segment */
	    N = N->Next;
	}

	/* If requested, define symbols for start and size of the memory area */
	if (M->Flags & MF_DEFINE) {
	    StrBuf Buf = STATIC_STRBUF_INITIALIZER;
	    SB_Printf (&Buf, "__%s_START__", GetString (M->Name));
	    CreateMemoryExport (GetStrBufId (&Buf), M, 0);
	    SB_Printf (&Buf, "__%s_SIZE__", GetString (M->Name));
	    CreateConstExport (GetStrBufId (&Buf), M->Size);
	    SB_Printf (&Buf, "__%s_LAST__", GetString (M->Name));
	    CreateMemoryExport (GetStrBufId (&Buf), M, M->FillLevel);
            SB_Done (&Buf);
	}

	/* Next memory area */
	M = M->Next;
    }

    /* Return the number of memory area overflows */
    return Overflows;
}