Add tcc -ar x and t options

On macos we cannot use the ar because is does not support elf files
and then does not generate a symbol table.
The solution is to use 'tcc -ar'. The problem now is that some
pacages first built an archive with 'tcc -ar c' and later extracts
the archive with 'tcc -ar x' and built with this a dylib file.
The 'tcc -ar x' failed. So I implemented it. I also added the t
option because it was simple to do,
This commit is contained in:
herman ten brugge 2022-12-20 07:34:41 +01:00
parent d5f25d19b3
commit 909d58dd5e

View file

@ -61,8 +61,8 @@ static int contains_any(const char *s, const char *list) {
} }
static int ar_usage(int ret) { static int ar_usage(int ret) {
fprintf(stderr, "usage: tcc -ar [rcsv] lib [file...]\n"); fprintf(stderr, "usage: tcc -ar [rcstxv] lib [file...]\n");
fprintf(stderr, "create library ([abdioptxN] not supported).\n"); fprintf(stderr, "create library ([abdiopN] not supported).\n");
return ret; return ret;
} }
@ -94,7 +94,9 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
char tfile[260], stmp[20]; char tfile[260], stmp[20];
char *file, *name; char *file, *name;
int ret = 2; int ret = 2;
const char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored. const char *ops_conflict = "habdiopN"; // unsupported but destructive if ignored.
int extract = 0;
int table = 0;
int verbose = 0; int verbose = 0;
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
@ -105,6 +107,10 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
if (contains_any(a, ops_conflict)) if (contains_any(a, ops_conflict))
ret = 1; ret = 1;
if (strstr(a, "x"))
extract = 1;
if (strstr(a, "t"))
table = 1;
if (strstr(a, "v")) if (strstr(a, "v"))
verbose = 1; verbose = 1;
} else { // lib or obj files: don't abort - keep validating all args. } else { // lib or obj files: don't abort - keep validating all args.
@ -122,9 +128,63 @@ ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
if (ret == 1) if (ret == 1)
return ar_usage(ret); return ar_usage(ret);
if (extract || table) {
if ((fh = fopen(argv[i_lib], "rb")) == NULL)
{
fprintf(stderr, "tcc: ar: can't open file %s\n", argv[i_lib]);
goto finish;
}
fread(stmp, 1, 8, fh);
if (memcmp(stmp,ARMAG,8))
{
no_ar:
fprintf(stderr, "tcc: ar: not an ar archive %s\n", argv[i_lib]);
goto finish;
}
while (fread(&arhdr, 1, sizeof(arhdr), fh) == sizeof(arhdr)) {
char *p, *e;
if (memcmp(arhdr.ar_fmag, ARFMAG, 2))
goto no_ar;
p = arhdr.ar_name;
for (e = p + sizeof arhdr.ar_name; e > p && e[-1] == ' ';)
e--;
*e = '\0';
arhdr.ar_size[sizeof arhdr.ar_size-1] = 0;
fsize = atoi(arhdr.ar_size);
buf = tcc_malloc(fsize + 1);
fread(buf, fsize, 1, fh);
if (strcmp(arhdr.ar_name,"/") && strcmp(arhdr.ar_name,"/SYM64/")) {
if (e > p && e[-1] == '/')
e[-1] = '\0';
/* tv not implemented */
if (table || verbose)
printf("%s%s\n", extract ? "x - " : "", arhdr.ar_name);
if (extract) {
if ((fo = fopen(arhdr.ar_name, "wb")) == NULL)
{
fprintf(stderr, "tcc: ar: can't create file %s\n",
arhdr.ar_name);
tcc_free(buf);
goto finish;
}
fwrite(buf, fsize, 1, fo);
fclose(fo);
/* ignore date/uid/gid/mode */
}
}
tcc_free(buf);
}
ret = 0;
finish:
if (fh)
fclose(fh);
return ret;
}
if ((fh = fopen(argv[i_lib], "wb")) == NULL) if ((fh = fopen(argv[i_lib], "wb")) == NULL)
{ {
fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_lib]); fprintf(stderr, "tcc: ar: can't create file %s\n", argv[i_lib]);
goto the_end; goto the_end;
} }