static void PrintUnresolved (ExpCheckFunc F, void* Data) /* Print a list of unresolved symbols. On unresolved symbols, F is ** called (see the comments on ExpCheckFunc in the data section). */ { unsigned I; /* Print all open imports */ for (I = 0; I < ExpCount; ++I) { Export* E = ExpPool [I]; if (E->Expr == 0 && E->ImpCount > 0 && F (E->Name, Data) == 0) { /* Unresolved external */ Import* Imp = E->ImpList; fprintf (stderr, "Unresolved external `%s' referenced in:\n", GetString (E->Name)); while (Imp) { unsigned J; for (J = 0; J < CollCount (&Imp->RefLines); ++J) { const LineInfo* LI = CollConstAt (&Imp->RefLines, J); fprintf (stderr, " %s(%u)\n", GetSourceName (LI), GetSourceLine (LI)); } Imp = Imp->Next; } } } }
void CircularRefError (const Export* E) /* Print an error about a circular reference using to define the given export */ { const LineInfo* LI = GetExportPos (E); Error ("Circular reference for symbol `%s', %s(%u)", GetString (E->Name), GetSourceName (LI), GetSourceLine (LI)); }
void CheckAssertions (void) /* Check all assertions */ { unsigned I; /* Walk over all assertions */ for (I = 0; I < CollCount (&Assertions); ++I) { const LineInfo* LI; const char* Module; unsigned Line; /* Get the assertion */ Assertion* A = CollAtUnchecked (&Assertions, I); /* Ignore assertions that shouldn't be handled at link time */ if (!AssertAtLinkTime (A->Action)) { continue; } /* Retrieve the relevant line info for this assertion */ LI = CollConstAt (&A->LineInfos, 0); /* Get file name and line number from the source */ Module = GetSourceName (LI); Line = GetSourceLine (LI); /* If the expression is not constant, we're not able to handle it */ if (!IsConstExpr (A->Expr)) { Warning ("Cannot evaluate assertion in module `%s', line %u", Module, Line); } else if (GetExprVal (A->Expr) == 0) { /* Assertion failed */ const char* Message = GetString (A->Msg); switch (A->Action) { case ASSERT_ACT_WARN: case ASSERT_ACT_LDWARN: Warning ("%s(%u): %s", Module, Line, Message); break; case ASSERT_ACT_ERROR: case ASSERT_ACT_LDERROR: Error ("%s(%u): %s", Module, Line, Message); break; default: Internal ("Invalid assertion action (%u) in module `%s', " "line %u (file corrupt?)", A->Action, Module, Line); break; } } } }
void PrintImportMap (FILE* F) /* Print an import map to the given file */ { unsigned I; const Import* Imp; /* Loop over all exports */ for (I = 0; I < ExpCount; ++I) { /* Get the export */ const Export* Exp = ExpPool [I]; /* Print the symbol only if there are imports, or if a verbose map ** file is requested. */ if (VerboseMap || Exp->ImpCount > 0) { /* Print the export */ fprintf (F, "%s (%s):\n", GetString (Exp->Name), GetObjFileName (Exp->Obj)); /* Print all imports for this symbol */ Imp = Exp->ImpList; while (Imp) { /* Print the import. Beware: The import might be linker ** generated, in which case there is no object file and ** sometimes no line information. */ const LineInfo* LI = GetImportPos (Imp); if (LI) { fprintf (F, " %-25s %s(%u)\n", GetObjFileName (Imp->Obj), GetSourceName (LI), GetSourceLine (LI)); } else { fprintf (F, " %-25s\n", GetObjFileName (Imp->Obj)); } /* Next import */ Imp = Imp->Next; } } } fprintf (F, "\n"); }
char *BlakodDebugInfo() { static char s[100]; class_node *c; if (kod_stat.interpreting_class == INVALID_CLASS) { sprintf(s,"Server"); } else { c = GetClassByID(kod_stat.interpreting_class); if (c == NULL) sprintf(s,"Invalid class %i",kod_stat.interpreting_class); else sprintf(s,"%s (%i)",c->fname,GetSourceLine(c,bkod)); } return s; }
Import* ReadImport (FILE* F, ObjData* Obj) /* Read an import from a file and return it */ { Import* I; /* Read the import address size */ unsigned char AddrSize = Read8 (F); /* Create a new import */ I = NewImport (AddrSize, Obj); /* Read the name */ I->Name = MakeGlobalStringId (Obj, ReadVar (F)); /* Read the line infos */ ReadLineInfoList (F, Obj, &I->DefLines); ReadLineInfoList (F, Obj, &I->RefLines); /* Check the address size */ if (I->AddrSize == ADDR_SIZE_DEFAULT || I->AddrSize > ADDR_SIZE_LONG) { /* Beware: This function may be called in cases where the object file ** is not read completely into memory. In this case, the file list is ** invalid. Be sure not to access it in this case. */ if (ObjHasFiles (I->Obj)) { const LineInfo* LI = GetImportPos (I); Error ("Invalid import size in for `%s', imported from %s(%u): 0x%02X", GetString (I->Name), GetSourceName (LI), GetSourceLine (LI), I->AddrSize); } else { Error ("Invalid import size in for `%s', imported from %s: 0x%02X", GetString (I->Name), GetObjFileName (I->Obj), I->AddrSize); } } /* Return the new import */ return I; }
char *BlakodStackInfo() { static char buf[5000]; class_node *c; int i; buf[0] = '\0'; for (i=message_depth-1;i>=0;i--) { char s[1000]; if (stack[i].class_id == INVALID_CLASS) { sprintf(s,"Server"); } else { c = GetClassByID(stack[i].class_id); if (c == NULL) sprintf(s,"Invalid class %i",stack[i].class_id); else { char *bp; char *class_name; char buf2[200]; char parms[800]; int j; /* for current frame, stack[] has pointer at beginning of function; use current pointer instead */ bp = stack[i].bkod_ptr; if (i == message_depth-1) bp = bkod; class_name = "(unknown)"; if (c->class_name) class_name = c->class_name; /* use %.*s with a fixed string of pluses to get exactly one plus per propagate depth */ sprintf(s,"%.*s%s::%s",stack[i].propagate_depth,"++++++++++++++++++++++",class_name,GetNameByID(stack[i].message_id)); strcat(s,"("); parms[0] = '\0'; for (j=0;j<stack[i].num_parms;j++) { val_type val; val.int_val = stack[i].parms[j].value; sprintf(buf2,"#%s=%s %s",GetNameByID(stack[i].parms[j].name_id), GetTagName(val),GetDataName(val)); if (j > 0) strcat(parms,","); strcat(parms,buf2); } strcat(s,parms); strcat(s,")"); sprintf(buf2," %s (%i)",c->fname,GetSourceLine(c,bp)); strcat(s,buf2); } } if (i < message_depth-1) strcat(buf,"\n"); strcat(buf,s); if (strlen(buf) > sizeof(buf) - 1000) { strcat(buf,"\n...and more"); break; } } return buf; }
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; } }
/* // MacroEnter // Returns: // 0 - Success // -1 - Error */ int MacroEnter( SOURCEFILE *ps, char *Name ) { SRCLINE sl; MACRO *pm; char src[MAX_SOURCE_LINE]; int i; if( Core == CORE_V0 ) { Report(ps,REP_ERROR,".macro illegal with specified core version"); return(-1); } /* Create the macro */ pm = MacroCreate( ps, Name ); if( !pm ) return(-1); /* Scan source lines until we see .endm */ for(;;) { /* Abort on a total disaster */ if( FatalError || Errors >= 25 ) return(-1); /* Get a line of source code */ i = GetSourceLine( ps, src, MAX_SOURCE_LINE ); if( !i ) { Report(ps,REP_ERROR,"Missing .endm on macro"); return(-1); } if( i<0 ) continue; if( !ParseSourceLine(ps,i,src,&sl) ) continue; /* Check for a label */ if( sl.Flags & SRC_FLG_LABEL ) { if( pm->Labels==MACRO_MAX_LABELS ) Report(ps,REP_ERROR,"Macro contains too many labels"); else { strcpy( pm->LableName[pm->Labels], sl.Label ); pm->Labels++; } } /* Check for a macro related dot command */ if( sl.Terms && (sl.Flags & SRC_FLG_DOTCMD1) ) { if( !stricmp( sl.Term[0], ".mparam" ) ) { if( sl.Terms==1 ) { Report(ps,REP_ERROR,"Expected at least 1 parameter on .mparam"); continue; } for( i=1; i<(int)sl.Terms; i++) MacroAddArg(ps,pm,sl.Term[i]); continue; } else if( !stricmp( sl.Term[0], ".macro" ) ) { Report(ps,REP_ERROR,"Macro definitions may not be nested"); continue; } else if( !stricmp( sl.Term[0], ".endm" ) ) { pm->InUse = 0; return(0); } } /* Else store the line as part of the macro */ else { if( pm->CodeLines == MACRO_MAX_LINES ) { Report(ps,REP_ERROR,"Macro line count exceeded"); continue; } strcpy(pm->Code[pm->CodeLines],src); pm->CodeLines++; } } }