Move arguments parsing to option.c
This commit is contained in:
parent
6318a909ff
commit
db4e043cd9
11 changed files with 747 additions and 813 deletions
|
@ -1,6 +1,6 @@
|
||||||
noinst_LIBRARIES = libtcc.a
|
noinst_LIBRARIES = libtcc.a
|
||||||
libtcc_a_SOURCES = libtcc.c tccpp.c tccgen.c \
|
libtcc_a_SOURCES = libtcc.c option.c tccpp.c tccgen.c \
|
||||||
tccasm.c tccelf.c \
|
tccasm.c tccelf.c \
|
||||||
i386/gen.c i386/link.c \
|
i386/gen.c i386/link.c \
|
||||||
i386/asm.c tcccoff.c
|
i386/asm.c tcccoff.c
|
||||||
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
|
@ -25,9 +25,8 @@
|
||||||
#define _DARWIN_C_SOURCE
|
#define _DARWIN_C_SOURCE
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
/* gnu headers use to #define __attribute__ to empty for non-gcc compilers */
|
/* gnu headers use to #define __attribute__ to empty for non-gcc compilers */
|
||||||
#ifdef __TINYC__
|
#ifdef __TINYC__
|
||||||
# undef __attribute__
|
# undef __attribute__
|
||||||
|
@ -853,21 +852,13 @@ int tcc_add_support(TCCState *s1, const char *filename);
|
||||||
void tcc_add_pragma_libs(TCCState *s1);
|
void tcc_add_pragma_libs(TCCState *s1);
|
||||||
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
|
||||||
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
|
||||||
PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
|
char *tcc_load_text(int fd);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *normalize_slashes(char *path);
|
char *normalize_slashes(char *path);
|
||||||
#endif
|
#endif
|
||||||
/* for #pragma once */
|
/* for #pragma once */
|
||||||
int normalized_PATHCMP(const char *f1, const char *f2);
|
int normalized_PATHCMP(const char *f1, const char *f2);
|
||||||
|
|
||||||
/* tcc_parse_args return codes: */
|
|
||||||
#define OPT_HELP 1
|
|
||||||
#define OPT_HELP2 2
|
|
||||||
#define OPT_V 3
|
|
||||||
#define OPT_PRINT_DIRS 4
|
|
||||||
#define OPT_AR 5
|
|
||||||
#define OPT_IMPDEF 6
|
|
||||||
|
|
||||||
/* ------------ tccpp.c ------------ */
|
/* ------------ tccpp.c ------------ */
|
||||||
|
|
||||||
extern struct BufferedFile *file;
|
extern struct BufferedFile *file;
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
# define TCC_OPTION_HAS_ARG 0x0001
|
# define TCC_OPTION_HAS_ARG 0x0001
|
||||||
# define TCC_OPTION_NOSEP 0x0002 /** cannot have space before option and arg */
|
# define TCC_OPTION_NOSEP 0x0002 /** cannot have space before option and arg */
|
||||||
|
|
||||||
# define TCC_OPT_HELP 'h'
|
# define TCC_OPT_HELP 'h'
|
||||||
# define TCC_OPT_HELP_MORE 'm'
|
# define TCC_OPT_HELP_MORE 'm'
|
||||||
# define TCC_OPT_ARCHIVE 'a'
|
# define TCC_OPT_ARCHIVE 'a'
|
||||||
# define TCC_OPT_VERSION 'V'
|
# define TCC_OPT_VERSION 'V'
|
||||||
|
# define TCC_OPT_PRINT_DIRS 'P'
|
||||||
|
|
||||||
typedef struct TCCOption {
|
typedef struct TCCOption {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
713
libtcc/libtcc.c
713
libtcc/libtcc.c
|
@ -18,7 +18,7 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tcc.h"
|
#include <tcc.h>
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
|
@ -989,717 +989,6 @@ void tcc_set_lib_path(TCCState *s, const char *path)
|
||||||
/********************************************************/
|
/********************************************************/
|
||||||
/* options parser */
|
/* options parser */
|
||||||
|
|
||||||
static int strstart(const char *val, const char **str)
|
|
||||||
{
|
|
||||||
const char *p, *q;
|
|
||||||
p = *str;
|
|
||||||
q = val;
|
|
||||||
while (*q) {
|
|
||||||
if (*p != *q)
|
|
||||||
return 0;
|
|
||||||
p++;
|
|
||||||
q++;
|
|
||||||
}
|
|
||||||
*str = p;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Like strstart, but automatically takes into account that ld options can
|
|
||||||
*
|
|
||||||
* - start with double or single dash (e.g. '--soname' or '-soname')
|
|
||||||
* - arguments can be given as separate or after '=' (e.g. '-Wl,-soname,x.so'
|
|
||||||
* or '-Wl,-soname=x.so')
|
|
||||||
*
|
|
||||||
* you provide `val` always in 'option[=]' form (no leading -)
|
|
||||||
*/
|
|
||||||
static int link_option(const char *str, const char *val, const char **ptr)
|
|
||||||
{
|
|
||||||
const char *p, *q;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* there should be 1 or 2 dashes */
|
|
||||||
if (*str++ != '-')
|
|
||||||
return 0;
|
|
||||||
if (*str == '-')
|
|
||||||
str++;
|
|
||||||
|
|
||||||
/* then str & val should match (potentially up to '=') */
|
|
||||||
p = str;
|
|
||||||
q = val;
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
if (q[0] == '?') {
|
|
||||||
++q;
|
|
||||||
if (strstart("no-", &p))
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*q != '\0' && *q != '=') {
|
|
||||||
if (*p != *q)
|
|
||||||
return 0;
|
|
||||||
p++;
|
|
||||||
q++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* '=' near eos means ',' or '=' is ok */
|
|
||||||
if (*q == '=') {
|
|
||||||
if (*p == 0)
|
|
||||||
*ptr = p;
|
|
||||||
if (*p != ',' && *p != '=')
|
|
||||||
return 0;
|
|
||||||
p++;
|
|
||||||
} else if (*p) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*ptr = p;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int link_arg(const char *opt, const char *str)
|
|
||||||
{
|
|
||||||
int l = strlen(opt);
|
|
||||||
return 0 == strncmp(opt, str, l) && (str[l] == '\0' || str[l] == ',');
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *skip_linker_arg(const char **str)
|
|
||||||
{
|
|
||||||
const char *s1 = *str;
|
|
||||||
const char *s2 = strchr(s1, ',');
|
|
||||||
*str = s2 ? s2++ : (s2 = s1 + strlen(s1));
|
|
||||||
return s2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void copy_linker_arg(char **pp, const char *s, int sep)
|
|
||||||
{
|
|
||||||
const char *q = s;
|
|
||||||
char *p = *pp;
|
|
||||||
int l = 0;
|
|
||||||
if (p && sep)
|
|
||||||
p[l = strlen(p)] = sep, ++l;
|
|
||||||
skip_linker_arg(&q);
|
|
||||||
pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
|
|
||||||
{
|
|
||||||
struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
|
|
||||||
f->type = filetype;
|
|
||||||
strcpy(f->name, filename);
|
|
||||||
dynarray_add(&s->files, &s->nb_files, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set linker options */
|
|
||||||
static int tcc_set_linker(TCCState *s, const char *option)
|
|
||||||
{
|
|
||||||
TCCState *s1 = s;
|
|
||||||
while (*option) {
|
|
||||||
|
|
||||||
const char *p = NULL;
|
|
||||||
char *end = NULL;
|
|
||||||
int ignoring = 0;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (link_option(option, "Bsymbolic", &p)) {
|
|
||||||
s->symbolic = 1;
|
|
||||||
} else if (link_option(option, "nostdlib", &p)) {
|
|
||||||
s->nostdlib = 1;
|
|
||||||
} else if (link_option(option, "e=", &p)
|
|
||||||
|| link_option(option, "entry=", &p)) {
|
|
||||||
copy_linker_arg(&s->elf_entryname, p, 0);
|
|
||||||
} else if (link_option(option, "fini=", &p)) {
|
|
||||||
copy_linker_arg(&s->fini_symbol, p, 0);
|
|
||||||
ignoring = 1;
|
|
||||||
} else if (link_option(option, "image-base=", &p)
|
|
||||||
|| link_option(option, "Ttext=", &p)) {
|
|
||||||
s->text_addr = strtoull(p, &end, 16);
|
|
||||||
s->has_text_addr = 1;
|
|
||||||
} else if (link_option(option, "init=", &p)) {
|
|
||||||
copy_linker_arg(&s->init_symbol, p, 0);
|
|
||||||
ignoring = 1;
|
|
||||||
} else if (link_option(option, "Map=", &p)) {
|
|
||||||
copy_linker_arg(&s->mapfile, p, 0);
|
|
||||||
ignoring = 1;
|
|
||||||
} else if (link_option(option, "oformat=", &p)) {
|
|
||||||
if (strstart("elf32-", &p)) {
|
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
|
||||||
} else if (link_arg("binary", p)) {
|
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
|
||||||
#ifdef TCC_TARGET_COFF
|
|
||||||
} else if (link_arg("coff", p)) {
|
|
||||||
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
|
||||||
#endif
|
|
||||||
} else
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
} else if (link_option(option, "as-needed", &p)) {
|
|
||||||
ignoring = 1;
|
|
||||||
} else if (link_option(option, "O", &p)) {
|
|
||||||
ignoring = 1;
|
|
||||||
} else if (link_option(option, "rpath=", &p)) {
|
|
||||||
copy_linker_arg(&s->rpath, p, ':');
|
|
||||||
} else if (link_option(option, "enable-new-dtags", &p)) {
|
|
||||||
s->enable_new_dtags = 1;
|
|
||||||
} else if (link_option(option, "section-alignment=", &p)) {
|
|
||||||
s->section_align = strtoul(p, &end, 16);
|
|
||||||
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
|
||||||
if (ret > 0)
|
|
||||||
s->filetype |= AFF_WHOLE_ARCHIVE;
|
|
||||||
else
|
|
||||||
s->filetype &= ~AFF_WHOLE_ARCHIVE;
|
|
||||||
} else if (link_option(option, "z=", &p)) {
|
|
||||||
ignoring = 1;
|
|
||||||
} else if (p) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
err:
|
|
||||||
return tcc_error_noabort("unsupported linker option '%s'", option);
|
|
||||||
}
|
|
||||||
if (ignoring)
|
|
||||||
tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option);
|
|
||||||
option = skip_linker_arg(&p);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct TCCOption {
|
|
||||||
const char *name;
|
|
||||||
uint16_t index;
|
|
||||||
uint16_t flags;
|
|
||||||
} TCCOption;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TCC_OPTION_ignored = 0,
|
|
||||||
TCC_OPTION_HELP,
|
|
||||||
TCC_OPTION_HELP2,
|
|
||||||
TCC_OPTION_v,
|
|
||||||
TCC_OPTION_I,
|
|
||||||
TCC_OPTION_D,
|
|
||||||
TCC_OPTION_U,
|
|
||||||
TCC_OPTION_P,
|
|
||||||
TCC_OPTION_L,
|
|
||||||
TCC_OPTION_B,
|
|
||||||
TCC_OPTION_l,
|
|
||||||
TCC_OPTION_bench,
|
|
||||||
TCC_OPTION_bt,
|
|
||||||
TCC_OPTION_b,
|
|
||||||
TCC_OPTION_ba,
|
|
||||||
TCC_OPTION_g,
|
|
||||||
TCC_OPTION_c,
|
|
||||||
TCC_OPTION_dumpmachine,
|
|
||||||
TCC_OPTION_dumpversion,
|
|
||||||
TCC_OPTION_d,
|
|
||||||
TCC_OPTION_static,
|
|
||||||
TCC_OPTION_std,
|
|
||||||
TCC_OPTION_shared,
|
|
||||||
TCC_OPTION_soname,
|
|
||||||
TCC_OPTION_o,
|
|
||||||
TCC_OPTION_r,
|
|
||||||
TCC_OPTION_Wl,
|
|
||||||
TCC_OPTION_Wp,
|
|
||||||
TCC_OPTION_W,
|
|
||||||
TCC_OPTION_O,
|
|
||||||
TCC_OPTION_mfloat_abi,
|
|
||||||
TCC_OPTION_m,
|
|
||||||
TCC_OPTION_f,
|
|
||||||
TCC_OPTION_isystem,
|
|
||||||
TCC_OPTION_iwithprefix,
|
|
||||||
TCC_OPTION_include,
|
|
||||||
TCC_OPTION_nostdinc,
|
|
||||||
TCC_OPTION_nostdlib,
|
|
||||||
TCC_OPTION_print_search_dirs,
|
|
||||||
TCC_OPTION_rdynamic,
|
|
||||||
TCC_OPTION_pthread,
|
|
||||||
TCC_OPTION_w,
|
|
||||||
TCC_OPTION_E,
|
|
||||||
TCC_OPTION_M,
|
|
||||||
TCC_OPTION_MD,
|
|
||||||
TCC_OPTION_MF,
|
|
||||||
TCC_OPTION_MM,
|
|
||||||
TCC_OPTION_MMD,
|
|
||||||
TCC_OPTION_MP,
|
|
||||||
TCC_OPTION_x,
|
|
||||||
TCC_OPTION_ar,
|
|
||||||
TCC_OPTION_impdef,
|
|
||||||
TCC_OPTION_dynamiclib,
|
|
||||||
TCC_OPTION_flat_namespace,
|
|
||||||
TCC_OPTION_two_levelnamespace,
|
|
||||||
TCC_OPTION_undefined,
|
|
||||||
TCC_OPTION_install_name,
|
|
||||||
TCC_OPTION_compatibility_version ,
|
|
||||||
TCC_OPTION_current_version,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TCC_OPTION_HAS_ARG 0x0001
|
|
||||||
#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
|
|
||||||
|
|
||||||
static const TCCOption tcc_options[] = {
|
|
||||||
{ "h", TCC_OPTION_HELP, 0 },
|
|
||||||
{ "-help", TCC_OPTION_HELP, 0 },
|
|
||||||
{ "?", TCC_OPTION_HELP, 0 },
|
|
||||||
{ "hh", TCC_OPTION_HELP2, 0 },
|
|
||||||
{ "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "-version", TCC_OPTION_v, 0 }, /* handle as verbose, also prints version*/
|
|
||||||
{ "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "bench", TCC_OPTION_bench, 0 },
|
|
||||||
{ "c", TCC_OPTION_c, 0 },
|
|
||||||
{ "dumpmachine", TCC_OPTION_dumpmachine, 0},
|
|
||||||
{ "dumpversion", TCC_OPTION_dumpversion, 0},
|
|
||||||
{ "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "pthread", TCC_OPTION_pthread, 0},
|
|
||||||
{ "rdynamic", TCC_OPTION_rdynamic, 0 },
|
|
||||||
{ "r", TCC_OPTION_r, 0 },
|
|
||||||
{ "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
|
|
||||||
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "nostdinc", TCC_OPTION_nostdinc, 0 },
|
|
||||||
{ "nostdlib", TCC_OPTION_nostdlib, 0 },
|
|
||||||
{ "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
|
|
||||||
{ "w", TCC_OPTION_w, 0 },
|
|
||||||
{ "E", TCC_OPTION_E, 0},
|
|
||||||
{ "M", TCC_OPTION_M, 0},
|
|
||||||
{ "MD", TCC_OPTION_MD, 0},
|
|
||||||
{ "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "MM", TCC_OPTION_MM, 0},
|
|
||||||
{ "MMD", TCC_OPTION_MMD, 0},
|
|
||||||
{ "MP", TCC_OPTION_MP, 0},
|
|
||||||
{ "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "ar", TCC_OPTION_ar, 0},
|
|
||||||
/* ignored (silently, except after -Wunsupported) */
|
|
||||||
{ "arch", 0, TCC_OPTION_HAS_ARG},
|
|
||||||
{ "g", 0, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
|
||||||
{ "C", 0, 0 },
|
|
||||||
{ "-param", 0, TCC_OPTION_HAS_ARG },
|
|
||||||
{ "pedantic", 0, 0 },
|
|
||||||
{ "pipe", 0, 0 },
|
|
||||||
{ "s", 0, 0 },
|
|
||||||
{ "traditional", 0, 0 },
|
|
||||||
{ "static", 0, 0},
|
|
||||||
{ "shared", 0, 0},
|
|
||||||
{ "soname", 0, 0},
|
|
||||||
{ NULL, 0, 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct FlagDef {
|
|
||||||
uint16_t offset;
|
|
||||||
uint16_t flags;
|
|
||||||
const char *name;
|
|
||||||
} FlagDef;
|
|
||||||
|
|
||||||
#define WD_ALL 0x0001 /* warning is activated when using -Wall */
|
|
||||||
#define FD_INVERT 0x0002 /* invert value before storing */
|
|
||||||
|
|
||||||
static const FlagDef options_W[] = {
|
|
||||||
{ offsetof(TCCState, warn_all), WD_ALL, "all" },
|
|
||||||
{ offsetof(TCCState, warn_error), 0, "error" },
|
|
||||||
{ offsetof(TCCState, warn_write_strings), 0, "write-strings" },
|
|
||||||
{ offsetof(TCCState, warn_unsupported), 0, "unsupported" },
|
|
||||||
{ offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, "implicit-function-declaration" },
|
|
||||||
{ offsetof(TCCState, warn_discarded_qualifiers), WD_ALL, "discarded-qualifiers" },
|
|
||||||
{ 0, 0, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const FlagDef options_f[] = {
|
|
||||||
{ offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
|
|
||||||
{ offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
|
|
||||||
{ offsetof(TCCState, nocommon), FD_INVERT, "common" },
|
|
||||||
{ offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
|
|
||||||
{ offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
|
|
||||||
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
|
|
||||||
{ offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs" },
|
|
||||||
{ offsetof(TCCState, gnu89_inline), 0, "gnu89-inline" },
|
|
||||||
{ offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables" },
|
|
||||||
{ 0, 0, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static const FlagDef options_m[] = {
|
|
||||||
{ offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" },
|
|
||||||
{ 0, 0, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int set_flag(TCCState *s, const FlagDef *flags, const char *name)
|
|
||||||
{
|
|
||||||
int value, mask, ret;
|
|
||||||
const FlagDef *p;
|
|
||||||
const char *r;
|
|
||||||
unsigned char *f;
|
|
||||||
|
|
||||||
r = name, value = !strstart("no-", &r), mask = 0;
|
|
||||||
|
|
||||||
/* when called with options_W, look for -W[no-]error=<option> */
|
|
||||||
if ((flags->flags & WD_ALL) && strstart("error=", &r))
|
|
||||||
value = value ? WARN_ON|WARN_ERR : WARN_NOE, mask = WARN_ON;
|
|
||||||
|
|
||||||
for (ret = -1, p = flags; p->name; ++p) {
|
|
||||||
if (ret) {
|
|
||||||
if (strcmp(r, p->name))
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
if (0 == (p->flags & WD_ALL))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
f = (unsigned char *)s + p->offset;
|
|
||||||
*f = (*f & mask) | (value ^ !!(p->flags & FD_INVERT));
|
|
||||||
|
|
||||||
if (ret) {
|
|
||||||
ret = 0;
|
|
||||||
if (strcmp(r, "all"))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char dumpmachine_str[] = "i386-pc-stupidos";
|
|
||||||
|
|
||||||
static int args_parser_make_argv(const char *r, int *argc, char ***argv)
|
|
||||||
{
|
|
||||||
int ret = 0, q, c;
|
|
||||||
CString str;
|
|
||||||
for(;;) {
|
|
||||||
while (c = (unsigned char)*r, c && c <= ' ')
|
|
||||||
++r;
|
|
||||||
if (c == 0)
|
|
||||||
break;
|
|
||||||
q = 0;
|
|
||||||
cstr_new(&str);
|
|
||||||
while (c = (unsigned char)*r, c) {
|
|
||||||
++r;
|
|
||||||
if (c == '\\' && (*r == '"' || *r == '\\')) {
|
|
||||||
c = *r++;
|
|
||||||
} else if (c == '"') {
|
|
||||||
q = !q;
|
|
||||||
continue;
|
|
||||||
} else if (q == 0 && c <= ' ') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cstr_ccat(&str, c);
|
|
||||||
}
|
|
||||||
cstr_ccat(&str, 0);
|
|
||||||
//printf("<%s>\n", str.data), fflush(stdout);
|
|
||||||
dynarray_add(argv, argc, tcc_strdup(str.data));
|
|
||||||
cstr_free(&str);
|
|
||||||
++ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read list file */
|
|
||||||
static int args_parser_listfile(TCCState *s,
|
|
||||||
const char *filename, int optind, int *pargc, char ***pargv)
|
|
||||||
{
|
|
||||||
TCCState *s1 = s;
|
|
||||||
int fd, i;
|
|
||||||
char *p;
|
|
||||||
int argc = 0;
|
|
||||||
char **argv = NULL;
|
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY | O_BINARY);
|
|
||||||
if (fd < 0)
|
|
||||||
return tcc_error_noabort("listfile '%s' not found", filename);
|
|
||||||
|
|
||||||
p = tcc_load_text(fd);
|
|
||||||
for (i = 0; i < *pargc; ++i)
|
|
||||||
if (i == optind)
|
|
||||||
args_parser_make_argv(p, &argc, &argv);
|
|
||||||
else
|
|
||||||
dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i]));
|
|
||||||
|
|
||||||
tcc_free(p);
|
|
||||||
dynarray_reset(&s->argv, &s->argc);
|
|
||||||
*pargc = s->argc = argc, *pargv = s->argv = argv;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
|
||||||
{
|
|
||||||
TCCState *s1 = s;
|
|
||||||
const TCCOption *popt;
|
|
||||||
const char *optarg, *r;
|
|
||||||
const char *run = NULL;
|
|
||||||
int x;
|
|
||||||
int tool = 0, arg_start = 0, noaction = optind;
|
|
||||||
char **argv = *pargv;
|
|
||||||
int argc = *pargc;
|
|
||||||
|
|
||||||
cstr_reset(&s->linker_arg);
|
|
||||||
|
|
||||||
while (optind < argc) {
|
|
||||||
r = argv[optind];
|
|
||||||
if (r[0] == '@' && r[1] != '\0') {
|
|
||||||
if (args_parser_listfile(s, r + 1, optind, &argc, &argv))
|
|
||||||
return -1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
optind++;
|
|
||||||
if (tool) {
|
|
||||||
if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
|
|
||||||
++s->verbose;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
reparse:
|
|
||||||
if (r[0] != '-' || r[1] == '\0') {
|
|
||||||
args_parser_add_file(s, r, s->filetype);
|
|
||||||
if (run) {
|
|
||||||
dorun:
|
|
||||||
if (tcc_set_options(s, run))
|
|
||||||
return -1;
|
|
||||||
arg_start = optind - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allow "tcc files... -run -- args ..." */
|
|
||||||
if (r[1] == '-' && r[2] == '\0' && run)
|
|
||||||
goto dorun;
|
|
||||||
|
|
||||||
/* find option in table */
|
|
||||||
for(popt = tcc_options; ; ++popt) {
|
|
||||||
const char *p1 = popt->name;
|
|
||||||
const char *r1 = r + 1;
|
|
||||||
if (p1 == NULL)
|
|
||||||
return tcc_error_noabort("invalid option -- '%s'", r);
|
|
||||||
if (!strstart(p1, &r1))
|
|
||||||
continue;
|
|
||||||
optarg = r1;
|
|
||||||
if (popt->flags & TCC_OPTION_HAS_ARG) {
|
|
||||||
if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
|
|
||||||
if (optind >= argc)
|
|
||||||
arg_err:
|
|
||||||
return tcc_error_noabort("argument to '%s' is missing", r);
|
|
||||||
optarg = argv[optind++];
|
|
||||||
}
|
|
||||||
} else if (*r1 != '\0')
|
|
||||||
continue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(popt->index) {
|
|
||||||
case TCC_OPTION_HELP:
|
|
||||||
x = OPT_HELP;
|
|
||||||
goto extra_action;
|
|
||||||
case TCC_OPTION_HELP2:
|
|
||||||
x = OPT_HELP2;
|
|
||||||
goto extra_action;
|
|
||||||
case TCC_OPTION_I:
|
|
||||||
tcc_add_include_path(s, optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_D:
|
|
||||||
tcc_define_symbol(s, optarg, NULL);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_U:
|
|
||||||
tcc_undefine_symbol(s, optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_L:
|
|
||||||
tcc_add_library_path(s, optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_B:
|
|
||||||
/* set tcc utilities path (mainly for tcc development) */
|
|
||||||
tcc_set_lib_path(s, optarg);
|
|
||||||
++noaction;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_l:
|
|
||||||
args_parser_add_file(s, optarg, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK));
|
|
||||||
s->nb_libraries++;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_pthread:
|
|
||||||
s->option_pthread = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_bench:
|
|
||||||
s->do_bench = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_c:
|
|
||||||
x = TCC_OUTPUT_OBJ;
|
|
||||||
set_output_type:
|
|
||||||
if (s->output_type)
|
|
||||||
tcc_warning("-%s: overriding compiler action already specified", popt->name);
|
|
||||||
s->output_type = x;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_d:
|
|
||||||
if (*optarg == 'D')
|
|
||||||
s->dflag = 3;
|
|
||||||
else if (*optarg == 'M')
|
|
||||||
s->dflag = 7;
|
|
||||||
else
|
|
||||||
goto unsupported_option;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_std:
|
|
||||||
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
|
||||||
s->cversion = 201112;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_o:
|
|
||||||
if (s->outfile) {
|
|
||||||
tcc_warning("multiple -o option");
|
|
||||||
tcc_free(s->outfile);
|
|
||||||
}
|
|
||||||
s->outfile = tcc_strdup(optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_r:
|
|
||||||
/* generate a .o merging several output files */
|
|
||||||
s->option_r = 1;
|
|
||||||
x = TCC_OUTPUT_OBJ;
|
|
||||||
goto set_output_type;
|
|
||||||
case TCC_OPTION_isystem:
|
|
||||||
tcc_add_sysinclude_path(s, optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_include:
|
|
||||||
cstr_printf(&s->cmdline_incl, "#include \"%s\"\n", optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_nostdinc:
|
|
||||||
s->nostdinc = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_nostdlib:
|
|
||||||
s->nostdlib = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_v:
|
|
||||||
do ++s->verbose; while (*optarg++ == 'v');
|
|
||||||
++noaction;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_f:
|
|
||||||
if (set_flag(s, options_f, optarg) < 0)
|
|
||||||
goto unsupported_option;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_m:
|
|
||||||
if (set_flag(s, options_m, optarg) < 0) {
|
|
||||||
if (x = atoi(optarg), x != 32 && x != 64)
|
|
||||||
goto unsupported_option;
|
|
||||||
if (PTR_SIZE != x/8)
|
|
||||||
return x;
|
|
||||||
++noaction;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_W:
|
|
||||||
s->warn_none = 0;
|
|
||||||
if (optarg[0] && set_flag(s, options_W, optarg) < 0)
|
|
||||||
goto unsupported_option;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_w:
|
|
||||||
s->warn_none = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_Wl:
|
|
||||||
if (s->linker_arg.size)
|
|
||||||
((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
|
|
||||||
cstr_cat(&s->linker_arg, optarg, 0);
|
|
||||||
x = tcc_set_linker(s, s->linker_arg.data);
|
|
||||||
if (x)
|
|
||||||
cstr_reset(&s->linker_arg);
|
|
||||||
if (x < 0)
|
|
||||||
return -1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_Wp:
|
|
||||||
r = optarg;
|
|
||||||
goto reparse;
|
|
||||||
case TCC_OPTION_E:
|
|
||||||
x = TCC_OUTPUT_PREPROCESS;
|
|
||||||
goto set_output_type;
|
|
||||||
case TCC_OPTION_P:
|
|
||||||
s->Pflag = atoi(optarg) + 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_M:
|
|
||||||
s->include_sys_deps = 1;
|
|
||||||
// fall through
|
|
||||||
case TCC_OPTION_MM:
|
|
||||||
s->just_deps = 1;
|
|
||||||
if(!s->deps_outfile)
|
|
||||||
s->deps_outfile = tcc_strdup("-");
|
|
||||||
// fall through
|
|
||||||
case TCC_OPTION_MMD:
|
|
||||||
s->gen_deps = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_MD:
|
|
||||||
s->gen_deps = 1;
|
|
||||||
s->include_sys_deps = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_MF:
|
|
||||||
s->deps_outfile = tcc_strdup(optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_MP:
|
|
||||||
s->gen_phony_deps = 1;
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_dumpmachine:
|
|
||||||
printf("%s\n", dumpmachine_str);
|
|
||||||
exit(0);
|
|
||||||
case TCC_OPTION_dumpversion:
|
|
||||||
printf ("%s\n", PACKAGE_VERSION);
|
|
||||||
exit(0);
|
|
||||||
case TCC_OPTION_x:
|
|
||||||
x = 0;
|
|
||||||
if (*optarg == 'c')
|
|
||||||
x = AFF_TYPE_C;
|
|
||||||
else if (*optarg == 'a')
|
|
||||||
x = AFF_TYPE_ASMPP;
|
|
||||||
else if (*optarg == 'b')
|
|
||||||
x = AFF_TYPE_BIN;
|
|
||||||
else if (*optarg == 'n')
|
|
||||||
x = AFF_TYPE_NONE;
|
|
||||||
else
|
|
||||||
tcc_warning("unsupported language '%s'", optarg);
|
|
||||||
s->filetype = x | (s->filetype & ~AFF_TYPE_MASK);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_O:
|
|
||||||
s->optimize = atoi(optarg);
|
|
||||||
break;
|
|
||||||
case TCC_OPTION_print_search_dirs:
|
|
||||||
x = OPT_PRINT_DIRS;
|
|
||||||
goto extra_action;
|
|
||||||
case TCC_OPTION_impdef:
|
|
||||||
x = OPT_IMPDEF;
|
|
||||||
goto extra_action;
|
|
||||||
case TCC_OPTION_ar:
|
|
||||||
x = OPT_AR;
|
|
||||||
extra_action:
|
|
||||||
arg_start = optind - 1;
|
|
||||||
if (arg_start != noaction)
|
|
||||||
return tcc_error_noabort("cannot parse %s here", r);
|
|
||||||
tool = x;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
unsupported_option:
|
|
||||||
tcc_warning_c(warn_unsupported)("unsupported option '%s'", r);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s->linker_arg.size) {
|
|
||||||
r = s->linker_arg.data;
|
|
||||||
goto arg_err;
|
|
||||||
}
|
|
||||||
*pargc = argc - arg_start;
|
|
||||||
*pargv = argv + arg_start;
|
|
||||||
if (tool)
|
|
||||||
return tool;
|
|
||||||
if (optind != noaction)
|
|
||||||
return 0;
|
|
||||||
if (s->verbose == 2)
|
|
||||||
return OPT_PRINT_DIRS;
|
|
||||||
if (s->verbose)
|
|
||||||
return OPT_V;
|
|
||||||
return OPT_HELP;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tcc_set_options(TCCState *s, const char *r)
|
|
||||||
{
|
|
||||||
char **argv = NULL;
|
|
||||||
int argc = 0, ret;
|
|
||||||
args_parser_make_argv(r, &argc, &argv);
|
|
||||||
ret = tcc_parse_args(s, &argc, &argv, 0);
|
|
||||||
dynarray_reset(&argv, &argc);
|
|
||||||
return ret < 0 ? ret : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
|
PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
|
||||||
{
|
{
|
||||||
if (!total_time)
|
if (!total_time)
|
||||||
|
|
674
libtcc/option.c
674
libtcc/option.c
|
@ -1,10 +1,28 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <tcc.h>
|
||||||
#include <tcc/option.h>
|
#include <tcc/option.h>
|
||||||
#include "utils/cstr.h"
|
#include "utils/string.h"
|
||||||
|
|
||||||
|
# define F_WD_ALL 0x0001 /* warning is activated when using -Wall */
|
||||||
|
# define F_FD_INVERT 0x0002 /* invert value before storing */
|
||||||
|
|
||||||
|
# define WARN_ON 1 /* warning is on (-Woption) */
|
||||||
|
# define WARN_ERR 2 /* warning is an error (-Werror=option) */
|
||||||
|
# define WARN_NOE 4 /* warning is not an error (-Wno-error=option) */
|
||||||
|
|
||||||
|
typedef struct Flag {
|
||||||
|
uint16_t offset;
|
||||||
|
uint16_t flags;
|
||||||
|
const char *name;
|
||||||
|
} Flag;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
OPTION_ignored = 0,
|
OPTION_ignored = 0,
|
||||||
|
OPTION_HELP,
|
||||||
|
OPTION_HELP_MORE,
|
||||||
|
OPTION_v,
|
||||||
OPTION_I,
|
OPTION_I,
|
||||||
OPTION_D,
|
OPTION_D,
|
||||||
OPTION_U,
|
OPTION_U,
|
||||||
|
@ -41,9 +59,16 @@ enum {
|
||||||
OPTION_MMD,
|
OPTION_MMD,
|
||||||
OPTION_MP,
|
OPTION_MP,
|
||||||
OPTION_x,
|
OPTION_x,
|
||||||
|
OPTION_ar,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const TCCOption options[] = {
|
static const TCCOption options[] = {
|
||||||
|
{"h", OPTION_HELP, 0},
|
||||||
|
{"-help", OPTION_HELP, 0},
|
||||||
|
{"?", OPTION_HELP, 0},
|
||||||
|
{"hh", OPTION_HELP_MORE, 0},
|
||||||
|
{"v", OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP},
|
||||||
|
{"-version", OPTION_v, 0}, /* handle as verbose, also prints version*/
|
||||||
{"I", OPTION_I, TCC_OPTION_HAS_ARG},
|
{"I", OPTION_I, TCC_OPTION_HAS_ARG},
|
||||||
{"D", OPTION_D, TCC_OPTION_HAS_ARG},
|
{"D", OPTION_D, TCC_OPTION_HAS_ARG},
|
||||||
{"U", OPTION_U, TCC_OPTION_HAS_ARG},
|
{"U", OPTION_U, TCC_OPTION_HAS_ARG},
|
||||||
|
@ -91,23 +116,662 @@ static const TCCOption options[] = {
|
||||||
{"s", 0, 0},
|
{"s", 0, 0},
|
||||||
{"traditional", 0, 0},
|
{"traditional", 0, 0},
|
||||||
{"shared", 0, 0},
|
{"shared", 0, 0},
|
||||||
|
{"soname", 0, 0},
|
||||||
|
{"static", 0, 0},
|
||||||
|
|
||||||
{NULL, 0, 0}
|
{NULL, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static TCCOption *options_ext = NULL;
|
static const Flag options_W[] = {
|
||||||
|
{offsetof(TCCState, warn_all), F_WD_ALL, "all"},
|
||||||
|
{offsetof(TCCState, warn_error), 0, "error"},
|
||||||
|
{offsetof(TCCState, warn_write_strings), 0, "write-strings"},
|
||||||
|
{offsetof(TCCState, warn_unsupported), 0, "unsupported"},
|
||||||
|
{offsetof(TCCState, warn_implicit_function_declaration), F_WD_ALL, "implicit-function-declaration"},
|
||||||
|
{offsetof(TCCState, warn_discarded_qualifiers), F_WD_ALL, "discarded-qualifiers"},
|
||||||
|
{0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Flag options_f[] = {
|
||||||
|
{offsetof(TCCState, char_is_unsigned), 0, "unsigned-char"},
|
||||||
|
{offsetof(TCCState, char_is_unsigned), F_FD_INVERT, "signed-char"},
|
||||||
|
{offsetof(TCCState, nocommon), F_FD_INVERT, "common"},
|
||||||
|
{offsetof(TCCState, leading_underscore), 0, "leading-underscore"},
|
||||||
|
{offsetof(TCCState, ms_extensions), 0, "ms-extensions"},
|
||||||
|
{offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers"},
|
||||||
|
{offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs"},
|
||||||
|
{offsetof(TCCState, gnu89_inline), 0, "gnu89-inline"},
|
||||||
|
{offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables"},
|
||||||
|
{0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Flag options_m[] = {
|
||||||
|
{offsetof(TCCState, ms_bitfields), 0, "ms-bitfields"},
|
||||||
|
{0, 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
static const char dumpmachine_str[] = "i386-pc-stupidos";
|
static const char dumpmachine_str[] = "i386-pc-stupidos";
|
||||||
|
|
||||||
void
|
static int
|
||||||
tcc_add_options(TCCOption *opt)
|
strstart(const char *val, const char **str)
|
||||||
{
|
{
|
||||||
options_ext = opt;
|
const char *p;
|
||||||
|
const char *q;
|
||||||
|
|
||||||
|
p = *str;
|
||||||
|
q = val;
|
||||||
|
|
||||||
|
while (*q)
|
||||||
|
{
|
||||||
|
if (*p != *q) return (0);
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*str = p;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_flag(TCCState *s, const Flag *flags, const char *name)
|
||||||
|
{
|
||||||
|
int value, mask, ret;
|
||||||
|
const Flag *p;
|
||||||
|
const char *r;
|
||||||
|
unsigned char *f;
|
||||||
|
|
||||||
|
r = name;
|
||||||
|
value = !strstart("no-", &r);
|
||||||
|
mask = 0;
|
||||||
|
|
||||||
|
/* when called with options_W, look for -W[no-]error=<option> */
|
||||||
|
if ((flags->flags & F_WD_ALL) && strstart("error=", &r))
|
||||||
|
{
|
||||||
|
value = value ? WARN_ON|WARN_ERR : WARN_NOE;
|
||||||
|
mask = WARN_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ret = -1, p = flags; p->name; ++p)
|
||||||
|
{
|
||||||
|
if ((ret && strcmp(r, p->name))
|
||||||
|
|| ((p->flags & F_WD_ALL) == 0))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
f = (unsigned char *)s + p->offset;
|
||||||
|
*f = (*f & mask) | (value ^ !!(p->flags & F_FD_INVERT));
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ret = 0;
|
||||||
|
if (strcmp(r, "all"))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Like strstart, but automatically takes into account that ld options can
|
||||||
|
*
|
||||||
|
* - start with double or single dash (e.g. '--soname' or '-soname')
|
||||||
|
* - arguments can be given as separate or after '=' (e.g. '-Wl,-soname,x.so'
|
||||||
|
* or '-Wl,-soname=x.so')
|
||||||
|
*
|
||||||
|
* you provide `val` always in 'option[=]' form (no leading -)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
link_option(const char *str, const char *val, const char **ptr)
|
||||||
|
{
|
||||||
|
const char *p, *q;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* there should be 1 or 2 dashes */
|
||||||
|
if (*str++ != '-')
|
||||||
|
return 0;
|
||||||
|
if (*str == '-')
|
||||||
|
str++;
|
||||||
|
|
||||||
|
/* then str & val should match (potentially up to '=') */
|
||||||
|
p = str;
|
||||||
|
q = val;
|
||||||
|
|
||||||
|
ret = 1;
|
||||||
|
if (q[0] == '?')
|
||||||
|
{
|
||||||
|
++q;
|
||||||
|
if (strstart("no-", &p))
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*q != '\0' && *q != '=')
|
||||||
|
{
|
||||||
|
if (*p != *q)
|
||||||
|
return (0);
|
||||||
|
p++;
|
||||||
|
q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* '=' near eos means ',' or '=' is ok */
|
||||||
|
if (*q == '=')
|
||||||
|
{
|
||||||
|
if (*p == 0)
|
||||||
|
*ptr = p;
|
||||||
|
if (*p != ',' && *p != '=')
|
||||||
|
return 0;
|
||||||
|
p++;
|
||||||
|
} else if (*p) {
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
*ptr = p;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
link_arg(const char *opt, const char *str)
|
||||||
|
{
|
||||||
|
int l = strlen(opt);
|
||||||
|
return 0 == strncmp(opt, str, l) && (str[l] == '\0' || str[l] == ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
skip_linker_arg(const char **str)
|
||||||
|
{
|
||||||
|
const char *s1 = *str;
|
||||||
|
const char *s2 = strchr(s1, ',');
|
||||||
|
*str = s2 ? s2++ : (s2 = s1 + strlen(s1));
|
||||||
|
return s2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
copy_linker_arg(char **pp, const char *s, int sep)
|
||||||
|
{
|
||||||
|
const char *q = s;
|
||||||
|
char *p = *pp;
|
||||||
|
int l = 0;
|
||||||
|
if (p && sep)
|
||||||
|
p[l = strlen(p)] = sep, ++l;
|
||||||
|
skip_linker_arg(&q);
|
||||||
|
pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set linker options */
|
||||||
|
static int
|
||||||
|
set_linker(TCCState *s, const char *option)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
char *end;
|
||||||
|
int ignoring;
|
||||||
|
int ret;
|
||||||
|
TCCState *s1 = s;
|
||||||
|
|
||||||
|
while (*option)
|
||||||
|
{
|
||||||
|
p = NULL;
|
||||||
|
end = NULL;
|
||||||
|
ignoring = 0;
|
||||||
|
|
||||||
|
if (link_option(option, "Bsymbolic", &p))
|
||||||
|
{
|
||||||
|
s->symbolic = 1;
|
||||||
|
} else if (link_option(option, "nostdlib", &p)) {
|
||||||
|
s->nostdlib = 1;
|
||||||
|
} else if (link_option(option, "e=", &p)
|
||||||
|
|| link_option(option, "entry=", &p)) {
|
||||||
|
copy_linker_arg(&s->elf_entryname, p, 0);
|
||||||
|
} else if (link_option(option, "fini=", &p)) {
|
||||||
|
copy_linker_arg(&s->fini_symbol, p, 0);
|
||||||
|
ignoring = 1;
|
||||||
|
} else if (link_option(option, "image-base=", &p)
|
||||||
|
|| link_option(option, "Ttext=", &p)) {
|
||||||
|
s->text_addr = strtoull(p, &end, 16);
|
||||||
|
s->has_text_addr = 1;
|
||||||
|
} else if (link_option(option, "init=", &p)) {
|
||||||
|
copy_linker_arg(&s->init_symbol, p, 0);
|
||||||
|
ignoring = 1;
|
||||||
|
} else if (link_option(option, "Map=", &p)) {
|
||||||
|
copy_linker_arg(&s->mapfile, p, 0);
|
||||||
|
ignoring = 1;
|
||||||
|
} else if (link_option(option, "oformat=", &p)) {
|
||||||
|
if (strstart("elf32-", &p)) {
|
||||||
|
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
||||||
|
} else if (link_arg("binary", p)) {
|
||||||
|
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
||||||
|
#ifdef TCC_TARGET_COFF
|
||||||
|
} else if (link_arg("coff", p)) {
|
||||||
|
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
} else if (link_option(option, "as-needed", &p)) {
|
||||||
|
ignoring = 1;
|
||||||
|
} else if (link_option(option, "O", &p)) {
|
||||||
|
ignoring = 1;
|
||||||
|
} else if (link_option(option, "rpath=", &p)) {
|
||||||
|
copy_linker_arg(&s->rpath, p, ':');
|
||||||
|
} else if (link_option(option, "enable-new-dtags", &p)) {
|
||||||
|
s->enable_new_dtags = 1;
|
||||||
|
} else if (link_option(option, "section-alignment=", &p)) {
|
||||||
|
s->section_align = strtoul(p, &end, 16);
|
||||||
|
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
||||||
|
if (ret > 0)
|
||||||
|
s->filetype |= AFF_WHOLE_ARCHIVE;
|
||||||
|
else
|
||||||
|
s->filetype &= ~AFF_WHOLE_ARCHIVE;
|
||||||
|
} else if (link_option(option, "z=", &p)) {
|
||||||
|
ignoring = 1;
|
||||||
|
} else if (p) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
err:
|
||||||
|
return tcc_error_noabort("unsupported linker option '%s'", option);
|
||||||
|
}
|
||||||
|
if (ignoring)
|
||||||
|
tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option);
|
||||||
|
option = skip_linker_arg(&p);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
args_parser_make_argv(const char *r, int *argc, char ***argv)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int q;
|
||||||
|
int c;
|
||||||
|
CString str;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
while (c = (unsigned char)*r, c && c <= ' ')
|
||||||
|
{
|
||||||
|
++r;
|
||||||
|
}
|
||||||
|
if (c == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
q = 0;
|
||||||
|
cstr_new(&str);
|
||||||
|
while (c = (unsigned char)*r, c)
|
||||||
|
{
|
||||||
|
++r;
|
||||||
|
if (c == '\\' && (*r == '"' || *r == '\\'))
|
||||||
|
{
|
||||||
|
c = *r++;
|
||||||
|
}
|
||||||
|
else if (c == '"')
|
||||||
|
{
|
||||||
|
q = !q;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (q == 0 && c <= ' ')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cstr_ccat(&str, c);
|
||||||
|
}
|
||||||
|
cstr_ccat(&str, 0);
|
||||||
|
dynarray_add(argv, argc, tcc_strdup(str.data));
|
||||||
|
cstr_free(&str);
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
args_parser_listfile(TCCState *s, const char *fname, int optind, int *pargc,
|
||||||
|
char ***pargv)
|
||||||
|
{
|
||||||
|
TCCState *s1;
|
||||||
|
int fd, i;
|
||||||
|
char *p;
|
||||||
|
int argc = 0;
|
||||||
|
char **argv = NULL;
|
||||||
|
|
||||||
|
s1 = s;
|
||||||
|
|
||||||
|
fd = open(fname, O_RDONLY | O_BINARY);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
return (tcc_error_noabort("listfile '%s' not found", fname));
|
||||||
|
}
|
||||||
|
|
||||||
|
p = tcc_load_text(fd);
|
||||||
|
for (i = 0; i < *pargc; ++i)
|
||||||
|
{
|
||||||
|
if (i == optind)
|
||||||
|
{
|
||||||
|
args_parser_make_argv(p, &argc, &argv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tcc_free(p);
|
||||||
|
dynarray_reset(&s->argv, &s->argc);
|
||||||
|
*pargc = s->argc = argc, *pargv = s->argv = argv;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
args_parser_add_file(TCCState *s, const char *fname, int ftype)
|
||||||
|
{
|
||||||
|
struct filespec *f;
|
||||||
|
|
||||||
|
f= tcc_malloc(sizeof *f + strlen(fname));
|
||||||
|
f->type = ftype;
|
||||||
|
strcpy(f->name, fname);
|
||||||
|
dynarray_add(&s->files, &s->nb_files, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
|
||||||
{
|
{
|
||||||
|
TCCState *s1 = s;
|
||||||
|
const TCCOption *popt;
|
||||||
|
const char *optarg, *r;
|
||||||
|
const char *p1;
|
||||||
|
const char *r1;
|
||||||
|
int x;
|
||||||
|
int tool = 0;
|
||||||
|
int arg_start = 0;
|
||||||
|
int noaction;
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
|
||||||
|
noaction = optind;
|
||||||
|
argv = *pargv;
|
||||||
|
argc = *pargc;
|
||||||
|
|
||||||
|
cstr_reset(&s->linker_arg);
|
||||||
|
|
||||||
|
while (optind < argc) {
|
||||||
|
r = argv[optind];
|
||||||
|
if (r[0] == '@' && r[1] != '\0')
|
||||||
|
{
|
||||||
|
if (args_parser_listfile(s, r + 1, optind, &argc, &argv))
|
||||||
|
{
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
optind++;
|
||||||
|
if (tool)
|
||||||
|
{
|
||||||
|
if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
|
||||||
|
{
|
||||||
|
s->verbose++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
reparse:
|
||||||
|
if (r[0] != '-' || r[1] == '\0')
|
||||||
|
{
|
||||||
|
args_parser_add_file(s, r, s->filetype);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find option in table */
|
||||||
|
for (popt = options; ; ++popt)
|
||||||
|
{
|
||||||
|
p1 = popt->name;
|
||||||
|
r1 = r + 1;
|
||||||
|
if (p1 == NULL)
|
||||||
|
{
|
||||||
|
return tcc_error_noabort("invalid option -- '%s'", r);
|
||||||
|
}
|
||||||
|
if (!strstart(p1, &r1))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
optarg = r1;
|
||||||
|
if (popt->flags & TCC_OPTION_HAS_ARG)
|
||||||
|
{
|
||||||
|
if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP))
|
||||||
|
{
|
||||||
|
if (optind >= argc)
|
||||||
|
{
|
||||||
|
return (tcc_error_noabort("argument to '%s' is missing", r));
|
||||||
|
}
|
||||||
|
optarg = argv[optind++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*r1 != '\0')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(popt->index)
|
||||||
|
{
|
||||||
|
case OPTION_HELP:
|
||||||
|
x = TCC_OPT_HELP;
|
||||||
|
goto extra_action;
|
||||||
|
case OPTION_HELP_MORE:
|
||||||
|
x = TCC_OPT_HELP_MORE;
|
||||||
|
goto extra_action;
|
||||||
|
case OPTION_I:
|
||||||
|
tcc_add_include_path(s, optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_D:
|
||||||
|
tcc_define_symbol(s, optarg, NULL);
|
||||||
|
break;
|
||||||
|
case OPTION_U:
|
||||||
|
tcc_undefine_symbol(s, optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_L:
|
||||||
|
tcc_add_library_path(s, optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_B:
|
||||||
|
/* set tcc utilities path (mainly for tcc development) */
|
||||||
|
tcc_set_lib_path(s, optarg);
|
||||||
|
++noaction;
|
||||||
|
break;
|
||||||
|
case OPTION_l:
|
||||||
|
args_parser_add_file(s, optarg, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK));
|
||||||
|
s->nb_libraries++;
|
||||||
|
break;
|
||||||
|
case OPTION_pthread:
|
||||||
|
s->option_pthread = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_bench:
|
||||||
|
s->do_bench = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_c:
|
||||||
|
x = TCC_OUTPUT_OBJ;
|
||||||
|
set_output_type:
|
||||||
|
if (s->output_type)
|
||||||
|
tcc_warning("-%s: overriding compiler action already specified", popt->name);
|
||||||
|
s->output_type = x;
|
||||||
|
break;
|
||||||
|
case OPTION_d:
|
||||||
|
if (*optarg == 'D')
|
||||||
|
s->dflag = 3;
|
||||||
|
else if (*optarg == 'M')
|
||||||
|
s->dflag = 7;
|
||||||
|
else
|
||||||
|
goto unsupported_option;
|
||||||
|
break;
|
||||||
|
case OPTION_std:
|
||||||
|
if (strcmp(optarg, "=c11") == 0 || strcmp(optarg, "=gnu11") == 0)
|
||||||
|
s->cversion = 201112;
|
||||||
|
break;
|
||||||
|
case OPTION_o:
|
||||||
|
if (s->outfile)
|
||||||
|
{
|
||||||
|
tcc_warning("multiple -o option");
|
||||||
|
tcc_free(s->outfile);
|
||||||
|
}
|
||||||
|
s->outfile = tcc_strdup(optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_r:
|
||||||
|
/* generate a .o merging several output files */
|
||||||
|
s->option_r = 1;
|
||||||
|
x = TCC_OUTPUT_OBJ;
|
||||||
|
goto set_output_type;
|
||||||
|
case OPTION_isystem:
|
||||||
|
tcc_add_sysinclude_path(s, optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_include:
|
||||||
|
cstr_printf(&s->cmdline_incl, "#include \"%s\"\n", optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_nostdinc:
|
||||||
|
s->nostdinc = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_nostdlib:
|
||||||
|
s->nostdlib = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_v:
|
||||||
|
do { ++s->verbose; } while (*optarg++ == 'v');
|
||||||
|
++noaction;
|
||||||
|
break;
|
||||||
|
case OPTION_f:
|
||||||
|
if (set_flag(s, options_f, optarg) < 0)
|
||||||
|
goto unsupported_option;
|
||||||
|
break;
|
||||||
|
case OPTION_m:
|
||||||
|
if (set_flag(s, options_m, optarg) < 0)
|
||||||
|
{
|
||||||
|
if (x = atoi(optarg), x != 32 && x != 64)
|
||||||
|
goto unsupported_option;
|
||||||
|
if (PTR_SIZE != x/8)
|
||||||
|
return x;
|
||||||
|
++noaction;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPTION_W:
|
||||||
|
s->warn_none = 0;
|
||||||
|
if (optarg[0] && set_flag(s, options_W, optarg) < 0)
|
||||||
|
goto unsupported_option;
|
||||||
|
break;
|
||||||
|
case OPTION_w:
|
||||||
|
s->warn_none = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_Wl:
|
||||||
|
if (s->linker_arg.size)
|
||||||
|
((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
|
||||||
|
cstr_cat(&s->linker_arg, optarg, 0);
|
||||||
|
x = set_linker(s, s->linker_arg.data);
|
||||||
|
if (x)
|
||||||
|
cstr_reset(&s->linker_arg);
|
||||||
|
if (x < 0)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case OPTION_Wp:
|
||||||
|
r = optarg;
|
||||||
|
goto reparse;
|
||||||
|
case OPTION_E:
|
||||||
|
x = TCC_OUTPUT_PREPROCESS;
|
||||||
|
goto set_output_type;
|
||||||
|
case OPTION_P:
|
||||||
|
s->Pflag = atoi(optarg) + 1;
|
||||||
|
break;
|
||||||
|
case OPTION_M:
|
||||||
|
s->include_sys_deps = 1;
|
||||||
|
// fall through
|
||||||
|
case OPTION_MM:
|
||||||
|
s->just_deps = 1;
|
||||||
|
if(!s->deps_outfile)
|
||||||
|
s->deps_outfile = tcc_strdup("-");
|
||||||
|
// fall through
|
||||||
|
case OPTION_MMD:
|
||||||
|
s->gen_deps = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_MD:
|
||||||
|
s->gen_deps = 1;
|
||||||
|
s->include_sys_deps = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_MF:
|
||||||
|
s->deps_outfile = tcc_strdup(optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_MP:
|
||||||
|
s->gen_phony_deps = 1;
|
||||||
|
break;
|
||||||
|
case OPTION_dumpmachine:
|
||||||
|
printf("%s\n", dumpmachine_str);
|
||||||
|
exit(0);
|
||||||
|
case OPTION_dumpversion:
|
||||||
|
printf ("%s\n", PACKAGE_VERSION);
|
||||||
|
exit(0);
|
||||||
|
case OPTION_x:
|
||||||
|
x = 0;
|
||||||
|
if (*optarg == 'c')
|
||||||
|
x = AFF_TYPE_C;
|
||||||
|
else if (*optarg == 'a')
|
||||||
|
x = AFF_TYPE_ASMPP;
|
||||||
|
else if (*optarg == 'b')
|
||||||
|
x = AFF_TYPE_BIN;
|
||||||
|
else if (*optarg == 'n')
|
||||||
|
x = AFF_TYPE_NONE;
|
||||||
|
else
|
||||||
|
tcc_warning("unsupported language '%s'", optarg);
|
||||||
|
s->filetype = x | (s->filetype & ~AFF_TYPE_MASK);
|
||||||
|
break;
|
||||||
|
case OPTION_O:
|
||||||
|
s->optimize = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case OPTION_print_search_dirs:
|
||||||
|
x = TCC_OPT_PRINT_DIRS;
|
||||||
|
goto extra_action;
|
||||||
|
case OPTION_ar:
|
||||||
|
x = TCC_OPT_ARCHIVE;
|
||||||
|
extra_action:
|
||||||
|
arg_start = optind - 1;
|
||||||
|
if (arg_start != noaction)
|
||||||
|
return tcc_error_noabort("cannot parse %s here", r);
|
||||||
|
tool = x;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unsupported_option:
|
||||||
|
tcc_warning_c(warn_unsupported)("unsupported option '%s'", r);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s->linker_arg.size)
|
||||||
|
{
|
||||||
|
r = s->linker_arg.data;
|
||||||
|
return (tcc_error_noabort("argument to '%s' is missing", r));
|
||||||
|
}
|
||||||
|
*pargc = argc - arg_start;
|
||||||
|
*pargv = argv + arg_start;
|
||||||
|
if (tool)
|
||||||
|
return (tool);
|
||||||
|
if (optind != noaction)
|
||||||
|
return (0);
|
||||||
|
if (s->verbose == 2)
|
||||||
|
return (TCC_OPT_PRINT_DIRS);
|
||||||
|
if (s->verbose)
|
||||||
|
return (TCC_OPT_VERSION);
|
||||||
|
return (TCC_OPT_HELP);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
tcc_set_options(TCCState *s, const char *str)
|
||||||
|
{
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
argv = NULL;
|
||||||
|
argc = 0;
|
||||||
|
args_parser_make_argv(str, &argc, &argv);
|
||||||
|
ret = tcc_parse_args(s, &argc, &argv, 0);
|
||||||
|
dynarray_reset(&argv, &argc);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#include "tcc/coff.h"
|
#include <tcc.h>
|
||||||
#include "tcc.h"
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tcc.h"
|
#include <tcc.h>
|
||||||
|
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
|
|
||||||
/* Define this to get some debug output during relocation processing. */
|
/* Define this to get some debug output during relocation processing. */
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include <tcc.h>
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USING_GLOBALS
|
#define USING_GLOBALS
|
||||||
#include "tcc.h"
|
#include <tcc.h>
|
||||||
#include "utils/string.h"
|
#include "utils/string.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -1343,7 +1343,7 @@ static int parse_include(TCCState *s1, int do_next, int test)
|
||||||
cstr_reset(&tokcstr);
|
cstr_reset(&tokcstr);
|
||||||
file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &tokcstr);
|
file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &tokcstr);
|
||||||
i = tokcstr.size;
|
i = tokcstr.size;
|
||||||
pstrncpy(name, tokcstr.data, i >= sizeof name ? sizeof name - 1 : i);
|
pstrncpy(name, tokcstr.data, i >= sizeof(name) ? sizeof(name) - 1 : i);
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
} else {
|
} else {
|
||||||
/* computed #include : concatenate tokens until result is one of
|
/* computed #include : concatenate tokens until result is one of
|
||||||
|
|
79
tcc/tcc.c
79
tcc/tcc.c
|
@ -19,17 +19,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <tcc.h>
|
#include <tcc.h>
|
||||||
|
#include <tcc/option.h>
|
||||||
#include "tcctools.h"
|
#include "tcctools.h"
|
||||||
|
|
||||||
static const char HELP_STR[] =
|
static const char help_str[] =
|
||||||
"Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
"Tiny C Compiler "PACKAGE_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
|
||||||
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
|
"Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
|
||||||
" tcc [options...] -run infile (or --) [arguments...]\n"
|
|
||||||
"General options:\n"
|
"General options:\n"
|
||||||
" -c compile only - generate an object file\n"
|
" -c compile only - generate an object file\n"
|
||||||
" -o outfile set output filename\n"
|
" -o outfile set output filename\n"
|
||||||
" -run run compiled source\n"
|
|
||||||
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
" -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
|
||||||
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
" -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
|
||||||
" -w disable all warnings\n"
|
" -w disable all warnings\n"
|
||||||
|
@ -48,9 +50,6 @@ static const char HELP_STR[] =
|
||||||
" -Ldir add library path 'dir'\n"
|
" -Ldir add library path 'dir'\n"
|
||||||
" -llib link with dynamic or static library 'lib'\n"
|
" -llib link with dynamic or static library 'lib'\n"
|
||||||
" -r generate (relocatable) object file\n"
|
" -r generate (relocatable) object file\n"
|
||||||
" -shared generate a shared library/dll\n"
|
|
||||||
" -rdynamic export all global symbols to dynamic linker\n"
|
|
||||||
" -soname set name for shared library to be used at runtime\n"
|
|
||||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||||
"Misc. options:\n"
|
"Misc. options:\n"
|
||||||
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
|
" -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
|
||||||
|
@ -65,7 +64,7 @@ static const char HELP_STR[] =
|
||||||
" create library : tcc -ar [crstvx] lib [files]\n"
|
" create library : tcc -ar [crstvx] lib [files]\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char HELP_MORE_STR[] =
|
static const char help_more_str[] =
|
||||||
"Tiny C Compiler "PACKAGE_VERSION" - More Options\n"
|
"Tiny C Compiler "PACKAGE_VERSION" - More Options\n"
|
||||||
"Special options:\n"
|
"Special options:\n"
|
||||||
" -P -P1 with -E: no/alternative #line output\n"
|
" -P -P1 with -E: no/alternative #line output\n"
|
||||||
|
@ -75,11 +74,10 @@ static const char HELP_MORE_STR[] =
|
||||||
" -Wp,-opt same as -opt\n"
|
" -Wp,-opt same as -opt\n"
|
||||||
" -include file include 'file' above each input file\n"
|
" -include file include 'file' above each input file\n"
|
||||||
" -isystem dir add 'dir' to system include path\n"
|
" -isystem dir add 'dir' to system include path\n"
|
||||||
" -static link to static libraries (not recommended)\n"
|
|
||||||
" -dumpversion print version\n"
|
" -dumpversion print version\n"
|
||||||
" -print-search-dirs print search paths\n"
|
" -print-search-dirs print search paths\n"
|
||||||
"Ignored options:\n"
|
"Ignored options:\n"
|
||||||
" -arch -C --param -pedantic -pipe -s -traditional\n"
|
" -arch -C --param -pedantic -pipe -s -traditional -g -static -shared -soname\n"
|
||||||
"-W[no-]... warnings:\n"
|
"-W[no-]... warnings:\n"
|
||||||
" all turn on some (*) warnings\n"
|
" all turn on some (*) warnings\n"
|
||||||
" error[=warning] stop after warning (any or specified)\n"
|
" error[=warning] stop after warning (any or specified)\n"
|
||||||
|
@ -102,14 +100,9 @@ static const char HELP_MORE_STR[] =
|
||||||
"-Wl,... linker options:\n"
|
"-Wl,... linker options:\n"
|
||||||
" -nostdlib do not link with standard crt/libs\n"
|
" -nostdlib do not link with standard crt/libs\n"
|
||||||
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
||||||
" -export-all-symbols same as -rdynamic\n"
|
|
||||||
" -export-dynamic same as -rdynamic\n"
|
|
||||||
" -image-base= -Ttext= set base address of executable\n"
|
" -image-base= -Ttext= set base address of executable\n"
|
||||||
" -section-alignment= set section alignment in executable\n"
|
" -section-alignment= set section alignment in executable\n"
|
||||||
" -rpath= set dynamic library search path\n"
|
|
||||||
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
||||||
" -soname= set DT_SONAME elf tag\n"
|
|
||||||
" -Bsymbolic set DT_SYMBOLIC elf tag\n"
|
|
||||||
" -oformat=[coff,binary] set executable output format\n"
|
" -oformat=[coff,binary] set executable output format\n"
|
||||||
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
||||||
"Predefined macros:\n"
|
"Predefined macros:\n"
|
||||||
|
@ -117,10 +110,11 @@ static const char HELP_MORE_STR[] =
|
||||||
"See also the manual for more details.\n"
|
"See also the manual for more details.\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static const char VERSION_STR[] =
|
static const char version_str[] =
|
||||||
"tcc version "PACKAGE_VERSION" (i386)\n";
|
"tcc version "PACKAGE_VERSION" (i386)\n";
|
||||||
|
|
||||||
static void print_dirs(const char *msg, char **paths, int nb_paths)
|
static void
|
||||||
|
print_dirs(const char *msg, char **paths, int nb_paths)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
|
||||||
|
@ -128,17 +122,18 @@ static void print_dirs(const char *msg, char **paths, int nb_paths)
|
||||||
printf(" %s\n", paths[i]);
|
printf(" %s\n", paths[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_search_dirs(TCCState *s)
|
static void
|
||||||
|
print_search_dirs(TCCState *s)
|
||||||
{
|
{
|
||||||
printf("install: %s\n", s->tcc_lib_path);
|
printf("install: %s\n", s->tcc_lib_path);
|
||||||
/* print_dirs("programs", NULL, 0); */
|
|
||||||
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
|
||||||
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
print_dirs("libraries", s->library_paths, s->nb_library_paths);
|
||||||
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
|
printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
|
||||||
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_environment(TCCState *s)
|
static void
|
||||||
|
set_environment(TCCState *s)
|
||||||
{
|
{
|
||||||
char * path;
|
char * path;
|
||||||
|
|
||||||
|
@ -156,7 +151,8 @@ static void set_environment(TCCState *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *default_outputfile(TCCState *s, const char *first_file)
|
static char
|
||||||
|
*default_outputfile(TCCState *s, const char *first_file)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *ext;
|
char *ext;
|
||||||
|
@ -173,7 +169,8 @@ static char *default_outputfile(TCCState *s, const char *first_file)
|
||||||
return tcc_strdup(buf);
|
return tcc_strdup(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned getclock_ms(void)
|
static unsigned
|
||||||
|
getclock_ms(void)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return GetTickCount();
|
return GetTickCount();
|
||||||
|
@ -184,10 +181,11 @@ static unsigned getclock_ms(void)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc0, char **argv0)
|
int
|
||||||
|
main(int argc0, char **argv0)
|
||||||
{
|
{
|
||||||
TCCState *s, *s1;
|
TCCState *s, *s1;
|
||||||
int ret, opt, n = 0, t = 0, done;
|
int ret, opt, n = 0, done;
|
||||||
unsigned start_time = 0, end_time = 0;
|
unsigned start_time = 0, end_time = 0;
|
||||||
const char *first_file;
|
const char *first_file;
|
||||||
int argc; char **argv;
|
int argc; char **argv;
|
||||||
|
@ -196,36 +194,41 @@ int main(int argc0, char **argv0)
|
||||||
redo:
|
redo:
|
||||||
argc = argc0, argv = argv0;
|
argc = argc0, argv = argv0;
|
||||||
s = s1 = tcc_new();
|
s = s1 = tcc_new();
|
||||||
|
|
||||||
#ifdef CONFIG_TCC_SWITCHES /* predefined options */
|
#ifdef CONFIG_TCC_SWITCHES /* predefined options */
|
||||||
tcc_set_options(s, CONFIG_TCC_SWITCHES);
|
tcc_set_options(s, CONFIG_TCC_SWITCHES);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
opt = tcc_parse_args(s, &argc, &argv, 1);
|
opt = tcc_parse_args(s, &argc, &argv, 1);
|
||||||
if (opt < 0)
|
if (opt < 0)
|
||||||
return 1;
|
return (EXIT_FAILURE);
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0)
|
||||||
if (opt == OPT_HELP) {
|
{
|
||||||
fputs(HELP_STR, stdout);
|
if (opt == TCC_OPT_HELP)
|
||||||
|
{
|
||||||
|
fputs(help_str, stdout);
|
||||||
if (!s->verbose)
|
if (!s->verbose)
|
||||||
return 0;
|
return (EXIT_SUCCESS);
|
||||||
++opt;
|
++opt;
|
||||||
}
|
}
|
||||||
if (opt == OPT_HELP2) {
|
if (opt == TCC_OPT_HELP_MORE)
|
||||||
fputs(HELP_MORE_STR, stdout);
|
{
|
||||||
return 0;
|
fputs(help_more_str, stdout);
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
if (s->verbose)
|
if (s->verbose)
|
||||||
printf("%s", VERSION_STR);
|
printf("%s", version_str);
|
||||||
if (opt == OPT_AR)
|
if (opt == TCC_OPT_ARCHIVE)
|
||||||
return tcc_tool_ar(s, argc, argv);
|
return tcc_tool_ar(s, argc, argv);
|
||||||
if (opt == OPT_V)
|
if (opt == TCC_OPT_VERSION)
|
||||||
return 0;
|
return 0;
|
||||||
if (opt == OPT_PRINT_DIRS) {
|
if (opt == TCC_OPT_PRINT_DIRS) {
|
||||||
/* initialize search dirs */
|
/* initialize search dirs */
|
||||||
set_environment(s);
|
set_environment(s);
|
||||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||||
print_search_dirs(s);
|
print_search_dirs(s);
|
||||||
return 0;
|
return (EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->nb_files == 0) {
|
if (s->nb_files == 0) {
|
||||||
|
@ -290,9 +293,7 @@ redo:
|
||||||
}
|
}
|
||||||
|
|
||||||
done = 1;
|
done = 1;
|
||||||
if (t)
|
if (ret) {
|
||||||
done = 0; /* run more tests with -dt -run */
|
|
||||||
else if (ret) {
|
|
||||||
if (s->nb_errors)
|
if (s->nb_errors)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
/* else keep the original exit code from tcc_run() */
|
/* else keep the original exit code from tcc_run() */
|
||||||
|
|
|
@ -30,18 +30,7 @@
|
||||||
|
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
//#define ARMAG "!<arch>\n"
|
#include <tcc/object/archive.h>
|
||||||
#define ARFMAG "`\n"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char ar_name[16];
|
|
||||||
char ar_date[12];
|
|
||||||
char ar_uid[6];
|
|
||||||
char ar_gid[6];
|
|
||||||
char ar_mode[8];
|
|
||||||
char ar_size[10];
|
|
||||||
char ar_fmag[2];
|
|
||||||
} ArHdr;
|
|
||||||
|
|
||||||
static unsigned long le2belong(unsigned long ul) {
|
static unsigned long le2belong(unsigned long ul) {
|
||||||
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
|
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
|
||||||
|
@ -56,18 +45,18 @@ static int ar_usage(int ret) {
|
||||||
|
|
||||||
int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
int tcc_tool_ar(TCCState *s1, int argc, char **argv)
|
||||||
{
|
{
|
||||||
static const ArHdr arhdr_init = {
|
static const ArchiveFileHeader arhdr_init = {
|
||||||
"/ ",
|
"/ ",
|
||||||
"0 ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
"0 ",
|
"0 ",
|
||||||
ARFMAG
|
ARCHIVE_FILMAG
|
||||||
};
|
};
|
||||||
|
|
||||||
ArHdr arhdr = arhdr_init;
|
ArchiveFileHeader arhdr = arhdr_init;
|
||||||
ArHdr arhdro = arhdr_init;
|
ArchiveFileHeader arhdro = arhdr_init;
|
||||||
|
|
||||||
FILE *fi, *fh = NULL, *fo = NULL;
|
FILE *fi, *fh = NULL, *fo = NULL;
|
||||||
const char *created_file = NULL; // must delete on error
|
const char *created_file = NULL; // must delete on error
|
||||||
|
@ -133,27 +122,27 @@ no_ar:
|
||||||
while (fread(&arhdr, 1, sizeof(arhdr), fh) == sizeof(arhdr)) {
|
while (fread(&arhdr, 1, sizeof(arhdr), fh) == sizeof(arhdr)) {
|
||||||
char *p, *e;
|
char *p, *e;
|
||||||
|
|
||||||
if (memcmp(arhdr.ar_fmag, ARFMAG, 2))
|
if (memcmp(arhdr.fmag, ARFMAG, 2))
|
||||||
goto no_ar;
|
goto no_ar;
|
||||||
p = arhdr.ar_name;
|
p = arhdr.name;
|
||||||
for (e = p + sizeof arhdr.ar_name; e > p && e[-1] == ' ';)
|
for (e = p + sizeof arhdr.name; e > p && e[-1] == ' ';)
|
||||||
e--;
|
e--;
|
||||||
*e = '\0';
|
*e = '\0';
|
||||||
arhdr.ar_size[sizeof arhdr.ar_size-1] = 0;
|
arhdr.size[sizeof arhdr.size-1] = 0;
|
||||||
fsize = atoi(arhdr.ar_size);
|
fsize = atoi(arhdr.size);
|
||||||
buf = tcc_malloc(fsize + 1);
|
buf = tcc_malloc(fsize + 1);
|
||||||
fread(buf, fsize, 1, fh);
|
fread(buf, fsize, 1, fh);
|
||||||
if (strcmp(arhdr.ar_name,"/") && strcmp(arhdr.ar_name,"/SYM64/")) {
|
if (strcmp(arhdr.name,"/") && strcmp(arhdr.name,"/SYM64/")) {
|
||||||
if (e > p && e[-1] == '/')
|
if (e > p && e[-1] == '/')
|
||||||
e[-1] = '\0';
|
e[-1] = '\0';
|
||||||
/* tv not implemented */
|
/* tv not implemented */
|
||||||
if (table || verbose)
|
if (table || verbose)
|
||||||
printf("%s%s\n", extract ? "x - " : "", arhdr.ar_name);
|
printf("%s%s\n", extract ? "x - " : "", arhdr.name);
|
||||||
if (extract) {
|
if (extract) {
|
||||||
if ((fo = fopen(arhdr.ar_name, "wb")) == NULL)
|
if ((fo = fopen(arhdr.name, "wb")) == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "tcc: ar: can't create file %s\n",
|
fprintf(stderr, "tcc: ar: can't create file %s\n",
|
||||||
arhdr.ar_name);
|
arhdr.name);
|
||||||
tcc_free(buf);
|
tcc_free(buf);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +178,7 @@ finish:
|
||||||
|
|
||||||
funcmax = 250;
|
funcmax = 250;
|
||||||
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
||||||
memcpy(&arhdro.ar_mode, "100644", 6);
|
memcpy(&arhdro.mode, "100644", 6);
|
||||||
|
|
||||||
// i_obj = first input object file
|
// i_obj = first input object file
|
||||||
while (i_obj < argc)
|
while (i_obj < argc)
|
||||||
|
@ -277,13 +266,13 @@ finish:
|
||||||
name > file && name[-1] != '/' && name[-1] != '\\';
|
name > file && name[-1] != '/' && name[-1] != '\\';
|
||||||
--name);
|
--name);
|
||||||
istrlen = strlen(name);
|
istrlen = strlen(name);
|
||||||
if (istrlen >= sizeof(arhdro.ar_name))
|
if (istrlen >= sizeof(arhdro.name))
|
||||||
istrlen = sizeof(arhdro.ar_name) - 1;
|
istrlen = sizeof(arhdro.name) - 1;
|
||||||
memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
|
memset(arhdro.name, ' ', sizeof(arhdro.name));
|
||||||
memcpy(arhdro.ar_name, name, istrlen);
|
memcpy(arhdro.name, name, istrlen);
|
||||||
arhdro.ar_name[istrlen] = '/';
|
arhdro.name[istrlen] = '/';
|
||||||
sprintf(stmp, "%-10d", fsize);
|
sprintf(stmp, "%-10d", fsize);
|
||||||
memcpy(&arhdro.ar_size, stmp, 10);
|
memcpy(&arhdro.size, stmp, 10);
|
||||||
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
||||||
fwrite(buf, fsize, 1, fo);
|
fwrite(buf, fsize, 1, fo);
|
||||||
tcc_free(buf);
|
tcc_free(buf);
|
||||||
|
@ -304,7 +293,7 @@ finish:
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)) + fpos);
|
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)) + fpos);
|
||||||
memcpy(&arhdr.ar_size, stmp, 10);
|
memcpy(&arhdr.size, stmp, 10);
|
||||||
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
||||||
afpos[0] = le2belong(funccnt);
|
afpos[0] = le2belong(funccnt);
|
||||||
for (i=1; i<=funccnt; i++)
|
for (i=1; i<=funccnt; i++)
|
||||||
|
|
Loading…
Reference in a new issue