Logo Search packages:      
Sourcecode: faucc version File versions

faucc.c

/* $Id: faucc.c,v 1.35 2009-01-27 15:40:22 potyra Exp $ 
 *
 * Copyright (C) 2008-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include "config.h"

#define _GNU_SOURCE
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

const char *progname;
const char *opt_B = FAUCCDIR;
int opt_E;
int opt_S;
int opt_c;
int opt_o;
const char *opt_o_arg;
const char *input[256];
unsigned int ninputs;
const char *output[256];
unsigned int noutputs;

const char *cpp_param[256];
unsigned int ncpp_params;
const char *cc1_param[256];
unsigned int ncc1_params;
const char *as_param[256];
unsigned int nas_params;
const char *ld_param[256];
unsigned int nld_params;

/*
 * Possible race condition!!! FIXME
 */
static void
tmpname(char *buf, const char *suffix)
{
      struct stat st;
      unsigned int i;
      int ret;

      for (i = 0; ; i++) {
            sprintf(buf, "/tmp/faucc.%u.%u.%s",
                        (unsigned int) getpid(), i, suffix);
            ret = lstat(buf, &st);
            if (ret < 0
             && errno == ENOENT) {
                  break;
            }
      }
}

static void
debug(const char *file, const char **param)
{
#if 0
      fprintf(stderr, "%s", file);
      while (*param) {
            fprintf(stderr, " %s", *param++);
      }
      fprintf(stderr, "\n");
#endif
}

static void
exit_status(const char *prog, int status)
{
      if (WIFEXITED(status)) {
            if (WEXITSTATUS(status) != 0) {
                  fprintf(stderr, "%s: %s: exit status %u.\n",
                              progname, prog, WEXITSTATUS(status));
            }
      } else if (WIFSIGNALED(status)) {
            fprintf(stderr, "%s: %s: %s", progname, prog,
                        strsignal(WTERMSIG(status)));
            if (WCOREDUMP(status)) {
                  fprintf(stderr, " (core dumped)");
            }
            fprintf(stderr, "\n");
      }
}

static int
cpp(const char *in, const char *out)
{
      int pid;
      int status;
      int ret;

      cpp_param[ncpp_params++] = in;
      cpp_param[ncpp_params] = NULL;

      switch (pid = fork()) {
      case -1:
            assert(0);

      case 0:
            if (strcmp(out, "") != 0) {
                  ret = close(1);
                  assert(0 <= ret);

                  ret = open(out, O_CREAT | O_TRUNC | O_WRONLY, 0666);
                  assert(0 <= ret);
                  assert(ret == 1);
            }

            debug("cpp", cpp_param);
            execvp("cpp", cpp_param);
            assert(0);

      default:
            ret = wait(&status);
            assert(0 <= ret);
            exit_status("cpp", status);
            break;
      }

      return 0;
}

static int
cc1(const char *in, const char *out)
{
      int pid;
      char path[1024];
      int status;
      int ret;

      cc1_param[ncc1_params] = NULL;

      switch (pid = fork()) {
      case -1:
            assert(0);

      case 0:
            ret = close(0);
            assert(0 <= ret);

            ret = open(in, O_RDONLY);
            assert(0 <= ret);
            assert(ret == 0);

            ret = close(1);
            assert(0 <= ret);

            ret = open(out, O_CREAT | O_TRUNC | O_WRONLY, 0666);
            assert(0 <= ret);
            assert(ret == 1);

            strcpy(path, opt_B);
            strcat(path, "/cc1");
            debug(path, cc1_param);
            execvp(path, cc1_param);
            assert(0);

      default:
            ret = wait(&status);
            assert(0 <= ret);
            exit_status("cc1", status);
            break;
      }
      
      return 0;
}

static int
as(const char *in, const char *out)
{
      int pid;
      int status;
      int ret;

      as_param[nas_params++] = "-c";
      as_param[nas_params++] = "-o";
      as_param[nas_params++] = out;
      as_param[nas_params++] = in;
      as_param[nas_params] = NULL;

      switch (pid = fork()) {
      case -1:
            assert(0);

      case 0:
            ret = close(0);
            assert(0 <= ret);

            ret = open(in, O_RDONLY);
            assert(0 <= ret);
            assert(ret == 0);

            ret = close(1);
            assert(0 <= ret);

            ret = open(out, O_CREAT | O_TRUNC | O_WRONLY, 0666);
            assert(0 <= ret);
            assert(ret == 1);

            debug("gcc", as_param);
            execvp("gcc", as_param);
            assert(0);

      default:
            ret = wait(&status);
            assert(0 <= ret);
            exit_status("as", status);
            break;
      }
      
      return 0;
}

static int
ld(void)
{
      int pid;
      int status;
      int ret;

      ld_param[nld_params] = NULL;

      switch (pid = fork()) {
      case -1:
            assert(0);

      case 0:
            debug("ld", ld_param);
            execvp("gcc", ld_param);
            assert(0);

      default:
            ret = wait(&status);
            assert(0 <= ret);
            exit_status("ld", status);
            break;
      }
      
      return 0;
}

static int
rm(const char *file)
{
      int ret;

      ret = unlink(file);
      assert(0 <= ret);

      return 0;
}

static __attribute__((__noreturn__)) void
usage(int retval)
{
      fprintf(stderr, "Usage: %s [-D macro[=def]] [-E] [-I dir] [-O level] [-U macro] [-S] [-c] -b arch [-o output] [-print-libfaucc-file-name] file...\n", progname);
      exit(retval);
}

int
main(int argc, char **argv)
{
      unsigned int i;

#if 0
      for (i = 0; i < argc; i++) {
            fprintf(stderr, "%u: '%s'\n", i, argv[i]);
      }
#endif

      progname = *argv;

      ncpp_params = 0;
      cpp_param[ncpp_params++] = "cpp";
      ncc1_params = 0;
      cc1_param[ncc1_params++] = "cc1";
      nas_params = 0;
      as_param[nas_params++] = "as";
      as_param[nas_params++] = "-m32";
      nld_params = 0;
      ld_param[nld_params++] = "gcc";
      ld_param[nld_params++] = "-m32";

      for (i = 1; i < argc; i++) {
            if (strcmp(argv[i], "-B") == 0) {
                  opt_B = argv[++i];
            } else if (strncmp(argv[i], "-B", 2) == 0) {
                  opt_B = &argv[i][2];

            } else if (strcmp(argv[i], "-D") == 0) {
                  cpp_param[ncpp_params++] = "-D";
                  cpp_param[ncpp_params++] = argv[++i];
            } else if (strncmp(argv[i], "-D", 2) == 0) {
                  cpp_param[ncpp_params++] = "-D";
                  cpp_param[ncpp_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-E") == 0) {
                  opt_E = 1;

            } else if (strcmp(argv[i], "-I") == 0) {
                  cpp_param[ncpp_params++] = "-I";
                  cpp_param[ncpp_params++] = argv[++i];
            } else if (strncmp(argv[i], "-I", 2) == 0) {
                  cpp_param[ncpp_params++] = "-I";
                  cpp_param[ncpp_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-L") == 0) {
                  ld_param[nld_params++] = "-L";
                  ld_param[nld_params++] = argv[++i];
            } else if (strncmp(argv[i], "-L", 2) == 0) {
                  ld_param[nld_params++] = "-L";
                  ld_param[nld_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-MD") == 0) {
                  cpp_param[ncpp_params++] = "-MD";

            } else if (strcmp(argv[i], "-MF") == 0) {
                  cpp_param[ncpp_params++] = "-MF";
                  cpp_param[ncpp_params++] = argv[++i];
            } else if (strncmp(argv[i], "-MF", 3) == 0) {
                  cpp_param[ncpp_params++] = "-MF";
                  cpp_param[ncpp_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-MP") == 0) {
                  cpp_param[ncpp_params++] = "-MP";

            } else if (strcmp(argv[i], "-MT") == 0) {
                  cpp_param[ncpp_params++] = "-MT";
                  cpp_param[ncpp_params++] = argv[++i];
            } else if (strncmp(argv[i], "-MT", 3) == 0) {
                  cpp_param[ncpp_params++] = "-MT";
                  cpp_param[ncpp_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-O") == 0) {
                  cc1_param[ncc1_params++] = "-O";
                  cc1_param[ncc1_params++] = argv[++i];
            } else if (strncmp(argv[i], "-O", 2) == 0) {
                  cc1_param[ncc1_params++] = "-O";
                  cc1_param[ncc1_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-S") == 0) {
                  opt_S = 1;

            } else if (strcmp(argv[i], "-T") == 0) {
                  ld_param[nld_params++] = "-T";
                  ld_param[nld_params++] = argv[++i];

            } else if (strcmp(argv[i], "-U") == 0) {
                  cpp_param[ncpp_params++] = "-U";
                  cpp_param[ncpp_params++] = argv[++i];
            } else if (strncmp(argv[i], "-U", 2) == 0) {
                  cpp_param[ncpp_params++] = "-U";
                  cpp_param[ncpp_params++] = &argv[i][2];

            } else if (strncmp(argv[i], "-Wl,", 4) == 0) {
                  ld_param[nld_params++] = &argv[i][4];

            } else if (strcmp(argv[i], "-Xlinker") == 0) {
                  ld_param[nld_params++] = "-Xlinker";
                  ld_param[nld_params++] = argv[++i];

            } else if (strcmp(argv[i], "-b") == 0) {
                  cc1_param[ncc1_params++] = "-b";
                  cc1_param[ncc1_params++] = argv[++i];
            } else if (strncmp(argv[i], "-b", 2) == 0) {
                  cc1_param[ncc1_params++] = "-b";
                  cc1_param[ncc1_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-c") == 0) {
                  opt_c = 1;

            } else if (strcmp(argv[i], "-f") == 0) {
                  cc1_param[ncc1_params++] = "-f";
                  cc1_param[ncc1_params++] = argv[++i];
            } else if (strncmp(argv[i], "-f", 2) == 0) {
                  cc1_param[ncc1_params++] = "-f";
                  cc1_param[ncc1_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-m") == 0) {
                  cc1_param[ncc1_params++] = "-m";
                  cc1_param[ncc1_params++] = argv[++i];
            } else if (strncmp(argv[i], "-m", 2) == 0) {
                  cc1_param[ncc1_params++] = "-m";
                  cc1_param[ncc1_params++] = &argv[i][2];

            } else if (strcmp(argv[i], "-nostdlib") == 0) {
                  ld_param[nld_params++] = "-nostdlib";

            } else if (strcmp(argv[i], "-o") == 0) {
                  opt_o = 1;
                  opt_o_arg = argv[++i];
                  ld_param[nld_params++] = "-o";
                  ld_param[nld_params++] = opt_o_arg;
            } else if (strncmp(argv[i], "-o", 2) == 0) {
                  opt_o = 1;
                  opt_o_arg = &argv[i][2];
                  ld_param[nld_params++] = "-o";
                  ld_param[nld_params++] = opt_o_arg;

            } else if (strcmp(argv[i], "-print-libfaucc-file-name") == 0) {
                  printf("%s/libfaucc.a\n", opt_B);
                  exit(0);

            } else if (strcmp(argv[i], "-static") == 0) {
                  ld_param[nld_params++] = "-static";

            } else if (strcmp(argv[i], "--freestanding") == 0) {
                  /* FIXME */

            } else if (strcmp(argv[i], "--no-stack-protector") == 0) {
                  /* FIXME */

            } else if (argv[i][0] == '-') {
                  fprintf(stderr, "%s: Unknown option %s.\n",
                              progname, argv[i]);
                  usage(1);

            } else {
                  char file[256];
                  char *suffix;
                  char file_o[256];

                  strcpy(file, argv[i]);
                  if (strrchr(file, '.')) {
                        *strrchr(file, '.') = '\0';
                  }
                  suffix = strrchr(argv[i], '.');
                  assert(suffix);

                  input[ninputs++] = argv[i];
                  if (strcmp(suffix, ".a") == 0
                   || strcmp(suffix, ".o") == 0) {
                        output[noutputs] = argv[i];
                  } else {
                        tmpname(file_o, "o");
                        output[noutputs] = strdup(file_o);
                  }

                  ld_param[nld_params++] = output[noutputs++];
            }
      }

      /*
       * Check options.
       */
      if (1 < opt_E + opt_S + opt_c) {
            fprintf(stderr, "%s: Only one of -E/-S/-c allowed.\n", progname);
            exit(1);
      }
      if (opt_o
       && 1 < ninputs
       && (opt_E
        || opt_S
        || opt_c)) {
            fprintf(stderr, "%s: bad usage of -o.\n", progname);
            exit(1);
      }

      /*
       * Check parameter.
       */
      if (ninputs == 0) {
            fprintf(stderr, "%s: no input files.\n", progname);
            exit(1);
      }

      if (opt_E + opt_S + opt_c == 0) {
            opt_o = 0; /* -o part of ld_param. */
      }

      for (i = 0; i < ninputs; i++) {
            char file[256];
            const char *suffix;
            char file_c[256];
            char file_i[256];
            char file_S[256];
            char file_s[256];
            char file_o[256];

            strcpy(file, input[i]);
            if (strrchr(file, '.')) {
                  *strrchr(file, '.') = '\0';
            }
            suffix = strrchr(input[i], '.');
            assert(suffix);

            if (strcmp(suffix, ".c") == 0) {
                  if (opt_E) {
                        sprintf(file_c, "%s.c", file);
                        if (opt_o) {
                              sprintf(file_i, "%s", opt_o_arg);
                        } else {
                              strcpy(file_i, "");
                        }

                        cpp(file_c, file_i);

                  } else if (opt_S) {
                        sprintf(file_c, "%s.c", file);
                        tmpname(file_i, "i");
                        if (opt_o) {
                              sprintf(file_s, "%s", opt_o_arg);
                        } else {
                              sprintf(file_s, "%s.s", file);
                        }

                        cpp(file_c, file_i);
                        cc1(file_i, file_s);

                        rm(file_i);

                  } else {
                        sprintf(file_c, "%s.c", file);
                        tmpname(file_i, "i");
                        tmpname(file_s, "s");
                        if (opt_o) {
                              sprintf(file_o, "%s", opt_o_arg);
                        } else {
                              strcpy(file_o, output[i]);
                        }

                        cpp(file_c, file_i);
                        cc1(file_i, file_s);
                        as(file_s, file_o);

                        rm(file_i);
                        rm(file_s);
                  }

            } else if (strcmp(suffix, ".i") == 0) {
                  if (opt_E) {
                        /* Nothing to do... */

                  } else if (opt_S) {
                        sprintf(file_i, "%s.i", file);
                        if (opt_o) {
                              sprintf(file_s, "%s", opt_o_arg);
                        } else {
                              sprintf(file_s, "%s.s", file);
                        }

                        cc1(file_i, file_s);

                  } else {
                        sprintf(file_i, "%s.i", file);
                        tmpname(file_s, "s");
                        if (opt_o) {
                              sprintf(file_o, "%s", opt_o_arg);
                        } else {
                              strcpy(file_o, output[i]);
                        }

                        cc1(file_i, file_s);
                        as(file_s, file_o);

                        rm(file_s);
                  }

            } else if (strcmp(suffix, ".S") == 0) {
                  if (opt_E) {
                        sprintf(file_S, "%s.S", file);
                        if (opt_o) {
                              sprintf(file_i, "%s", opt_o_arg);
                        } else {
                              strcpy(file_i, "");
                        }

                        cpp(file_S, file_i);

                  } else if (opt_S) {
                        sprintf(file_S, "%s.S", file);
                        sprintf(file_s, "%s.s", file);
                        if (opt_o) {
                              sprintf(file_s, "%s", opt_o_arg);
                        } else {
                              sprintf(file_s, "%s.s", file);
                        }

                        cpp(file_S, file_s);

                  } else {
                        sprintf(file_S, "%s.S", file);
                        tmpname(file_s, "s");
                        if (opt_o) {
                              sprintf(file_o, "%s", opt_o_arg);
                        } else {
                              strcpy(file_o, output[i]);
                        }

                        cpp(file_S, file_s);
                        as(file_s, file_o);

                        rm(file_s);
                  }

            } else if (strcmp(suffix, ".s") == 0) {
                  if (opt_E) {
                        /* Nothing to do... */

                  } else if (opt_S) {
                        /* Nothing to do... */

                  } else {
                        sprintf(file_s, "%s.s", file);
                        if (opt_o) {
                              sprintf(file_o, "%s", opt_o_arg);
                        } else {
                              strcpy(file_o, output[i]);
                        }

                        as(file_s, file_o);
                  }

            } else if (strcmp(suffix, ".o") == 0
                  || strcmp(suffix, ".a") == 0) {
                  /* Nothing to do... */

            } else {
                  fprintf(stderr, "%s: ERROR: Unknown input %s.\n",
                              progname, input[i]);
                  assert(0); /* FIXME */
            }
      }
      if (opt_E + opt_S + opt_c == 0) {
            /*
             * Do linking.
             */
            ld();
      }

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index