Compare commits
3 Commits
d4ac0be316
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9da2bb5404 | ||
|
|
bd07952569 | ||
|
|
b69a6c6eec |
54
.gitignore
vendored
54
.gitignore
vendored
@@ -1,54 +0,0 @@
|
||||
# ---> C
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
|
||||
24
Makefile
Normal file
24
Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
CC=gcc
|
||||
CFLAGS=-O3 -Wall
|
||||
|
||||
SRC=src
|
||||
BIN=bin
|
||||
|
||||
VMBL_FILES=$(wildcard $(SRC)/vmbl/*.c)
|
||||
SYLT_FILES=$(wildcard $(SRC)/sylt/*.c)
|
||||
UTIL_FILES=$(wildcard $(SRC)/utils/*.c)
|
||||
|
||||
all: vmbl sylt
|
||||
|
||||
$(BIN)/vmbl: $(VMBL_FILES)
|
||||
mkdir -p $(BIN)
|
||||
$(CC) $(CFLAGS) $(UTIL_FILES) $(VMBL_FILES) -o $(BIN)/vmbl
|
||||
vmbl: $(BIN)/vmbl
|
||||
|
||||
$(BIN)/sylt: $(SYLT_FILES)
|
||||
mkdir -p $(BIN)
|
||||
$(CC) $(CFLAGS) $(UTIL_FILES) $(SYLT_FILES) -o $(BIN)/sylt
|
||||
sylt: $(BIN)/sylt
|
||||
|
||||
clean:
|
||||
rm -r $(BIN)
|
||||
@@ -9,7 +9,7 @@
|
||||
But uhh that's the name of the VM itself, the name of the programming language I made is Sylt, named after the German island.
|
||||
|
||||
To compile the VM for Linux: `gcc src/main.c src/vmbl.c src/exception.c src/file_utils.c -o vmbl -O3`
|
||||
To compile the SYLT compiler for Linux: `gcc src/sylt/main.c src/file_utils.c src/sylt/lexer.c -o sylt -O3`
|
||||
To compile the SYLT compiler for Linux: `gcc src/sylt/main.c src/sylt/exception.c src/sylt/token.c src/file_utils.c src/sylt/lexer.c -o sylt -O3`
|
||||
|
||||
SASM and Sylt are written in Python for now as I'm too mentally challenged to write C code rn.
|
||||
|
||||
|
||||
1
src/sylt/ast.c
Normal file
1
src/sylt/ast.c
Normal file
@@ -0,0 +1 @@
|
||||
#include "ast.h"
|
||||
65
src/sylt/ast.h
Normal file
65
src/sylt/ast.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef AST_H
|
||||
#define AST_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef enum {
|
||||
NODE_PROGRAM,
|
||||
|
||||
// Statements
|
||||
NODE_EXPRESSION_STATEMENT,
|
||||
|
||||
// Expressions
|
||||
NODE_INFIX_EXPRESSION,
|
||||
|
||||
// Literals
|
||||
NODE_INT_LITERAL,
|
||||
NODE_FLOAT_LITERAL
|
||||
} AST_Type;
|
||||
|
||||
typedef struct AST AST;
|
||||
struct AST
|
||||
{
|
||||
AST_Type type;
|
||||
char *(*to_json)(AST *node);
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AST base;
|
||||
AST **statements;
|
||||
size_t statementCount;
|
||||
} Program;
|
||||
char *programToJSON(AST *node);
|
||||
|
||||
// statements
|
||||
typedef struct
|
||||
{
|
||||
AST base;
|
||||
AST *expr;
|
||||
} ExpressionStatement;
|
||||
char *expressionStatementToJSON(AST *node);
|
||||
|
||||
// expressions
|
||||
typedef struct {
|
||||
AST base;
|
||||
AST *left;
|
||||
char *operator;
|
||||
AST *right;
|
||||
} InfixExpression;
|
||||
char *infixExpressionToJSON(AST *node);
|
||||
|
||||
// literals
|
||||
typedef struct {
|
||||
AST base;
|
||||
int value;
|
||||
} IntegerLiteral;
|
||||
char *integerLiteralToJSON(AST *node);
|
||||
|
||||
typedef struct {
|
||||
AST base;
|
||||
double value;
|
||||
} FloatLiteral;
|
||||
char *floatLiteralToJSON(AST *node);
|
||||
|
||||
#endif // !AST_H
|
||||
21
src/sylt/exception.c
Normal file
21
src/sylt/exception.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "exception.h"
|
||||
#include <stdio.h>
|
||||
#include "../utils/ansii.h"
|
||||
|
||||
char *exceptionTypeToCString(ExceptionType type) {
|
||||
switch (type)
|
||||
{
|
||||
case EXCEPTION_MALFORMED_NUMBER:
|
||||
return "MalformedNumberException";
|
||||
|
||||
case EXCEPTION_MEMORY_ALLOCATION_FAILURE:
|
||||
return "MemoryAllocationFailException";
|
||||
|
||||
default:
|
||||
return "UnkownException (fix me please)";
|
||||
}
|
||||
}
|
||||
|
||||
void exceptionMessage(ExceptionType type, char *message, int lineNumber, int position) {
|
||||
printf(ESC_RED_FG ESC_BOLD "%s: %s" ESC_RESET "\n", exceptionTypeToCString(type), message);
|
||||
}
|
||||
12
src/sylt/exception.h
Normal file
12
src/sylt/exception.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef EXCEPTION_H
|
||||
#define EXCEPTION_H
|
||||
|
||||
typedef enum {
|
||||
EXCEPTION_MALFORMED_NUMBER,
|
||||
EXCEPTION_MEMORY_ALLOCATION_FAILURE
|
||||
} ExceptionType;
|
||||
|
||||
char *exceptionTypeToCString(ExceptionType type);
|
||||
void exceptionMessage(ExceptionType type, char *message, int lineNumber, int position);
|
||||
|
||||
#endif // !EXCEPTION_H
|
||||
102
src/sylt/lexer.c
102
src/sylt/lexer.c
@@ -1,7 +1,9 @@
|
||||
#include "lexer.h"
|
||||
#include "exception.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio,h>
|
||||
#include <stdio.h>
|
||||
|
||||
Lexer initLexer(char *source) {
|
||||
Lexer newLexer = {
|
||||
@@ -11,6 +13,7 @@ Lexer initLexer(char *source) {
|
||||
.lineNumber = 1,
|
||||
.currentChar = '\0'
|
||||
};
|
||||
readChar(&newLexer);
|
||||
return newLexer;
|
||||
}
|
||||
|
||||
@@ -25,6 +28,10 @@ void readChar(Lexer *lexer) {
|
||||
}
|
||||
|
||||
void skipWhitespace(Lexer *lexer) {
|
||||
bool whitespace = true;
|
||||
|
||||
while (whitespace)
|
||||
{
|
||||
switch (lexer->currentChar)
|
||||
{
|
||||
case ' ':
|
||||
@@ -38,50 +45,117 @@ void skipWhitespace(Lexer *lexer) {
|
||||
break;
|
||||
|
||||
default:
|
||||
whitespace = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Token readNumber(Lexer *lexer) {
|
||||
int startPos = lexer->position;
|
||||
int dotCount = 0;
|
||||
int strLength = 0;
|
||||
|
||||
size_t outputCap = 8;
|
||||
char *output = malloc(outputCap);
|
||||
|
||||
if (!output) {
|
||||
exceptionMessage(EXCEPTION_MEMORY_ALLOCATION_FAILURE, "Lexer failed to allocate memory.", lexer->lineNumber, lexer->position);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (isdigit(lexer->currentChar) || lexer->currentChar == '.')
|
||||
{
|
||||
if (lexer->currentChar == '.') {
|
||||
dotCount++;
|
||||
|
||||
if (dotCount > 1) {
|
||||
exceptionMessage(EXCEPTION_MALFORMED_NUMBER, "Too many dots in decimal.", lexer->lineNumber, lexer->position);
|
||||
|
||||
char buffer[strLength+1];
|
||||
strncpy(buffer, lexer->source + startPos, strLength+1);
|
||||
buffer[strLength+1] = 0;
|
||||
|
||||
return NEW_TOKEN(lexer, TOKEN_ILLEGAL, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
// allocate more memory if we reach the end of our buffer
|
||||
if (strLength + 1 >= outputCap) {
|
||||
char *temp = realloc(output, outputCap*=2);
|
||||
|
||||
if (!temp) {
|
||||
exceptionMessage(EXCEPTION_MEMORY_ALLOCATION_FAILURE, "Lexer failed to allocate memory.", lexer->lineNumber, lexer->position);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
output = temp;
|
||||
}
|
||||
|
||||
output[strLength] = lexer->source[lexer->position];
|
||||
strLength++;
|
||||
readChar(lexer);
|
||||
|
||||
if (lexer->currentChar == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
output[strLength] = 0;
|
||||
|
||||
if (dotCount == 0)
|
||||
return NEW_TOKEN(lexer, TOKEN_INT, output);
|
||||
else
|
||||
return NEW_TOKEN(lexer, TOKEN_FLOAT, output);
|
||||
}
|
||||
|
||||
Token nextToken(Lexer *lexer) {
|
||||
//Token tok;
|
||||
Token tok;
|
||||
skipWhitespace(lexer);
|
||||
|
||||
switch (lexer->currentChar)
|
||||
{
|
||||
case '+':
|
||||
return NEW_TOKEN(lexer, PLUS, "+");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_PLUS, "+");
|
||||
break;
|
||||
case '-':
|
||||
return NEW_TOKEN(lexer, MINUS, "-");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_MINUS, "-");
|
||||
break;
|
||||
case '*':
|
||||
return NEW_TOKEN(lexer, ASTERISK, "*");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_ASTERISK, "*");
|
||||
break;
|
||||
case '/':
|
||||
return NEW_TOKEN(lexer, SLASH, "/");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_SLASH, "/");
|
||||
break;
|
||||
case '%':
|
||||
return NEW_TOKEN(lexer, MODULUS, "%");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_MODULUS, "%");
|
||||
break;
|
||||
case '^':
|
||||
return NEW_TOKEN(lexer, POW, "^");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_POW, "^");
|
||||
break;
|
||||
case '(':
|
||||
return NEW_TOKEN(lexer, LPAREN, "(");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_LPAREN, "(");
|
||||
break;
|
||||
case ')':
|
||||
return NEW_TOKEN(lexer, RPAREN, ")");
|
||||
tok = NEW_TOKEN(lexer, TOKEN_RPAREN, ")");
|
||||
break;
|
||||
case '\0':
|
||||
return NEW_TOKEN(lexer, EOF, "");
|
||||
|
||||
case '\0': // EOF
|
||||
tok = NEW_TOKEN(lexer, TOKEN_EOF, "EOF");
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isdigit())
|
||||
if (isdigit(lexer->currentChar)) {
|
||||
tok = readNumber(lexer);
|
||||
} else {
|
||||
tok = NEW_TOKEN(lexer, TOKEN_ILLEGAL, &lexer->currentChar);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//return tok;
|
||||
readChar(lexer);
|
||||
return tok;
|
||||
}
|
||||
@@ -17,6 +17,6 @@ Lexer initLexer(char *source);
|
||||
void readChar(Lexer *lexer);
|
||||
void skipWhitespace(Lexer *lexer);
|
||||
Token nextToken(Lexer *lexer);
|
||||
char *tokenToCStr(Token token);
|
||||
Token readNumber(Lexer *lexer);
|
||||
|
||||
#endif // !LEXER_H
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#include "lexer.h"
|
||||
#include <stdio.h>
|
||||
#include "../file_utils.h"
|
||||
#include "../utils/file_utils.h"
|
||||
#include "../utils/ansii.h"
|
||||
|
||||
int main() {
|
||||
Lexer lexer = initLexer("const x, y = 1, 3\n");
|
||||
printf(nextToken(&lexer).literal);
|
||||
Lexer lexer = initLexer("123 456.789 + - * / % ^ ()");
|
||||
|
||||
while (lexer.currentChar != 0)
|
||||
{
|
||||
Token next = nextToken(&lexer);
|
||||
printf("%s: %s\n", tokenTypeToCString(next.type), next.literal);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
1
src/sylt/parser.c
Normal file
1
src/sylt/parser.c
Normal file
@@ -0,0 +1 @@
|
||||
#include "parser.h"
|
||||
28
src/sylt/parser.h
Normal file
28
src/sylt/parser.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include "lexer.h"
|
||||
#include "ast.h"
|
||||
|
||||
typedef enum {
|
||||
PRECEDENCE_LOWEST = 0,
|
||||
PRECEDENCE_EQUALS,
|
||||
PRECEDENCE_LESSGREATER,
|
||||
PRECEDENCE_SUM,
|
||||
PRECEDENCE_PRODUCT,
|
||||
PRECEDENCE_EXPONENT,
|
||||
PRECEDENCE_PREFIX,
|
||||
PRECEDENCE_CALL,
|
||||
PRECEDENCE_INDEX,
|
||||
} PrecedenceType;
|
||||
|
||||
PrecedenceType PRECEDENCES[] = {
|
||||
[TOKEN_PLUS] = PRECEDENCE_SUM,
|
||||
[TOKEN_MINUS] = PRECEDENCE_SUM,
|
||||
[TOKEN_SLASH] = PRECEDENCE_PRODUCT,
|
||||
[TOKEN_ASTERISK] = PRECEDENCE_PRODUCT,
|
||||
[TOKEN_MODULUS] = PRECEDENCE_PRODUCT,
|
||||
[TOKEN_POW] = PRECEDENCE_EXPONENT,
|
||||
};
|
||||
|
||||
#endif // !PARSER_H
|
||||
45
src/sylt/token.c
Normal file
45
src/sylt/token.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "token.h"
|
||||
|
||||
char *tokenTypeToCString(TokenType type) {
|
||||
switch (type)
|
||||
{
|
||||
case TOKEN_EOF:
|
||||
return "TOKEN_EOF";
|
||||
|
||||
case TOKEN_ILLEGAL:
|
||||
return "TOKEN_ILLEGAL";
|
||||
|
||||
case TOKEN_INT:
|
||||
return "TOKEN_INT";
|
||||
|
||||
case TOKEN_FLOAT:
|
||||
return "TOKEN_FLOAT";
|
||||
|
||||
case TOKEN_PLUS:
|
||||
return "TOKEN_EOF";
|
||||
|
||||
case TOKEN_MINUS:
|
||||
return "TOKEN_MINUS";
|
||||
|
||||
case TOKEN_ASTERISK:
|
||||
return "TOKEN_ASTERISK";
|
||||
|
||||
case TOKEN_SLASH:
|
||||
return "TOKEN_SLASH";
|
||||
|
||||
case TOKEN_POW:
|
||||
return "TOKEN_POW";
|
||||
|
||||
case TOKEN_MODULUS:
|
||||
return "TOKEN_MODULUS";
|
||||
|
||||
case TOKEN_LPAREN:
|
||||
return "TOKEN_LPAREN";
|
||||
|
||||
case TOKEN_RPAREN:
|
||||
return "TOKEN_RPAREN";
|
||||
|
||||
default:
|
||||
return "UNKOWN (fix me please)";
|
||||
}
|
||||
}
|
||||
@@ -3,24 +3,24 @@
|
||||
|
||||
typedef enum {
|
||||
// Special Tokens
|
||||
EOF,
|
||||
ILLEGAL,
|
||||
TOKEN_EOF,
|
||||
TOKEN_ILLEGAL,
|
||||
|
||||
// Data Types
|
||||
INT,
|
||||
FLOAT,
|
||||
TOKEN_INT,
|
||||
TOKEN_FLOAT,
|
||||
|
||||
// Arithmetic Symbols
|
||||
PLUS,
|
||||
MINUS,
|
||||
ASTERISK,
|
||||
SLASH,
|
||||
POW,
|
||||
MODULUS,
|
||||
TOKEN_PLUS,
|
||||
TOKEN_MINUS,
|
||||
TOKEN_ASTERISK,
|
||||
TOKEN_SLASH,
|
||||
TOKEN_POW,
|
||||
TOKEN_MODULUS,
|
||||
|
||||
// Symbols
|
||||
LPAREN,
|
||||
RPAREN
|
||||
TOKEN_LPAREN,
|
||||
TOKEN_RPAREN
|
||||
} TokenType;
|
||||
|
||||
typedef struct
|
||||
@@ -33,4 +33,6 @@ typedef struct
|
||||
|
||||
#define NEW_TOKEN(lexer, tokType, tokLiteral) (Token){ .type = (tokType), .literal = (tokLiteral), .lineNumber = (lexer->lineNumber), .position = (lexer->position) }
|
||||
|
||||
char *tokenTypeToCString(TokenType type);
|
||||
|
||||
#endif // !TOKEN_H
|
||||
67
src/utils/ansii.h
Normal file
67
src/utils/ansii.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// ansii.h - made by SpookyDervish
|
||||
// version 1.0.0
|
||||
// do with this whatever you want
|
||||
//
|
||||
// example usage with printf: printf(ESC_BOLD ESC_RED_FG "hi\n");
|
||||
|
||||
#ifndef ANSII_H
|
||||
#define ANSII_H
|
||||
|
||||
#define ESC_RESET "\x1b[0m"
|
||||
#define ESC_BOLD "\x1b[1m"
|
||||
#define ESC_DIM "\x1b[2m"
|
||||
#define ESC_ITALIC "\x1b[3m"
|
||||
#define ESC_UNDERLINE "\x1b[4m"
|
||||
#define ESC_BLINKING "\x1b[5m"
|
||||
#define ESC_REVERSE "\x1b[7m"
|
||||
#define ESC_HIDDEN "\x1b[8m"
|
||||
#define ESC_STRIKETHROUGH "\x1b[8m"
|
||||
|
||||
#define ESC_TERMINAL_BELL "\a"
|
||||
|
||||
#define ESC_BLACK_FG "\x1b[30m"
|
||||
#define ESC_RED_FG "\x1b[31m"
|
||||
#define ESC_GREEN_FG "\x1b[32m"
|
||||
#define ESC_YELLOW_FG "\x1b[33m"
|
||||
#define ESC_BLUE_FG "\x1b[34m"
|
||||
#define ESC_MAGENTA_FG "\x1b[35m"
|
||||
#define ESC_CYAN_FG "\x1b[36m"
|
||||
#define ESC_WHITE_FG "\x1b[37m"
|
||||
|
||||
#define ESC_BLACK_FG "\x1b[30m"
|
||||
#define ESC_RED_FG "\x1b[31m"
|
||||
#define ESC_GREEN_FG "\x1b[32m"
|
||||
#define ESC_YELLOW_FG "\x1b[33m"
|
||||
#define ESC_BLUE_FG "\x1b[34m"
|
||||
#define ESC_MAGENTA_FG "\x1b[35m"
|
||||
#define ESC_CYAN_FG "\x1b[36m"
|
||||
#define ESC_WHITE_FG "\x1b[37m"
|
||||
#define ESC_BRIGHT_BLACK_FG "\x1b[90m"
|
||||
#define ESC_BRIGHT_RED_FG "\x1b[91m"
|
||||
#define ESC_BRIGHT_GREEN_FG "\x1b[92m"
|
||||
#define ESC_BRIGHT_YELLOW_FG "\x1b[93m"
|
||||
#define ESC_BRIGHT_BLUE_FG "\x1b[94m"
|
||||
#define ESC_BRIGHT_MAGENTA_FG "\x1b[95m"
|
||||
#define ESC_BRIGHT_CYAN_FG "\x1b[96m"
|
||||
#define ESC_BRIGHT_WHITE_FG "\x1b[97m"
|
||||
|
||||
#define ESC_BLACK_BG "\x1b[40m"
|
||||
#define ESC_RED_BG "\x1b[41m"
|
||||
#define ESC_GREEN_BG "\x1b[42m"
|
||||
#define ESC_YELLOW_BG "\x1b[43m"
|
||||
#define ESC_BLUE_BG "\x1b[44m"
|
||||
#define ESC_MAGENTA_BG "\x1b[45m"
|
||||
#define ESC_CYAN_BG "\x1b[46m"
|
||||
#define ESC_WHITE_BG "\x1b[47m"
|
||||
#define ESC_BRIGHT_BLACK_BG "\x1b[100m"
|
||||
#define ESC_BRIGHT_RED_BG "\x1b[101m"
|
||||
#define ESC_BRIGHT_GREEN_BG "\x1b[102m"
|
||||
#define ESC_BRIGHT_YELLOW_BG "\x1b[103m"
|
||||
#define ESC_BRIGHT_BLUE_BG "\x1b[104m"
|
||||
#define ESC_BRIGHT_MAGENTA_BG "\x1b[105m"
|
||||
#define ESC_BRIGHT_CYAN_BG "\x1b[106m"
|
||||
#define ESC_BRIGHT_WHITE_BG "\x1b[107m"
|
||||
|
||||
#define ESC_DEFAULT_FG "\x1b[39m"
|
||||
|
||||
#endif // !ANSII_H
|
||||
@@ -4,12 +4,7 @@
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]));
|
||||
|
||||
VMBL_Instruction program[] = {
|
||||
MAKE_INST_PUSH(0),
|
||||
MAKE_INST_PUSH(1),
|
||||
MAKE_INST_DUP(1),
|
||||
MAKE_INST_DUP(1),
|
||||
MAKE_INST_ADD,
|
||||
MAKE_INST_JMP(2)
|
||||
MAKE_INST_JMP(0)
|
||||
};
|
||||
|
||||
int main() {
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "vmbl.h"
|
||||
#include "file_utils.h"
|
||||
#include "../utils/file_utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
Reference in New Issue
Block a user