summaryrefslogtreecommitdiff
path: root/cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'cc.c')
-rw-r--r--cc.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/cc.c b/cc.c
new file mode 100644
index 0000000..71e179b
--- /dev/null
+++ b/cc.c
@@ -0,0 +1,157 @@
+#define _XOPEN_SOURCE 700
+#include <errno.h>
+#include <libgen.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "cc.h"
+#include "cpp.h"
+#include "link.h"
+#include "version.h"
+
+void error(const char *file, uintmax_t line, const char *fmt, ...)
+{
+ if (file) {
+ fprintf(stderr, "%s:%ju: ", file, line);
+ } else if (line == 0) {
+ fprintf(stderr, "<BUILTIN>: ");
+ } else {
+ fprintf(stderr, "<COMMAND LINE>: ");
+ }
+
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+static struct macro *do_predefs(const char *argv0)
+{
+ long int version = LATEST;
+ char *fullname = strdup(argv0);
+ char *progname = basename(fullname);
+
+ struct macro *defs = define(NULL, NULL, 0, "__STDC__", "1");
+
+ if (!strcmp(progname, "c18")) {
+ version = C18;
+ } else if (!strcmp(progname, "c11")) {
+ /* warn */
+ version = C11;
+ } else if (!strcmp(progname, "c99")) {
+ version = C99;
+ } else if (!strcmp(progname, "c89")) {
+ version = C95;
+ }
+
+ if (version >= C95) {
+ char ppversion[8] = "";
+ sprintf(ppversion, "%ldL", version);
+ define(defs, NULL, 0, "__STDC_VERSION__", ppversion);
+ }
+
+ if (version >= C99) {
+ define(defs, NULL, 0, "__STDC_HOSTED__", "1");
+ define(defs, NULL, 0, "__STDC_IEC_559__", "1");
+ define(defs, NULL, 0, "__STDC_IEC_559_COMPLEX__", "1");
+ define(defs, NULL, 0, "__STDC_ISO_10646__", ISO_10646_VERSION);
+ }
+
+ if (version >= C11) {
+ define(defs, NULL, 0, "__STDC_UTF_16__", "1");
+ define(defs, NULL, 0, "__STDC_UTF_32__", "1");
+ define(defs, NULL, 0, "__STDC_ANALYZABLE__", "1");
+ define(defs, NULL, 0, "__STDC_LIB_EXT1__", "1");
+ /* __STDC_NO_ATOMICS__ */
+ /* __STDC_NO_COMPLEX__ */
+ /* __STDC_NO_THREADS__ */
+ /* __STDC_NO_VLA__ */
+ }
+
+ return defs;
+}
+
+static int getoptarg(char *argv[], int i, char **arg)
+{
+ if (argv[i][2] != '\0') {
+ *arg = argv[i] + 2;
+ return 0;
+ }
+ *arg = argv[i + 1];
+ return 1;
+}
+
+int main(int argc, char *argv[])
+{
+ enum { PREPROCESSED, ASSEMBLY, OBJECT, BINARY } output = BINARY;
+ char *progname = basename(argv[0]);
+ char *output_path = "a.out";
+
+ struct macro *predef = do_predefs(argv[0]);
+
+ for (int i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-c")) {
+ output = OBJECT;
+
+ } else if (!strcmp(argv[i], "-g")) {
+ /* include debugging symbols */
+
+ } else if (!strcmp(argv[i], "-s")) {
+ /* strip */
+
+ } else if (!strcmp(argv[i], "-E")) {
+ output = PREPROCESSED;
+
+ } else if (!strncmp(argv[i], "-o", 2)) {
+ i += getoptarg(argv, i, &output_path);
+
+ } else if (!strncmp(argv[i], "-D", 2)) {
+ char *macro = NULL;
+ i += getoptarg(argv, i, &macro);
+ char *eq = strchr(macro, '=');
+ if (eq) {
+ *eq = '\0';
+ eq++;
+ }
+ define(predef, NULL, 1, macro, eq ? eq : "1");
+
+ } else if (!strncmp(argv[i], "-I", 2)) {
+ char *path = NULL;
+ i += getoptarg(argv, i, &path);
+ //include(path);
+
+ } else if (!strncmp(argv[i], "-L", 2)) {
+ char *path = NULL;
+ i += getoptarg(argv, i, &path);
+ //libpath(path);
+
+ } else if (!strncmp(argv[i], "-O", 2)) {
+ /* optimize */
+
+ } else if (!strncmp(argv[i], "-U", 2)) {
+ char *macro = NULL;
+ i += getoptarg(argv, i, &macro);
+ //undef(macro);
+
+ } else if (!strncmp(argv[i], "-l", 2)) {
+ char *lib = NULL;
+ i += getoptarg(argv, i, &lib);
+ //addobj(lib);
+
+ } else if (argv[i][0] == '-') {
+ fprintf(stderr, "%s: unknown option %s\n", progname, argv[i]);
+ /* invalid option */
+ } else {
+ switch (output) {
+ case PREPROCESSED:
+ preprocess(argv[i], output_path, predef);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}