-
Notifications
You must be signed in to change notification settings - Fork 0
/
emxomfld.c
2497 lines (2107 loc) · 73.3 KB
/
emxomfld.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* emxomfld.c -- Provide an ld-like interface to the IBM and M$ linkers
Copyright (c) 1992-1998 Eberhard Mattes
Copyright (c) 2003 InnoTek Systemberatung GmbH
Copyright (c) 2003-2004 Knut St. Osmundsen
This file is part of emxomld.
emxomfld 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.
emxomfld 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 emxomfld; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <stdlib.h>
//#include <alloca.h>
#include <errno.h>
#include <string.h>
#include <process.h>
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utime.h>
//#include <sys/moddef.h>
#include <getopt.h>
//#include <alloca.h>
#include <time.h>
#include <windows.h>
#define FALSE 0
#define TRUE 1
////////////////////
/* omflib0.h (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
/* Private header file for the emx OMFLIB library. */
#ifndef _BYTE_WORD_DWORD
#define _BYTE_WORD_DWORD
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
#endif /* _BYTE_WORD_DWORD */
struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int gettimeofday(struct timeval *tv, struct timezone *tz);
////////////////////////////////
#include <sys/omflib.h>
#include "defs.h"
#include "weakld.h"
/* A member of a linked list of strings such as file names. */
typedef struct name_list
{
struct name_list *next;
unsigned flags;
char *name;
} name_list;
/* Whether or not linker tracing is enabled. */
static int opt_t;
/* Whether or not to include .dll in the shared library searching. */
static int opt_dll_search;
/* The output file name, specified by the -o option. */
static const char *output_fname = NULL;
/* The map file name (output), set by the -Zmap option. */
static const char *map_fname = NULL;
static int map_flag = FALSE;
/* The sym file output flag, set by the -Zsym option. */
static int sym_flag = FALSE;
/* The module definition file name (input), set if a file matching
*.def is given on the command line. */
static const char *def_fname = NULL;
/* The binary resource file name (input), set if a file matching *.res
is given on the command line. */
static const char *res_fname = NULL;
/* Base address of the excecutable file, specified by the -T
option. */
static const char *base = NULL;
/* List of directories searched for libraries. Each -L option adds a
directory to this list. add_libdirs is used to add another entry
at the end of the list. */
static name_list *libdirs = NULL;
static name_list **add_libdirs = &libdirs;
/* List of object files. Each file given on the command line which
does not match *.def, *.lib and *.res is added to this list.
add_obj_fnames is used to add another entry at the end of the
list. */
static name_list *obj_fnames = NULL;
static name_list **add_obj_fnames = &obj_fnames;
/* List of library files. Each file matching *.lib given on the
command line is added to this list. The -l option also adds an
entry to this list. add_lib_fnames is used to add another entry at
the end of the list.
The flags member indicates library search method. If set search for
static lib, if clear search for shared lib before search for static lib. */
static name_list *lib_fnames = NULL;
static name_list **add_lib_fnames = &lib_fnames;
/* List of linker options. Linker options can be specified with the
-O option. add_options is used to add another entry at the end of
the list. */
static name_list *options = NULL;
static name_list **add_options = &options;
/* The command line passed to the linker. */
static char command_line[260];
/* The current length of the command line. */
static int line_len;
/* Non-zero if arguments go into the response file instead of
command_line. */
static int response_flag;
/* The name of the response file. */
static char response_fname[L_tmpnam] = "";
/* The response file. */
static FILE *response_file = NULL;
/* Force the use of a response file from the next put_arg(). */
static int force_response_file = FALSE;
/* Weak alias object file. */
static char weakobj_fname[_MAX_PATH + 1];
/* Weak definition file (modified def_fname). */
static char weakdef_fname[_MAX_PATH + 1];
/* list of converted libraries and objects which must be removed upon exit. */
static name_list *conv_list = NULL;
/* Non-zero if debugging information is to be omitted. Set by the -s
and -S options. */
static int strip_symbols = FALSE;
/* Non-zero if emxomfld should create an .exe file and touch the
output file. Set by the -Zexe option. */
static int exe_flag = FALSE;
/* Non-zero when creating a dynamic link library. Set by the -Zdll
option. */
static int dll_flag = FALSE;
/* The stack size, specified by the -Zstack option, in Kbyte. If the
-Zstack option is not used, this variable defaults to 1024 to match
the defaults of emxbind. */
static long stack_size = 1024;
/* Indicates that we've seen -Zstack. */
static int stack_size_flag = 0;
/* The name of the linker to use. By default, ilink is used. This
can be overridden with the EMXOMFLD_LINKER environment variable. */
static const char *linker_name = "ilink.exe";
/* The type of linker to use. By default we assume it's VAC365 or later
version of ilink. This can be overridden with the EMXOMFLD_TYPE env.
var. using any of the values WLINK, VAC365, VAC308 and LINK386. */
static const char *linker_type = "VAC365";
/* The name of the resource compiler to use. By default, rc is used.
This can be overridden with the EMXOMFLD_RC environment variable. */
static const char *rc_name = "rc.exe";
/* The type of resource compiler to use. By default we assume it's
IBM resource compiler. This can be overridden with the EMXOMFLD_RC_TYPE
env. var. using any of the values RC, WRC. */
static const char *rc_type = "RC";
/* Non-zero if emxomfld should automatically convert a.out objects and
archives to the OMF equivalents during linking. */
static int autoconvert_flag = 1;
/* Prototypes. */
static void usage (void) NORETURN2;
extern void *xmalloc (size_t n);
extern void *xrealloc (void *ptr, size_t n);
extern char *xstrdup (const char *s);
static void add_name_list (name_list ***add, const char *src, unsigned flags);
static void conv_path (char *name);
static void put_arg (const char *src, int path, int quotable);
static void put_args (const name_list *list, int paths);
static void make_env (void);
static void cleanup (void);
static void arg_init (int rsp);
static void arg_end (void);
int main (int argc, char *argv[]);
/* To avoid including os2.h... */
#ifndef _System
#define _System
#endif
extern int _System DosCopy (char *, char *, int);
/* Allocate N bytes of memory. Quit on failure. This function is
used like malloc(), but we don't have to check the return value. */
void *xmalloc (size_t n)
{
void *p;
p = malloc (n);
if (p == NULL && n)
{
fprintf (stderr, "emxomfld: out of memory\n");
exit (2);
}
return p;
}
/* Change the allocation of PTR to N bytes. Quit on failure. This
function is used like realloc(), but we don't have to check the
return value. */
void *xrealloc (void *ptr, size_t n)
{
void *p;
p = realloc (ptr, n);
if (p == NULL && n)
{
fprintf (stderr, "emxomfld: out of memory\n");
exit (2);
}
return p;
}
/* Create a duplicate of the string S on the heap. Quit on failure.
This function is used like strdup(), but we don't have to check the
return value. */
char *xstrdup (const char *s)
{
char *p;
int cch = strlen (s) + 1;
p = xmalloc (cch);
memcpy (p, s, cch);
return p;
}
/* Add the name SRC to a list. ADD is a pointer to the pointer of the
end of the list. We duplicate the string before adding it to the
list. */
static void add_name_list (name_list ***add, const char *src, unsigned flags)
{
name_list *node;
node = xmalloc (sizeof (name_list));
node->next = NULL;
node->name = xstrdup (src);
node->flags = flags;
*(*add) = node;
(*add) = &node->next;
}
/* Opens a response file. */
static void open_response_file(void)
{
int fd;
if (response_file)
return;
/* Complain if we are not allowed to use a response
file. */
if (!response_flag)
{
fprintf (stderr, "emxomfld: command line too long\n");
exit (2);
}
/* Choose a unique file name and create the response
file. */
strcpy (response_fname, "ldXXXXXX");
fd = mkstemp (response_fname);
if (fd < 0)
{
perror ("emxomfld");
exit (2);
}
close(fd);
response_file = fopen (response_fname, "wt");
if (response_file == NULL)
{
perror ("emxomfld");
exit (2);
}
/* Add the name of the response file to the command
line. */
command_line[line_len++] = ' ';
command_line[line_len++] = '@';
strcpy (command_line+line_len, response_fname);
if (!stricmp (linker_type, "WLINK"))
strcat (command_line, ".");
if (force_response_file)
force_response_file = FALSE;
}
/* Replace forward slashes `/' in NAME with backslashes `\'. The linkers
requires backslashes in path names. */
static void conv_path (char *name)
{
char *p;
for (p = name; *p != 0; ++p)
if (*p == '/')
*p = '\\';
}
/* Add the argument SRC to the command line or to the response file.
If PATH is non-zero, SRC is a path name and slashes are to be
replaced by backslashes. If the command line gets too long, a
response file is created.
If quotable is non-zero SRC will be quoted. This is required for
supporting files names which includes '+' and spaces. */
static void put_arg (const char *src, int path, int quotable)
{
int len, max_len;
char *tmp;
if (src != NULL)
{
/* Instead of a comma, we write a newline to the response
file. */
if (response_file != NULL && strcmp (src, ",") == 0)
{
fputc ('\n', response_file);
line_len = 0;
return;
}
/* Make a local copy of SRC to be able to modify it. Then,
translate forward slashes to backslashes if PATH is
non-zero. */
len = strlen (src);
tmp = alloca (len + (quotable ? 3 : 1));
if (path)
{
/* needs quoting? */
if (quotable)
{
*tmp = '"';
strcpy (tmp+1, src);
tmp[++len] = '"';
tmp[++len] = '\0';
}
else
strcpy (tmp, src);
conv_path (tmp);
}
else
strcpy (tmp, src);
/* Check if we've reached the maximum line length. If the
maximum command line length is exceeded, create a response
file and write the remaining arguments to that file instead
of putting them on the command line. */
max_len = (response_file == NULL ? 110 : 52);
if ( line_len + len + 1 > max_len
|| (force_response_file && !response_file))
{
/* If SRC is a single comma or a single semicolon, copy it
to the output, ignoring the maximum line length. This is
to meet the IBM/M$ linker command syntax. The maximum line
length allows for enough commas and semicolons added this
way. */
if ((*tmp == ',' || *tmp == ';') && tmp[1] == 0)
{
if (response_file == NULL)
{
command_line[line_len+0] = *tmp;
command_line[line_len+1] = 0;
}
else
fputc (*tmp, response_file);
++line_len;
return;
}
/* If a response file has not yet been opened, open it. */
if (response_file == NULL)
open_response_file();
else if (line_len != 0)
{
/* Start a new line in the response file. */
fputs (" +\n", response_file);
}
line_len = 0;
}
/* Separate command line arguments by spaces (unless the
argument to be added starts with a delimiter. */
if (line_len != 0 && *src != ',' && *src != ';')
{
if (response_file == NULL)
command_line[line_len++] = ' ';
else
fputc (' ', response_file);
}
/* Finally write the argument to the command line or to the
response file and adjust the current line length. */
if (response_file == NULL)
strcpy (command_line + line_len, tmp);
else
fputs (tmp, response_file);
line_len += len;
}
}
/* Put a list of arguments onto the command line or into the response
file. If PATHS is non-zero, the arguments are path names and
slashes are to be replaced by backslashes. */
static void put_args (const name_list *list, int paths)
{
while (list != NULL)
{
put_arg (list->name, paths, paths);
list = list->next;
}
}
/* Build the environment for the IBM/M$ Linkers: define the LIB
environment variable. */
static void make_env (void)
{
static char tmp[4096];
char *p;
int len;
const name_list *list;
/* Create a string for putenv(). */
strcpy (tmp, "LIB=");
len = strlen (tmp);
/* Add the library directories to LIB, using `;' as separator. */
for (list = libdirs; list != NULL; list = list->next)
{
if (list != libdirs && tmp[len-1] != ';')
tmp[len++] = ';';
strcpy (tmp+len, list->name);
conv_path (tmp+len);
len += strlen (list->name);
}
/* Append to the end the previous definition of LIB. */
p = getenv ("LIB");
if (p != NULL)
{
if (tmp[len-1] != ';')
tmp[len++] = ';';
strcpy (tmp+len, p);
}
/* Put the new value of LIB into the environment. */
putenv (tmp);
if (opt_t)
fprintf(stderr, "*** %s\n", tmp);
}
/**
* Checks if the stream phFile is an OMF library.
*
* @returns 1 if OMF library.
* @returns 0 if not OMF library.
* @param phFile Filestream to check.
*/
static int check_omf_library(FILE *phFile)
{
#pragma pack(1)
struct
{
byte rec_type;
word rec_len;
dword dict_offset;
word dict_blocks;
byte flags;
} libhdr;
#pragma pack()
if ( fread(&libhdr, 1, sizeof(libhdr), phFile) == sizeof (libhdr)
&& !fseek(phFile, 0, SEEK_SET)
&& libhdr.rec_type == LIBHDR
&& libhdr.flags <= 1 /* ASSUME only first bit is used... */
)
{
int page_size = libhdr.rec_len + 3;
if (page_size >= 16
&& page_size <= 32768
&& !(page_size & (page_size - 1)) != 0)
return 1;
}
return 0;
}
/**
* Checks if the stream phFile is an OMF object or library.
*
* @returns 1 if OMF.
* @returns 0 if not OMF.
* @param phFile Filestream to check.
*/
static int check_omf(FILE *phFile)
{
#pragma pack(1)
struct
{
byte rec_type;
word rec_len;
} omfhdr;
#pragma pack()
if ( fread(&omfhdr, 1, sizeof(omfhdr), phFile) == sizeof (omfhdr)
&& omfhdr.rec_type == THEADR
&& omfhdr.rec_len >= sizeof(omfhdr)
&& !fseek(phFile, 0, SEEK_SET)
)
return 1;
return !fseek(phFile, 0, SEEK_SET)
&& check_omf_library(phFile);
}
/**
* Checks if the stream phFile is an LX DLL.
*
* @returns 1 if LX DLL.
* @returns 0 if not LX DLL.
* @param phFile File stream to check.
*/
static int check_lx_dll(FILE *phFile)
{
unsigned long ul;
char achMagic[2];
if ( fseek(phFile, 0, SEEK_SET)
|| fread(&achMagic, 1, 2, phFile) != 2)
goto thats_not_it;
if (!memcmp(achMagic, "MZ", 2))
{
if ( fseek(phFile, 0x3c, SEEK_SET)
|| fread(&ul, 1, 4, phFile) != 4 /* offset of the 'new' header */
|| ul < 0x40
|| ul >= 0x10000000 /* 512MB stubs sure */
|| fseek(phFile, ul, SEEK_SET)
|| fread(&achMagic, 1, 2, phFile) != 2)
goto thats_not_it;
}
if ( memcmp(achMagic, "LX", 2)
|| fseek(phFile, 14, SEEK_CUR)
|| fread(&ul, 1, 4, phFile) != 4) /*e32_mflags*/
goto thats_not_it;
#define E32MODDLL 0x08000L
#define E32MODPROTDLL 0x18000L
#define E32MODMASK 0x38000L
if ( (ul & E32MODMASK) != E32MODDLL
&& (ul & E32MODMASK) != E32MODPROTDLL)
goto thats_not_it;
/* it's a LX DLL! */
fseek(phFile, 0, SEEK_SET);
return 1;
thats_not_it:
fseek(phFile, 0, SEEK_SET);
return 0;
}
/**
* Generates an unique temporary file.
*
* @returns 0 on success.
* @returns -1 on failure.
* @param pszFile Where to put the filename.
* @param pszPrefix Prefix.
* @param pszSuffix Suffix.
* @param pszLooklike Filename which name is to be incorporated into the temp filename.
* @remark The code is nicked from the weak linker.
*/
static int make_tempfile(char *pszFile, const char *pszPrefix, const char *pszSuffix, const char *pszLooklike)
{
struct stat s;
unsigned c = 0;
char szLooklike[32];
pid_t pid = getpid();
static char s_szTmp[_MAX_PATH + 1];
/* We need to apply _realrealpath to the tmpdir, so resolve that once and for all. */
if (!s_szTmp[0])
{
const char * pszTmp = getenv("TMP");
if (!pszTmp) pszTmp = getenv("TMPDIR");
if (!pszTmp) pszTmp = getenv("TEMP");
if (!pszTmp) pszTmp = ".";
if (!_realrealpath(pszTmp, s_szTmp, sizeof(s_szTmp)))
{
printf("emxomfld: _realrealpath failed on '%s'!!!\n", pszTmp);
exit(1);
}
}
if (pszLooklike)
{
int cch;
char *psz = (char*)pszLooklike; /* we're nice fellows. */
while ((psz = strpbrk(psz, ":/\\")) != NULL)
pszLooklike = ++psz;
cch = strlen(pszLooklike);
if (cch + 3 > sizeof(szLooklike))
cch = sizeof(szLooklike) - 3;
szLooklike[0] = '_';
memcpy(&szLooklike[1], pszLooklike, cch);
szLooklike[cch + 1] = '_';
szLooklike[cch + 2] = '\0';
pszLooklike = psz = &szLooklike[0];
while ((psz = strpbrk(psz, ".@%^&#()")) != NULL)
*psz++ = '_';
}
else
pszLooklike = "";
do
{
struct timeval tv = {0,0};
if (c++ >= 200)
return -1;
gettimeofday(&tv, NULL);
sprintf(pszFile, "%s\\%s%s%x%lx%d%lx%s", s_szTmp, pszPrefix, pszLooklike, pid, tv.tv_sec, c, tv.tv_usec, pszSuffix);
} while (!stat(pszFile, &s));
return 0;
}
/**
* Converts the file indicated by phFile & pszFilename to omf closing
* phFile and updating pszFilename with the new (temporary filename).
*
* @returns Pointer to an filestream for the converted file and pszFilename
* containing the name of the converted file.
* @returns exit the program
* @param phFile Filestream of the file to convert. (close this)
* @param pszFilename Name of the file to convert on entry.
* Name of the converted file on return.
*/
static FILE *aout_to_omf(FILE *pf, char *pszFilename, int fLibrary)
{
int rc;
char * pszNewFile;
name_list *pName;
fclose(pf); /* don't need this! */
if (opt_t)
fprintf(stderr, "emxomfld: info: converting %s %s to OMF.\n",
fLibrary ? "lib" : "obj", pszFilename);
/*
* Make temporary file.
*/
pName = xmalloc(sizeof(name_list));
pName->name = pszNewFile = xmalloc(_MAX_PATH);
if (make_tempfile(pszNewFile, "ldconv", fLibrary ? ".lib" : ".obj", pszFilename))
{
free(pszNewFile);
return NULL;
}
/*
* Do the conversion.
*/
rc = spawnlp(P_WAIT, "emxomf.exe", "emxomf.exe", "-o", pszNewFile, pszFilename, NULL);
if (!rc)
{
/* open the file */
pf = fopen(pszNewFile, "rb");
if (pf)
{
/* add to auto delete list for removal on exit(). */
pName->next = conv_list;
conv_list = pName;
strcpy(pszFilename, pszNewFile);
if (opt_t)
fprintf(stderr, "emxomfld: info: convert result '%s'.\n",
pszFilename);
return pf;
}
remove(pszNewFile);
}
free(pszNewFile);
free(pName);
fprintf(stderr, "emxomfld: a.out to omf conversion failed for '%s'.\n",
pszFilename);
exit(1);
return NULL;
}
/**
* Converts the file indicated by phFile & pszFilename to omf closing
* phFile and updating pszFilename with the new (temporary filename).
*
* @returns Pointer to an filestream for the converted file and pszFilename
* containing the name of the converted file.
* @returns exit the program
* @param phFile Filestream of the file to convert. (close this)
* @param pszFilename Name of the file to convert on entry.
* Name of the converted file on return.
*/
static FILE *lx_to_omf(FILE *pf, char *pszFilename)
{
int rc;
char * pszNewFile;
name_list *pName;
fclose(pf); /* don't need this! */
if (opt_t)
fprintf(stderr, "emxomfld: info: converting %s %s to an OMF import lib.\n",
"lib", pszFilename);
/*
* Make temporary file.
*/
pName = xmalloc(sizeof(name_list));
pName->name = pszNewFile = xmalloc(_MAX_PATH);
if (make_tempfile(pszNewFile, "ldconv", ".lib", pszFilename))
{
free(pszNewFile);
return NULL;
}
/*
* Do the conversion.
*/
rc = spawnlp(P_WAIT, "emximp.exe", "emximp.exe", "-o", pszNewFile, pszFilename, NULL);
if (!rc)
{
/* open the file */
pf = fopen(pszNewFile, "rb");
if (pf)
{
/* add to auto delete list for removal on exit(). */
pName->next = conv_list;
conv_list = pName;
strcpy(pszFilename, pszNewFile);
if (opt_t)
fprintf(stderr, "emxomfld: info: convert result '%s'.\n",
pszFilename);
return pf;
}
remove(pszNewFile);
}
free(pszNewFile);
free(pName);
fprintf(stderr, "emxomfld: lx dll to omf conversion failed for '%s'.\n",
pszFilename);
exit(2);
return NULL;
}
/**
* Finds the full path of a OMF object file and opens the file.
*
* This function may perform conversion from a.out to omf if that feature
* is enabled.
*
* We choose to be UNIX compatible her, and not search the LIB env.var.
* for unqualified objects. Nor will we add any suffixes to the name
* if it's witout any extension.
*
* @returns Pointer to a file stream for the object file to use in the link.
* @returns NULL on failure with pszFullname containing a copy of
* pszName (or something like that).
* @param pszFullname Where to store the name of the file to be used
* in the linking (and which stream is returned).
* @param pszName Object name given to on the linker commandline.
*/
static FILE *find_obj(char *pszFullname, const char *pszName)
{
FILE *phFile;
char *psz;
/*
* Make abspath with slashes the desired way and such.
*/
if (!_realrealpath(pszName, pszFullname, _MAX_PATH + 1))
{
printf("emxomfld: _abspath failed on '%s'!!!\n", pszName);
exit(1);
}
psz = pszFullname;
while ((psz = strchr(psz, '/')) != NULL)
*psz++ = '\\';
/*
* Try open the file.
*/
phFile = fopen(pszFullname, "rb");
if (!phFile)
return NULL;
/*
* If autoconversion check if such is needed.
*/
if ( autoconvert_flag
&& !check_omf(phFile))
phFile = aout_to_omf(phFile, pszFullname, FALSE);
return phFile;
}
/* Finds the full path of a library file and opens the file.
*
* This function may perform conversion from a.out to omf if that feature
* is enabled.
*
* The function assumes that LIB has been updated with all the search paths
* specified on the commandline.
*
* Library names with no extension are given extensions after the rules
* indicated by the IS_SHARED parameter. If IS_SHARED is set then libraries
* with suffixes indicating shared libraries will be looked for before
* libraries with suffixes indicated static libraries. The list is as
* follows for set IS_SHARED:
* 1. _dll.lib
* 2. .lib
* 3. .dll (optional)
* 4. _s.lib
*
* If IS_SHARED is clear:
* 1. _s.lib
* 2. .lib
*
* Library names with no path is searched for in the semicolon separated list
* of paths the env.var. LIB contains. For each directory in LIB we'll start
* by see if it contains a 'lib' prefixed file, if not found we'll check for
* the unprefixed filename. If we're appending suffixes too, we'll loop thru
* all the possible suffixes for each directory before advancing to the next,
* having the prefixing as the inner most loop.
*
* @returns Pointer to a file stream for the library file to use in the link.
* @returns NULL on failure with pszFullname containing a copy of
* pszName (or something like that).
* @param pszFullname Where to store the name of the file to be used
* in the linking (and which stream is returned).
* @param pszName Library name given to on the linker commandline.
*/
static FILE *find_lib(char *pszFullname, const char *pszName, int fShared)
{
/* Suffix list for shared linking. */
static const char *apszSharedSuff[] = { "_dll.lib", "_dll.a", ".lib", ".a", "_s.lib", "_s.a", NULL };
/* Suffix list for shared linking with .dll. */
static const char *apszSharedDllSuff[] = { "_dll.lib", "_dll.a", ".lib", ".a", ".dll", "_s.lib", "_s.a", NULL };
/* Suffix list for static linking. */
static const char *apszStaticSuff[] = { "_s.lib", "_s.a", ".lib", ".a", NULL };
/* Suffix list for names with extension. */
static const char *apszExtensionSuff[] = { "", NULL };
/* Prefix list for names with path. */
static const char *apszWithPathPref[] = { "", NULL };
/* Prefix list for names with no path. */
static const char *apszWithoutPathPref[]= { "lib", "", NULL };
int fPath; /* set if the library name have a path. */
int fExt; /* set if the library name have an extension. */
const char **papszSuffs; /* Pointer to the suffix list. */
const char **papszPrefs; /* Pointer to the prefix list. */
const char *pszLibPath; /* The path we're searching. */
size_t cchCurPath; /* Size of the current path. */
size_t cchName = strlen(pszName);
const char *psz;
/*
* Check if the file name has a path.
* (If it has, we won't check the LIB directories.)
* Choose the prefix list accordingly.
*/
fPath = (strpbrk(pszName, ":/\\") != NULL);
papszPrefs = fPath ? apszWithPathPref : apszWithoutPathPref;
/*
* Check if the file has a real extension.
* Real extension means, .lib, .dll or .a. It also implies something
* before the dot.
* Choose the suffix list accordingly.
*/
fExt = ( (cchName > 4 && !stricmp(pszName + cchName - 4, ".lib"))
|| (cchName > 4 && !stricmp(pszName + cchName - 4, ".dll"))
|| (cchName > 2 && !stricmp(pszName + cchName - 2, ".a")) );
if (!fExt)
{
if (fShared)
papszSuffs = opt_dll_search ? &apszSharedDllSuff[0] : &apszSharedSuff[0];
else
papszSuffs = &apszStaticSuff[0];
}
else
papszSuffs = apszExtensionSuff;
/*
* Loop 1: LIB (with a fake .\ as the first iteration)
* (Looping on pszLibPath, with preinitiated cchCurPath & pszFullname.)
*/
cchCurPath = 0;
if (!fPath)
{
cchCurPath = 2;
memcpy(pszFullname, ".\\", 2);
}
pszLibPath = getenv("LIB");
do