diff options
| author | Nakidai <plaza521@inbox.ru> | 2024-07-05 00:04:56 +0300 |
|---|---|---|
| committer | Nakidai <plaza521@inbox.ru> | 2024-07-05 00:04:56 +0300 |
| commit | a9c159f5f7bf3479c3236735960597b4bc36a204 (patch) | |
| tree | f325e249f11a4bb8518f01151114b1239207a33b | |
| download | 3cl-a9c159f5f7bf3479c3236735960597b4bc36a204.tar.gz 3cl-a9c159f5f7bf3479c3236735960597b4bc36a204.zip | |
Add code
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | CMakeLists.txt | 19 | ||||
| -rw-r--r-- | LICENSE | 9 | ||||
| -rw-r--r-- | LICENSE.cvector | 21 | ||||
| -rw-r--r-- | README.md | 14 | ||||
| -rw-r--r-- | include/cccl.h | 49 | ||||
| -rw-r--r-- | include/cvector.h | 483 | ||||
| -rw-r--r-- | include/main.h | 9 | ||||
| -rw-r--r-- | include/types.h | 17 | ||||
| -rw-r--r-- | include/utils.h | 11 | ||||
| -rw-r--r-- | src/cccl.c | 80 | ||||
| -rw-r--r-- | src/main.c | 56 | ||||
| -rw-r--r-- | src/utils.c | 23 |
13 files changed, 795 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8e273e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +3cl +compile_commands.json +.cache +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..aa41599 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.5) +project(3cl VERSION 0.1 LANGUAGES C) + +if (PROJECT_SOURCE_DIR STREQUAL PORJECT_BINARY_DIR) + message(FATAL_ERROR "In-source builds are not allowed") +endif() + +add_executable( + "${PROJECT_NAME}" + src/main.c + src/utils.c +) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") + +set_target_properties("${PROJECT_NAME}" PROPERTIES C_STANDARD 11) +set_target_properties("${PROJECT_NAME}" PROPERTIES C_EXTENSIONS FALSE) + +target_include_directories("${PROJECT_NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include") diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7977ab2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +Copyright 2024 Nakidai + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/LICENSE.cvector b/LICENSE.cvector new file mode 100644 index 0000000..2eb0839 --- /dev/null +++ b/LICENSE.cvector @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Evan Teran + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f492dff --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +3CL +-- +CCCL is an implementation of [cool\_char\_lang](https://github.com/holy-8/cool_char_lang), +which is a brainfuck-inspired language + +Documentation +-- +To write code for it, follow [this documentation](https://github.com/holy-8/cool_char_lang/blob/main/reference/documentation.md) + +Also there're [examples](https://github.com/holy-8/cool_char_lang/tree/main/programs) + +Dependencies +-- +- [cvector](https://github.com/eteran/c-vector) (header only, so included in the source) diff --git a/include/cccl.h b/include/cccl.h new file mode 100644 index 0000000..6652453 --- /dev/null +++ b/include/cccl.h @@ -0,0 +1,49 @@ +#ifndef __CCCL_H__ +#define __CCCL_H__ + +#include "types.h" + +#include <stdbool.h> + +#include "cvector.h" + + +typedef struct cccl_varpair +{ + i16 value; + s8 name; +} cccl_varpair; + +typedef struct cccl_procpair +{ + i32 value; + s8 name; +} cccl_procpair; + +typedef struct cccl_pointer +{ + i32 value; + bool is_loop; +} cccl_pointer; + +typedef struct cccl +{ + cccl_varpair *variables; /* Array with variables */ + cccl_procpair *procedures; /* Array with procedures */ + i16 *stack; /* User stack */ + s8 *br_stack; /* Stack for brackets */ + i32 *ep_stack; /* Call stack */ + i32 ep; /* Pointer to current symbol */ + s8 *code; /* Code being executed */ + s8 *filename; /* File being executed */ + i32 size; /* File size */ +} cccl; + +void cccl_init(s8 *filename); +void cccl_read(void); +void cccl_run(void); +void cccl_free(void); + +i32 cccl_readnext(void); + +#endif /* __CCCL_H__ */ diff --git a/include/cvector.h b/include/cvector.h new file mode 100644 index 0000000..7be970d --- /dev/null +++ b/include/cvector.h @@ -0,0 +1,483 @@ +/* + * Copyright (c) 2015 Evan Teran + * + * License: The MIT License (MIT) + */ + +#ifndef CVECTOR_H_ +#define CVECTOR_H_ + +#ifndef CVECTOR_LOGARITHMIC_GROWTH +#define CVECTOR_LOGARITHMIC_GROWTH +#endif + +/* cvector heap implemented using C library malloc() */ + +/* in case C library malloc() needs extra protection, + * allow these defines to be overridden. + */ +#ifndef cvector_clib_free +#include <stdlib.h> /* for free */ +#define cvector_clib_free free +#endif +#ifndef cvector_clib_malloc +#include <stdlib.h> /* for malloc */ +#define cvector_clib_malloc malloc +#endif +#ifndef cvector_clib_calloc +#include <stdlib.h> /* for calloc */ +#define cvector_clib_calloc calloc +#endif +#ifndef cvector_clib_realloc +#include <stdlib.h> /* for realloc */ +#define cvector_clib_realloc realloc +#endif +#ifndef cvector_clib_assert +#include <assert.h> /* for assert */ +#define cvector_clib_assert assert +#endif +#ifndef cvector_clib_memcpy +#include <string.h> /* for memcpy */ +#define cvector_clib_memcpy memcpy +#endif +#ifndef cvector_clib_memmove +#include <string.h> /* for memmove */ +#define cvector_clib_memmove memmove +#endif + +/* NOTE: Similar to C's qsort and bsearch, you will receive a T* + * for a vector of Ts. This means that you cannot use `free` directly + * as a destructor. Instead if you have for example a cvector_vector_type(int *) + * you will need to supply a function which casts `elem_ptr` to an `int**` + * and then does a free on what that pointer points to: + * + * ex: + * + * void free_int(void *p) { free(*(int **)p); } + */ +typedef void (*cvector_elem_destructor_t)(void *elem_ptr); + +typedef struct cvector_metadata_t { + size_t size; + size_t capacity; + cvector_elem_destructor_t elem_destructor; +} cvector_metadata_t; + +/** + * @brief cvector_vector_type - The vector type used in this library + */ +#define cvector_vector_type(type) type * + +/** + * @brief cvector - Syntactic sugar to retrieve a vector type + * + * @param type The type of vector to act on. + */ +#define cvector(type) cvector_vector_type(type) + +/* + * @brief cvector_iterator - The iterator type used for cvector + */ +#define cvector_iterator(type) cvector_vector_type(type) + +/** + * @brief cvector_vec_to_base - For internal use, converts a vector pointer to a metadata pointer + * @param vec - the vector + * @return the metadata pointer of the vector + * @internal + */ +#define cvector_vec_to_base(vec) \ + (&((cvector_metadata_t *)(vec))[-1]) + +/** + * @brief cvector_base_to_vec - For internal use, converts a metadata pointer to a vector pointer + * @param ptr - pointer to the metadata + * @return the vector + * @internal + */ +#define cvector_base_to_vec(ptr) \ + ((void *)&((cvector_metadata_t *)(ptr))[1]) + +/** + * @brief cvector_capacity - gets the current capacity of the vector + * @param vec - the vector + * @return the capacity as a size_t + */ +#define cvector_capacity(vec) \ + ((vec) ? cvector_vec_to_base(vec)->capacity : (size_t)0) + +/** + * @brief cvector_size - gets the current size of the vector + * @param vec - the vector + * @return the size as a size_t + */ +#define cvector_size(vec) \ + ((vec) ? cvector_vec_to_base(vec)->size : (size_t)0) + +/** + * @brief cvector_elem_destructor - get the element destructor function used + * to clean up elements + * @param vec - the vector + * @return the function pointer as cvector_elem_destructor_t + */ +#define cvector_elem_destructor(vec) \ + ((vec) ? cvector_vec_to_base(vec)->elem_destructor : NULL) + +/** + * @brief cvector_empty - returns non-zero if the vector is empty + * @param vec - the vector + * @return non-zero if empty, zero if non-empty + */ +#define cvector_empty(vec) \ + (cvector_size(vec) == 0) + +/** + * @brief cvector_reserve - Requests that the vector capacity be at least enough + * to contain n elements. If n is greater than the current vector capacity, the + * function causes the container to reallocate its storage increasing its + * capacity to n (or greater). + * @param vec - the vector + * @param n - Minimum capacity for the vector. + * @return void + */ +#define cvector_reserve(vec, n) \ + do { \ + size_t cv_cap__ = cvector_capacity(vec); \ + if (cv_cap__ < (n)) { \ + cvector_grow((vec), (n)); \ + } \ + } while (0) + +/* + * @brief cvector_init - Initialize a vector. The vector must be NULL for this to do anything. + * @param vec - the vector + * @param capacity - vector capacity to reserve + * @param elem_destructor_fn - element destructor function + * @return void + */ +#define cvector_init(vec, capacity, elem_destructor_fn) \ + do { \ + if (!(vec)) { \ + cvector_reserve((vec), capacity); \ + cvector_set_elem_destructor((vec), (elem_destructor_fn)); \ + } \ + } while (0) + +/** + * @brief cvector_erase - removes the element at index i from the vector + * @param vec - the vector + * @param i - index of element to remove + * @return void + */ +#define cvector_erase(vec, i) \ + do { \ + if (vec) { \ + const size_t cv_sz__ = cvector_size(vec); \ + if ((i) < cv_sz__) { \ + cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ + if (elem_destructor__) { \ + elem_destructor__(&(vec)[i]); \ + } \ + cvector_set_size((vec), cv_sz__ - 1); \ + cvector_clib_memmove( \ + (vec) + (i), \ + (vec) + (i) + 1, \ + sizeof(*(vec)) * (cv_sz__ - 1 - (i))); \ + } \ + } \ + } while (0) + +/** + * @brief cvector_clear - erase all of the elements in the vector + * @param vec - the vector + * @return void + */ +#define cvector_clear(vec) \ + do { \ + if (vec) { \ + cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ + if (elem_destructor__) { \ + size_t i__; \ + for (i__ = 0; i__ < cvector_size(vec); ++i__) { \ + elem_destructor__(&(vec)[i__]); \ + } \ + } \ + cvector_set_size(vec, 0); \ + } \ + } while (0) + +/** + * @brief cvector_free - frees all memory associated with the vector + * @param vec - the vector + * @return void + */ +#define cvector_free(vec) \ + do { \ + if (vec) { \ + void *p1__ = cvector_vec_to_base(vec); \ + cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ + if (elem_destructor__) { \ + size_t i__; \ + for (i__ = 0; i__ < cvector_size(vec); ++i__) { \ + elem_destructor__(&(vec)[i__]); \ + } \ + } \ + cvector_clib_free(p1__); \ + } \ + } while (0) + +/** + * @brief cvector_begin - returns an iterator to first element of the vector + * @param vec - the vector + * @return a pointer to the first element (or NULL) + */ +#define cvector_begin(vec) \ + (vec) + +/** + * @brief cvector_end - returns an iterator to one past the last element of the vector + * @param vec - the vector + * @return a pointer to one past the last element (or NULL) + */ +#define cvector_end(vec) \ + ((vec) ? &((vec)[cvector_size(vec)]) : NULL) + +/* user request to use logarithmic growth algorithm */ +#ifdef CVECTOR_LOGARITHMIC_GROWTH + +/** + * @brief cvector_compute_next_grow - returns an the computed size in next vector grow + * size is increased by multiplication of 2 + * @param size - current size + * @return size after next vector grow + */ +#define cvector_compute_next_grow(size) \ + ((size) ? ((size) << 1) : 1) + +#else + +/** + * @brief cvector_compute_next_grow - returns an the computed size in next vector grow + * size is increased by 1 + * @param size - current size + * @return size after next vector grow + */ +#define cvector_compute_next_grow(size) \ + ((size) + 1) + +#endif /* CVECTOR_LOGARITHMIC_GROWTH */ + +/** + * @brief cvector_push_back - adds an element to the end of the vector + * @param vec - the vector + * @param value - the value to add + * @return void + */ +#define cvector_push_back(vec, value) \ + do { \ + size_t cv_cap__ = cvector_capacity(vec); \ + if (cv_cap__ <= cvector_size(vec)) { \ + cvector_grow((vec), cvector_compute_next_grow(cv_cap__)); \ + } \ + (vec)[cvector_size(vec)] = (value); \ + cvector_set_size((vec), cvector_size(vec) + 1); \ + } while (0) + +/** + * @brief cvector_insert - insert element at position pos to the vector + * @param vec - the vector + * @param pos - position in the vector where the new elements are inserted. + * @param val - value to be copied (or moved) to the inserted elements. + * @return void + */ +#define cvector_insert(vec, pos, val) \ + do { \ + size_t cv_cap__ = cvector_capacity(vec); \ + if (cv_cap__ <= cvector_size(vec)) { \ + cvector_grow((vec), cvector_compute_next_grow(cv_cap__)); \ + } \ + if ((pos) < cvector_size(vec)) { \ + cvector_clib_memmove( \ + (vec) + (pos) + 1, \ + (vec) + (pos), \ + sizeof(*(vec)) * ((cvector_size(vec)) - (pos))); \ + } \ + (vec)[(pos)] = (val); \ + cvector_set_size((vec), cvector_size(vec) + 1); \ + } while (0) + +/** + * @brief cvector_pop_back - removes the last element from the vector + * @param vec - the vector + * @return void + */ +#define cvector_pop_back(vec) \ + do { \ + cvector_elem_destructor_t elem_destructor__ = cvector_elem_destructor(vec); \ + if (elem_destructor__) { \ + elem_destructor__(&(vec)[cvector_size(vec) - 1]); \ + } \ + cvector_set_size((vec), cvector_size(vec) - 1); \ + } while (0) + +/** + * @brief cvector_copy - copy a vector + * @param from - the original vector + * @param to - destination to which the function copy to + * @return void + */ +#define cvector_copy(from, to) \ + do { \ + if ((from)) { \ + cvector_grow(to, cvector_size(from)); \ + cvector_set_size(to, cvector_size(from)); \ + cvector_clib_memcpy((to), (from), cvector_size(from) * sizeof(*(from))); \ + } \ + } while (0) + +/** + * @brief cvector_swap - exchanges the content of the vector by the content of another vector of the same type + * @param vec - the original vector + * @param other - the other vector to swap content with + * @param type - the type of both vectors + * @return void + */ +#define cvector_swap(vec, other, type) \ + do { \ + if (vec && other) { \ + cvector_vector_type(type) cv_swap__ = vec; \ + vec = other; \ + other = cv_swap__; \ + } \ + } while (0) + +/** + * @brief cvector_set_capacity - For internal use, sets the capacity variable of the vector + * @param vec - the vector + * @param size - the new capacity to set + * @return void + * @internal + */ +#define cvector_set_capacity(vec, size) \ + do { \ + if (vec) { \ + cvector_vec_to_base(vec)->capacity = (size); \ + } \ + } while (0) + +/** + * @brief cvector_set_size - For internal use, sets the size variable of the vector + * @param vec - the vector + * @param size - the new capacity to set + * @return void + * @internal + */ +#define cvector_set_size(vec, _size) \ + do { \ + if (vec) { \ + cvector_vec_to_base(vec)->size = (_size); \ + } \ + } while (0) + +/** + * @brief cvector_set_elem_destructor - set the element destructor function + * used to clean up removed elements. The vector must NOT be NULL for this to do anything. + * @param vec - the vector + * @param elem_destructor_fn - function pointer of type cvector_elem_destructor_t used to destroy elements + * @return void + */ +#define cvector_set_elem_destructor(vec, elem_destructor_fn) \ + do { \ + if (vec) { \ + cvector_vec_to_base(vec)->elem_destructor = (elem_destructor_fn); \ + } \ + } while (0) + +/** + * @brief cvector_grow - For internal use, ensures that the vector is at least <count> elements big + * @param vec - the vector + * @param count - the new capacity to set + * @return void + * @internal + */ +#define cvector_grow(vec, count) \ + do { \ + const size_t cv_sz__ = (count) * sizeof(*(vec)) + sizeof(cvector_metadata_t); \ + if (vec) { \ + void *cv_p1__ = cvector_vec_to_base(vec); \ + void *cv_p2__ = cvector_clib_realloc(cv_p1__, cv_sz__); \ + cvector_clib_assert(cv_p2__); \ + (vec) = cvector_base_to_vec(cv_p2__); \ + } else { \ + void *cv_p__ = cvector_clib_malloc(cv_sz__); \ + cvector_clib_assert(cv_p__); \ + (vec) = cvector_base_to_vec(cv_p__); \ + cvector_set_size((vec), 0); \ + cvector_set_elem_destructor((vec), NULL); \ + } \ + cvector_set_capacity((vec), (count)); \ + } while (0) + +/** + * @brief cvector_shrink_to_fit - requests the container to reduce its capacity to fit its size + * @param vec - the vector + * @return void + */ +#define cvector_shrink_to_fit(vec) \ + do { \ + if (vec) { \ + const size_t cv_sz___ = cvector_size(vec); \ + cvector_grow(vec, cv_sz___); \ + } \ + } while (0) + +/** + * @brief cvector_at - returns a reference to the element at position n in the vector. + * @param vec - the vector + * @param n - position of an element in the vector. + * @return the element at the specified position in the vector. + */ +#define cvector_at(vec, n) \ + ((vec) ? (((int)(n) < 0 || (size_t)(n) >= cvector_size(vec)) ? NULL : &(vec)[n]) : NULL) + +/** + * @brief cvector_front - returns a reference to the first element in the vector. Unlike member cvector_begin, which returns an iterator to this same element, this function returns a direct reference. + * @return a reference to the first element in the vector container. + */ +#define cvector_front(vec) \ + ((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, 0) : NULL) : NULL) + +/** + * @brief cvector_back - returns a reference to the last element in the vector.Unlike member cvector_end, which returns an iterator just past this element, this function returns a direct reference. + * @return a reference to the last element in the vector. + */ +#define cvector_back(vec) \ + ((vec) ? ((cvector_size(vec) > 0) ? cvector_at(vec, cvector_size(vec) - 1) : NULL) : NULL) + +/** + * @brief cvector_resize - resizes the container to contain count elements. + * @param vec - the vector + * @param count - new size of the vector + * @param value - the value to initialize new elements with + * @return void + */ +#define cvector_resize(vec, count, value) \ + do { \ + if (vec) { \ + size_t cv_sz_count__ = (size_t)(count); \ + size_t cv_sz__ = cvector_vec_to_base(vec)->size; \ + if (cv_sz_count__ > cv_sz__) { \ + cvector_reserve((vec), cv_sz_count__); \ + cvector_set_size((vec), cv_sz_count__); \ + do { \ + (vec)[cv_sz__++] = (value); \ + } while (cv_sz__ < cv_sz_count__); \ + } else { \ + while (cv_sz_count__ < cv_sz__--) { \ + cvector_pop_back(vec); \ + } \ + } \ + } \ + } while (0) + +#endif /* CVECTOR_H_ */ diff --git a/include/main.h b/include/main.h new file mode 100644 index 0000000..9cdf6ac --- /dev/null +++ b/include/main.h @@ -0,0 +1,9 @@ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#include "types.h" + + +extern const s8 *program_name; + +#endif /* __MAIN_H__ */ diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..9c92d57 --- /dev/null +++ b/include/types.h @@ -0,0 +1,17 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +#include <stdint.h> + + +typedef char s8; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; + +#endif /* __TYPES_H__ */ diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..29c59f1 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,11 @@ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include <stdnoreturn.h> + +#include "types.h" + + +noreturn void die(i32 code, s8 *fmt, ...); + +#endif /* __UTILS_H__ */ diff --git a/src/cccl.c b/src/cccl.c new file mode 100644 index 0000000..1803fcf --- /dev/null +++ b/src/cccl.c @@ -0,0 +1,80 @@ +#include "cccl.h" +#include "types.h" + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include "cvector.h" +#include "utils.h" + + +static cccl pc = {0}; + +void cccl_init(s8 *filename) +{ + memset(&pc, 0, sizeof(pc)); + + cvector_init(pc.stack, 1, NULL); + cvector_init(pc.variables, 1, NULL); + cvector_init(pc.procedures, 1, NULL); + cvector_init(pc.ep_stack, 1, NULL); + if (errno) die(1, strerror(errno)); + + pc.filename = filename; +} + +void cccl_free() +{ + cvector_free(pc.stack); + cvector_free(pc.variables); + cvector_free(pc.procedures); + cvector_free(pc.ep_stack); + free(pc.code); +} + +void cccl_read(void) +{ + s8 chr; + FILE *file = fopen(pc.filename, "r"); + if (errno) die(1, strerror(errno)); + fseek(file, 0, SEEK_END); + pc.size = ftell(file); + fseek(file, 0, SEEK_SET); + pc.code = calloc(pc.size + 1, sizeof(s8)); + + for (u32 i = 0; i < pc.size; ++i) + { + if ((chr = fgetc(file)) == EOF) + { + if (errno) + { + fclose(file); + die(1, strerror(errno)); + } + else + { + break; + } + } + pc.code[i] = chr; + } + fclose(file); +} + +void cccl_run(void) +{ + bool is_comment; + for (pc.ep = 0; pc.ep < pc.size; ++pc.ep) + { + if (is_comment && pc.code[pc.ep] == '\n') + is_comment = false; + switch (pc.code[pc.ep]) + { + case '/': + is_comment = true; + break; + } + } +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..36cdf5b --- /dev/null +++ b/src/main.c @@ -0,0 +1,56 @@ +#include "main.h" +#include "types.h" + +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdnoreturn.h> + + +const s8 *program_name; + +static const s8 *const usage_message = + "usage: %s [-h] file\n"; +static const s8 *const usage_description = + "ccl language interpreter\n" + "Arguments:\n" + " file file to execute\n" + "Options\n" + " -h, --help show this help message and quit\n"; + +static struct option long_options[] = +{ + {"help", no_argument, NULL, 'b'}, + {0} +}; + +noreturn void usage(bool full) +{ + printf(usage_message, program_name); + if (full) printf(usage_description); + exit(full ? 0 : 1); +} + +int main(i32 argc, s8 **argv) +{ + program_name = argv[0]; + + i32 ch; + while ((ch = getopt_long(argc, argv, "h", long_options, NULL)) != EOF) + { + switch (ch) + { + case 'h': + usage(true); + break; + default: + usage(false); + break; + } + } + if (argv[optind] == NULL) + usage(false); + + return 0; +} diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..ee37110 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,23 @@ +#include "utils.h" +#include "types.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdnoreturn.h> + +#include "main.h" + + +noreturn void die(i32 code, s8 *fmt, ...) +{ + va_list args; + + fprintf(stderr, "%s: ", program_name); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + exit(code); +} |