123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- /* export.c: Routines for file exports
- Copyright (C) 2002-2004 Sebastian Reichelt
- Copyright (C) 2003-2005 Kevin Kofler
- Copyright (C) 2004 Billy Charvet
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
- #include "export.h"
- #ifdef TIOS_SUPPORT
- #include "exp_tios.h"
- #endif /* TIOS_SUPPORT */
- #ifdef FLASH_OS_SUPPORT
- #include "exp_os.h"
- #endif /* FLASH_OS_SUPPORT */
- #ifdef NOSTUB_DLL_SUPPORT
- #include "exp_ndll.h"
- #endif /* NOSTUB_DLL_SUPPORT */
- #ifdef FARGO_SUPPORT
- #include "exp_farg.h"
- #endif /* FARGO_SUPPORT */
- #ifdef DATA_VAR_SUPPORT
- #include "exp_data.h"
- #endif /* DATA_VAR_SUPPORT */
- #ifdef DEBUGGING_INFO_SUPPORT
- #include "exp_dbg.h"
- #endif /* DEBUGGING_INFO_SUPPORT */
- #include "../formats/tios.h"
- #include "../formats/tiosupgd.h"
- #include "../special.h"
- #include <string.h>
- typedef struct {
- OUTPUT_FILE_FUNCTION GetOutputFile;
- OUTPUT_FILE_FINALIZE_FUNCTION FinalizeOutputFile;
- GET_FILE_SIZE_FUNCTION GetFileSize;
- EXPORT_FILE_FUNCTION ExportFile, ExportDataFile;
- FileFormats FileFormat, DataFileFormat;
- unsigned int FileType, DataFileType;
- const char *Extension;
- } EXPORT_STRUCT;
- // Return the maximum file size allowed for a given format
- // (without header and footer).
- static SIZE GetMaxFileSize (FileFormats FileFormat, ProgramCalcs Calc)
- {
- switch (FileFormat)
- {
- case FF_TIOS:
- return MAX_TIOS_FILE_SIZE;
- case FF_TIOS_UPGRADE:
- if (Calc == CALC_V200 || (Calc == (CALC_TI89 | CALC_FLAG_TITANIUM)))
- return MAX_TIOS_UPGRADE_FILE_SIZE_NEW;
- else
- return MAX_TIOS_UPGRADE_FILE_SIZE_OLD;
- default:
- return 0;
- }
- }
- // Export the internal data structures to an external file for the given
- // calculator.
- static BOOLEAN ExportProgramToFormat (const PROGRAM *Program, const EXPORT_STRUCT *ExportStruct, ProgramCalcs Calc)
- {
- BOOLEAN Success;
- EXP_FILE File;
- SIZE Size, MaxSize;
- I4 EffectiveSize = 0;
-
- // Fill the output file struct with zeroes.
- memset (&File, 0, sizeof (File));
-
- // Get the file size needed to export the file.
- Size = ExportStruct->GetFileSize (Program);
-
- // A size of 0 indicates an error.
- if (Size <= 0)
- return FALSE;
-
- // Check for maximum file size.
- MaxSize = GetMaxFileSize (ExportStruct->FileFormat, Calc);
-
- if (Size > MaxSize)
- {
- Error (NULL, "Program size of %ld bytes exceeds maximum by %ld.", (long) Size, (long) (Size - MaxSize));
- return FALSE;
- }
-
- // Create an output file with the specified format.
- if (!(ExportStruct->GetOutputFile (&(File.File), Size, Calc, FR_MAIN, ExportStruct->FileFormat, ExportStruct->FileType, ExportStruct->Extension, !(Program->Library), &EffectiveSize)))
- return FALSE;
-
- // Export the program into the output file.
- Success = ExportStruct->ExportFile (Program, &File, Size, Calc);
-
- // Finalize and close the output file.
- if (ExportStruct->FinalizeOutputFile)
- ExportStruct->FinalizeOutputFile (&(File.File));
-
- if (Success)
- {
- if (Program->OptimizeInfo->ProgramSize < (SI4) EffectiveSize)
- Program->OptimizeInfo->ProgramSize = (SI4) EffectiveSize;
- }
- else
- return FALSE;
-
- #ifdef DATA_VAR_SUPPORT
- // Write the data file, if any.
- if (Program->DataVarInfo->Name && Program->DataSection)
- {
- if (ExportStruct->DataFileFormat == FF_NONE)
- {
- Error (NULL, "Data variable is not supported in this file format.");
- return FALSE;
- }
-
- // Fill the output file struct with zeroes.
- memset (&File, 0, sizeof (File));
-
- // Get the file size needed to export the file.
- Size = GetDataFileSize (Program);
-
- // A size of 0 indicates an error.
- if (Size <= 0)
- return FALSE;
-
- MaxSize = GetMaxFileSize (ExportStruct->DataFileFormat, Calc);
-
- // Check for maximum file size.
- if (Size > MaxSize)
- {
- Error (NULL, "Data variable size of %ld bytes exceeds maximum by %ld.", (long) Size, (long) (MaxSize - Size));
- return FALSE;
- }
- // Create an output file with the specified format.
- if (!(ExportStruct->GetOutputFile (&(File.File), Size, Calc, FR_DATA, ExportStruct->DataFileFormat, ExportStruct->DataFileType, "DAT", FALSE, &EffectiveSize)))
- return FALSE;
-
- // Export the program into the output file.
- Success = ExportStruct->ExportDataFile (Program, &File, Size, Calc);
-
- // Finalize and close the output file.
- if (ExportStruct->FinalizeOutputFile)
- ExportStruct->FinalizeOutputFile (&(File.File));
-
- if (Success)
- {
- if (Program->OptimizeInfo->DataSize < (SI4) EffectiveSize)
- Program->OptimizeInfo->DataSize = (SI4) EffectiveSize;
- }
- else
- return FALSE;
- }
- #endif /* DATA_VAR_SUPPORT */
-
- return TRUE;
- }
- // Export the internal data structures to external files, creating as many
- // files as needed.
- BOOLEAN ExportProgram (const PROGRAM *Program, OUTPUT_FILE_FUNCTION GetOutputFile, OUTPUT_FILE_FINALIZE_FUNCTION FinalizeOutputFile)
- {
- EXPORT_STRUCT ExportStruct = {GetOutputFile, FinalizeOutputFile, NULL, NULL, NULL, FF_TIOS, FF_TIOS, TIOS_TAG_ASM, TIOS_TAG_OTH, NULL};
-
- if (!GetOutputFile)
- return FALSE;
-
- #ifdef DEBUGGING_INFO_SUPPORT
- // If we have debugging information to export, do it.
- if (Program->HaveDebuggingInfo)
- {
- if (!ExportDebuggingInfo (Program, GetOutputFile, FinalizeOutputFile))
- return FALSE;
- }
- #endif
- switch (Program->Type)
- {
- #ifdef FLASH_OS_SUPPORT
- case PT_FLASH_OS:
- ExportStruct.GetFileSize = GetFlashOSFileSize;
- ExportStruct.ExportFile = ExportFlashOSFile;
- ExportStruct.FileFormat = FF_TIOS_UPGRADE;
- ExportStruct.FileType = 0; // Different types for Flash OSs do not exist.
- ExportStruct.DataFileFormat = FF_NONE;
- ExportStruct.DataFileType = 0;
- break;
- #endif /* FLASH_OS_SUPPORT */
-
- #ifdef NOSTUB_DLL_SUPPORT
- case PT_NOSTUB_DLL:
- ExportStruct.GetFileSize = GetNostubDLLFileSize;
- ExportStruct.ExportFile = ExportNostubDLLFile;
- ExportStruct.FileType = TIOS_TAG_OTH;
- ExportStruct.Extension = "DLL";
- break;
- #endif /* NOSTUB_DLL_SUPPORT */
-
- #ifdef FARGO_SUPPORT
- case PT_FARGO:
- ExportStruct.GetFileSize = GetFargoFileSize;
- ExportStruct.ExportFile = ExportFargoFile;
- ExportStruct.FileType = TIOS_TAG_PRGM;
- break;
- #endif /* FARGO_SUPPORT */
-
- default:
- #ifdef TIOS_SUPPORT
- ExportStruct.GetFileSize = GetTIOSFileSize;
- ExportStruct.ExportFile = ExportTIOSFile;
- #else /* !TIOS_SUPPORT */
- Error (NULL, "No default export target for this program type.");
- return FALSE;
- #endif /* !TIOS_SUPPORT */
- }
-
- #ifdef DATA_VAR_SUPPORT
- ExportStruct.ExportDataFile = ExportDataFile;
- #endif /* DATA_VAR_SUPPORT */
-
- {
- ProgramCalcs CurCalc;
-
- // For all calculators...
- for (CurCalc = 1; CurCalc <= HIGHEST_CALC; CurCalc <<= 1)
- {
- if (Program->Calcs & CurCalc)
- {
- if (!(ExportProgramToFormat (Program, &ExportStruct, CurCalc)))
- return FALSE;
-
- if (Program->Type == PT_FLASH_OS && CurCalc == CALC_TI89 && (Program->Calcs & CALC_FLAG_TITANIUM))
- {
- if (!(ExportProgramToFormat (Program, &ExportStruct, CurCalc | CALC_FLAG_TITANIUM)))
- return FALSE;
- }
- }
- }
- }
-
- Program->OptimizeInfo->RelocCount += Program->OptimizeInfo->NativeRelocCount;
-
- return TRUE;
- }
- // Non-embedded file output functions as defined in intrface.h.
- #ifndef TARGET_EMBEDDED
- #include <stdio.h>
- // Destination file name without extension.
- const char *DestFile = NULL;
- SIZE DestFileSize = 0;
- // Folder and variable name for main file.
- char ProgramFolder[MAX_NAME_LEN+1] = "main", ProgramName[MAX_NAME_LEN+1] = "program";
- #ifdef DATA_VAR_SUPPORT
- // Folder and variable name for data file.
- char DataFolder[MAX_NAME_LEN+1] = "", DataName[MAX_NAME_LEN+1] = "data";
- #endif /* DATA_VAR_SUPPORT */
- #ifdef PUCRUNCH_SUPPORT
- // Specifies whether to pack the main file with pucrunch.
- BOOLEAN Pack = FALSE;
- #endif /* PUCRUNCH_SUPPORT */
- // Specifies whether to output only the binary image of the program.
- BOOLEAN OutputBin = FALSE;
- // Specifies whether to output only the binary image of the main file.
- BOOLEAN OutputBinMainOnly = FALSE;
- // Maximum length of a file extension.
- #define MAX_FILE_EXT_LEN 3
- BOOLEAN GetOutputFile (INT_EXP_FILE *File, SIZE FileSize, unsigned int DestCalc, unsigned int FileRole, unsigned int FileFormat, unsigned int FileType, const char *Extension, BOOLEAN Executable ATTRIBUTE_UNUSED, I4 *EffectiveSize)
- {
- // Keep some of the parameters for finalization.
- File->OutputBin = OutputBin || (OutputBinMainOnly && FileRole == FR_MAIN);
- File->FileFormat = FileFormat;
- File->FileType = FileType;
- File->Extension = Extension;
-
- // Determine the destination file format and act accordingly.
- switch (FileFormat)
- {
- #ifdef TIOS_FILE_SUPPORT
- case FF_TIOS:
- {
- const char *FolderName, *VarName;
- const char *FileExtCalc, *FileExtType;
- unsigned int LinkType;
-
- // Calculate the size needed for the two size bytes and the
- // tag.
- SIZE VarFileSize = 2 + FileSize + 1;
-
- // If the file has an extension, add the size needed for it.
- if (Extension)
- VarFileSize += 1 + strlen (Extension) + 1;
-
- // The variable size is what the user will see.
- *EffectiveSize = VarFileSize;
-
- // Determine the role of the file and set the folder and
- // variable names according to the user settings.
- switch (FileRole)
- {
- case FR_MAIN:
- FolderName = ProgramFolder;
- VarName = ProgramName;
- break;
- #ifdef DATA_VAR_SUPPORT
- case FR_DATA:
- if (*DataFolder)
- FolderName = DataFolder;
- else
- FolderName = ProgramFolder;
- VarName = DataName;
- break;
- #endif /* DATA_VAR_SUPPORT */
- default:
- Error (NULL, "Unknown file role.");
- return FALSE;
- }
-
- // Determine the destination calculator and set part of the
- // file extension.
- switch (DestCalc)
- {
- case CALC_TI92:
- FileExtCalc = "92";
- break;
- case CALC_TI89:
- FileExtCalc = "89";
- break;
- case CALC_TI92PLUS:
- FileExtCalc = "9x";
- break;
- case CALC_V200:
- FileExtCalc = "v2";
- break;
- default:
- Error (NULL, "Unknown calculator.");
- return FALSE;
- }
-
- // Determine the file type and set the other part of the file
- // extension.
- switch (FileType)
- {
- case TIOS_TAG_STR:
- FileExtType = "s";
- LinkType = TIOS_LINK_TYPE_STR;
- break;
- case TIOS_TAG_PRGM:
- FileExtType = "p";
- LinkType = TIOS_LINK_TYPE_PRGM;
- break;
- case TIOS_TAG_ASM:
- FileExtType = "z";
- LinkType = TIOS_LINK_TYPE_ASM;
- break;
- case TIOS_TAG_OTH:
- FileExtType = "y";
- LinkType = TIOS_LINK_TYPE_OTH;
- break;
- default:
- Error (NULL, "Unknown file type.");
- return FALSE;
- }
-
- {
- SIZE FileNameSize = DestFileSize;
-
- // Create a temporary file name string.
- char CurOutputFileName[FileNameSize+1+MAX_FILE_EXT_LEN+1];
- strncpy (CurOutputFileName, DestFile, FileNameSize);
-
- // Insert the dot into the file name.
- CurOutputFileName [FileNameSize++] = '.';
-
- // Insert the extension. Reverse in binary mode.
- if (File->OutputBin)
- {
- strcpy (CurOutputFileName + FileNameSize, FileExtType);
- FileNameSize += strlen (FileExtType);
- strcpy (CurOutputFileName + FileNameSize, FileExtCalc);
- FileNameSize += strlen (FileExtCalc);
- }
- else
- {
- strcpy (CurOutputFileName + FileNameSize, FileExtCalc);
- FileNameSize += strlen (FileExtCalc);
- strcpy (CurOutputFileName + FileNameSize, FileExtType);
- FileNameSize += strlen (FileExtType);
- }
-
- // Zero-terminate the string.
- CurOutputFileName [FileNameSize] = 0;
-
- // Open a file with the specified name.
- if (!(File->File = fopen (CurOutputFileName, "wb")))
- {
- Error (CurOutputFileName, "Could not open file for writing.");
- return FALSE;
- }
-
- // Write the host file header, if desired.
- if (!File->OutputBin)
- {
- TIOS_HOST_FILE_HEADER Header;
-
- memset (&Header, 0, sizeof (Header));
-
- // Write the signature.
- switch (DestCalc)
- {
- case CALC_TI92:
- strncpy (Header.Signature, "**TI92**", 8);
- break;
- case CALC_TI89:
- strncpy (Header.Signature, "**TI89**", 8);
- break;
- case CALC_TI92PLUS:
- case CALC_V200:
- strncpy (Header.Signature, "**TI92P*", 8);
- break;
- default:
- Error (NULL, "Unknown calculator.");
- return FALSE;
- }
-
- // Write folder name.
- strncpy (Header.FolderName, FolderName, sizeof (Header.FolderName));
-
- // Write variable name.
- strncpy (Header.VarName, VarName, sizeof (Header.VarName));
-
- // Write link type.
- WriteHI1 (Header.LinkType, LinkType);
-
- // Write file size.
- WriteHI4 (Header.FileSize, VarFileSize + sizeof (TIOS_HOST_FILE_HEADER) + sizeof (TIOS_HOST_FILE_FOOTER));
-
- // Write reserved bytes.
- Header.Reserved1 [0] = 0x01;
- Header.Reserved2 [0] = 0x01;
- Header.Reserved2 [2] = 0x52;
- Header.Reserved4 [0] = 0xA5;
- Header.Reserved4 [1] = 0x5A;
-
- // Export the header.
- fwrite (&Header, sizeof (Header), 1, File->File);
- }
-
- // Write the on-calc file header.
- {
- TI2 EncVarFileSize;
-
- // Encode the embedded size into the target
- // endianness.
- WriteTI2 (EncVarFileSize, VarFileSize - 2);
-
- // Export the file size.
- fwrite (&EncVarFileSize, 2, 1, File->File);
-
- // Update the checksum, since this is still included
- // in the on-calc file image.
- File->CheckSum += ReadTI1 (EncVarFileSize.Hi) + ReadTI1 (EncVarFileSize.Lo);
- }
-
- return TRUE;
- }
- }
- break;
- #endif /* TIOS_FILE_SUPPORT */
-
- #ifdef TIOS_UPGRADE_FILE_SUPPORT
- case FF_TIOS_UPGRADE:
- *EffectiveSize = FileSize + sizeof (TIOS_UPGRADE_CALC_FOOTER);
- if (File->OutputBin)
- {
- const char *FileExtCalc;
-
- // Determine the destination calculator and set part of the
- // file extension.
- switch (DestCalc)
- {
- case CALC_TI92:
- FileExtCalc = "92";
- break;
- case CALC_TI89:
- FileExtCalc = "89";
- break;
- case CALC_TI89 | CALC_FLAG_TITANIUM:
- FileExtCalc = "89ti";
- break;
- case CALC_TI92PLUS:
- FileExtCalc = "9x";
- break;
- case CALC_V200:
- FileExtCalc = "v2";
- break;
- default:
- Error (NULL, "Unknown calculator.");
- return FALSE;
- }
-
- {
- SIZE FileNameSize = DestFileSize;
-
- // Create a temporary file name string.
- char CurOutputFileName[FileNameSize+1+4+1+sizeof("tib")];
- strncpy (CurOutputFileName, DestFile, FileNameSize);
-
- // Insert a dash into the file name.
- CurOutputFileName [FileNameSize++] = '-';
-
- // Insert the calculator model into the file name.
- strcpy (CurOutputFileName + FileNameSize, FileExtCalc);
- FileNameSize += strlen (FileExtCalc);
-
- // Insert the dot into the file name.
- CurOutputFileName [FileNameSize++] = '.';
-
- // Insert the .tib extension.
- strcpy (CurOutputFileName + FileNameSize, "tib");
- FileNameSize += sizeof ("tib") - 1;
-
- // Zero-terminate the string.
- CurOutputFileName [FileNameSize] = 0;
-
- // Open a file with the specified name.
- if (!(File->File = fopen (CurOutputFileName, "wb")))
- {
- Error (CurOutputFileName, "Could not open file for writing.");
- return FALSE;
- }
- return TRUE;
- }
- }
- else
- Error (NULL, "Support for `.??u' files is not implemented yet. Use `--outputbin'.");
-
- break;
- #endif /* TIOS_UPGRADE_FILE_SUPPORT */
-
- #ifdef DEBUGGING_INFO_SUPPORT
- case FF_GDB_COFF:
- *EffectiveSize = FileSize;
- {
- SIZE FileNameSize = DestFileSize+4;
-
- // Create a temporary file name string.
- char CurOutputFileName[FileNameSize+1];
- strncpy (CurOutputFileName, DestFile, DestFileSize);
-
- // Append ".dbg" to the file name.
- strcpy (CurOutputFileName + DestFileSize, ".dbg");
-
- // Zero-terminate the string.
- CurOutputFileName [FileNameSize] = 0;
-
- // Open a file with the specified name.
- if (!(File->File = fopen (CurOutputFileName, "wb")))
- {
- Error (CurOutputFileName, "Could not open file for writing.");
- return FALSE;
- }
-
- return TRUE;
- }
- break;
- #endif /* DEBUGGING_INFO_SUPPORT */
- default:
- Error (NULL, "Unrecognized output file format.");
- }
-
- return FALSE;
- }
- void FinalizeOutputFile (INT_EXP_FILE *File)
- {
- // Determine the destination file format and finish it.
- switch (File->FileFormat)
- {
- #ifdef TIOS_FILE_SUPPORT
- case FF_TIOS:
- {
- // Write the on-calc file footer.
- {
- TI1 EncFileTag;
-
- // Export the possible file extension.
- if (File->Extension)
- {
- // Export the leading 0 byte.
- WriteTI1 (EncFileTag, 0);
- fwrite (&EncFileTag, 1, 1, File->File);
-
- // Export the extension string and terminating 0
- // byte.
- fwrite (File->Extension, 1, strlen (File->Extension) + 1, File->File);
-
- // Update the checksum.
- while (*(File->Extension))
- File->CheckSum += (*(File->Extension++));
- }
-
- // Encode the file tag.
- WriteTI1 (EncFileTag, File->FileType);
-
- // Export the file tag.
- fwrite (&EncFileTag, 1, 1, File->File);
-
- File->CheckSum += (I1) (File->FileType);
- }
-
- // Write the host file footer, if desired.
- if (!File->OutputBin)
- {
- TIOS_HOST_FILE_FOOTER Footer;
-
- memset (&Footer, 0, sizeof (Footer));
-
- // Write the checksum.
- WriteHI2 (Footer.CheckSum, File->CheckSum);
-
- // Export the footer.
- fwrite (&Footer, sizeof (Footer), 1, File->File);
- }
- }
- break;
- #endif /* TIOS_FILE_SUPPORT */
-
- #ifdef TIOS_UPGRADE_FILE_SUPPORT
- case FF_TIOS_UPGRADE:
- {
- // Write the on-calc upgrade file footer.
- {
- TIOS_UPGRADE_CALC_FOOTER Footer;
-
- // Since we do not have TI's private key, we cannot
- // write a real checksum and signature.
- memset (&Footer, 0, sizeof (Footer));
-
- // Encode the fixed data we know.
- WriteTI2 (Footer.SignatureHeader, 0x020D);
- WriteTI1 (Footer.SignatureType, 0x40);
-
- // Export the footer.
- fwrite (&Footer, sizeof (Footer), 1, File->File);
- }
- }
- break;
- #endif /* TIOS_UPGRADE_FILE_SUPPORT */
- #ifdef DEBUGGING_INFO_SUPPORT
- case FF_GDB_COFF:
- // Do nothing.
- break;
- #endif /* DEBUGGING_INFO_SUPPORT */
- }
-
- // Close the file.
- fclose (File->File);
- }
- #endif /* !TARGET_EMBEDDED */
|