@@ -13,6 +13,7 @@ Date: June 2006
13
13
14
14
#include " compile.h"
15
15
16
+ #include < cstring>
16
17
#include < fstream>
17
18
#include < sstream>
18
19
#include < iostream>
@@ -135,56 +136,113 @@ bool compilet::doit()
135
136
warnings_before;
136
137
}
137
138
139
+ enum class file_typet
140
+ {
141
+ NO_SUCH_FILE,
142
+ UNKNOWN,
143
+ SOURCE_FILE,
144
+ NORMAL_ARCHIVE,
145
+ THIN_ARCHIVE,
146
+ GOTO_BINARY,
147
+ ELF_OBJECT
148
+ };
149
+
150
+ static file_typet detect_file_type (const std::string &file_name)
151
+ {
152
+ // first of all, try to open the file
153
+ std::ifstream in (file_name);
154
+ if (!in)
155
+ return file_typet::NO_SUCH_FILE;
156
+
157
+ const std::string::size_type r = file_name.rfind (' .' , file_name.length () - 1 );
158
+
159
+ const std::string ext =
160
+ r == std::string::npos ? " " : file_name.substr (r + 1 , file_name.length ());
161
+
162
+ if (
163
+ ext == " c" ||
164
+ ext == " cc" || ext == " cp" || ext == " cpp" || ext == " CPP" ||
165
+ ext == " c++" || ext == " C" ||
166
+ ext == " i" || ext == " ii" ||
167
+ ext == " class" || ext == " jar" ||
168
+ ext == " jsil" )
169
+ return file_typet::SOURCE_FILE;
170
+
171
+ char hdr[8 ];
172
+ in.get (hdr, 8 );
173
+ if ((ext == " a" || ext == " o" ) && strncmp (hdr, " !<thin>" , 8 ) == 0 )
174
+ return file_typet::THIN_ARCHIVE;
175
+
176
+ if (ext == " a" )
177
+ return file_typet::NORMAL_ARCHIVE;
178
+
179
+ if (is_goto_binary (file_name))
180
+ return file_typet::GOTO_BINARY;
181
+
182
+ if (hdr[0 ] == 0x7f && memcmp (hdr + 1 , " ELF" , 3 ) == 0 )
183
+ return file_typet::ELF_OBJECT;
184
+
185
+ return file_typet::UNKNOWN;
186
+ }
187
+
138
188
// / puts input file names into a list and does preprocessing for libraries.
139
189
// / \return false on success, true on error.
140
190
bool compilet::add_input_file (const std::string &file_name)
141
191
{
142
- // first of all, try to open the file
192
+ switch ( detect_file_type (file_name))
143
193
{
144
- std::ifstream in (file_name);
145
- if (!in)
146
- {
147
- warning () << " failed to open file `" << file_name << " '" << eom;
148
- return warning_is_fatal; // generously ignore unless -Werror
149
- }
150
- }
194
+ case file_typet::NO_SUCH_FILE:
195
+ warning () << " failed to open file `" << file_name << " '" << eom;
196
+ return warning_is_fatal; // generously ignore unless -Werror
151
197
152
- size_t r=file_name.rfind (' .' , file_name.length ()-1 );
198
+ case file_typet::UNKNOWN:
199
+ // unknown extension, not a goto binary, will silently ignore
200
+ debug () << " unknown file type in `" << file_name << " '" << eom;
201
+ return false ;
153
202
154
- if (r==std::string::npos)
155
- {
156
- // a file without extension; will ignore
157
- warning () << " input file `" << file_name
158
- << " ' has no extension, not considered" << eom;
159
- return warning_is_fatal;
160
- }
203
+ case file_typet::ELF_OBJECT:
204
+ // ELF file without goto-cc section, silently ignore
205
+ debug () << " ELF object without goto-cc section: `" << file_name << " '"
206
+ << eom;
207
+ return false ;
161
208
162
- std::string ext = file_name.substr (r+1 , file_name.length ());
163
-
164
- if (ext==" c" ||
165
- ext==" cc" ||
166
- ext==" cp" ||
167
- ext==" cpp" ||
168
- ext==" CPP" ||
169
- ext==" c++" ||
170
- ext==" C" ||
171
- ext==" i" ||
172
- ext==" ii" ||
173
- ext==" class" ||
174
- ext==" jar" ||
175
- ext==" jsil" )
176
- {
209
+ case file_typet::SOURCE_FILE:
177
210
source_files.push_back (file_name);
211
+ return false ;
212
+
213
+ case file_typet::NORMAL_ARCHIVE:
214
+ return add_files_from_archive (file_name, false );
215
+
216
+ case file_typet::THIN_ARCHIVE:
217
+ return add_files_from_archive (file_name, true );
218
+
219
+ case file_typet::GOTO_BINARY:
220
+ object_files.push_back (file_name);
221
+ return false ;
178
222
}
179
- else if (ext==" a" )
180
- {
181
- #ifdef _WIN32
182
- char td[MAX_PATH+1 ];
183
- #else
184
- char td[] = " goto-cc.XXXXXX" ;
185
- #endif
186
223
187
- std::string tstr=get_temporary_directory (td);
224
+ UNREACHABLE;
225
+ }
226
+
227
+ // / extracts goto binaries from AR archive and add them as input files.
228
+ // / \return false on success, true on error.
229
+ bool compilet::add_files_from_archive (
230
+ const std::string &file_name, bool thin_archive)
231
+ {
232
+ #ifdef _WIN32
233
+ char td[MAX_PATH+1 ];
234
+ #else
235
+ char td[] = " goto-cc.XXXXXX" ;
236
+ #endif
237
+
238
+ std::stringstream cmd;
239
+ FILE *stream;
240
+
241
+ std::string tstr=working_directory;
242
+
243
+ if (!thin_archive)
244
+ {
245
+ tstr = get_temporary_directory (td);
188
246
189
247
if (tstr==" " )
190
248
{
@@ -193,7 +251,6 @@ bool compilet::add_input_file(const std::string &file_name)
193
251
}
194
252
195
253
tmp_dirs.push_back (tstr);
196
- std::stringstream cmd (" " );
197
254
if (chdir (tmp_dirs.back ().c_str ())!=0 )
198
255
{
199
256
error () << " Cannot switch to temporary directory" << eom;
@@ -203,76 +260,47 @@ bool compilet::add_input_file(const std::string &file_name)
203
260
// unpack now
204
261
cmd << " ar x " << concat_dir_file (working_directory, file_name);
205
262
206
- FILE *stream;
207
-
208
263
stream=popen (cmd.str ().c_str (), " r" );
209
264
pclose (stream);
210
265
211
266
cmd.clear ();
212
267
cmd.str (" " );
268
+ }
213
269
214
- // add the files from "ar t"
215
- #ifdef _WIN32
216
- if (file_name[0 ]!=' /' && file_name[1 ]!=' :' ) // NOLINT(readability/braces)
217
- #else
218
- if (file_name[0 ]!=' /' ) // NOLINT(readability/braces)
219
- #endif
220
- {
221
- cmd << " ar t " <<
222
- #ifdef _WIN32
223
- working_directory << " \\ " << file_name;
224
- #else
225
- working_directory << " /" << file_name;
226
- #endif
227
- }
228
- else
229
- {
230
- cmd << " ar t " << file_name;
231
- }
270
+ // add the files from "ar t"
271
+ cmd << " ar t " << concat_dir_file (working_directory, file_name);
232
272
233
- stream=popen (cmd.str ().c_str (), " r" );
273
+ stream=popen (cmd.str ().c_str (), " r" );
234
274
235
- if (stream!=nullptr )
275
+ if (stream!=nullptr )
276
+ {
277
+ std::string line;
278
+ int ch; // fgetc returns an int, not char
279
+ while ((ch=fgetc (stream))!=EOF)
236
280
{
237
- std::string line;
238
- int ch; // fgetc returns an int, not char
239
- while ((ch=fgetc (stream))!=EOF)
281
+ if (ch!=' \n ' )
240
282
{
241
- if (ch!=' \n ' )
242
- {
243
- line+=static_cast <char >(ch);
244
- }
245
- else
246
- {
247
- std::string t;
248
- #ifdef _WIN32
249
- t = tmp_dirs.back () + ' \\ ' + line;
250
- #else
251
- t = tmp_dirs.back () + ' /' + line;
252
- #endif
253
-
254
- if (is_goto_binary (t))
255
- object_files.push_back (t);
256
-
257
- line = " " ;
258
- }
283
+ line+=static_cast <char >(ch);
259
284
}
285
+ else
286
+ {
287
+ std::string t = concat_dir_file (tstr, line);
260
288
261
- pclose (stream);
262
- }
289
+ if (is_goto_binary (t))
290
+ object_files.push_back (t);
291
+ else
292
+ debug () << " Object file is not a goto binary: " << line << eom;
263
293
264
- cmd.str (" " );
294
+ line = " " ;
295
+ }
296
+ }
265
297
266
- if (chdir (working_directory.c_str ())!=0 )
267
- error () << " Could not change back to working directory" << eom;
268
- }
269
- else if (is_goto_binary (file_name))
270
- object_files.push_back (file_name);
271
- else
272
- {
273
- // unknown extension, not a goto binary, will silently ignore
298
+ pclose (stream);
274
299
}
275
300
301
+ if (!thin_archive && chdir (working_directory.c_str ()) != 0 )
302
+ error () << " Could not change back to working directory" << eom;
303
+
276
304
return false ;
277
305
}
278
306
@@ -302,41 +330,24 @@ bool compilet::find_library(const std::string &name)
302
330
{
303
331
std::string libname=tmp+name+" .so" ;
304
332
305
- if (is_goto_binary (libname))
306
- return !add_input_file (libname);
307
- else if (is_elf_file (libname))
333
+ switch (detect_file_type (libname))
308
334
{
335
+ case file_typet::GOTO_BINARY:
336
+ return !add_input_file (libname);
337
+
338
+ case file_typet::ELF_OBJECT:
309
339
warning () << " Warning: Cannot read ELF library " << libname << eom;
310
340
return warning_is_fatal;
341
+
342
+ default :
343
+ break ;
311
344
}
312
345
}
313
346
}
314
347
315
348
return false ;
316
349
}
317
350
318
- // / checking if we can load an object file
319
- // / \par parameters: file name
320
- // / \return true if the given file name exists and is an ELF file, false
321
- // / otherwise
322
- bool compilet::is_elf_file (const std::string &file_name)
323
- {
324
- std::fstream in;
325
-
326
- in.open (file_name, std::ios::in);
327
- if (in.is_open ())
328
- {
329
- char buf[4 ];
330
- for (std::size_t i=0 ; i<4 ; i++)
331
- buf[i]=static_cast <char >(in.get ());
332
- if (buf[0 ]==0x7f && buf[1 ]==' E' &&
333
- buf[2 ]==' L' && buf[3 ]==' F' )
334
- return true ;
335
- }
336
-
337
- return false ;
338
- }
339
-
340
351
// / parses object files and links them
341
352
// / \return true on error, false otherwise
342
353
bool compilet::link ()
0 commit comments