Makefile and pkgbuild
This commit is contained in:
274
reddust.c
Normal file
274
reddust.c
Normal file
@@ -0,0 +1,274 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// --- Definições Globais ---
|
||||
|
||||
// Memória da máquina, igual à versão em Python
|
||||
int memory[256] = {0};
|
||||
|
||||
typedef enum {
|
||||
TOKEN_NUMBER,
|
||||
TOKEN_IDENTIFIER
|
||||
} TokenType;
|
||||
|
||||
typedef struct {
|
||||
TokenType type;
|
||||
union {
|
||||
int number;
|
||||
char letter;
|
||||
} value;
|
||||
|
||||
int line;
|
||||
int column;
|
||||
} Token;
|
||||
|
||||
// Estrutura para uma única instrução (4 tokens)
|
||||
typedef struct {
|
||||
int tokens[4];
|
||||
int line;
|
||||
} Instruction;
|
||||
|
||||
// --- Funções Auxiliares ---
|
||||
|
||||
// Converte um inteiro para uma string hexadecimal (para debug)
|
||||
// Em C, precisamos gerenciar o buffer de string manualmente.
|
||||
void to_hex_string(int val, char *hex_str, size_t size) {
|
||||
snprintf(hex_str, size, "%X", val);
|
||||
}
|
||||
|
||||
// Analisa uma linha de código .redd e a converte em 4 inteiros.
|
||||
// Retorna 1 em caso de sucesso, 0 em caso de falha.
|
||||
int parse_line(char *line, int *instr_tokens) {
|
||||
// Remove comentários que começam com "//"
|
||||
char *comment = strstr(line, "//");
|
||||
if (comment != NULL) {
|
||||
*comment = '\0'; // Termina a string no início do comentário
|
||||
}
|
||||
|
||||
// Usa strtok para dividir a string pelo delimitador ";"
|
||||
// strtok é "destrutivo", ele modifica a string original.
|
||||
char *token = strtok(line, ";");
|
||||
int i = 0;
|
||||
while (token != NULL && i < 4) {
|
||||
// strtol converte string para long, aqui usado para hex (base 16)
|
||||
instr_tokens[i] = (int)strtol(token, NULL, 16);
|
||||
token = strtok(NULL, ";");
|
||||
i++;
|
||||
}
|
||||
|
||||
// Se não tivermos exatamente 4 tokens, a linha é inválida
|
||||
if (i != 4) {
|
||||
// Ignora linhas vazias ou com erro de formatação
|
||||
if (i > 0) printf("[ERRO] Linha inválida (esperado 4 valores): %s\n", line);
|
||||
return 0; // Falha
|
||||
}
|
||||
return 1; // Sucesso
|
||||
}
|
||||
|
||||
|
||||
// --- Lógica de Execução ---
|
||||
|
||||
void run_program(Instruction *program, int num_instructions, int debug) {
|
||||
int pc = 0; // Program Counter (Contador de Programa)
|
||||
|
||||
while (pc < num_instructions) {
|
||||
Instruction instr = program[pc];
|
||||
int cmd = instr.tokens[0];
|
||||
|
||||
if (debug) {
|
||||
char hex_instr[50];
|
||||
char mem_preview[100];
|
||||
|
||||
// Monta a string de debug para a instrução
|
||||
snprintf(hex_instr, sizeof(hex_instr), "%X;%X;%X;%X", instr.tokens[0], instr.tokens[1], instr.tokens[2], instr.tokens[3]);
|
||||
|
||||
// Monta a string de debug para a memória
|
||||
mem_preview[0] = '\0';
|
||||
for(int i = 0; i < 16; i++) {
|
||||
char hex_val[4];
|
||||
to_hex_string(memory[i], hex_val, sizeof(hex_val));
|
||||
strcat(mem_preview, hex_val);
|
||||
strcat(mem_preview, " ");
|
||||
}
|
||||
printf("[DEBUG] PC=%02X, CMD=%s, MEM[0..F]=%s\n", pc + 1, hex_instr, mem_preview);
|
||||
}
|
||||
|
||||
// Usa um switch-case, que é mais eficiente e idiomático em C do que if-else if.
|
||||
switch (cmd) {
|
||||
case 0: // HALT
|
||||
printf("[INFO] Programa finalizado.\n");
|
||||
return;
|
||||
|
||||
case 1: { // INPUT
|
||||
int a = instr.tokens[1];
|
||||
int b = instr.tokens[2];
|
||||
if (b != 0) {
|
||||
memory[a] = b;
|
||||
} else {
|
||||
printf("[INFO] Waiting for input...\n");
|
||||
char value_str[10];
|
||||
printf("Digite valor HEX para mem[%X]: ", a);
|
||||
scanf("%s", value_str);
|
||||
memory[a] = (int)strtol(value_str, NULL, 16);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // OUTPUT
|
||||
printf("%X\n", memory[instr.tokens[1]]);
|
||||
break;
|
||||
|
||||
case 3: // ADD
|
||||
memory[instr.tokens[3]] = memory[instr.tokens[1]] + memory[instr.tokens[2]];
|
||||
break;
|
||||
|
||||
case 4: // SUB
|
||||
memory[instr.tokens[3]] = memory[instr.tokens[1]] - memory[instr.tokens[2]];
|
||||
break;
|
||||
|
||||
case 5: // DIV
|
||||
if (memory[instr.tokens[2]] != 0) {
|
||||
memory[instr.tokens[3]] = memory[instr.tokens[1]] / memory[instr.tokens[2]];
|
||||
} else {
|
||||
memory[instr.tokens[3]] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // MUL
|
||||
memory[instr.tokens[3]] = memory[instr.tokens[1]] * memory[instr.tokens[2]];
|
||||
break;
|
||||
|
||||
case 7: // COND JUMP
|
||||
if (memory[instr.tokens[1]] == instr.tokens[2]) {
|
||||
pc = instr.tokens[3] - 1; // -1 para compensar o pc++ no final do loop
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case 8: // JUMP
|
||||
pc = instr.tokens[1] - 1; // -1 para compensar o pc++
|
||||
continue;
|
||||
|
||||
case 9: // CLEAR
|
||||
memory[instr.tokens[1]] = 0;
|
||||
break;
|
||||
|
||||
case 0xA: // RANDOM
|
||||
srand(time(NULL)); // Semente para o gerador de números aleatórios
|
||||
memory[instr.tokens[1]] = rand() % 16;
|
||||
break;
|
||||
|
||||
case 0xB: // CMP GREATER
|
||||
memory[instr.tokens[3]] = (memory[instr.tokens[1]] > memory[instr.tokens[2]]) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 0xC: // CMP LESS
|
||||
memory[instr.tokens[3]] = (memory[instr.tokens[1]] < memory[instr.tokens[2]]) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 0xD: // MOVE
|
||||
memory[instr.tokens[2]] = memory[instr.tokens[1]];
|
||||
break;
|
||||
|
||||
case 0xE: // INC/DEC
|
||||
if (instr.tokens[2] == 1) memory[instr.tokens[1]]++;
|
||||
else if (instr.tokens[2] == 0) memory[instr.tokens[1]]--;
|
||||
else printf("[ERROR]: Invalid flag: %X\n", instr.tokens[2]);
|
||||
break;
|
||||
|
||||
case 0xF: // WAIT
|
||||
printf("[INFO]: Waiting %d seconds...\n", instr.tokens[1]);
|
||||
sleep(instr.tokens[1]); // Em C, sleep está em <unistd.h> (geralmente)
|
||||
break;
|
||||
|
||||
default:
|
||||
printf(
|
||||
"CommandNotFoundError: opcode %X not found\n"
|
||||
" --> line %d\n",
|
||||
cmd,
|
||||
instr.line
|
||||
);
|
||||
return;
|
||||
}
|
||||
pc++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Função Principal ---
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Uso: %s <arquivo.redd> [--debug]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checa por argumentos, como --version ou --debug
|
||||
if (strcmp(argv[1], "--version") == 0) {
|
||||
printf("RedDust Interpreter v3.1 (C-Version)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int debug = 0;
|
||||
if (argc > 2 && strcmp(argv[2], "--debug") == 0) {
|
||||
debug = 1;
|
||||
}
|
||||
|
||||
// --- Leitura do Arquivo ---
|
||||
char *filename = argv[1];
|
||||
if (!strstr(filename, ".redd")) {
|
||||
printf("[ERRO] Arquivo deve ter extensão .redd\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE *file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
printf("[ERRO] Arquivo '%s' não encontrado.\n", filename);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Aloca memória para o programa. Começamos com espaço para 100 instruções.
|
||||
// Em C, precisamos gerenciar o tamanho do array dinamicamente se não soubermos o tamanho.
|
||||
int max_instr = 100;
|
||||
Instruction *program = malloc(max_instr * sizeof(Instruction));
|
||||
if (program == NULL) {
|
||||
printf("[ERRO] Falha ao alocar memória para o programa.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char line[100];
|
||||
int num_instructions = 0;
|
||||
int line_number = 1;
|
||||
|
||||
while (fgets(line, sizeof(line), file)) {
|
||||
if (num_instructions >= max_instr) {
|
||||
max_instr *= 2;
|
||||
Instruction *new_program = realloc(program, max_instr * sizeof(Instruction));
|
||||
if (new_program == NULL) {
|
||||
printf("[ERRO] Falha ao realocar memória para o programa.\n");
|
||||
free(program);
|
||||
return 1;
|
||||
}
|
||||
program = new_program;
|
||||
}
|
||||
|
||||
if (parse_line(line, program[num_instructions].tokens)) {
|
||||
program[num_instructions].line = line_number;
|
||||
num_instructions++;
|
||||
}
|
||||
|
||||
line_number++;
|
||||
};
|
||||
fclose(file);
|
||||
|
||||
// --- Execução ---
|
||||
run_program(program, num_instructions, debug);
|
||||
|
||||
// Libera a memória que foi alocada dinamicamente
|
||||
free(program);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user