ALERROR CCodeChain::Boot (void) // Boot // // Initializes the object. Clean up is done in the destructor { ALERROR error; int i; ICCItem *pItem; // Initialize memory error m_sMemoryError.SetError(); m_sMemoryError.SetValue(LITERAL("Out of memory")); // Initialize Nil pItem = new CCNil; if (pItem == NULL) return ERR_FAIL; m_pNil = pItem->Reference(); // Initialize True pItem = new CCTrue; if (pItem == NULL) return ERR_FAIL; m_pTrue = pItem->Reference(); // Initialize global symbol table pItem = CreateSymbolTable(); if (pItem->IsError()) return ERR_FAIL; m_pGlobalSymbols = pItem; // Register the built-in primitives for (i = 0; i < DEFPRIMITIVES_COUNT; i++) if (error = RegisterPrimitive(&g_DefPrimitives[i])) return error; return NOERROR; }
ICCItem *CCodeChain::EvalLiteralStruct (CEvalContext *pCtx, ICCItem *pItem) // EvalLiteralStruct // // Evalues the values in a structure and returns a structure // (or an error). { int i; CCSymbolTable *pTable = dynamic_cast<CCSymbolTable *>(pItem); if (pTable == NULL) return CreateError(CONSTLIT("Not a structure"), pItem); ICCItem *pNew = CreateSymbolTable(); if (pNew->IsError()) return pNew; CCSymbolTable *pNewTable = dynamic_cast<CCSymbolTable *>(pNew); // Loop over all key/value pairs for (i = 0; i < pTable->GetCount(); i++) { CString sKey = pTable->GetKey(i); ICCItem *pValue = pTable->GetElement(i); ICCItem *pNewKey = CreateString(sKey); ICCItem *pNewValue = (pValue ? Eval(pCtx, pValue) : CreateNil()); ICCItem *pResult = pNewTable->AddEntry(this, pNewKey, pNewValue); pNewKey->Discard(this); pNewValue->Discard(this); if (pResult->IsError()) { pNewTable->Discard(this); return pResult; } pResult->Discard(this); } // Done return pNewTable; }
int main(int argc, char *argv[]) { int ch; char *ep; if (argc == 1) usage(); progname = argv[0]; while ((ch = getopt(argc, argv, "m:n:o:O:p:s:tw")) != -1) { switch (ch) { case 'm': SetMapfileName(optarg); break; case 'n': SetSymfileName(optarg); break; case 'o': out_Setname(optarg); break; case 'O': out_SetOverlayname(optarg); options |= OPT_OVERLAY; break; case 'p': fillchar = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { errx(1, "Invalid argument for option 'p'"); } if (fillchar < 0 || fillchar > 0xFF) { fprintf(stderr, "Argument for option 'p' must be between 0 and 0xFF"); exit(1); } break; case 's': options |= OPT_SMART_C_LINK; smartlinkstartsymbol = optarg; break; case 't': options |= OPT_SMALL; break; case 'w': /* Set to set WRAM as a single continuous block as on DMG. All WRAM sections must be WRAM0 as bankable WRAM sections do not exist in this mode. A WRAMX section will raise an error. */ options |= OPT_CONTWRAM; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc == 0) usage(); for (int i = 0; i < argc; ++i) obj_Readfile(argv[i]); AddNeededModules(); AssignSections(); CreateSymbolTable(); Patch(); Output(); CloseMapfile(); return (0); }
int main( int argc, char *argv[] ) { SLONG argn=0; argc-=1; argn+=1; if( argc==0 ) PrintUsage(); while( *argv[argn]=='-' ) { char opt; argc-=1; switch( opt=argv[argn++][1] ) { case '?': case 'h': PrintUsage(); break; case 'm': SetMapfileName( argv[argn-1]+2 ); break; case 'n': SetSymfileName( argv[argn-1]+2 ); break; case 't': switch( opt=argv[argn-1][2] ) { case 'g': outputtype=OUTPUT_GBROM; break; case 's': outputtype=OUTPUT_GBROM; options|=OPT_SMALL; break; case 'p': outputtype=OUTPUT_PSION2; break; default: sprintf( temptext, "Unknown option 't%c'\n", opt ); fatalerror( temptext ); break; } break; case 'z': if( strlen(argv[argn-1]+2)<=2 ) { if( strcmp(argv[argn-1]+2,"?")==0 ) { fillchar=-1; } else { int result; result=sscanf( argv[argn-1]+2, "%x", &fillchar ); if( !((result==EOF) || (result==1)) ) { fatalerror("Invalid argument for option 'z'\n" ); } } } else { fatalerror("Invalid argument for option 'z'\n" ); } break; case 's': options|=OPT_SMART_C_LINK; strcpy( smartlinkstartsymbol, argv[argn-1]+2 ); break; case 'i': g_identifyBanks = 1 ; break ; default: sprintf( temptext, "Unknown option '%c'\n", opt ); fatalerror( temptext ); break; } } if( argc==1 ) { ProcessLinkfile( argv[argn++] ); AddNeededModules(); AssignSections(); CreateSymbolTable(); Patch(); Output(); CloseMapfile(); } else PrintUsage(); return( 0 ); }
int main(int argc, char *argv[]) { int ch; char *ep; if (argc == 1) print_usage(); while ((ch = getopt(argc, argv, "dl:m:n:O:o:p:s:tVw")) != -1) { switch (ch) { case 'l': SetLinkerscriptName(optarg); break; case 'm': SetMapfileName(optarg); break; case 'n': SetSymfileName(optarg); break; case 'o': out_Setname(optarg); break; case 'O': out_SetOverlayname(optarg); options |= OPT_OVERLAY; break; case 'p': fillchar = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') errx(1, "Invalid argument for option 'p'"); if (fillchar < 0 || fillchar > 0xFF) errx(1, "Argument for option 'p' must be between 0 and 0xFF"); break; case 's': options |= OPT_SMART_C_LINK; smartlinkstartsymbol = optarg; break; case 't': options |= OPT_TINY; break; case 'd': /* * Set to set WRAM as a single continuous block as on * DMG. All WRAM sections must be WRAM0 as bankable WRAM * sections do not exist in this mode. A WRAMX section * will raise an error. VRAM bank 1 can't be used if * this option is enabled either. * * This option implies OPT_CONTWRAM. */ options |= OPT_DMG_MODE; /* FALLTHROUGH */ case 'w': /* * Set to set WRAM as a single continuous block as on * DMG. All WRAM sections must be WRAM0 as bankable WRAM * sections do not exist in this mode. A WRAMX section * will raise an error. */ options |= OPT_CONTWRAM; break; case 'V': printf("rgblink %s\n", get_package_version_string()); exit(0); default: print_usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc == 0) print_usage(); for (int32_t i = 0; i < argc; ++i) obj_Readfile(argv[i]); AddNeededModules(); AssignSections(); CreateSymbolTable(); Patch(); Output(); CloseMapfile(); return 0; }
void BuildSymTab(){ strcpy(path, "global"); nestLevel = 0; SymTab = CreateSymbolTable(path, nestLevel); SymtabTraverseTree(root, path, nestLevel, SymTab); }
void SymtabTraverseTree(TreeNode *p, char *path, int nestLevel, SymbolTable *symtab){ char local_path[256]; if (!p) return ; // printf("path:%s\n", path); switch (p->node){ case routine_kind: { SymtabTraverseTree(p->children[0], path, nestLevel, symtab); SymtabTraverseTree(p->children[1], path, nestLevel, symtab); break; } case const_kind: { if (DuplicateIdentifier(p->name, path)) throw_error("duplicate identifier", p); InsertSymbol(p->name, p, symtab); SymtabTraverseTree(p->sibling, path, nestLevel, symtab); break; } case type_kind: { switch (p->type){ case decl_type:{ if (DuplicateIdentifier(p->name, path)) throw_error("duplicate identifier", p); InsertSymbol(p->name, p, symtab); if(p->dtype->type!=record_type){ SymtabTraverseTree(p->sibling, path, nestLevel, symtab); } else { sprintf(local_path, "%s/%s", path, p->name); SymbolTable *new_symtab = CreateSymbolTable(local_path, nestLevel+1); ConnectSymtabs(symtab, new_symtab); SymtabTraverseTree(p->dtype, local_path, nestLevel+1, new_symtab); SymtabTraverseTree(p->sibling, path, nestLevel, symtab); } break; } case record_type:{ SymtabTraverseTree(p->children[0], path, nestLevel, symtab); break; } default:{ break; } } break; } case var_kind:{ TreeNode *q; q = p->children[0]; while (q){ if (DuplicateIdentifier(q->name, path)) throw_error("duplicate identifier", q); InsertSymbol(q->name, p, symtab); q = q->sibling; } SymtabTraverseTree(p->sibling, path, nestLevel, symtab); break; } case sub_kind: { switch(p->sub){ case func_kind:{ // printf("enter function %s decl:\n", p->name); InsertSymbol(p->name, p, symtab); sprintf(local_path, "%s/%s", path, p->name); SymbolTable * new_symtab = CreateSymbolTable(local_path, nestLevel+1); ConnectSymtabs(symtab, new_symtab); SymtabTraverseTree(p->children[0], local_path, nestLevel+1, new_symtab); SymtabTraverseTree(p->children[1], local_path, nestLevel+1, new_symtab); SymtabTraverseTree(p->children[2], local_path, nestLevel+1, new_symtab); break; } case proc_kind:{ // printf("enter procedure %s decl:\n", p->name); InsertSymbol(p->name, p, symtab); sprintf(local_path, "%s/%s", path, p->name); SymbolTable * new_symtab = CreateSymbolTable(local_path, nestLevel+1); ConnectSymtabs(symtab, new_symtab); SymtabTraverseTree(p->children[0], local_path, nestLevel+1, new_symtab); SymtabTraverseTree(p->children[1], local_path, nestLevel+1, new_symtab); SymtabTraverseTree(p->children[2], local_path, nestLevel+1, new_symtab); break; } case param_var_kind:{ TreeNode *q; q = p->children[0]; while (q){ if (DuplicateIdentifier(q->name, path)) throw_error("duplicate identifier", q); InsertSymbol(q->name, p, symtab); q = q->sibling; } break; } case param_val_kind:{ TreeNode *q; q = p->children[0]; while (q){ if (DuplicateIdentifier(q->name, path)) throw_error("duplicate identifier", q); InsertSymbol(q->name, p, symtab); q = q->sibling; } break; } } SymtabTraverseTree(p->sibling, path, nestLevel, symtab); break; }; case expr_kind:{ switch (p->expr){ case id_kind:{ // printf("look for identifier: %s\n", p->name); if (!Lookup(p->name, path)) throw_error("unknown identifier", p); break; } case fn_kind:{ // printf("look for function: %s\n", p->name); if (!Lookup(p->name, path) && !p->system) throw_error("unknown identifier", p); } default: break; } SymtabTraverseTree(p->children[0], path, nestLevel, symtab); SymtabTraverseTree(p->children[1], path, nestLevel, symtab); SymtabTraverseTree(p->children[2], path, nestLevel, symtab); SymtabTraverseTree(p->sibling, path, nestLevel, symtab); break; } case stmt_kind:{ switch (p->stmt){ case for_stmt:{ if (!Lookup(p->name, path)) throw_error("unknown identifier", p); } case proc_stmt:{ if (!Lookup(p->name, path) && !p->system) throw_error("unknown identifier", p); } } SymtabTraverseTree(p->children[0], path, nestLevel, symtab); SymtabTraverseTree(p->children[1], path, nestLevel, symtab); SymtabTraverseTree(p->children[2], path, nestLevel, symtab); SymtabTraverseTree(p->sibling, path, nestLevel, symtab); break; } default: { SymtabTraverseTree(p->children[0], path, nestLevel, symtab); SymtabTraverseTree(p->children[1], path, nestLevel, symtab); SymtabTraverseTree(p->children[2], path, nestLevel, symtab); SymtabTraverseTree(p->sibling, path, nestLevel, symtab); break; } } }
//main function - call with the name of the AST input file int main(int argc, char **argv) { //generate the array of quads (okay we have a limit of 10,000 - we really don't think people //in C48 will get beyond this using our compiler - consider it a "compiler limit" quads = calloc(10000, sizeof(Quad *)); //CODE FROM THC's ast.c if (argc != 2) { fprintf(stderr, "Usage: %s input_file\n", argv[0]); return -1; } ast_node root; printf("Building AST\n"); root = build_ast(argv[1]); /* build an abstract syntax tree */ printf("Printing AST\n"); print_ast(root, 0); /* and print it out */ printf("Creating Symbol Table\n"); //OUR CODE AGAIN //create symbol table symtab = CreateSymbolTable(); //now we call CG of the root node InsertIntoSymbolTable(symtab, "dog"); printf("Calling CG on root node\n"); CG(root); //print all of our quads for debug purposes int i = 0; //char a1[5]; //char a2[5]; //char a3[5]; printf("Entering Debug Printing While Loop - we have %d quads and they are:\n", currentQuad); FILE *qfile; qfile = fopen("quadsout.txt","w"); while(quads[i] != NULL) { char* a1 = malloc(sizeof(char) * 15); char* a2 = malloc(sizeof(char) * 15); char* a3 = malloc(sizeof(char) * 15); printf("Printing quad %d", i); //printf("entered while\n"); switch (quads[i]->addr1.kind) { case Empty: a1 = " - "; break; case IntConst: sprintf(a1,"%d",quads[i]->addr1.contents.val); break; case DouConst: sprintf(a1,"%f",quads[i]->addr1.contents.dval); break; case String: //printf("%s", quads[i]->addr1.contents.name); a1 = quads[i]->addr1.contents.name; //printf("%s", a1); break; default: break; } switch (quads[i]->addr2.kind) { case Empty: a2 = " - "; break; case IntConst: sprintf(a2,"%d",quads[i]->addr2.contents.val); break; case DouConst: sprintf(a2,"%f",quads[i]->addr2.contents.dval); break; case String: //printf("%s", quads[i]->addr2.contents.name); a2 = quads[i]->addr2.contents.name; break; default: break; } switch (quads[i]->addr3.kind) { case Empty: a3 = " - "; break; case IntConst: sprintf(a3,"%d",quads[i]->addr3.contents.val); break; case DouConst: sprintf(a3,"%f",quads[i]->addr3.contents.dval); break; case String: //printf("%s", quads[i]->addr3.contents.name); a3 = quads[i]->addr3.contents.name; break; default: break; } //printf("Finished switches, printing quad details\n"); //printf("%s",a1); //printf("%s",a2); //printf("%s",a3); printf("(%s,%s,%s,%s)\n",namesOfOps[quads[i]->op],a1,a2,a3); fprintf(qfile, "(%s,%s,%s,%s)\n",namesOfOps[quads[i]->op],a1,a2,a3); i++; } fclose(qfile); /* EnterScope(symtab); EnterScope(symtab); char *c = malloc(sizeof(char) *5); c = "a"; printf("before segfault?\n"); SymNode *sn = LookupInSymbolTable(symtab, c); printf("%d the offset of a is\n", GetOffsetAttr(sn)); */ if(DOASSEMBLY) { //File for final assembly output FILE *file; file = fopen("tm48code.txt","w"); //Send over to the assembly generator, the quads array and symbol table AssemblyGen(quads, file, symtab); fclose(file); } return 0; }
ICCItem *CCodeChain::Link (const CString &sString, int iOffset, int *retiLinked, int *ioiCurLine) // Link // // Parses the given string and converts it into a linked // chain of items { char *pStart; char *pPos; ICCItem *pResult = NULL; int iCurLine = (ioiCurLine ? *ioiCurLine : 1); pStart = sString.GetPointer() + iOffset; pPos = pStart; // Skip any whitespace pPos = SkipWhiteSpace(pPos, &iCurLine); // If we've reached the end, then we have // nothing if (*pPos == '\0') pResult = CreateNil(); // If we've got a literal quote, then remember it else if (*pPos == SYMBOL_QUOTE) { int iLinked; pPos++; pResult = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pResult->IsError()) return pResult; pPos += iLinked; // Make it a literal pResult->SetQuoted(); } // If we've got an open paren then we start a list else if (*pPos == SYMBOL_OPENPAREN) { ICCItem *pNew = CreateLinkedList(); if (pNew->IsError()) return pNew; CCLinkedList *pList = dynamic_cast<CCLinkedList *>(pNew); // Keep reading until we find the end pPos++; // If the list is empty, then there's nothing to do pPos = SkipWhiteSpace(pPos, &iCurLine); if (*pPos == SYMBOL_CLOSEPAREN) { pList->Discard(this); pResult = CreateNil(); pPos++; } // Get all the items in the list else { while (*pPos != SYMBOL_CLOSEPAREN && *pPos != '\0') { ICCItem *pItem; int iLinked; pItem = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pItem->IsError()) return pItem; // Add the item to the list pList->Append(this, pItem, NULL); pItem->Discard(this); // Move the position pPos += iLinked; // Skip whitespace pPos = SkipWhiteSpace(pPos, &iCurLine); } // If we have a close paren then we're done; Otherwise we've // got an error of some kind if (*pPos == SYMBOL_CLOSEPAREN) { pPos++; pResult = pList; } else { pList->Discard(this); pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched open parenthesis")); } } } // If this is an open brace then we've got a literal structure else if (*pPos == SYMBOL_OPENBRACE) { ICCItem *pNew = CreateSymbolTable(); if (pNew->IsError()) return pNew; CCSymbolTable *pTable = dynamic_cast<CCSymbolTable *>(pNew); // Always literal pTable->SetQuoted(); // Keep reading until we find the end pPos++; // If the list is empty, then there's nothing to do pPos = SkipWhiteSpace(pPos, &iCurLine); if (*pPos == SYMBOL_CLOSEBRACE) { pResult = pTable; pPos++; } // Get all the items in the list else { while (*pPos != SYMBOL_CLOSEBRACE && *pPos != '\0') { // Get the key ICCItem *pKey; int iLinked; pKey = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pKey->IsError()) { pTable->Discard(this); return pKey; } // Move the position and read a colon pPos += iLinked; pPos = SkipWhiteSpace(pPos, &iCurLine); if (*pPos != SYMBOL_COLON) { pKey->Discard(this); pTable->Discard(this); return CreateParseError(iCurLine, CONSTLIT("Struct value not found.")); } pPos++; // Get the value ICCItem *pValue; pValue = Link(sString, iOffset + (pPos - pStart), &iLinked, &iCurLine); if (pValue->IsError()) { pKey->Discard(this); pTable->Discard(this); return pValue; } // Move the position pPos += iLinked; // Add the item to the table pResult = pTable->AddEntry(this, pKey, pValue); pKey->Discard(this); pValue->Discard(this); if (pResult->IsError()) { pTable->Discard(this); return pResult; } // Skip whitespace because otherwise we won't know whether we // hit the end brace. pPos = SkipWhiteSpace(pPos, &iCurLine); } // If we have a close paren then we're done; Otherwise we've // got an error of some kind if (*pPos == SYMBOL_CLOSEBRACE) { pPos++; pResult = pTable; } else { pTable->Discard(this); pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched open brace")); } } } // If this is an open quote, then read everything until // the close quote else if (*pPos == SYMBOL_OPENQUOTE) { // Parse the string, until the end quote, parsing escape codes char *pStartFragment = NULL; CString sResultString; bool bDone = false; while (!bDone) { pPos++; switch (*pPos) { case SYMBOL_CLOSEQUOTE: case '\0': { if (pStartFragment) { sResultString.Append(CString(pStartFragment, pPos - pStartFragment)); pStartFragment = NULL; } bDone = true; break; } case SYMBOL_BACKSLASH: { if (pStartFragment) { sResultString.Append(CString(pStartFragment, pPos - pStartFragment)); pStartFragment = NULL; } pPos++; if (*pPos == '\0') bDone = true; else if (*pPos == 'n') sResultString.Append(CString("\n", 1)); else if (*pPos == 'r') sResultString.Append(CString("\r", 1)); else if (*pPos == 't') sResultString.Append(CString("\t", 1)); else if (*pPos == '0') sResultString.Append(CString("\0", 1)); else if (*pPos == 'x' || *pPos == 'X') { pPos++; int iFirstDigit = strGetHexDigit(pPos); pPos++; int iSecondDigit = 0; if (*pPos == '\0') bDone = true; else iSecondDigit = strGetHexDigit(pPos); char chChar = (char)(16 * iFirstDigit + iSecondDigit); sResultString.Append(CString(&chChar, 1)); } else sResultString.Append(CString(pPos, 1)); break; } default: { if (pStartFragment == NULL) pStartFragment = pPos; break; } } } // If we found the close, then create a string; otherwise, // it is an error if (*pPos == SYMBOL_CLOSEQUOTE) { pResult = CreateString(sResultString); // Always a literal pResult->SetQuoted(); // Skip past quote pPos++; } else pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched quote")); } // If this is a close paren, then it is an error else if (*pPos == SYMBOL_CLOSEPAREN) pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched close parenthesis")); // If this is a close brace, then it is an error else if (*pPos == SYMBOL_CLOSEBRACE) pResult = CreateParseError(iCurLine, CONSTLIT("Mismatched close brace")); // Colons cannot appear alone else if (*pPos == SYMBOL_COLON) pResult = CreateParseError(iCurLine, CONSTLIT("':' character must appear inside quotes or in a struct definition.")); // Otherwise this is an string of some sort else { char *pStartString; CString sIdentifier; int iInt; bool bNotInteger; pStartString = pPos; // Look for whitespace while (*pPos != '\0' && *pPos != ' ' && *pPos != '\n' && *pPos != '\r' && *pPos != '\t' && *pPos != SYMBOL_OPENPAREN && *pPos != SYMBOL_CLOSEPAREN && *pPos != SYMBOL_OPENQUOTE && *pPos != SYMBOL_CLOSEQUOTE && *pPos != SYMBOL_OPENBRACE && *pPos != SYMBOL_CLOSEBRACE && *pPos != SYMBOL_COLON && *pPos != SYMBOL_QUOTE && *pPos != ';') pPos++; // If we did not advance, then we clearly hit an error if (pStartString == pPos) pResult = CreateParseError(iCurLine, strPatternSubst(CONSTLIT("Unexpected character: %s"), CString(pPos, 1))); // If we ended in a quote then that's a bug else if (*pPos == SYMBOL_QUOTE) pResult = CreateParseError(iCurLine, strPatternSubst(CONSTLIT("Identifiers must not use single quote characters: %s"), strSubString(sString, iOffset + (pStartString - pStart), (pPos + 1 - pStartString)))); // Otherwise, get the identifier else { // Create a string from the portion sIdentifier = strSubString(sString, iOffset + (pStartString - pStart), (pPos - pStartString)); // Check to see if this is a reserved identifier if (strCompareAbsolute(sIdentifier, CONSTLIT("Nil")) == 0) pResult = CreateNil(); else if (strCompareAbsolute(sIdentifier, CONSTLIT("True")) == 0) pResult = CreateTrue(); else { // If this is an integer, create an integer; otherwise // create a string iInt = strToInt(sIdentifier, 0, &bNotInteger); if (bNotInteger) pResult = CreateString(sIdentifier); else pResult = CreateInteger(iInt); } } } // Return the result and the number of characters // that we read if (retiLinked) *retiLinked = (pPos - pStart); if (ioiCurLine) *ioiCurLine = iCurLine; return pResult; }
EXP_CREATE_ARCHIVE () { const char **CurFile; #else /* !TARGET_EMBEDDED */ int main (int ArgCount, const char **Args) { int CurArg; const char *DestFile = NULL; BOOLEAN NoNames = FALSE; #endif /* !TARGET_EMBEDDED */ int Result = RESULT_GENERAL_ERROR; #ifdef ENABLE_DUMP BOOLEAN Dump = FALSE; #endif /* ENABLE_DUMP */ ARCHIVE Archive; // Check the sizes of basic integer types. if (sizeof (I1) != 1 || sizeof (I2) != 2 || sizeof (I4) != 4 || sizeof (SI1) != 1 || sizeof (SI2) != 2 || sizeof (SI4) != 4 || sizeof (OFFSET) < sizeof (SI4)) { Error (NULL, "Generic type size error!"); return RESULT_STRANGE_ERROR; } // Initialize. memset (&Archive, 0, sizeof (Archive)); #ifdef TARGET_EMBEDDED ErrorFunction = ErrorMessage; #endif /* TARGET_EMBEDDED */ #ifdef TARGET_EMBEDDED for (CurFile = ObjectFiles; *CurFile; CurFile++) { FILE *File = fopen (*CurFile, "rb"); if (File) { SIZE Size; fseek (File, 0, SEEK_END); Size = ftell (File); rewind (File); { I1 *Data = malloc (Size); if (Data) { if (fread (Data, Size, 1, File) == 1) { // Create a new object file inside the current archive. OBJECT_FILE *ObjectFile = calloc (1, sizeof (OBJECT_FILE)); if (!ObjectFile) { Error (*CurFile, "Out of memory."); break; } ObjectFile->Parent = &Archive; ObjectFile->Data = Data; ObjectFile->Size = Size; ObjectFile->FileName = *CurFile; GetFileStats (*CurFile, ObjectFile->FileStats); Append (Archive.ObjectFiles, ObjectFile); // Update the statistics of the archive accordingly. if (StatFileIsNewer (ObjectFile->FileStats, Archive.FileStats)) StatCopyAttributes (Archive.FileStats, ObjectFile->FileStats); // Try to import the object file's contents. ArImportObjectFile (ObjectFile); } else Error (*CurFile, "Unable to read file."); } else Error (*CurFile, "Not enough memory to load file."); } fclose (File); } else Error (*CurFile, "Unable to open file."); } #else /* !TARGET_EMBEDDED */ #include "main_opt.inc" #endif /* !TARGET_EMBEDDED */ { OBJECT_FILE *FirstFile = GetFirst (Archive.ObjectFiles); if (FirstFile) { // Set the destination file, in case it has not been set yet. if (!DestFile) { // alloca should not fail in any case, so we don't generate an error message. DestFile = alloca (strlen (FirstFile->FileName) + 2 + 1); if (DestFile) { strcpy ((char *) DestFile, FirstFile->FileName); strcat ((char *) DestFile, ".a"); } } #ifdef ENABLE_DUMP if (Dump) DumpArchive (stdout, NULL, &Archive); #endif /* ENABLE_DUMP */ // Create the symbol table information. CreateSymbolTable (&Archive); // Create other necessary information. FillExportHelpFields (&Archive); if (DestFile && (GetArchiveFileSize (&Archive) > 0)) { // Write the archive. FILE *File = fopen (DestFile, "wb"); if (File) { BOOLEAN ThisResult; if ((ThisResult = ExportArchiveFile (&Archive, File, NoNames))) { if (Result == RESULT_GENERAL_ERROR) Result = RESULT_OK; } else Result = RESULT_EXPORT_ERROR; fclose (File); if (!ThisResult) remove (DestFile); } else Error (DestFile, "Unable to create file."); } else Result = RESULT_EXPORT_ERROR; } else Error (DestFile, "Cannot create empty archive."); } Cleanup: ATTRIBUTE_UNUSED // Final Cleanup. FreeArchive (&Archive); return Result; }
int main(int argc, char *argv[]) { int ch; char *ep; if (argc == 1) usage(); while ((ch = getopt(argc, argv, "l:m:n:o:p:s:t")) != -1) { switch (ch) { case 'l': lib_Readfile(optarg); break; case 'm': SetMapfileName(optarg); break; case 'n': SetSymfileName(optarg); break; case 'o': out_Setname(optarg); break; case 'p': fillchar = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { fprintf(stderr, "Invalid argument for option 'p'\n"); exit(1); } if (fillchar < 0 || fillchar > 0xFF) { fprintf(stderr, "Argument for option 'p' must be between 0 and 0xFF"); exit(1); } break; case 's': options |= OPT_SMART_C_LINK; strcpy(smartlinkstartsymbol, optarg); break; case 't': options |= OPT_SMALL; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc == 0) usage(); for (int i = 0; i < argc; ++i) obj_Readfile(argv[i]); AddNeededModules(); AssignSections(); CreateSymbolTable(); Patch(); Output(); CloseMapfile(); return (0); }