Beispiel #1
0
int main(int argc, char** argv)
{
	/*
	 * These counters will be used as offsets for messages when using pipes
	 * i.e. write(stack + stack_pos, strlen(stack + stack_pos))
	 */
	int stack_pos = 0;
	int input_pos = 1;

	char input[MAX_BUF_SIZE] = "";
	char stack[MAX_BUF_SIZE] = "";
	char result[MAX_BUF_SIZE] = "";

	fgets(input, MAX_BUF_SIZE - 1, stdin);
	fgets(stack, MAX_BUF_SIZE - 1, stdin);
	fgets(result, MAX_BUF_SIZE - 1, stdin);

	input[strcspn(input, "\n")] = 0;
	stack[strcspn(stack, "\n")] = 0;
	result[strcspn(result, "\n")] = 0;

	if ((strlen(input) == 0)) // End of input, clearing stack
	{
		while (stack_pos < strlen(stack))
		{
				write_to_result(result, ' ');
				write_to_result(result, stack[stack_pos++]);
		}

		if (debug)
			fprintf(stderr, "pid: %d end of input! result: %s \n",
				getpid(), result
			);

		printf("%s", result);
		return 0;
	}

	if (debug)
		fprintf(stderr, "pid: %d input[0]: %c stack: %s result: %s \n",
			getpid(), input[0], stack, result
		);

	switch (input[0])
	{
		case '-': /* Odp.: Przez liczbę całkowitą należy rozumież liczbę całkowitą bez znaku */
		case '^':
		case '*':
		case '/':
		case '+':
			while (stack_pos < strlen(stack))
			{
				/* treating every op as left-associative */
				if (op_priority(input[0]) <= op_priority(stack[stack_pos]))
				{
					write_to_result(result, ' ');
					write_to_result(result, stack[stack_pos++]);
				}
				else break;
			}

			write_to_result(result, ' ');

		case '(':
			write_to_stack(stack, input[0], &stack_pos);
			break;
		case ')':
			while(stack_pos <= strlen(stack))
			{
				if (stack[stack_pos] != '(')
				{
					write_to_result(result, ' ');
					write_to_result(result, stack[stack_pos++]);
				}
				else
				{
					 stack_pos++;
					 break;
				}
			}
		case ' ':
		case '\n':
			break;
		default:
			add_space_to_result(result);
			/*
			 * We only checked first character of expression (input[0])
			 * Now let's check if there are other characters in expression
			 */
			for (int i = 0; i < strlen(input); i++)
			{
				/* When there's no space around parenthesis
				 * easier testing
				 */
				if (!isspace(input[i]) && (input[i] != ')'))
				{
					write_to_result(result, input[i]);
				}
				else
				{
					input_pos = i + ((input[i] != ')') ? (1) : (0));
					break;
				}
			}
			break;
	}

	/* Moving offset to first nonwhite character in input */
	while ((input_pos < strlen(input)) && (isspace(input[input_pos]))) input_pos++;

	spawn_worker(input + input_pos, stack + stack_pos, result);

	return 0;
}
Beispiel #2
0
int main(int argc, char **argv)
{
    FILE *file;
    char instruction;
    char* filename;
    struct vector instruction_stream;

    if(argc != 2)
    {
        /* wrong number of args */
        fprintf(stderr, "Error: exactly 1 HQ9+ source file as arg required\n");
        exit(EXIT_FAILURE);
    }

    /* open file */
    filename = argv[1];
    file = fopen(filename, "r");
    if (file == NULL)
    {
        /* could not open file */
        perror("Error opening file");
        exit(EXIT_FAILURE);
    }


    /*** prologue ***/
    vector_create(&instruction_stream, 100);
    char prologue [] = {
        0x55, // push %rbp
        0x48, 0x89, 0xE5, // mov %rsp, %rbp

        // backup %r12 (callee saved register)
        0x41, 0x54, // pushq %r12
        // store %rdi content (putchar) in %r12 as callee saved
        0x49, 0x89, 0xFC, // movq %rdi, %r12

        // push accumulator on stack
        0x6a, 0x00, // pushq $0
    };
    vector_push(&instruction_stream, prologue, sizeof(prologue));

    int stack_offset = -0x10; // offset from %rbp
    int offset_accumulator = stack_offset; // accumulator address: -0x10(%rbp)

    // hello world
    write_to_stack(&instruction_stream, "Hello World\n", &stack_offset);
    int offset_hello_world = stack_offset;

    // source code
    char* source_code = get_source_code(filename);
    write_to_stack(&instruction_stream, source_code, &stack_offset);
    free(source_code);
    int offset_source = stack_offset;

    // lyrics
    char* lyrics = get_lyrics(99);
    write_to_stack(&instruction_stream, lyrics, &stack_offset);
    free(lyrics);
    int offset_bottles = stack_offset;

    // everything after accumulator is text bytes
    int text_bytes_on_stack = -(stack_offset - offset_accumulator);


    /*** parse file ***/
    while((instruction = fgetc(file)) != EOF)
    {
        switch (instruction)
        {
            case 'H':
                {
                    // access single chars of int
                    char *hw = (char*) &offset_hello_world;
                    char opcodes [] = {
                        0xB0, 00, // movb $0, %al
                        0x48, 0x8D, 0xBD, hw[0], hw[1], hw[2], hw[3], // leaq -0x<offset>(%rbp),%rdi
                        0x41, 0xFF, 0xD4 // callq *%r12
                    };
                    vector_push(&instruction_stream, opcodes, sizeof(opcodes));
                }
                break;

            case 'Q':
                {
                    // access single chars of int
                    char *s = (char*) &offset_source;
                    char opcodes [] = {
                        0xB0, 00, // movb $0, %al
                        0x48, 0x8D, 0xBD, s[0], s[1], s[2], s[3], // leaq -0x<offset>(%rbp),%rdi
                        0x41, 0xFF, 0xD4 // callq *%r12
                    };
                    vector_push(&instruction_stream, opcodes, sizeof(opcodes));
                }
                break;

            case '9':
                {
                    // access single chars of int
                    char *b = (char*) &offset_bottles;
                    char opcodes [] = {
                        0xB0, 00, // movb $0, %al
                        0x48, 0x8D, 0xBD, b[0], b[1], b[2], b[3], // leaq -0x<offset>(%rbp),%rdi
                        // 0xBF, 0x39, 0x00, 0x00, 0x00, // mov $0x39, %edi
                        0x41, 0xFF, 0xD4 // callq *%r12
                    };
                    vector_push(&instruction_stream, opcodes, sizeof(opcodes));
                }
                break;

            case '+':
                {
                    char *acc = (char*) &offset_accumulator;
                    char opcodes [] = {
                        // increment the accumulator
                        // TODO from variable instead of constant offset
                        0x48, 0xFF, 0x45, 0xF0, // incq -0x10(%rbp)
                    };
                    vector_push(&instruction_stream, opcodes, sizeof(opcodes));
                }
                break;
        }
    }
    if (!feof(file)) {
        perror("Error reading file");
    }
    fclose(file);


    /*** epilogue ***/
    // access single chars of long
    char *t = (char*) &text_bytes_on_stack;
    char epilogue [] = {
        // free strings
        0x48, 0x81, 0xC4, t[0], t[1], t[2], t[3], // addq $<x>, %rsp

        // free accumulator
        0x48, 0x83, 0xC4, 0x08, // addq $8, %rsp

        // restore callee saved register
        0x41, 0x5C, // popq %r12

        0x5d, // pop rbp
        0xC3 // ret
    };
    vector_push(&instruction_stream, epilogue, sizeof(epilogue));


    /*** invoke generated code ***/
    /* allocate and copy instruction stream into executable memory */
    void* mem = mmap(NULL, instruction_stream.size, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    memcpy(mem, instruction_stream.data, instruction_stream.size);

    /* typecast memory to a function pointer and call the dynamically created executable code */
    void (*hq9p_program) (fn_printf) = mem;
    hq9p_program(printf);

    /* clear up */
    munmap(mem, instruction_stream.size);
    vector_destroy(&instruction_stream);

    exit(EXIT_SUCCESS);
}