1 /* main.c: Main entry point for ar-tigcc, handling the command line input
2
3 Copyright (C) 2003 Sebastian Reichelt
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 #include "../generic.h"
20 #include "../intrface.h"
21 #include "data.h"
22 #include "manip.h"
23 #include "import/import.h"
24 #include "export/exp_ar.h"
25
26 #ifdef ENABLE_DUMP
27 #include "dump.h"
28 #endif /* ENABLE_DUMP */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #ifdef __WIN32__
35 // This definition seems to be missing in MinGW.
36 extern void *alloca (size_t);
37 #endif /* __WIN32__ */
38
39 #define RESULT_OK 0
40 #define RESULT_GENERAL_ERROR 1
41 #define RESULT_EXPORT_ERROR 2
42 #define RESULT_STRANGE_ERROR 3
43
44 #ifdef TARGET_EMBEDDED
45 extern ERROR_FUNCTION ErrorFunction;
EXP_CREATE_ARCHIVE()46 EXP_CREATE_ARCHIVE ()
47 {
48 const char **CurFile;
49 #else /* !TARGET_EMBEDDED */
50 int main (int ArgCount, const char **Args)
51 {
52 int CurArg;
53 const char *DestFile = NULL;
54 BOOLEAN NoNames = FALSE;
55 #endif /* !TARGET_EMBEDDED */
56
57 int Result = RESULT_GENERAL_ERROR;
58 #ifdef ENABLE_DUMP
59 BOOLEAN Dump = FALSE;
60 #endif /* ENABLE_DUMP */
61
62 ARCHIVE Archive;
63
64 // Check the sizes of basic integer types.
65 if (sizeof (I1) != 1 || sizeof (I2) != 2 || sizeof (I4) != 4 || sizeof (SI1) != 1 || sizeof (SI2) != 2 || sizeof (SI4) != 4 || sizeof (OFFSET) < sizeof (SI4))
66 {
67 Error (NULL, "Generic type size error!");
68 return RESULT_STRANGE_ERROR;
69 }
70
71 // Initialize.
72 memset (&Archive, 0, sizeof (Archive));
73 #ifdef TARGET_EMBEDDED
74 ErrorFunction = ErrorMessage;
75 #endif /* TARGET_EMBEDDED */
76
77 #ifdef TARGET_EMBEDDED
78 for (CurFile = ObjectFiles; *CurFile; CurFile++)
79 {
80 FILE *File = fopen (*CurFile, "rb");
81 if (File)
82 {
83 SIZE Size;
84 fseek (File, 0, SEEK_END);
85 Size = ftell (File);
86 rewind (File);
87 {
88 I1 *Data = malloc (Size);
89 if (Data)
90 {
91 if (fread (Data, Size, 1, File) == 1)
92 {
93 // Create a new object file inside the current archive.
94 OBJECT_FILE *ObjectFile = calloc (1, sizeof (OBJECT_FILE));
95
96 if (!ObjectFile)
97 {
98 Error (*CurFile, "Out of memory.");
99 break;
100 }
101
102 ObjectFile->Parent = &Archive;
103 ObjectFile->Data = Data;
104 ObjectFile->Size = Size;
105 ObjectFile->FileName = *CurFile;
106 GetFileStats (*CurFile, ObjectFile->FileStats);
107 Append (Archive.ObjectFiles, ObjectFile);
108
109 // Update the statistics of the archive accordingly.
110 if (StatFileIsNewer (ObjectFile->FileStats, Archive.FileStats))
111 StatCopyAttributes (Archive.FileStats, ObjectFile->FileStats);
112
113 // Try to import the object file's contents.
114 ArImportObjectFile (ObjectFile);
115 }
116 else
117 Error (*CurFile, "Unable to read file.");
118 }
119 else
120 Error (*CurFile, "Not enough memory to load file.");
121 }
122 fclose (File);
123 }
124 else
125 Error (*CurFile, "Unable to open file.");
126 }
127 #else /* !TARGET_EMBEDDED */
128 #include "main_opt.inc"
129 #endif /* !TARGET_EMBEDDED */
130
131 {
132 OBJECT_FILE *FirstFile = GetFirst (Archive.ObjectFiles);
133
134 if (FirstFile)
135 {
136 // Set the destination file, in case it has not been set yet.
137 if (!DestFile)
138 {
139 // alloca should not fail in any case, so we don't generate an error message.
140 DestFile = alloca (strlen (FirstFile->FileName) + 2 + 1);
141 if (DestFile)
142 {
143 strcpy ((char *) DestFile, FirstFile->FileName);
144 strcat ((char *) DestFile, ".a");
145 }
146 }
147
148 #ifdef ENABLE_DUMP
149 if (Dump)
150 DumpArchive (stdout, NULL, &Archive);
151 #endif /* ENABLE_DUMP */
152
153 // Create the symbol table information.
154 CreateSymbolTable (&Archive);
155
156 // Create other necessary information.
157 FillExportHelpFields (&Archive);
158
159 if (DestFile && (GetArchiveFileSize (&Archive) > 0))
160 {
161 // Write the archive.
162 FILE *File = fopen (DestFile, "wb");
163 if (File)
164 {
165 BOOLEAN ThisResult;
166 if ((ThisResult = ExportArchiveFile (&Archive, File, NoNames)))
167 {
168 if (Result == RESULT_GENERAL_ERROR)
169 Result = RESULT_OK;
170 }
171 else
172 Result = RESULT_EXPORT_ERROR;
173 fclose (File);
174 if (!ThisResult)
175 remove (DestFile);
176 }
177 else
178 Error (DestFile, "Unable to create file.");
179 }
180 else
181 Result = RESULT_EXPORT_ERROR;
182 }
183 else
184 Error (DestFile, "Cannot create empty archive.");
185 }
186
187 Cleanup: ATTRIBUTE_UNUSED
188 // Final Cleanup.
189 FreeArchive (&Archive);
190
191 return Result;
192 }
193