Пример #1
0
int bcopy_01()
{
	BFILE* in;
	BFILE* out;
	int i = 0;

	in = bfopen("test.txt", "rb");
	TEST_EXPECT(in != NULL);
	out = bfopen("copy.txt", "wb");
	TEST_EXPECT(out != NULL);

	while (!bfeof(in))
	{
		bfputc(bfgetc(in), out);
		i++;
	}

	bfclose(in);
	bfclose(out);

	if (i == LENGTH_OF_TEST_FILE)
	{
		TEST_SUCCESS;
	}
	else
	{
		TEST_FAILURE("didn't copy all expected data (total bytes copied incorrect).");
	}
}
void test2(void)
{
    FILE  *in1;
    bfile *in2;
    int    ch;

    in1 = fopen("bitfiles.c", "rb");
    in2 = bfopen("bitfiles.cc", "rb");
    if ((NULL == in1) || (NULL == in2))
    {
        printf("Can't open test files\n");
        exit(1);
    }
    while (!feof(in1) && !feof(in2->file))
    {
        ch = fgetc(in1);
        if (ch < ' ')
            ch = '.';
        printf(" '%c' ", ch);
        for (ch = 0; ch < 8; ch++)
            printf("%c", "01"[bfread(in2)]);
        printf("   ");
    }
    fclose(in1);
    bfclose(in2);

}
void test1(void)
{
    bfile *out;
    bfile *in;
    FILE  *in1;
    FILE  *in2;


    in = bfopen("bitfiles.c", "rb");
    out = bfopen("bitfiles.cc", "wb");
    if ((NULL == in) || (NULL == out))
    {
        printf("Can't open/create test files\n");
        exit(1);
    }
    while (!feof(in->file))
        bfwrite(bfread(in), out);
    bfclose(in);
    bfclose(out);
    in1 = fopen("bitfiles.c", "rb");
    in2 = fopen("bitfiles.cc", "rb");
    if ((NULL == in1) || (NULL == in2))
    {
        printf("Can't open test files for verifying\n");
        exit(1);
    }
    while (!feof(in1) && !feof(in2))
    {
        if (fgetc(in1) != fgetc(in2))
        {
            printf("Files not identical, copy failed!\n");
            exit(1);
        }
    }
    if (!feof(in1) || !feof(in2))
    {
        printf("Not same size, copy failed!\n");
        exit(1);
    }
    fclose(in1);
    fclose(in2);

}
Пример #4
0
int bopen_01()
{
    BFILE* f;

    f = bfopen("nonexistant.blah", "rb");
    TEST_EXPECT(f == NULL);
    f = bfopen("test.txt", "rb");
    TEST_EXPECT(f != NULL);
    bfclose(f);

    TEST_SUCCESS;
}
/* Encodes a block of up to BUF samples.

   The first output is a 32-bit integer showing the size of the
   block. After that follow 3 blocks of that size containing the
   delta-encoding of the timestamp, then the humidity data, and
   the temperature data. Returns the block size or EOF on error.
 */
int handleblock() {
	char buf[64];
	int ret;
	int32_t i;
	
	struct tm tm = (struct tm) {0};
	tm.tm_isdst = -1;

	int32_t diffs[BUF][3];

	time_t oldtime, curtime;
	int32_t hum, humd, temp, tempd;
	int32_t oldhum, curhum, oldtemp, curtemp;

	/* Read up to BUF samples into the diffs[] array */
	if(fgets(buf, 64, stdin) == NULL) {
		return EOF;
	}
	ret = sscanf(buf, "%d-%d-%d_%d:%d:%d %d.%d %d.%d\n",
				&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
				&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
				&hum, &humd,
				&temp, &tempd);
	if(ret != 10) {
		return EOF;
	}

	tm.tm_year -= 1900;
	tm.tm_mon -= 1;

	oldtime = mktime(&tm);
	oldhum = hum * 10 + humd;
	oldtemp = temp * 10 + tempd;

	diffs[0][0] = oldtime;
	diffs[0][1] = oldhum;
	diffs[0][2] = oldtemp;

	for(i = 1; i < BUF; i++) {
		if(fgets(buf, 64, stdin) == NULL) {
			/* End of file, stop */
			break;
		}
		ret = sscanf(buf, "%d-%d-%d_%d:%d:%d %d.%d %d.%d\n",
					&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
					&tm.tm_hour, &tm.tm_min, &tm.tm_sec,
					&hum, &humd,
					&temp, &tempd);
		if(ret != 10) {
			if(ret == 0) {
				/* Maybe an empty line */
				break;
			} else {
				/* Other crap */
				return EOF;
			}
		}

		tm.tm_year -= 1900;
		tm.tm_mon -= 1;

		curtime = mktime(&tm);
		curhum = hum * 10 + humd;
		curtemp = temp * 10 + tempd;

		diffs[i][0] = curtime - oldtime;
		diffs[i][1] = curhum - oldhum;
		diffs[i][2] = curtemp - oldtemp;

		oldtime = curtime;
		oldhum  = curhum;
		oldtemp = curtemp;
	}
	/* Write the block size */
	bfwrite(i, 32, bf);
	/* Pack the timestamps, then the humidity, then the
	   temperature. */
	for(int j = 0; j < 3; j++) {
		for(int k = 0; k < i; k++) {
			if(pack(diffs[k][j]) == EOF) {
				return EOF;
			}
		}
	}
	return i;
}

int main() {
	bf = bfopen(stdout);
	bfwrite(PACKBITS, 8, bf);
	while(handleblock() != EOF);
	bfclose(bf);
	return 0;
}
Пример #6
0
uint16_t aout_write(FILE* out, bool relocatable, bool intermediate)
{
	struct aout_byte* current_outer;
	struct aout_byte* current_inner;
	struct lprov_entry* linker_provided = NULL;
	struct lprov_entry* linker_required = NULL;
	struct lprov_entry* linker_adjustment = NULL;
	struct lprov_entry* linker_section = NULL;
	struct lprov_entry* linker_output = NULL;
	struct lprov_entry* linker_temp = NULL;
	uint32_t mem_index, out_index;
	uint16_t inst;
	BFILE* temp = NULL;
	bstring bname, ename;
	uint16_t eaddr;
	bool did_find;
	bool shown_expr_warning = false;
	bool has_output = false;

	// Initialize out our extension table.
	code_offset += textn_init(start);

	// If relocatable, initialize out our relocation table.
	if (relocatable)
		code_offset += treloc_init(start);

	// First go through and evaluate all expressions that need to be.
	current_outer = start;
	out_index = code_offset;
	while (current_outer != NULL)
	{
		if (current_outer->type == AOUT_TYPE_METADATA_ORIGIN)
		{
			// Adjust memory address.
			out_index = current_outer->opcode;
		}
		else if (current_outer->type == AOUT_TYPE_METADATA_SECTION)
		{
			assert(current_outer->label != NULL);

			// We're exporting the current address as the beginning
			// of a section.
			if (!intermediate)
				ahalt(ERR_NOT_GENERATING_INTERMEDIATE_CODE, NULL);

			// Check to make sure outputs haven't previously been emitted.
			if (has_output)
				ahalt(ERR_OUTPUT_BEFORE_SECTION, NULL);

			// Create linker entry.
			linker_temp = lprov_create(current_outer->label, out_index);
			linker_temp->next = linker_section;
			linker_section = linker_temp;
			printd(LEVEL_VERBOSE, "LINK SECTION %s -> 0x%04X\n", current_outer->label, out_index);
		}
		else if (current_outer->type == AOUT_TYPE_METADATA_OUTPUT)
		{
			assert(current_outer->label != NULL);

			// We're exporting the current address as the beginning
			// of a section.
			if (!intermediate)
				ahalt(ERR_NOT_GENERATING_INTERMEDIATE_CODE, NULL);

			// Create linker entry.
			has_output = true;
			linker_temp = lprov_create(current_outer->label, out_index);
			linker_temp->next = linker_output;
			linker_output = linker_temp;
			printd(LEVEL_VERBOSE, "LINK OUTPUT 0x%04X -> %s\n", out_index, current_outer->label);
		}
		else if (current_outer->type == AOUT_TYPE_METADATA_EXPORT)
		{
			assert(current_outer->label != NULL);

			// We're exporting the address of this label in the
			// object table.
			if (!intermediate)
				ahalt(ERR_NOT_GENERATING_INTERMEDIATE_CODE, NULL);

			// Resolve label position.
			ename = bfromcstr(current_outer->label);
			eaddr = aout_get_label_address(ename);
			bdestroy(ename);

			// Create linker entry.
			linker_temp = lprov_create(current_outer->label, eaddr);
			linker_temp->next = linker_provided;
			linker_provided = linker_temp;
			printd(LEVEL_VERBOSE, "LINK REPLACE %s -> 0x%04X\n", current_outer->label, eaddr);
		}
		else if (current_outer->type == AOUT_TYPE_NORMAL && current_outer->expr != NULL)
		{
			if (current_outer->expr->type != EXPR_LABEL)
			{
				// This is either just a number or a more complicated expression, so
				// evaluate it using the preprocessor expression engine.
				if ((relocatable || intermediate) && !shown_expr_warning)
				{
					printd(LEVEL_WARNING, "warning: expressions will not be adjusted at link or relocation time.\n");
					printd(LEVEL_WARNING, "		ensure labels are not used as part of expressions.\n");
					shown_expr_warning = true;
				}
				current_outer->raw_used = true;
				current_outer->raw = expr_evaluate(current_outer->expr, &aout_get_label_address, &ahalt_expression_exit_handler);
				expr_delete(current_outer->expr);
				current_outer->expr = NULL;
			}
			else
			{
				// If this is just a label, we can handle it directly (this allows
				// us to handle imported labels in intermediate code).
				current_inner = start;
				mem_index = code_offset;
				did_find = false;

				// Search for .IMPORT directives first.
				while (current_inner != NULL)
				{
					if (current_inner->type == AOUT_TYPE_METADATA_ORIGIN)
					{
						// Adjust memory address.
						mem_index = current_inner->opcode;
					}
					else if (current_inner->type == AOUT_TYPE_METADATA_IMPORT)
					{
						// An imported label (we don't need to adjust
						// memory index because the existance of this type
						// of entry doesn't affect executable size).
						if (!intermediate)
							ahalt(ERR_NOT_GENERATING_INTERMEDIATE_CODE, NULL);

						assert(current_outer->expr->data != NULL);
						if (strcmp(current_inner->label, ((bstring)current_outer->expr->data)->data) == 0)
						{
							// We don't actually know our position yet;
							// that will be handled by the linker!
							current_outer->raw = 0xFFFF;
							expr_delete(current_outer->expr);
							current_outer->expr = NULL;
							linker_temp = lprov_create(current_inner->label, out_index);
							linker_temp->next = linker_required;
							linker_required = linker_temp;
							printd(LEVEL_VERBOSE, "LINK REPLACE 0x%04X -> %s\n", out_index, current_inner->label);
							did_find = true;
							break;
						}
					}

					// Goto next.
					current_inner = current_inner->next;
				}

				// If it wasn't found in the .IMPORT directives, try searching
				// labels directly using the expression engine.
				if (!did_find)
				{
					// Replace the label position.
					current_outer->raw_used = true;
					current_outer->raw = expr_evaluate(current_outer->expr, &aout_get_label_address, &ahalt_expression_exit_handler);
					expr_delete(current_outer->expr);
					current_outer->expr = NULL;
					did_find = true;

					// We also need to add this entry to the adjustment
					// table for the linker since it also needs to adjust
					// internal label jumps in files when it concatenates
					// all of the object code together.
					linker_temp = lprov_create(NULL, out_index);
					linker_temp->next = linker_adjustment;
					linker_adjustment = linker_temp;
					printd(LEVEL_VERBOSE, "LINK ADJUST 0x%04X\n", out_index);
				}
			}
		}

		if (current_outer->type == AOUT_TYPE_NORMAL && current_outer->label == NULL)
			out_index += 1;

		current_outer = current_outer->next;
	}

	// If intermediate, we need to write out our linker table
	// as the absolute first thing in the file.
	if (intermediate)
	{
		fwrite(ldata_objfmt, 1, strlen(ldata_objfmt) + 1, out);
		objfile_save(out, linker_provided, linker_required, linker_adjustment, linker_section, linker_output);

		// Adjust the "true origin" for .ORIGIN directivies because
		// the linker table won't exist in the final result when
		// linked.
		true_origin = (uint16_t)ftell(out);
	}

	// Write out our extension table.
	textn_write(out);

	// If relocatable, write out our relocation table.
	if (relocatable)
		treloc_write(out);

	// Now write to the file.
	current_outer = start;

	while (current_outer != NULL)
	{
		if (current_outer->type == AOUT_TYPE_METADATA_ORIGIN)
		{
			// Adjust origin.
			fseek(out, true_origin + current_outer->opcode * 2 /* double because the number is in words, not bytes */, SEEK_SET);
		}
		else if (current_outer->type == AOUT_TYPE_METADATA_INCBIN)
		{
			// Include binary file.
			bname = ppfind_locate(bautofree(bfromcstr(current_outer->label)));

			if (bname == NULL)
				ahalt(ERR_UNABLE_TO_INCBIN, current_outer->label);

			temp = bfopen((const char*)(bname->data), "rb");

			if (temp == NULL)
				ahalt(ERR_UNABLE_TO_INCBIN, current_outer->label);

			// Copy binary data.
			while (!bfeof(temp))
			{
				// TODO: This could be faster if we didn't do it character
				// by character.
				fputc(bfgetc(temp), out);
			}

			// Finalize.
			bfclose(temp);
			bdestroy(bname);
		}
		else if (current_outer->type == AOUT_TYPE_NORMAL)
		{
			// Update the debugging symbol.
			dbgfmt_update_symbol_list(&current_outer->symbols, (uint16_t)((ftell(out) - true_origin) / 2));

			// Normal output.
			if (current_outer->raw_used == true)
			{
				inst = current_outer->raw;
				iwrite(&inst, out);
			}
			else if (current_outer->label == NULL)
			{
				inst = INSTRUCTION_CREATE(current_outer->opcode, current_outer->a, current_outer->b);
				iwrite(&inst, out);
			}
		}

		// Goto next in linked list.
		current_outer = current_outer->next;
	}

	fflush(out);

	return (uint16_t)((ftell(out) - true_origin) / 2);
}
Пример #7
0
int main(int argc, char* argv[])
{
    bstring ldargs = bfromcstr("");
    int i, result;
    unsigned int match = 0, unmatch = 0;
    char ca, ce;
    BFILE* expect;
    BFILE* actual;

    // Define arguments.
    struct arg_lit* show_help = arg_lit0("h", "help", "Show this help.");
    struct arg_lit* gen_relocatable = arg_lit0("r", "relocatable", "Generate relocatable code.");
    struct arg_lit* gen_intermediate = arg_lit0("i", "intermediate", "Generate intermediate code for use with the linker.");
    struct arg_lit* little_endian_mode = arg_lit0(NULL, "little-endian", "Use little endian serialization.");
    struct arg_file* input_file = arg_file1(NULL, NULL, "<file>", "The input assembly file.");
    struct arg_file* expect_file = arg_file0("e", "expect", "<file>", "The output file that contains expected output.");
    struct arg_file* actual_file = arg_file1("a", "actual", "<file>", "The output file where actual output will be placed.");
    struct arg_file* symbols_file = arg_file0("s", "debug-symbols", "<file>", "The debugging symbol output file.");
    struct arg_lit* fail_opt = arg_lit0("f", "fail", "The assembler is expected to fail and the actual output file should not exist on completion.");
    struct arg_file* path = arg_file1("p", NULL, "<path>", "The path to the assembler.");
    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, gen_relocatable, gen_intermediate, little_endian_mode, symbols_file, input_file, expect_file, actual_file, fail_opt, path, verbose, quiet, end };

    // Parse arguments.
    int nerrors = arg_parse(argc, argv, argtable);

    version_print(bautofree(bfromcstr("Assembler Test Driver")));
    if (nerrors != 0 || show_help->count != 0 || (fail_opt->count == 0 && (expect_file->count == 0 || actual_file->count == 0)))
    {
        if (show_help->count != 0 && fail_opt->count == 0 && (expect_file->count == 0 || actual_file->count == 0))
            printd(LEVEL_ERROR, "error: you must provide either -f or -e and -a.\n");
        if (show_help->count != 0)
            arg_print_errors(stderr, end, "testasm");

        printd(LEVEL_DEFAULT, "syntax:\n    testasm");
        arg_print_syntax(stderr, argtable, "\n");
        printd(LEVEL_DEFAULT, "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])));

    // Generate the argument list for the assembler.
    ldargs = bfromcstr(path->filename[0]);
    binsertch(ldargs, 0, 1, '"');
    bconchar(ldargs, '"');
    bconchar(ldargs, ' ');

    // Verbosity options.
    if (verbose->count > 0)
    {
        bconchar(ldargs, '-');
        for (i = 0; i < verbose->count; i++) bconchar(ldargs, 'v');
        bconchar(ldargs, ' ');
    }
    if (quiet->count > 0)
    {
        bconchar(ldargs, '-');
        for (i = 0; i < quiet->count; i++) bconchar(ldargs, 'q');
        bconchar(ldargs, ' ');
    }

    // Literal options.
    if (gen_relocatable->count > 0)
    {
        bconchar(ldargs, '-');
        for (i = 0; i < gen_relocatable->count; i++) bconchar(ldargs, 'r');
        bconchar(ldargs, ' ');
    }
    if (gen_intermediate->count > 0)
    {
        bconchar(ldargs, '-');
        for (i = 0; i < gen_intermediate->count; i++) bconchar(ldargs, 'i');
        bconchar(ldargs, ' ');
    }
    if (little_endian_mode->count > 0)
    {
        for (i = 0; i < little_endian_mode->count; i++)
            bcatcstr(ldargs, "--little-endian ");
    }

    // Unlink the actual file so that if we are expecting
    // failure, we won't return incorrectly.
    unlink(actual_file->filename[0]);

    // Output file.
    bcatcstr(ldargs, "-o \"");
    bcatcstr(ldargs, actual_file->filename[0]);
    bcatcstr(ldargs, "\" ");

    // Input file.
    bcatcstr(ldargs, "\"");
    bcatcstr(ldargs, input_file->filename[0]);
    bcatcstr(ldargs, "\" ");

    // Windows needs the whole command wrapped in quotes and slashes to be correct.
    // See http://stackoverflow.com/questions/2642551/windows-c-system-call-with-spaces-in-command.
#ifdef _WIN32
    binsertch(ldargs, 0, 1, '"');
    bconchar(ldargs, '"');
#endif

    // Now run the assembler!
    result = system(ldargs->data);
    if (result != 0 && fail_opt->count == 0)
    {
        // Assembler returned error exit code.
        printd(LEVEL_ERROR, "error: expected success but assembler returned non-zero exit code (%i).\n", result);
        return 1;
    }
    else if (result == 0 && fail_opt->count >= 1)
    {
        // Assembler returned zero when failure was expected.
        printd(LEVEL_ERROR, "error: expected failure but assembler returned zero exit code.\n");
        return 1;
    }
    else if (result != 0 && fail_opt->count >= 1)
    {
        // Assembler failed and we expected it to.  Return success only
        // if the output file does not exist.
        actual = bfopen(actual_file->filename[0], "rb");
        if (actual != NULL)
        {
            printd(LEVEL_ERROR, "error: expected failure but actual output file exists.\n");
            bfclose(actual);
            return 1;
        }
        return 0;
    }

    // Open expect data.
    expect = bfopen(expect_file->filename[0], "rb");
    if (expect == NULL)
    {
        // The expect file was not provided.
        printd(LEVEL_ERROR, "error: path to expect file does not exist.\n");
        return 1;
    }

    // Open actual data.
    actual = bfopen(actual_file->filename[0], "rb");
    if (actual == NULL)
    {
        // The expect file was not provided.
        bfclose(expect);
        printd(LEVEL_ERROR, "error: expected data but actual output file does not exist after running assembler.\n");
        return 1;
    }

    // Now compare raw bytes.
    while (true)
    {
        if (!bfeof(actual) && !bfeof(expect))
        {
            ca = bfgetc(actual);
            ce = bfgetc(expect);
            if (ca == ce)
                match++;
            else
            {
                printd(LEVEL_WARNING, "warning: byte at 0x%04X is different (got 0x%02X, expected 0x%02X)!\n", bftell(actual), ca, ce);
                unmatch++;
            }
        }
        else if (!bfeof(actual))
        {
            ca = bfgetc(actual);
            printd(LEVEL_ERROR, "error: actual output contained trailing byte 0x%02X.\n", (unsigned char)ca);
            unmatch++;
        }
        else if (!bfeof(expect))
        {
            ce = bfgetc(expect);
            printd(LEVEL_ERROR, "error: expected actual output to contain 0x%02X.\n", (unsigned char)ce);
            unmatch++;
        }
        else
            break;
    }
    if (unmatch > 0)
    {
        printd(LEVEL_ERROR, "error: actual output differs from expected output in content (%f%%, %i bytes different).\n", 100.f / (unmatch + match) * unmatch, unmatch);
        if (bftell(actual) != bftell(expect))
            printd(LEVEL_ERROR, "error: actual output differs from expected output in length (%i bytes larger).\n", bftell(actual) - bftell(expect));
        bfclose(actual);
        bfclose(expect);
        return 1;
    }

    // Close files and delete actual because we have
    // succeeded.
    bfclose(actual);
    bfclose(expect);
    unlink(actual_file->filename[0]);

    return 0;
}