static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout) { int i; while ((i = poll(pp->pfd, pp->max_processes, output_timeout)) < 0) { if (errno == EINTR) continue; pp_cleanup(pp); die_errno("poll"); } /* Buffer output from all pipes. */ for (i = 0; i < pp->max_processes; i++) { if (pp->children[i].state == GIT_CP_WORKING && pp->pfd[i].revents & (POLLIN | POLLHUP)) { int n = strbuf_read_once(&pp->children[i].err, pp->children[i].process.err, 0); if (n == 0) { close(pp->children[i].process.err); pp->children[i].state = GIT_CP_WAIT_CLEANUP; } else if (n < 0) if (errno != EAGAIN) die_errno("read"); } } }
int run_processes_parallel(int n, get_next_task_fn get_next_task, start_failure_fn start_failure, task_finished_fn task_finished, void *pp_cb) { int i, code; int output_timeout = 100; int spawn_cap = 4; struct parallel_processes pp; pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb); while (1) { for (i = 0; i < spawn_cap && !pp.shutdown && pp.nr_processes < pp.max_processes; i++) { code = pp_start_one(&pp); if (!code) continue; if (code < 0) { pp.shutdown = 1; kill_children(&pp, -code); } break; } if (!pp.nr_processes) break; pp_buffer_stderr(&pp, output_timeout); pp_output(&pp); code = pp_collect_finished(&pp); if (code) { pp.shutdown = 1; if (code < 0) kill_children(&pp, -code); } } pp_cleanup(&pp); return 0; }
int main(int argc, char* argv[]) { // Define arguments. struct arg_lit* show_help = arg_lit0("h", "help", "Show this help."); struct arg_str* type_assembler = arg_str0("t", NULL, "<type>", "The type of assembler to output for."); struct arg_file* input_file = arg_file1(NULL, NULL, "<file>", "The input file (or - to read from standard input)."); struct arg_file* output_file = arg_file1("o", "output", "<file>", "The output file (or - to send to standard output)."); // 20 is maxcount for include directories, this has to be set to some constant number. struct arg_file* include_dirs = arg_filen("I", NULL, "<directory>", 0, 20, "Adds the directory <dir> to the directories to be searched for header files."); struct arg_lit* verbose = arg_litn("v", NULL, 0, LEVEL_EVERYTHING - LEVEL_DEFAULT, "Increase verbosity."); struct arg_lit* quiet = arg_litn("q", NULL, 0, LEVEL_DEFAULT - LEVEL_SILENT, "Decrease verbosity."); struct arg_end* end = arg_end(20); void* argtable[] = { output_file, show_help, type_assembler, include_dirs, input_file, verbose, quiet, end }; // Parse arguments. int nerrors = arg_parse(argc, argv, argtable); version_print(bautofree(bfromcstr("Compiler"))); if (nerrors != 0 || show_help->count != 0) { if (nerrors != 0) arg_print_errors(stderr, end, "compiler"); fprintf(stderr, "syntax:\n dtcc"); arg_print_syntax(stderr, argtable, "\n"); fprintf(stderr, "options:\n"); arg_print_glossary(stderr, argtable, " %-25s %s\n"); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } // Set verbosity level. debug_setlevel(LEVEL_DEFAULT + verbose->count - quiet->count); // Set global path variable. osutil_setarg0(bautofree(bfromcstr(argv[0]))); // Run the preprocessor. ppfind_add_path(bautofree(bfromcstr("."))); ppfind_add_path(bautofree(bfromcstr("include"))); ppfind_add_autopath(bautofree(bfromcstr(input_file->filename[0]))); for (int i = 0; i < include_dirs->count; ++i) ppfind_add_path(bautofree(bfromcstr(include_dirs->filename[i]))); bstring pp_result_name = pp_do(bautofree(bfromcstr(input_file->filename[0]))); if (pp_result_name == NULL) { fprintf(stderr, "compiler: invalid result returned from preprocessor.\n"); pp_cleanup(bautofree(pp_result_name)); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } // Parse C. yyout = stderr; yyin = fopen((const char*)(pp_result_name->data), "r"); if (yyin == NULL) { pp_cleanup(bautofree(pp_result_name)); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } yyparse(); if (yyin != stdin) fclose(yyin); pp_cleanup(bautofree(pp_result_name)); if (program == NULL) { std::cerr << "An error occurred while compiling." << std::endl; arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } // Assembler type. const char* asmtype = "toolchain"; if (type_assembler->count > 0) asmtype = type_assembler->sval[0]; // Initially save to a temporary file. std::string temp = std::string(tempnam(".", "cc.")); // Generate assembly using the AST. try { AsmGenerator generator(asmtype); AsmBlock* block = program->compile(generator); std::ofstream output(temp.c_str(), std::ios::out | std::ios::trunc); if (output.bad() || output.fail()) { printd(LEVEL_ERROR, "compiler: temporary file not writable.\n"); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } output << *block << std::endl; output.close(); delete block; } catch (CompilerException* ex) { std::string msg = ex->getMessage(); std::cerr << "An error occurred while compiling." << std::endl; std::cerr << msg << std::endl; arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } // Re-open the temporary file for reading. std::ifstream input(temp.c_str(), std::ios::in); if (input.bad() || input.fail()) { printd(LEVEL_ERROR, "compiler: temporary file not readable.\n"); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } // Open the output file. std::ostream* output; if (strcmp(output_file->filename[0], "-") != 0) { // Write to file. output = new std::ofstream(output_file->filename[0], std::ios::out | std::ios::trunc); if (output->bad() || output->fail()) { printd(LEVEL_ERROR, "compiler: output file not readable.\n"); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } } else { // Set output to cout. output = &std::cout; } // Copy data. std::copy(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(*output)); // Close files and delete temporary. if (strcmp(output_file->filename[0], "-") != 0) { ((std::ofstream*)output)->close(); delete output; } input.close(); unlink(temp.c_str()); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 0; }
int main(int argc, char* argv[]) { // Define arguments. struct arg_lit* show_help = arg_lit0("h", "help", "Show this help."); struct arg_str* type_assembler = arg_str0("t", NULL, "<type>", "The type of assembler to output for."); struct arg_file* input_file = arg_file1(NULL, NULL, "<file>", "The input file (or - to read from standard input)."); struct arg_file* output_file = arg_file1("o", "output", "<file>", "The output file (or - to send to standard output)."); struct arg_end *end = arg_end(20); void *argtable[] = { output_file, show_help, type_assembler, input_file, end }; // Parse arguments. int nerrors = arg_parse(argc,argv,argtable); if (nerrors != 0 || show_help->count != 0) { if (show_help->count != 0) arg_print_errors(stdout, end, "compiler"); fprintf(stderr, "syntax:\n compiler"); arg_print_syntax(stdout, argtable, "\n"); fprintf(stderr, "options:\n"); arg_print_glossary(stdout, argtable, " %-25s %s\n"); return 1; } // Parse C. pp_add_search_path("."); pp_add_search_path("include"); pp_add_search_path(dirname<std::string>(input_file->filename[0]).c_str()); yyout = stderr; yyin = pp_do(input_file->filename[0]); if (yyin == NULL) { pp_cleanup(); return 1; } yyparse(); if (yyin != stdin) fclose(yyin); pp_cleanup(); if (program == NULL) { std::cerr << "An error occurred while compiling." << std::endl; return 1; } // Assembler type. const char* asmtype = "dcpu16toolchain"; if (type_assembler->count > 0) asmtype = type_assembler->sval[0]; // Spacing. std::cerr << std::endl; // Generate assembly using the AST. try { AsmGenerator generator(asmtype); AsmBlock* block = program->compile(generator); if (strcmp(output_file->filename[0], "-") == 0) { std::cout << generator.m_Preassembly << std::endl; std::cout << *block << std::endl; std::cout << generator.m_Postassembly << std::endl; } else { std::ofstream output(output_file->filename[0], std::ios::out | std::ios::trunc); output << generator.m_Preassembly << std::endl; output << *block << std::endl; output << generator.m_Postassembly << std::endl; output.close(); } delete block; } catch (CompilerException* ex) { std::string msg = ex->getMessage(); std::cerr << "An error occurred while compiling." << std::endl; std::cerr << msg << std::endl; return 1; } return 0; }
int main(int argc, char* argv[]) { int nerrors, w; bstring temp = NULL; const char* warnprefix = "no-"; bool expect_failure; // Define arguments. struct arg_lit* show_help = arg_lit0("h", "help", "Show this help."); struct arg_lit* expect_failure_lit = arg_lit0("f", "fail", "Expect failure during preprocessing."); struct arg_str* input_lang = arg_str1(NULL, NULL, "<lang>", "The input language."); struct arg_file* input_file = arg_file1(NULL, NULL, "<file>", "The input preprocessor file."); struct arg_lit* verbose = arg_litn("v", NULL, 0, LEVEL_EVERYTHING - LEVEL_DEFAULT, "Increase verbosity."); struct arg_lit* quiet = arg_litn("q", NULL, 0, LEVEL_DEFAULT - LEVEL_SILENT, "Decrease verbosity."); struct arg_end* end = arg_end(20); void* argtable[] = { show_help, verbose, quiet, expect_failure_lit, input_lang, input_file, end }; // Parse arguments. nerrors = arg_parse(argc, argv, argtable); if (nerrors != 0 || show_help->count != 0) { if (nerrors != 0) arg_print_errors(stdout, end, "libdcpu-pp test suite"); printd(LEVEL_DEFAULT, "syntax:\n dtasm"); arg_print_syntax(stderr, argtable, "\n"); printd(LEVEL_DEFAULT, "options:\n"); arg_print_glossary(stderr, argtable, " %-25s %s\n"); if (show_help->count == 2) { printd(LEVEL_DEFAULT, "defined warnings:\n"); for (w = 0; w < _WARN_COUNT; w++) printd(LEVEL_DEFAULT, " %s\n", dwarnpolicy[w].name); } arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); return 1; } // Set failure expectation variable. expect_failure = (expect_failure_lit->count > 0); // Set verbosity level. debug_setlevel(LEVEL_DEFAULT + verbose->count - quiet->count); // Set global path variable. osutil_setarg0(bautofree(bfromcstr(argv[0]))); // Set up error handling. if (dsethalt()) { // Handle the error. dautohandle(); printd(LEVEL_ERROR, "libdcpu-pp test suite: error occurred.\n"); if (temp != NULL) pp_cleanup(bautofree(temp)); arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); if (expect_failure) return 0; else return 1; } // Perform preprocessing. ppfind_add_autopath(bautofree(bfromcstr(input_file->filename[0]))); temp = pp_do( bautofree(bfromcstr(input_lang->sval[0])), bautofree(bfromcstr(input_file->filename[0])) ); // Perform parsing. test_success = true; yyin = fopen(temp->data, "r"); yyout = NULL; yyparse(); fclose(yyin); // Cleanup. pp_cleanup(bautofree(temp)); if (test_success && expect_failure) return 1; else if (test_success && !expect_failure) return 0; else if (!test_success && expect_failure) return 0; else return 1; }