#include #include "parser.h" #include #include #include #include #include #include #include static char preprocessed_fname[] = "/tmp/cxlppXXXXXX"; static bool preprocessed_fname_created = false; bool preprocess(const char * input_fname) { int fd = mkstemp(preprocessed_fname); if (fd < 0) { perror("mkstemp"); return false; } preprocessed_fname_created = true; pid_t pid = fork(); if (pid < 0) { perror("fork"); return false; } else if (pid == 0) { dup2(fd, STDOUT_FILENO); close(fd); execlp("gcc", "gcc", "-x", "c", "-E", input_fname, NULL); } else { close(fd); waitpid(pid, NULL, 0); } return true; } void write_node(FILE * file, Node * node) { static bool write_space = false; switch (node->type) { case NODE_TYPE_LIST: { for (auto subnode : *node->list) { if (write_space) { fprintf(file, " "); } write_node(file, subnode); } } break; case NODE_TYPE_TOKEN: fprintf(file, "%s", node->token.text->c_str()); if (*node->token.text == ";") { fprintf(file, "\n"); write_space = false; } else { write_space = true; } break; } } bool emit_c(Node * node, const char * output_fname) { FILE * file = fopen(output_fname, "w"); write_node(file, node); fclose(file); return true; } std::string g_output_fname; const char * build_output_fname(const char * input_fname) { g_output_fname = input_fname; size_t pos = g_output_fname.rfind("."); if (pos != std::string::npos) { g_output_fname.replace(pos, g_output_fname.size() - pos, ".c"); } else { g_output_fname += ".c"; } return g_output_fname.c_str(); } int main(int argc, char * argv[]) { int opt; int option_index; const char * output_fname = nullptr; static const struct option long_options[] = { { NULL, 0, NULL, 0 }, }; while ((opt = getopt_long(argc, argv, "o:", long_options, &option_index)) != -1) { switch (opt) { case 'o': output_fname = optarg; break; } } if (optind >= argc) { return -2; } const char * input_fname = argv[optind]; if (output_fname == nullptr) { output_fname = build_output_fname(input_fname); } bool preprocess_successful = preprocess(input_fname); if (preprocess_successful) { Node * node = parse(preprocessed_fname); if (node != nullptr) { emit_c(node, output_fname); } } /* Clean up temporary files. */ if (preprocessed_fname_created) { unlink(preprocessed_fname); } return 0; }