Example #1
0
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");
		}
	}
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
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;
}
Example #5
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;
}