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