diff --git a/Array/include/array.h b/Array/include/array.h new file mode 100644 index 0000000..065a85a --- /dev/null +++ b/Array/include/array.h @@ -0,0 +1,46 @@ +#ifndef ARRAY_H +# define ARRAY_H + +# include + +typedef struct { + int len; + Var *members; +} Array; + +static Status ArrayIndexOutOfBound = { + .description = "Given index was accessing illegal address.", + .characteristic = STATUS_ERROR, + .prev = &MemoryViolation +}; + +static Status InvalidArrayLength = { + .description = "Given length is invalid.", + .characteristic = STATUS_ERROR, + .prev = &ErrorStatus +}; + +/* Elementary. */ +Status Array_Create(Array *inst, int len); +Status Array_CopyOf(Array *inst, Array *other); +Status Array_Delete(Array *inst); +Status Array_GetIdx(Array *inst, Var *store, int index); +Status Array_SetIdx(Array *inst, Var *source, int index); +Status Array_Literalise(Array *inst, char const *store); +bool Array_Equal(Array *arr1, Array *arr2); + +/* Extensional. */ +Status ArrayUtils_Insert(Array *inst, Var *item, int index); +Status ArrayUtils_InsertArray(Array *inst, Array *items, int index); +Status ArrayUtils_Remove(Array *inst, int index); +Status ArrayUtils_RemoveArray(Array *inst, int off, int len); +Status ArrayUtils_Subarray(Array *inst, Array *store, int off, int len); +Status ArrayUtils_Fill(Array *inst, Var *elem, int off, int len); +Status ArrayUtils_Search(Array *inst, Var *item, int *store); +Status ArrayUtils_SearchArray(Array *inst, Array *items, int *store); +Status ArrayUtils_Split(Array *inst, Array *fore, Array *rear, int index); +Status ArrayUtils_Revert(Array *inst); +bool ArrayUtils_IsEmpty(Array *inst); +bool ArrayUtils_IsBlank(Array *inst); + +#endif /* ARRAY_H */ diff --git a/Array/src/array.c b/Array/src/array.c new file mode 100644 index 0000000..e30c91f --- /dev/null +++ b/Array/src/array.c @@ -0,0 +1,83 @@ +#include + +Status Array_Create(Array *inst, int len) +{ + /* Skip unavailable inst and invalid param. */ + fails(inst, UnavailableInstance); + state((len < 0), InvalidArrayLength); + solve((!len), { inst->len = 0; inst->members = NULL; return NormalStatus; }) + + +} + +Status Array_CopyOf(Array *inst, Array *other) +{ + /* Skip unavailable inst and invalid param. */ + fails(inst, UnavailableInstance); + +} + +Status Array_Delete(Array *inst) +{ + /* Skip unavailable inst and invalid param. */ + fails(inst, UnavailableInstance); + +} + +Status Array_GetIdx(Array *inst, Var *store, int index) +{ + /* Skip unavailable inst and invalid param. */ + fails(inst, UnavailableInstance); + +} + +Status Array_SetIdx(Array *inst, Var *source, int index) +{ + /* Skip unavailable inst and invalid param. */ + fails(inst, UnavailableInstance); + +} + +Status Array_Literalise(Array *inst, char const *store) +{ + /* Skip unavailable inst and invalid param. */ + fails(inst, UnavailableInstance); + +} + +bool Array_Equal(Array *arr1, Array *arr2) +{ + /* Skip unavailable inst and invalid param. */ + state((arr1 == NULL || arr2 == NULL), false); + +} + + + + +// Status Array_Create(Array *inst, int len) +// { +// fails(inst, UnavailableInstance); +// state(len < 0, InvalidArrayLength); + +// Var arr[len] = {}; +// *inst = (Array) { +// .len = len, +// .members = arr +// }; + +// /* Initialise members. */ +// for (register int i = 0; i < inst->len; i++) { +// state(!(StatusUtils_IsOkay(Var_Create(&inst->members[i], NULL, 0, NULL))), +// error(RuntimeError, +// "Failed initialisations on var_create for array_create.")); +// } + +// return NormalStatus; +// } + +// Status Array_Delete(Array *inst); + +// bool ArrayUtils_IsEmpty(Array *inst); + +// bool Array_Equal(Array *arr1, Array *arr2); diff --git a/CMakeLists.txt b/CMakeLists.txt index 232f641..d15ae8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,14 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 3.5) project (Compound) -add_executable(CompoundTest test.c) +add_compile_options(-g -std=c99 -Wall -Wextra -Wformat) + +add_executable(CompoundTest test.c + Var/src/var.c + Status/src/status.c + Stack/src/stack.c + Array/src/array.c + Utils/src/utils.c + catlog.c + name.c) diff --git a/MemMan/include/memman.h b/MemMan/include/memman.h index bebc8da..5bad53d 100644 --- a/MemMan/include/memman.h +++ b/MemMan/include/memman.h @@ -1,8 +1,8 @@ -#ifndef MEMMAN_H -#define MEMMAN_H +#ifndef COMPOUND_MEMMAN_H +# define COMPOUND_MEMMAN_H -#include -#include +# include +# include /* Higher the priority it is, the less time for lifespan it has. @@ -10,48 +10,44 @@ typedef struct { void *addr; - int priority; // -1 for manual -} Memory; + size_t length; + int priority; // Negative for manual; Higher than 0 it is, + // higher the priority is. +} Memory; // 20 Bytes typedef struct { Memory *members; - size_t poolsize; + size_t volume; int priority; } MemoryPool; typedef struct { MemoryPool *members; void *(*allocator)(size_t sz); - void (*delocator)(void *addr); + void (*deallocator)(void *addr); } MemoryPoolManager; -Status memman_memory_allocate(Memory *inst, size_t sz); -Status memman_memory_reallocate(Memory *inst, size_t sz); -void memman_memory_release(Memory *inst); +Status MemMan_Memory_Allocate(Memory *inst, size_t length); +Status MemMan_Memory_Reallocate(Memory *inst, size_t length); +void MemMan_Memory_Release(Memory *inst); +Status MemMan_Memory_Prioritise(Memory *inst); +Status MemMan_Memory_Deprioritise(Memory *inst); +bool MemMan_Memory_Equal(Memory *inst, Memory *other); -Status memman_memorypool_create(MemoryPool *inst, Memory **members, - size_t poolsize); -Status memman_memorypool_constr(MemoryPool *inst, Memory **members, - size_t poolsize, int priority); -Status memman_memorypool_allocate(MemoryPool *inst, int idx, size_t sz); -Status memman_memorypool_reallocate(MemoryPool *inst, int idx, size_t sz); -Status memman_memorypool_release(MemoryPool *inst, int idx); -Status memman_memorypool_prioritise(MemoryPool *inst, int idx); -Status memman_memorypool_deprioritise(MemoryPool *inst, int idx); -void memman_memorypool_delete(MemoryPool *inst); +Status MemMan_MemoryPool_Create(MemoryPool *inst, size_t volume); +Status MemMan_MemoryPool_Constr(MemoryPool *inst, size_t volume, int priority); +Status MemMan_MemoryPool_AllocateAt(MemoryPool *inst, int idx, size_t sz); +Status MemMan_MemoryPool_ReallocateAt(MemoryPool *inst, int idx, size_t sz); +Status MemMan_MemoryPool_ReleaseAt(MemoryPool *inst, int idx); +void MemMan_MemoryPool_Delete(MemoryPool *inst); -Status memman_memorypoolmanager_create(MemoryPoolManager *inst, - MemoryPool **membersptr); -Status memman_memorypoolmanager_constr(MemoryPoolManager *inst, - MemoryPool **membersptr, +Status MemMan_MemoryPoolManager_Create(MemoryPoolManager *inst, + MemoryPool **members); +Status MemMan_MemoryPoolManager_Constr(MemoryPoolManager *inst, + MemoryPool **members, void *(*allocator)(size_t sz), - void (*delocator)(void *addr)); -Status memman_memorypoolmanager_addmember(MemoryPoolManager *inst, - MemoryPool *newmember); -Status memman_memorypoolmanager_removemember(MemoryPoolManager *inst, int idx); -Status memman_memorypoolmanager_allocate(MemoryPoolManager *inst, - ArrayIndexerRange selected, size_t sz); -Status memman_memorypoolmanager_release(MemoryPoolManager *inst, - ArrayIndexerRange selected); + void (*deallocator)(void *addr)); +Status MemMan_MemoryPoolManager_Merge(MemoryPool *pool1, MemoryPool *pool2); +Status MemMan_MemoryPoolManager_Divide(MemoryPool *src, int off, int len); -#endif /* MEMMAN_H */ +#endif /* COMPOUND_MEMMAN_H */ diff --git a/Object/include/object.h b/Object/include/object.h new file mode 100644 index 0000000..1a589bc --- /dev/null +++ b/Object/include/object.h @@ -0,0 +1,110 @@ +#ifndef COMPOUND_OBJECT_H +# define COMPOUND_OBJECT_H + +# include +# include +# include + +typedef struct { // interface + Var *data; + Array buffer; + int (*Literalise)(void); + int (*Correspond)(Var *other); +} Object; + +# define OBJECT_IMPLEMENTATION Var *data; Array buffer;\ + int (*Literalise)(void); int (*Correspond)(Var *other); + +// private final String IDENTITY = ":D"; +// public static final void main(String[] args) {} + +typedef enum { + EXPOSURE_PUBLIC = 0, + EXPOSURE_PROTECTED, + EXPOSURE_PACKAGE, + EXPOSURE_PRIVATE +} Exposure; + +typedef struct { + Type type; + Name identity; +} Parameter; + +typedef struct { + Type type; + Name identity; + Array parameters; +} Function; + +typedef struct { + Exposure prefix; + bool dynamic; + bool constant; + Type type; + Name identity; + Array type(Parameter) parameters; +} Member; + +typedef struct { + Exposure prefix; + Name identity; + Array type(Parameter) parameters; +} Constructor; + +/* As for destructors, they don't have prefixes or parameters, + because at the time you need destructors, you're already talking + in a environment that is private, private to this class alone. + And you also won't need any parameters, because to destruct, everything + you store in this class is bound to be vanished, and whatever you do to + modify them, the results are the same. + However, if you'd like to change something else that is not belong to + this class, why don't you just do them before calling destructors? + Therefor, in real practices, you won't find anything meaningful to let + a destructor having a prefix or a parameter. + + Summary. + Prefixes are fixed to be "Private"; + Parameters are fixed to be void. + */ +typedef struct { + Name identity; +} Destructor; + +typedef struct { + OBJECT_IMPLEMENTATION + + char *identity; + + Array type(Member type(Constructor)) constructors; // Array> + Member type(Destructor) destructor; // Member + + Array type(Member type(?)) fields; // Array> + Array type(Member type(?)) methods; // Array> +} Class; + +typedef enum { + MEMBER_ACCESS_READ = 0b001, + MEMBER_ACCESS_WRITE = 0b010, + MEMBER_ACCESS_EXEC = 0b100, +} MemberAccessMode; + +Status Extern(Class *inst, Class *extrn); +Status Implement(Class *inst, Class *impl); + +Status Class_Create(Class *inst, char *identity); +Status Class_CopyOf(Class *inst, Class *other); +Status Class_Constr(Class *inst, Array buffer, int (*Literalise)(void), + int (*Correspond)(Var*)); +Status Class_Delete(Class *inst); +Status Class_GetIdentity(Class *inst, char *store); +Status Class_GetObject(Class *inst, Object *store); +Status Class_GetFieldByIdentity(Class *inst, Name *identity, Member *store) + throws(MemberNotFound); +Status Class_GetMethodByIdentity(Class *inst, Name *identity, Member *store) + throws(MemberNotFound); +Status Class_GetMembers(Class *inst, Array *store); +Status Class_MemberAccess(Class *inst, MemberAccessMode mode, Member *store); +Status Class_AddMember(Class *inst, int index, Member *target); +Status Class_RemoveMember(Class *inst, int index); + +#endif /* COMPOUND_OBJECT_H */ diff --git a/Object/src/object.c b/Object/src/object.c new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e0814fb --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# YOU NEED COMPOUND + +Generally, Compound is a library for general-purposes programming which you will find essential for higher level of abstraction based on c. + +It is worth noticing that, this library is completely aimed for creating another language. That means, every feature update is supposedly to serve the language. + +--- +## BUILDING + +To build Compound, all you need is to type as follow in a terminal: +```shell +cmake . # Generate "Makefile" +make # Build +``` + +> *PLEASE NOTICE* +> *Compound is originally designed for GNU/Linux and other Unix-like operating systems.* +> *Support for MS Windows will be possible in the future.* + +### Platform specifications +```C +/* Copied on Fri 10 May 16:24:09 CST 2024 */ + +# if defined __x86_64__ || defined __x86_64 // For 64-bits operating systems. +# define __COMPOUND_64__ +# define __COMPOUND_PRODUCT__ compound64 +# elif defined __i386__ || __i486__ || __i586__ || __i686__ || _X86_ || __X86__ // For 32-bits operating systems. +# define __COMPOUND_32__ +# define __COMPOUND_PRODUCT__ compound32 +# else +# error Platform not supported. Please issue this on github.com/Wilhelm-Lee/Compound --William +# endif +``` +Compound, now, roughly divides platform compatibilities into 2 major parts, the 64-bits and the 32-bits. +This idea is ready for refinements, you can put up such suggestions and they're welcomed. + +## Installation +To install Compound, all you need to do is to run `install`, something like below. +```shell +./install # (Require root privilege) +``` + +If you cannot execute ./install script, try to add permission for execution: +```shell +chmod +x ./install # (Require root privilege) +``` diff --git a/Stack/include/stack.h b/Stack/include/stack.h new file mode 100644 index 0000000..a92ceaf --- /dev/null +++ b/Stack/include/stack.h @@ -0,0 +1,18 @@ +#ifndef STACK_H +# define STACK_H + +# include +# include + +typedef struct { + Var *members; + int len; +} Stack; + +Status Stack_Create(Stack *inst, int len); +Status Stack_CopyOf(Stack *inst, Stack *other); +Status Stack_Push(Stack *inst, Var *item); +Status Stack_Pop(Stack *inst); +bool Stack_IsEmpty(Stack *inst); + +#endif /* STACK_H */ diff --git a/Stack/src/stack.c b/Stack/src/stack.c new file mode 100644 index 0000000..0931d82 --- /dev/null +++ b/Stack/src/stack.c @@ -0,0 +1,28 @@ +#include + +Status Stack_Create(Stack *inst, int len) +{ + // /* Skip once len is negative. */ + // state((len < 0), InvalidParameter); + + // /* Initialise before access. */ + // if (inst == NULL) { + // *inst = (Stack) { + // .members = NULL, + // .len = len + // }; + + // /* Assign for each member. */ + // inst->members = malloc(len * sizeof(Var)); + // for (register int i = 0; i < len; i++) { + // inst->members[i] = (Var) { + // .addr = NULL, + // .sz = 0 + // }; + // } + // } +} +Status Stack_CopyOf(Stack *inst, Stack *other); +Status Stack_Push(Stack *inst, Var *item); +Status Stack_Pop(Stack *inst); +bool Stack_IsEmpty(Stack *inst); diff --git a/Status/include/status.h b/Status/include/status.h index fecc837..475f43a 100644 --- a/Status/include/status.h +++ b/Status/include/status.h @@ -9,7 +9,9 @@ # include # include -# define __HERE__ { .file = __FILE__, .line = __LINE__, .func = __func__ } +# include +# include +# include /* Status characteristics */ typedef enum { @@ -18,22 +20,30 @@ typedef enum { STATUS_ERROR = 1 } StatusCharacteristics; -//!!! UNKNOWN ENTITY !!! -// enum { -// ARGUE_FINALISED = 0b01, -// ARGUE_UNSETTLED =-0b01, -// ARGUE_POSITIVE = 0b10, -// ARGUE_NEGATIVE = -0b10, -// }; +typedef enum { + /* Settlement. */ + ARGUE_RESULT_FINALISED = 0b01, + ARGUE_RESULT_UNSETTLED = -0b01, + + /* Nature. */ + ARGUE_RESULT_POSITIVE = 0b10, + ARGUE_RESULT_NEGATIVE = -0b10, +} ArgueResult; /* Indicated the exact location where the "issue" was occurred at. */ typedef struct { - const char *file; + char *file; int line; - const char *func; + char *func; } Location; +# define __HERE__ (Location){ \ + .file = (char *)__FILE__, \ + .line = __LINE__, \ + .func = (char *)__func__ \ +} + /* Common return type for reporting functions that require to give more information about the procedure. */ typedef struct _Status { @@ -43,36 +53,41 @@ typedef struct _Status { Otherwise, the function would just return the structure Status. */ char *description; int characteristic; + Location loc; struct _Status *prev; } Status; -/* "Report" recollects essential informations, included but not limited to - Status and others for making an report for debugging and such. */ -typedef struct { - Status stat; - Location pos; - char *originator; - struct tm time; - int priority; -} Report; +/* -typedef struct { - FILE **dests_ref; - Report **reports_ref; - int totalreports; - int reportsent; - struct timespec elapsed; -} ReportSender; +{value "description" characteristic prev} -typedef Status (*ReportSendingTask) (FILE **, Report *); -typedef int ReportSendingTaskID; +"%d \"%s\" %d %p" -typedef struct { - ReportSendingTask *tasks_ref; - int sendercount; - int finishedcount; - Status *senderreturn; -} ReportSendingManager; +*/ + +# ifdef __COMPOUND_32__ +# define STATUS_LITERALISE_LENGTH(stat) \ + (utils_calc_digits(stat.value) + strlen(stat.description) + 2 + \ + utils_calc_digits(INT32_DIGITS_DEC)) +# elif defined __COMPOUND_64__ +# define STATUS_LITERALISE_LENGTH(stat) \ + (utils_calc_digits(stat.value) + strlen(stat.description) + 2 + \ + utils_calc_digits(INT64_DIGITS_DEC)) +# endif + +# define STATUS_LITERALISE_FORMAT "%d \"%s\" %d %p" + +typedef enum { + REPORT_SENDING_PRIORITY_ALL = 0, // Highest level; least value. + REPORT_SENDING_PRIORITY_FATAL, + REPORT_SENDING_PRIORITY_EXCEPTIONAL, + REPORT_SENDING_PRIORITY_CRITICAL, + REPORT_SENDING_PRIORITY_MAJOR, + REPORT_SENDING_PRIORITY_NORMAL, + REPORT_SENDING_PRIORITY_MINOR, + REPORT_SENDING_PRIORITY_DEBUG, + REPORT_SENDING_PRIORITY_NONE, // Lowest level, greatest value. +} ReportSendingPriority; typedef enum { REPORT_SENDING_TASK_STATUS_FINISHED = 0, @@ -82,30 +97,97 @@ typedef enum { REPORT_SENDING_TASK_STATUS_NOTFOUND } ReportSendingTaskStatus; -typedef Status (*Argue) (Report); - +/* "Report" recollects essential informations, included but not limited to + Status and others for making an report for debugging and such. */ typedef struct { - Argue argue_start; // Implicitly converting thrd_start_t to Argue - void *external_param; -} ArgueStarter; + Status stat; + char *originator; + time_t time; + ReportSendingPriority priority; + ReportSendingTaskStatus status; + FILE *dest; // The destination where the report is sending to. +} Report; + +/* + +TIME [PRIORITY] STATUSNAME (ORIGINATOR): STATUS.DESCRIPTION + at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC + at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC + at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC + at LOCATION.FILE:LOCATION.LINE, LOCATION.FUNC + + +Fri 10 May 03:02:37 CST 2024 [EXCEPTIONAL] InvalidParameter (Nullity): Given buffer was unavailable. + at /external/Documents/Projects/Compound/Status/src/status.c:104, report_literalise + at /external/Documents/Projects/Compound/Status/src/status.c:114, reportsender_send + at /external/Documents/Projects/Compound/Status/src/status.c:69, _throw +!!!!at /external/Documents/Projects/Compound/Array/src/array.c:16, array_create + at /external/Documents/Projects/Compound/test.c:24, main + +*/ + +# define REPORT_LITERALISE_HEADER_FORMAT "%ld [%s] %s (%s): %s" +# define REPORT_LITERALISE_CHAINS_FORMAT " at %s:%d, %s" +# define REPORT_LITERALISE_CHAINS_EXCLAIM_FORMAT "!!!!at %s:%d, %s" + +# define REPORT_LITERALISE_HEADER_FORMAT_LENGTH(PRIORITY, STATUSNAME, \ + ORIGINATOR, DESCRIPTION) \ + (INT64_DIGITS_DEC + strlen(PRIORITY) + strlen(STATUSNAME) + \ + strlen(ORIGINATOR) + strlen(DESCRIPTION) + 9) // Does not count '\0' +# define REPORT_LITERALISE_CHAINS_FORMAT_LENGTH(FILEPATH, LINE, FUNCNAME) \ + (strlen(FILEPATH) + utils_calc_digits(LINE) + \ + strlen(FUNCNAME) + 10) // Does not count '\0' +# define REPORT_LITERALISE_CHAINS_EXCLAIM_FORMAT_LENGTH \ + REPORT_LITERALISE_CHAINS_FORMAT_LENGTH -/* Argument levels (qualities) */ typedef enum { - ARGUMENT_NONE = 0, - ARGUMENT_MINOR, - ARGUMENT_NORMAL, - ARGUMENT_MAJOR, - ARGUMENT_CRITICAL, - ARGUMENT_SEVERE, - ARGUMENT_ALL, -} ArgumentLevel; + REPORT_SENDER_RESULT_FINISHED, + REPORT_SENDER_RESULT_PROGRESSING, + REPORT_SENDER_RESULT_PENDING +} ReportSenderResult; typedef struct { - ReportSender *streams; - ArgueStarter handler; - ArgumentLevel level; - bool muted; -} Argument; + thrd_t thread; + Report *report; // The report for sending. + time_t elapsed; // The individual elapsed time for each report. (Array) + ReportSenderResult result; + bool successful; +} ReportSender; + +typedef int (*ReportSendingTask)(Report *rep); +typedef int ReportSendingTaskID; + +typedef struct { + ReportSendingTask *tasks; // Array Ref + int sendercount; + int finishedcount; + int *results; // Array +} ReportSendingManager; + +// typedef thrd_start_t ArgueStart; + +// typedef struct { +// ArgueStart handler; +// void *external_param; +// } ArgueStartParam; + +// /* Argument levels (qualities) */ +// typedef enum { +// ARGUMENT_NONE = 0, +// ARGUMENT_MINOR, +// ARGUMENT_NORMAL, +// ARGUMENT_MAJOR, +// ARGUMENT_CRITICAL, +// ARGUMENT_SEVERE, +// ARGUMENT_ALL, +// } ArgumentLevel; + +// typedef struct { +// ReportSender stream; +// ArgueStartParam handler; // Obsolete? +// ArgumentLevel level; +// bool muted; +// } Argument; // typedef struct { // Argument *members; @@ -114,73 +196,58 @@ typedef struct { # define STATUS_BUFFER_MAXIMUM_LENGTH UINT32_MAX +bool Location_Equal(Location lc1, Location lc2); +void Status_Dump(Status stat, Status *statbuff, int idx); +bool Status_Equal(Status stat1, Status stat2); +bool StatusUtils_HasPrev(Status stat); +bool StatusUtils_IsOkay(Status stat); +bool StatusUtils_IsValid(Status stat); +bool StatusUtils_IsRecursive(Status stat); +int StatusUtils_Depth(Status *stat); +Status +Report_Create(Report *inst, Status *stat, FILE *dest, char *originator, + int priority); bool -status_issueposition_compare(Location lc1, Location lc2); -bool -status_hasprev(Status stat); -bool -status_isnormal(Status stat); -bool -status_isvalid(Status stat); -bool -status_recursive(Status stat); -void -status_dump(Status stat, Status *statbuff, int idx); -bool -status_compare(Status stat1, Status stat2); - - -bool -report_compare(Report repo1, Report repo2); +Report_Equal(Report repo1, Report repo2); +Status +Report_Literalise(Report *inst, char *buff); Status -reportsender_create(ReportSender *inst, FILE **dests_ref, - ReportSendingTask *tasks_ref); +ReportSender_Create(ReportSender *inst, Report *report); Status -reportsender_send(ReportSender sender, ReportSendingTask *tasks_ref); - +ReportSender_Send(ReportSender *inst, ReportSendingTask task); +ReportSendingTaskStatus +ReportSender_GetStatus(ReportSender *inst); ReportSendingTaskID -reportsendingmanager_appendtask(ReportSendingManager *inst, +ReportSenderManager_AppendTask(ReportSendingManager *inst, ReportSendingTask task); -Status -reportsendingmanager_removetask(ReportSendingManager *inst, - ReportSendingTaskID taskid); -ReportSendingTaskStatus -reportsendingmanager_taskstatus(ReportSendingManager *inst, - ReportSendingTaskID taskid); +Status ReportSenderManager_RemoveTask(ReportSendingManager *inst, + ReportSendingTaskID taskid); + +// Status +// arguestarter_create(ArgueStartParam *inst, void *external_param); +// Status +// arguestarter_constr(ArgueStartParam *inst, ArgueStart argue_start, +// void *external_param); +// Status +// arguestarter_start(ArgueStartParam *inst); +// bool +// arguestarter_equal(ArgueStartParam *inst1, ArgueStartParam *inst2); +// Status arguestarter_current(void); +// Status arguestarter_sleep(const struct timespec *time_point, +// struct timespec *remaining); +// void arguestarter_exit(int code) __attribute__ ((__noreturn__)); +// Status arguestarter_join(ArgueStart thrd); -Status -arguestarter_create(ArgueStarter *inst, void *external_param); -Status -arguestarter_constr(ArgueStarter *inst, Argue argue_start, - void *external_param); -Status -arguestarter_start(ArgueStarter *inst); -static inline int -arguestarter_equal(ArgueStarter *inst1, ArgueStarter *inst2) -{ - return (inst1->argue_start == inst2->argue_start) - || (inst1->external_param == inst2->external_param); -} -Status arguestarter_current(void); -Status arguestarter_sleep(const struct timespec *time_point, - struct timespec *remaining); -void arguestarter_exit(int code) __attribute__ ((__noreturn__)); -Status arguestarter_join(Argue thrd); +// Status +// argument_create(Argument *inst, ReportSender *streams, ArgueStartParam handler, +// int level, bool muted); - -Status -argument_create(Argument *inst, ReportSender *streams, ArgueStarter handler); -Status -argument_constr(Argument *inst, ReportSender *streams, ArgueStarter handler, - int level, bool muted); - - -// -------------------------------------------------------- +// ---------------------ELEMENTARY------------------------- static Status UnknownStatus = { .description = "An unknown status.", @@ -200,12 +267,18 @@ static Status ErrorStatus = { .prev = NULL }; -// -------------------------------------------------------- +// ----------------------EXTENDED-------------------------- + +static Status MemoryViolation = { + .description = "Illegal access on certain memory address.", + .characteristic = STATUS_ERROR, + .prev = &ErrorStatus +}; static Status NullPointerAccounted = { .description = "An involving null pointer was not accepted.", .characteristic = STATUS_ERROR, - .prev = &ErrorStatus + .prev = &MemoryViolation }; static Status InvalidParameter = { @@ -226,4 +299,127 @@ static Status ArithmeticError = { .prev = &ErrorStatus }; +static Status RuntimeError = { + .description = "A runtime error occurred.", + .characteristic = STATUS_ERROR, + .prev = &ErrorStatus +}; + +static Status ArrayLengthError = { + .description = "Given array length does not meet the requirement.", + .characteristic = STATUS_ERROR, + .prev = &ErrorStatus +}; + +static Status VariableFormatMismatch = { + .description = "Given format does not match with given subjects.", + .characteristic = STATUS_ERROR, + .prev = &ErrorStatus +}; + +static Status ImprecisionError = { + .description = "Precision was not enough for handling the calculation.", + .characteristic = STATUS_ERROR, + .prev = &RuntimeError +}; + +// ---------------USER DEFINED | RUNTIME------------------- + +static Status UnavailableInstance = { + .description = "An unavailable instance was given for initialisation.", + .characteristic = STATUS_ERROR, + .prev = &NullPointerAccounted +}; + +static Status UnavailableParameter = { + .description = "An unavailable instance was given as a parameter.", + .characteristic = STATUS_ERROR, + .prev = &UnavailableInstance +}; + +static Status InvalidReportTask = { + .description = "An unavailable or illegal report task was given.", + .characteristic = STATUS_ERROR, + .prev = &InvalidParameter +}; + +static Status UnableToThrowError = { + .description = "Unable to report an exceptional situation.", + .characteristic = STATUS_ERROR, + .prev = &RuntimeError +}; + +static Status ReadWriteError = { + .description = "Error occurred during IO session.", + .characteristic = STATUS_ERROR, + .prev = &RuntimeError +}; + +static Status FileNotFound = { + .description = "Target file was unavailable and unable to find.", + .characteristic = STATUS_ERROR, + .prev = &ReadWriteError +}; + +static Status InvalidFileName = { + .description = "Given file name was invalid.", + .characteristic = STATUS_ERROR, + .prev = &ReadWriteError +}; + +static Status ReportThrown = { + .description = "This function has thrown a report, " + "following instructions aborted.", + .characteristic = STATUS_ERROR, + .prev = &RuntimeError +}; + +static Status ReportMessageLengthTooLong = { + .description = "Given message is too long.", + .characteristic = STATUS_ERROR, + .prev = &ArrayLengthError +}; + +// ======================================================== + +# define ensure(e, c) { \ + Status stat = e; \ + solve(!(StatusUtils_IsOkay(stat)), { \ + Report rep = stamp(error(stat, c), (char *)__func__); \ + (void)throw(rep); \ + return ReportThrown; \ + }) \ +} + +/* Add location parameter requirement in order to give proper information + * before throwing the report out. */ +# define throw(report) __throw(report, __HERE__) + +/* Useless in C, only for human to see. + Probably rewrite this in Classify. */ +# define throws(e) + +ReportSendingTaskID __throw(Report report, Location loc); +Report catch(ReportSendingTaskID taskid); +static int HANDLER(void *report) +{ + /* Throw UnableToThrowError when param is unavailable. */ + if (report == NULL) { + /* Create report on this. */ + Report e; + Report_Create( + &e, + &error(UnableToThrowError, "Cannot perform throwing. Aborted."), + stderr, nameof(DEFAULT_ARGUE_STARTER), + REPORT_SENDING_PRIORITY_FATAL); + + /* Perform throwing. */ + (void)_throw(e); // Throw the report alone. + return 1; + } + + (void)_throw(*(Report *)report); // Lonely _throw, no catch will company. + return 0; +} + #endif /* COMPOUND_STATUS_H */ diff --git a/Status/src/status.c b/Status/src/status.c index fcb72be..1d08cb6 100644 --- a/Status/src/status.c +++ b/Status/src/status.c @@ -1,30 +1,174 @@ +#include #include -bool status_issueposition_compare(Location lc1, Location lc2) { +bool status_issuelocation_equal(Location lc1, Location lc2) { return ((!strcmp(lc1.file, lc2.file)) && (lc1.line == lc2.line) && (!strcmp(lc1.func, lc2.func))); } -bool status_hasprev(Status stat) { return (stat.prev != NULL); } +bool status_hasprev(Status stat) { + /* Skip when stat is unavailable for accessing. */ + state(status_equal(stat, (Status){}), false); -bool status_isnormal(Status stat) { return (!stat.characteristic); } + return (stat.prev != NULL); +} + +bool status_isokay(Status stat) { return (!stat.characteristic); } + +bool status_isvalid(Status stat) { + return (!strcmp(stat.description, "") && stat.characteristic >= 0 && + stat.prev != NULL); +} bool status_recursive(Status stat) { return (stat.prev != NULL && stat.prev == &stat); } -void status_dump(Status stat, Status *statbuff, int idx) { - if (statbuff == NULL || !status_hasprev(stat) || idx < 0) { - return; - } +void status_dump(Status inst, Status *statbuff, int idx) { - statbuff[idx] = stat; + /* Skip when either stat or stat.prev is unavailable, or, idx is invalid. */ + solve((statbuff == NULL || !status_hasprev(inst) || idx < 0), return;); - status_dump(*stat.prev, statbuff, ++idx); + statbuff[idx] = inst; + (void)printf("status_dump: Index %d has assigned with %p\n", idx, &inst); + + status_dump(*inst.prev, statbuff, ++idx); } -bool status_compare(Status stat1, Status stat2) { - return (!strcmp(stat1.description, stat2.description) && +bool status_equal(Status stat1, Status stat2) { + + /* Skip when both stat1 and stat2 are empty. */ + state((stat1.value == 0 && stat2.value == 0 && stat1.description == 0x0 && + stat2.description == 0x0 && stat1.characteristic == 0 && + stat2.characteristic == 0 && stat1.prev == 0x0 && stat2.prev == 0x0), + true); + + /* True for equality; False for inequality. */ + return ((stat1.value == stat2.value) && + (!strcmp(stat1.description, stat2.description)) && (stat1.characteristic == stat2.characteristic) && - (!status_compare(*stat1.prev, *stat2.prev))); + (status_equal(*stat1.prev, *stat2.prev))); +} + +int status_depth(Status *stat) { + /* Skip unavailable stat. */ + state((stat == NULL), -1); + + Status *p = stat; // Include this layer of Status. + int cnt = 1; + while (p != NULL) { + if (status_recursive(*p) || !status_hasprev(*stat)) break; + + p = p->prev; + cnt += 1; + } + + return cnt; +} + +Status report_create(Report *inst, Status *stat, FILE *dest, char *originator, + int priority) { + /* Skip unavailable parameters. */ + fails(inst, UnavailableInstance); + fails(stat, error(InvalidParameter, "Given originator was null.")); + fails(originator, error(InvalidParameter, "Given originator was null.")); + state(priority < 0, error(InvalidParameter, "Given priority was negative.")); + + /* Copy and assign. */ + inst->stat = *stat; + inst->originator = originator; + inst->time = time(NULL); + inst->priority = priority; + inst->status = REPORT_SENDING_TASK_STATUS_PENDING; + inst->dest = (dest == NULL ? stderr : dest); + + return NormalStatus; +} + +Status report_literalise(Report *inst, char *buff) { + /* Skip when inst or buff is unavailable. */ + fails(inst, UnavailableInstance); + fails(buff, error(InvalidParameter, "Given buffer was unavailable.")); + + const int depth = status_depth(&inst->stat); + char buff // TODO(william): HERE +} + +Status reportsender_create(ReportSender *inst, Report *report) { + fails(inst, UnavailableInstance); + fails(report, error(UnavailableParameter, "Given report was unavailable.")); + + thrd_create(&inst->thread, &HANDLER, report); + *inst->report = *report; + inst->elapsed = 0; + inst->result = REPORT_SENDER_RESULT_PENDING; + inst->successful = false; + + return NormalStatus; +} + +Status reportsender_send(ReportSender *inst, ReportSendingTask task) { + /* Skip when inst or task is unavailable. */ + fails(inst, + error(UnavailableInstance, "Report sender was given unavailable.")); + fails(task, InvalidReportTask); + + /* Assign for dest. */ + const FILE *dest = (inst->report->dest == NULL ? stdout : inst->report->dest); + // char buff[]; + // TODO(william): HERE, report_literalise + + /* Write/Send data. */ + inst->report->status = REPORT_SENDING_TASK_STATUS_PROCEEDING; + if (!fprintf(dest, buff)) { + } + + /* Sent successfully! Mark down properties. */ +} + +// bool arguestarter_equal(ArgueStarter *inst1, ArgueStarter *inst2) +// { +// /* Skip when either inst1 or inst2 is unavailable. */ +// state(inst1 == NULL || inst2 == NULL, false); + +// return (inst1->argue_start == inst2->argue_start) +// || (inst1->external_param == inst2->external_param); +// } + +ReportSendingTaskID _throw(Report report, Location loc) { + // /* Create new a instance of ReportSender. */ + // ReportSender sender; + // reportsender_create(&sender, stderr); + + // /* Send message. */ + // /* Initialise sender's thread. */ + // thrd_t sending; + // /* Skip on failing on creating thread. */ + // if (!thrd_create(&sending, starter, NULL)) { + + // /* Conclude the session of sender. */ + // report.status = REPORT_SENDING_TASK_STATUS_FINISHED, + // report.result = (ARGUE_RESULT_FINALISED | ARGUE_RESULT_NEGATIVE); + + // sender.result = REPORT_SENDER_RESULT_FINISHED; + // sender.successful = false; + + // return -1; + // } + + // /* Perform sending. */ + // reportsender_send(&sender, NULL); + + /* Initialise sender. */ + ReportSender sender; + /* Return with -1 when initialisation failed. */ + state(!(status_isokay(reportsender_create(&sender, &report))), -1); + + /* Inject location information. Could be more elegant, though. */ + sender.report->stat.loc = loc; + + /* Send. */ /* Return -1 when failed on sending. */ + state(!status_isokay(reportsender_send(&sender, HANDLER)), -1); + + } diff --git a/String/include/char.h b/String/include/char.h new file mode 100644 index 0000000..1cf242f --- /dev/null +++ b/String/include/char.h @@ -0,0 +1,9 @@ +#ifndef COMPOUND_CHAR_H +# define COMPOUND_CHAR_H + +typedef struct { + int value; + int width; +} Char; // 8 Bytes + +#endif /* COMPOUND_CHAR_H */ diff --git a/String/include/string.h b/String/include/string.h new file mode 100644 index 0000000..fb45682 --- /dev/null +++ b/String/include/string.h @@ -0,0 +1,97 @@ +#ifndef COMPOUND_STRING_H +# define COMPOUND_STRING_H + +# include +# include + +# include +# include + +typedef enum { + ASCII, + UTF8, + /* etc. */ +} StringEncoding; + +typedef Array(Char) String; + +/* Elementary. */ +Status String_Create(String *inst, int len); +Status String_CopyOf(String *inst, String *other); +Status String_Delete(String *inst); +Status String_GetIdx(String *inst, Char *item, int index); +Status String_SetIdx(String *inst, Char *item, int index); +Status String_Literalise(String *inst, String *store); +Status String_Encode(String *inst, StringEncoding encoding) + throws(UnsupportedEncoding EncodingError DecodingError); +Status String_Decode(String *inst, StringEncoding encoding); + throws(UnsupportedEncoding EncodingError DecodingError); +bool String_Equal(String *arr1, String *arr2); + +/* Extensional. */ +Status StringUtils_FromInteger(String *inst, int value); +Status StringUtils_FromShortInteger(String *inst, short int value); +Status StringUtils_FromLongInteger(String *inst, long int value); +Status StringUtils_FromLongLongInteger(String *inst, long long int value); +Status StringUtils_FromFloat(String *inst, float value); +Status StringUtils_FromDouble(String *inst, double value); +Status StringUtils_FromLongDouble(String *inst, long double value); +Status StringUtils_FromComplexInteger(String *inst, _Complex int value); +Status StringUtils_FromComplexShortInteger(String *inst, _Complex short int value); +Status StringUtils_FromComplexLongInteger(String *inst, _Complex long int value); +Status StringUtils_FromComplexLongLongInteger(String *inst, _Complex long long value); +Status StringUtils_FromComplexFloat(String *inst, _Complex float value); +Status StringUtils_FromComplexDouble(String *inst, _Complex double value); +Status StringUtils_FromComplexLongDouble(String *inst, _Complex long double value); +Status StringUtils_FromUnsignedInteger(String *inst, unsigned int value); +Status StringUtils_FromUnsignedShortInteger(String *inst, unsigned short int value); +Status StringUtils_FromUnsignedLongInteger(String *inst, unsigned long int value); +Status StringUtils_FromUnsignedLongLongInteger(String *inst, unsigned long long int value); +Status StringUtils_FromUnsignedComplexInteger(String *inst, unsigned _Complex int value); +Status StringUtils_FromUnsignedComplexShortInteger(String *inst, unsigned _Complex short int value); +Status StringUtils_FromUnsignedComplexLongInteger(String *inst, unsigned _Complex long int value); +Status StringUtils_FromUnsignedComplexLongLongInteger(String *inst, unsigned _Complex long long value); +Status StringUtils_FromAddress(String *inst, void *store); +Status StringUtils_FromCharBuff(String *inst, char const *buff, int base); +Status StringUtils_FromWideCharBuff(String *inst, wchar_t const *wbuff, int base); +Status StringUtils_ToInteger(String *inst, int *store); +Status StringUtils_ToShortInteger(String *inst, short int *store); +Status StringUtils_ToLongInteger(String *inst, long int *store); +Status StringUtils_ToLongLongInteger(String *inst, long long int *store); +Status StringUtils_ToFloat(String *inst, float *store); +Status StringUtils_ToDouble(String *inst, double *store); +Status StringUtils_ToLongDouble(String *inst, long double *store); +Status StringUtils_ToComplexInteger(String *inst, _Complex int *store); +Status StringUtils_ToComplexShortInteger(String *inst, _Complex short int *store); +Status StringUtils_ToComplexLongInteger(String *inst, _Complex long int *store); +Status StringUtils_ToComplexLongLongInteger(String *inst, _Complex long long *store); +Status StringUtils_ToComplexFloat(String *inst, _Complex float *store); +Status StringUtils_ToComplexDouble(String *inst, _Complex double *store); +Status StringUtils_ToUnsignedInteger(String *inst, unsigned int *store); +Status StringUtils_ToUnsignedShortInteger(String *inst, unsigned short int *store); +Status StringUtils_ToUnsignedLongInteger(String *inst, unsigned long int *store); +Status StringUtils_ToUnsignedLongLongInteger(String *inst, unsigned long long int *store); +Status StringUtils_ToUnsignedComplexInteger(String *inst, unsigned _Complex int *store); +Status StringUtils_ToUnsignedComplexShortInteger(String *inst, unsigned _Complex short int *store); +Status StringUtils_ToUnsignedComplexLongInteger(String *inst, unsigned _Complex long int *store); +Status StringUtils_ToUnsignedComplexLongLongInteger(String *inst, unsigned _Complex long long *store); +Status StringUtils_ToAddress(String *inst, void **store); +Status StringUtils_ToCharBuff(String *inst, char const *buff, int base); +Status StringUtils_ToWideCharBuff(String *inst, wchar_t const *wbuff, int base); +Status StringUtils_Format(String *inst, const String *__restrict fmt, ...); +Status StringUtils_Tokenise(String *inst, const String *delim, String *store); +int StringUtils_Compare(String *a, String *b); + +static Status StringConversionPrecisionError = { + .description = "Unpreventable precision loss was found during conversion " + "between string and raw data.", + .characteristic = STATUS_ERROR, + .prev = &ImprecisionError +}; + +typedef Array(int) InfiniteInteger; +typedef Array(double) InfiniteFloatingPoint; +typedef Array(_Complex double) InfintieComplex; + + +#endif /* COMPOUND_STRING_H */ diff --git a/String/src/char.c b/String/src/char.c new file mode 100644 index 0000000..e69de29 diff --git a/String/src/string.c b/String/src/string.c new file mode 100644 index 0000000..b9c3f0d --- /dev/null +++ b/String/src/string.c @@ -0,0 +1,45 @@ +#include + +Status String_Create(String *inst, int len) +{ + Status create = Array_Create(inst, len); + solve(!(StatusUtils_IsOkay(create)), { + Report e = stamp(error(create, "Failed to create a string."), + nameof(Array_Create)); + (void)_throw(e); + return ReportThrown; + }) + + return NormalStatus; +} + +Status String_CopyOf(String *inst, String *other) +{ + fails(inst, UnavailableInstance); +} + +Status String_Delete(String *inst) +{ + fails(inst, UnavailableInstance); +} + +Status String_GetIdx(String *inst, Char *store, int index) +{ + fails(inst, UnavailableInstance); +} + +Status String_SetIdx(String *inst, Char *source, int index) +{ + fails(inst, UnavailableInstance); +} + +Status String_Literalise(String *inst, String *store) +{ + fails(inst, UnavailableInstance); +} + +bool String_Equal(String *arr1, String *arr2) +{ + fails(inst, UnavailableInstance); +} + diff --git a/Utils/include/utils.h b/Utils/include/utils.h new file mode 100644 index 0000000..a28fffe --- /dev/null +++ b/Utils/include/utils.h @@ -0,0 +1,9 @@ +#ifndef COMPOUND_UTILS_H +# define COMPOUND_UTILS_H + +# include +# include + +int Utils_CalcDigits(long long n); + +#endif /* COMPOUND_UTILS_H */ diff --git a/Utils/src/utils.c b/Utils/src/utils.c new file mode 100644 index 0000000..e33f767 --- /dev/null +++ b/Utils/src/utils.c @@ -0,0 +1,16 @@ +#include + +int Utils_CalcDigits(long long n) +{ + if (n == 0) { + return 1; + } + + n = llabs(n); + + /* Accumulate. */ + register int i; + for (i = 0; n; i++) n /= 10; + + return i; +} diff --git a/Var/include/var.h b/Var/include/var.h index 71824a3..9a23f77 100644 --- a/Var/include/var.h +++ b/Var/include/var.h @@ -2,18 +2,52 @@ # define COMPOUND_VAR # include -# include -# include -# include + # include +# include + +# define VAR_IDENTITY_LENGTH 64 +# define VAR_LITERALISE_LENGTH (VAR_IDENTITY_LENGTH + 16 + 9 + 10) +# define VAR_LITERALISE_FORMAT ("%s @[%p]: %ld") +# define VAR_IDENTITY_ILLEGAL_CHAR "!@#$%^*()-=+;\'\"\\|,./<>?[]{}`~ " + +static Status IllegalVarIdentity = { + .description = "Given identity does not fit the standard of Var Naming " + "convension.", + .characteristic = STATUS_ERROR, + .prev = &InvalidParameter +}; + +// static Status VarIdentityTooLong = { +// .description = "Given identity has longer length that the maximum length " +// "limitation.", +// .characteristic = STATUS_ERROR, +// .prev = &IllegalVarIdentity +// }; typedef struct { + + /* Data */ void *addr; - size_t sz; + size_t size; + + /* Identification */ + char *identity; // Maximum up to VAR_IDENTITY_LENGTH + } Var; -void var_swap(Var *v1, Var *v2); +// typedef struct { +// union { +// /* Self Pointing (Var) */ +// const Var *__this__; +// }; +// } _Var; -int var_literalise(Var v, wchar_t **wbuff); +Status Var_Create(Var *inst, void *addr, size_t size, char *identity); +Status Var_CopyOf(Var *inst, Var *other); +void Var_Delete(Var *inst); +Status VarUtils_Literalise(Var *inst, char *buff); +void VarUtils_Swap(Var *v1, Var *v2); +bool VarUtils_IsIdentityLegal(char *identity); #endif /* COMPOUND_VAR */ diff --git a/Var/src/var.c b/Var/src/var.c index 2325ee3..0f680f7 100644 --- a/Var/src/var.c +++ b/Var/src/var.c @@ -1,17 +1,94 @@ #include -void var_swap(Var *v1, Var *v2) +Status Var_Create(Var *inst, void *addr, size_t size, char *identity) { - Var v3 = { - .addr = v1->addr, - .sz = v1->sz - }; + /* Skip when inst is unavailable. */ + fails(inst, UnavailableInstance); + /* Skip when identity is unavailable. */ + fails(identity, NullPointerAccounted); + /* Skip when identity does not pass the examine. */ + state(!VarUtils_IsIdentityLegal(identity), IllegalVarIdentity); + + inst->addr = addr; + inst->size = size; + *inst->identity = *identity; + return NormalStatus; +} + +Status Var_CopyOf(Var *inst, Var *other) +{ + /* Skip when inst or other is unavailable. */ + fails(inst, UnavailableInstance); + fails(other, NullPointerAccounted); + + /* Copy and assign. */ + inst->addr = other->addr; + inst->size = other->size; + *inst->identity = *other->identity; + + return NormalStatus; +} + +void Var_Delete(Var *inst) +{ + /* Skip when inst or inst->addr is unavailable. */ + svoid(inst == NULL || inst->addr == NULL); + + inst->addr = NULL; + inst->size = 0; + *inst->identity = 0; +} + +void VarUtils_Swap(Var *v1, Var *v2) +{ + /* Skip when v1 or v2 is unavailable. */ + svoid(v1 == NULL || v2 == NULL); + + Var v3 = *v1; *v1 = *v2; *v2 = v3; } -int var_literalise(Var v, wchar_t **wbuff) +Status VarUtils_Literalise(Var *inst, char *buff) { - return swprintf(*wbuff, (2*8 + 6), L"@[%p] +%u", v.addr, v.sz); + /* Skip when inst is unavailable. */ + state(inst == NULL, UnavailableInstance); + + /* Write into buffer. */ + state(!sprintf(buff, VAR_LITERALISE_FORMAT, inst->identity, + inst->addr, inst->size), + error(RuntimeError, "Sprintf returned 0 where it should never do.")); + + return NormalStatus; +} + +bool VarUtils_IsIdentityLegal(char *identity) +{ + /* Skip when identity is unavailable. */ + state(identity == NULL, false); + + const int len = strlen(identity); + + /* Skip when identity is empty. */ + state(len == 0, false); + + /* Skip when the first char is not within alphabet. */ + state(ATRANGE('a', 'z', identity[0]) + || ATRANGE('A', 'Z', identity[0]), false); + + /* Skip when the length of identity is greater that VAR_IDENTITY_LENGTH. */ + state(len > VAR_IDENTITY_LENGTH, false); + + /* Skip when identity has space and illegal characters in it. */ + const int illegal_len = strlen(VAR_IDENTITY_ILLEGAL_CHAR); + for (register int i = 0; i < len; i++) { + for (register int j = 0; j < illegal_len; j++) { + if (identity[i] == VAR_IDENTITY_ILLEGAL_CHAR[j]) { + return false; + } + } + } + + return true; } diff --git a/attr.h b/attr.h new file mode 100644 index 0000000..2dd68df --- /dev/null +++ b/attr.h @@ -0,0 +1,27 @@ +#ifndef COMPOUND_ATTR_H +# define COMPOUND_ATTR_H + +# include + +/* Only effect (probably) when formal Attribute is defined. + * __ATTRIBUTABLE indicates this field is used for further process by Attribute. + * Or, to put this way, this field has attributions not used so far, but + * eventually will. + */ +# define __ATTRIBUTABLE +# define __ATTRIBUTABLE__ +# define attr(a) + +typedef struct _Attribute{ + int serialNo; + int (*exec)(void *); + struct _Attribute *prev; +} attr(Executive) Attribute; + +/* The base of every attribute. */ +# define Attributable (Attribute){\ + .value = 0,\ + .exec = HANDLER /* Use report handler here. */\ +}; + +#endif /* COMPOUND_ATTR_H */ diff --git a/catlog.c b/catlog.c new file mode 100755 index 0000000..ab0e6bf --- /dev/null +++ b/catlog.c @@ -0,0 +1,105 @@ +#include +#include + +Status CatlogMsg_Create(CatlogMsg *inst, CatlogLevel level, + char const *originator, char const *msg) +{ + /* Skip unavailable instances and parameters. */ + fails(inst, UnavailableInstance); + state((originator == NULL || msg == NULL), InvalidParameter); + + inst->time = time(NULL); + inst->level = level; + *inst->originator = *originator; + *inst->msg = *msg; + + return NormalStatus; +} + +Status CatlogMsg_CopyOf(CatlogMsg *inst, CatlogMsg *other) +{ + /* Skip unavailable instances and parameters. */ + fails(inst, UnavailableInstance); + fails(other, InvalidParameter); + + *inst = *other; + + return NormalStatus; +} + +bool CatlogMsg_Equal(CatlogMsg *inst, CatlogMsg *other) +{ + /* Skip unavailable instances and parameters. */ + state((inst == NULL || other == NULL), false); + + return ( + inst->time == other->time && + inst->level == other->level && + (!strcmp(inst->originator, other->originator)) && + (!strcmp(inst->msg, other->msg)) + ); +} + +Status CatlogSender_Create(CatlogSender *inst, CatlogMsg *msg, FILE *dst) +{ + /* Skip unavailable instances and parameters. */ + fails(inst, UnavailableInstance); + fails(msg, InvalidParameter); + + /* Copy and assign, with detections. */ + inst->msg = *msg; + inst->dst = (dst == NULL ? (stdout) : dst); + inst->successful = false; + inst->elapsed = (struct timespec){.tv_sec = 0, .tv_nsec = 0}; + + return NormalStatus; +} + +Status CatlogSender_CopyOf(CatlogSender *inst, CatlogSender *other) +{ + /* Skip unavailable instances and parameters. */ + fails(inst, UnavailableInstance); + fails(other, InvalidParameter); + + /* Copy and assign */ + inst->msg = other->msg; + inst->dst = other->dst; + inst->successful = other->successful; + inst->elapsed = other->elapsed; + + return NormalStatus; +} + +bool CatlogSender_Equal(CatlogSender *inst, CatlogSender *other) +{ + /* Skip unavailable instances and parameters. */ + state((inst == NULL || other == NULL), false); + + return ( + CatlogMsg_Equal(&inst->msg, &other->msg) && + inst->dst == other->dst && + inst->successful == other->successful && + ((inst->elapsed.tv_sec == other->elapsed.tv_sec) && + (inst->elapsed.tv_nsec == other->elapsed.tv_nsec)) + ); +} + +Status CatlogSender_Send(CatlogSender *inst, int *store, bool append) + throws(ReadWriteError) +{ + /* Skip unavailable instances and parameters. */ + fails(inst, UnavailableInstance); + fails(store, InvalidParameter); + + /* Open file. */ + ensure(CatlogUtils_OpenFile(inst->dst, "r"), "Unable to open file."); + ensure(CatlogMsg_Create(&(CatlogMsg){}, 0, "", ""), "Failed!"); + + /* Read file. */ + /* Creating buffer, */ + // TODO(william): Finish this function. +} + +Status CatlogUtils_CalcElapsed(struct timespec t1, struct timespec t2); + +Status CatlogUtils_OpenFile(FILE *store, const char const *__restrict mode); diff --git a/catlog.h b/catlog.h new file mode 100755 index 0000000..1cf9dc6 --- /dev/null +++ b/catlog.h @@ -0,0 +1,45 @@ +#ifndef COMPOUND_CATLOG_H +# define COMPOUND_CATLOG_H + +# include +# include + +typedef enum { + CATLOG_LEVEL_ALL, // Least the value, most the information. + CATLOG_LEVEL_MINOR, + CATLOG_LEVEL_NORMAL, + CATLOG_LEVEL_MAJOR, + CATLOG_LEVEL_CRITICAL, + CATLOG_LEVEL_FATAL, + CATLOG_LEVEL_DEBUG, + CATLOG_LEVEL_NONE +} CatlogLevel; + +typedef struct { + time_t time; + CatlogLevel level; + char *originator; + char *msg; +} CatlogMsg; + +Status CatlogMsg_Create(CatlogMsg *inst, CatlogLevel level, + char const *originator, char const *msg); +Status CatlogMsg_CopyOf(CatlogMsg *inst, CatlogMsg *other); +bool CatlogMsg_Equal(CatlogMsg *inst, CatlogMsg *other); + +typedef struct { + CatlogMsg msg; + FILE *dst; + bool successful; + struct timespec elapsed; +} CatlogSender; + +Status CatlogSender_Create(CatlogSender *inst, CatlogMsg *msg, FILE *dst); +Status CatlogSender_CopyOf(CatlogSender *inst, CatlogSender *other); +bool CatlogSender_Equal(CatlogSender *inst, CatlogSender *other); +Status CatlogSender_Send(CatlogSender *inst, int *store, bool append) + throws(ReadWriteError); +Status CatlogUtils_CalcElapsed(struct timespec t1, struct timespec t2); +Status CatlogUtils_OpenFile(FILE *store, const char *__restrict mode); + +#endif /* COMPOUND_CATLOG_H */ diff --git a/common.h b/common.h index 76c702d..017604a 100644 --- a/common.h +++ b/common.h @@ -1,18 +1,9 @@ -#ifndef COMMON_H -# define COMMON_H +#ifndef COMPOUND_COMMON_h +# define COMPOUND_COMMON_h # include # include -# define _buffer_definition_without_assignment(type, length) \ - struct { type data[(length)]; const int len; } - -# define Buffer(type, length, var) \ - _buffer_definition_without_assignment(type, length) \ - var = { .data = {}, .len = length } - -# define Array(type, length, var) type var[(length)] - /** * @brief Return $n as the return value, once $o is NULL * @return given $n as the return value @@ -20,7 +11,7 @@ * @note 'o' stands for "Object" * @note 'n' stands for "Numeric on Return" */ -# define fails(o, n) {if ((o) == NULL) return (n);} +# define fails(o, n) { if ((o) == NULL) return (n); } /** * @brief Return $e as the return value, once $v equals $e @@ -29,16 +20,100 @@ * @note 'v' stands for "Value" * @note 'e' stands for "Error Code" */ -# define trans(v, e) {if ((v) == (e)) return (e);} +# define trans(v, e) { if ((v) == (e)) return (e); } -///** -// * @brief Evaluate given statement while the ptr to $s is not NULL -// * @return given $n as the return value -// * @note "state" stands for "Statement Evaluation" -// * @note 's' stands for "Statement" -// * @note 'n' stands for "Numeric on Return" -// */ -//# define state(s, n) {if ((#s)) return (n);} +/** + * @brief Evaluate given statement while the ptr to $s is not NULL + * @return given $n as the return value + * @note "state" stands for "Statement Evaluation" + * @note 's' stands for "Statement" + * @note 'n' stands for "Numeric on Return" + */ +# define state(s, n) { if ((s)) return (n); } + +/** + * @brief Evaluate given statement while the ptr to $s is not NULL + * @return nothing. + * @note "svoid" stands for "Statement Evaluation in Void" + * @note 's' stands for "Statement" + */ +# define svoid(s) { if ((s)) return; } + +/** + * @brief Return an Error Status with given parameter $c as the + * comment or description. + * @return A instance of Error Status customised. + * @note "error" stands for "Error in Status" + * @note 'e' stands for "Error" + * @note 'c' stands for "Comment" + */ +# define error(e, c) ((Status) {\ + .description = c,\ + .characteristic = e.characteristic,\ + .prev = e.prev\ +}) + +/** + * @brief Return an Error Status with given parameter $p as the + * predecessor. + * @return A instance of Error Status inherited. + * @note "extend" stands for "Extend from Predecessor" + * @note 'i' stands for 'Instance' + * @note 'p' stands for "Predecessor" + */ +# define extend(i, p) ((Status)) {\ + .prev = p\ +} + +# define modify(e, s, c) ((Status)) {\ + .description = s,\ + .characteristic = c,\ + .prev = e.prev\ +} + +/** @brief Create a report in place. + * @return A instance of Status Report customised. + * @note "stamp" stands for "Report Stamp" + * @note 'e' stands for "Exception" + * @note 'c' stands for "Char String of Originator" + */ +# define stamp(e, c) ((Report) {\ + .stat = e,\ + .originator = c,\ + .time = time(NULL),\ + .priority = REPORT_SENDING_PRIORITY_NORMAL,\ + .status = REPORT_SENDING_TASK_STATUS_PENDING\ +}) + +/** + * @brief Another way to handle if statements more cleanly. + * @note "solve" stands for "Solve with Statements." + * @note 's' stands for "Statement" + * @note 'b' stands for "Block of Forks" + */ +# define solve(s, b) if (s) b + +// /** +// * @brief Forcibly return desired value $v once $s is not $k. +// * @return $v once state for $s is false. +// * @note "force" stands for "Forcible value" +// * @note 's' stands for "Statement" +// * @note 'k' stands for "Key Value", the value that is targeted to detect. +// * @note 'v' stands for "Desire Value", the value that desires. +// */ +// # define force(s, k, v) solve((s) != (k), v) + +// # define sforce(s, k, v) solve((!status_equal(s, k)), v) + +/* Get the literal. */ +# define nameof(obj) #obj + +# define type(T) + +/* Only effects when Generic is defined. */ +# define Array(T) Array + +# define String(T) String typedef enum { COMMON_ERROR_NULLPTR = 1, @@ -73,4 +148,4 @@ typedef bool _Bit; # define ATRANGE(lf, rt, v) \ (INRANGE(lf, true, rt, true, v)) ? 0 : ((v < lf) ? (v - lf) : (v - rt)) -#endif /* NO COMMON_H */ +#endif /* NO COMPOUND_COMMON_h */ diff --git a/const.h b/const.h new file mode 100644 index 0000000..bd77d30 --- /dev/null +++ b/const.h @@ -0,0 +1,17 @@ +#ifndef COMPOUND_CONST_H +# define COMPOUND_CONST_H + +# define INT32_DIGITS_DEC 10 +# define INT32_DIGITS_HEX 8 + +# define INT64_DIGITS_DEC 19 +# define INT64_DIGITS_HEX 16 + + +// # define UINT32_DIGITS_DEC 10 +// # define UINT32_DIGITS_HEX + +// # define UINT64_DIGITS_DEC 20 +// # define UINT64_DIGITS_HEX 16 + +#endif /* COMPOUND_CONST_H */ diff --git a/install b/install index 7c48827..6edf7c2 100755 --- a/install +++ b/install @@ -11,7 +11,8 @@ fi SRC="$PWD" DST=/usr/include/Compound -PROJ=("Array" "Paper" "Pen" "Render" "Status" "Var" "MemMan") +PROJ=("Array" "Paper" "Pen" "Render" "Status" "Var" "MemMan" "Stack" "Utils"\ + "String") PROJLEN=${#PROJ[*]} echo "======== $PROJLEN projects in total ========" @@ -32,5 +33,7 @@ while :; do echo done -cp -v "common.h" "$DST" +cp -v "common.h" "const.h" "platform.h"\ + "name.h" "type.h" "catlog.h"\ + "attr.h" "$DST" printf "\nDone\n" diff --git a/name.c b/name.c new file mode 100644 index 0000000..2ad646a --- /dev/null +++ b/name.c @@ -0,0 +1,71 @@ +#include + +Status NameSpace_Create(NameSpace *inst) +{ + fails(inst, UnavailableInstance); + + /* Create instances for members from inst. */ + state(status_isokay(NameSpace_EmptyName(&inst->latest)), + error(RuntimeError, "Failed to initialise latest from NameSpace")); + state(status_isokay(NameSpace_EmptyName(&inst->idx)), + error(RuntimeError, "Failed to initialise idx from NameSpace")); + state(status_isokay(NameSpace_EmptyName(inst->occupied)), + error(RuntimeError, "Failed to initialise occupied from NameSpace")); + + return NormalStatus; +} + +Status NameSpace_CopyOf(NameSpace *inst, NameSpace *other) +{ + fails(inst, UnavailableInstance); + fails(other, UnavailableParameter); + + /* Copy and assign. */ + other->latest = inst->latest; + other->idx = inst->idx; + + const Name len = NameSpace_CalcNameArrayLength(&other->occupied); + for (Name i = (Name){0}; (NameSpace_CompareName(i, len) < 0);) { + + // TODO(william): HERE + + /* i++ */ + state((!status_isokay(NameSpace_CountUp(&i))), + error(RuntimeError, "Error occurred during calculations of Name.")); + } +} + +Status NameSpace_CreateName(NameSpace *inst, Name *buff); + +Status NameSpace_RemoveName(NameSpace *inst, Name idx); + +Status NameSpace_EmptyName(Name *inst); + +Status NameSpace_CountUp(Name *inst); + +Status NameSpace_CountDown(Name *inst); + +Status NameSpace_CountUpFor(Name *inst, Name amount); + +Status NameSpace_CountDownFor(Name *inst, Name amount); + +Status NameSpace_UpdateLatest(NameSpace *inst, Name idx); + +Status NameSpace_FormatTrim(Name *inst); + +Status NameSpace_FormatInflate(Name *inst); + +Name NameSpace_CalcNameArrayLength(Name **arr); + +bool NameSpace_IsAvailable(NameSpace *inst, Name idx); + +bool NameSpace_IsValidName(Name *inst); + +int NameSpace_CompareName(Name *a, Name *b) +{ + /* Validation comes the first. --William */ + if (!NameSpace_IsValidName(a) || !NameSpace_IsValidName(b)) { + Report e; ArgueStartParam h; + throw(stamp(&InvalidName)); + } +} diff --git a/name.h b/name.h new file mode 100644 index 0000000..e35fe99 --- /dev/null +++ b/name.h @@ -0,0 +1,88 @@ +#ifndef COMPOUND_NAME_H +# define COMPOUND_NAME_H + +# include +# include +# include + +// Name, is a base of numeral counting. +// It uses 63 as the base, lasts for 63 times. +// At the head of each Name, 8 pilots stores for its type. +// In total, ((26*2+10+1)^63)*8 +// = 63^63*8 +// = 1.82618429078e+114 +// Nice. :3 +// William, Sun 12 May, 2024, 02:29:36 + +# define NAME_LENGTH_MAXIMUM 64 +# define NAME_LEGAL_CHARACTERS "abcdefghijklmnopqrstuvwxyz"\ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\ + "1234567890" + +typedef struct { + char *identifier; + Array(int) attributions; +} Name; + +static const Name NullName = { + .identifier = + "_000000000000000000000000000000000000000000000000000000000000000", + .attributions = NULL +}; + +// typedef struct { +// Name value; +// Name idx; +// Name *occupied; +// } NameSpace; // Size: 8+8+8 =8*3 =24 Bytes (x64) + +/* + * Example: + * Var variable_from_namespace_Utils_in_class_Calculation_in_function_C; + * // Not enough room for representation. + * // Must use another more efficient method to store the name. + * Become (roughly): + * Var v0000000000000000000000000000000000000000000000000000000000001g3; + * Var v1g3; // Trimmed. + * PILOT: v, f, c, e, i, s, u, a + * v: Variable + * f: Function + * c: Class + * e: Enumeration + * i: Interface + * s: Struct + * u: Union + * a: Attribution + * ID: [a-zA-Z0-9_] + * MAXIMUM STORING SIZE: 63 Bytes + * TOTAL POSSIBILITIES: ((26*2+10+1)^63)*8 = 1.82618429078e+114 + * Definitely enough. + * + * Please note, numeral symbols cannot lead the name. + * They must have indexer that greater than ZERO. + */ + +Status Name_CountDown(Name *inst); +Status Name_CountDownFor(Name *inst, Name amount); +Status Name_CountUp(Name *inst); +Status Name_CountUpFor(Name *inst, Name amount); +Status Name_EmptyName(Name *inst); +Status Name_FormatInflate(Name *inst); +Status Name_FormatTrim(Name *inst); +Name Name_CalcNameArrayLength(Name **arr); +bool Name_IsValid(Name *inst); +int Name_Compare(Name *a, Name *b) throws(InvalidName); + +static Status NameOverFlowError = { + .description = "An overflow occurred while calculating Name.", + .characteristic = STATUS_ERROR, + .prev = &ArithmeticError +}; + +static Status InvalidName = { + .description = "Given Name was invalid.", + .characteristic = STATUS_ERROR, + .prev = &InvalidParameter +}; + +#endif /* COMPOUND_NAME_H */ diff --git a/namescope.c b/namescope.c new file mode 100644 index 0000000..e69de29 diff --git a/namescope.h b/namescope.h new file mode 100644 index 0000000..0cf091a --- /dev/null +++ b/namescope.h @@ -0,0 +1,26 @@ +#ifndef COMPOUND_NAMESCOPE_H +# define COMPOUND_NAMESCOPE_H + +# include +# include + +typedef struct { + Array(Name) name_data; + +} NameScope; + +# define NameScope(T) NameScope + +Status NameScope_Create(NameScope *inst); +Status NameScope_CopyOf(NameScope *inst, NameScope *other); +Status NameScope_CreateName(NameScope *inst, Name *buff); +Status NameScope_RemoveName(NameScope *inst, Name idx); +Status NameScope_UpdateLatest(NameScope *inst, Name idx); +bool NameScope_Equal(NameScope *inst, NameScope *other); +bool NameScope_IsAvailable(NameScope *inst, Name idx); + +/* Universal Attribute NameScope. (U.A.N.) */ +NameScope(Attribute) UniversalAttributeNameScope; +NameScope MemoryAllocationRegistry; + +#endif /* COMPOUND_NAMESCOPE_H */ diff --git a/platform.h b/platform.h new file mode 100644 index 0000000..c1c3b1a --- /dev/null +++ b/platform.h @@ -0,0 +1,14 @@ +#ifndef COMPOUND_PLATFORM_H +# define COMPOUND_PLATFORM_H + +# if defined __x86_64__ || defined __x86_64 +# define __COMPOUND_64__ +# define __COMPOUND_PRODUCT__ compound64 +# elif defined __i386__ || __i486__ || __i586__ || __i686__ || _X86_ || __X86__ +# define __COMPOUND_32__ +# define __COMPOUND_PRODUCT__ compound32 +# else +# error Platform not supported. Please issue this on github.com/Wilhelm-Lee/Compound --William +# endif + +#endif /* COMPOUND_PLATFORM_H */ diff --git a/registry.h b/registry.h new file mode 100644 index 0000000..abb25ae --- /dev/null +++ b/registry.h @@ -0,0 +1,54 @@ +#ifndef COMPOUND_SECURITY_REGISTRY_H +# define COMPOUND_SECURITY_REGISTRY_H + +# include + +/* + By calculating SHA256, we can identify whether the original data has been + modified maliciously or not. + However, In current particular cases, it is contradictive that we would + wish to use the same approach to validate and protect the data that we used + for validating and protecting other data. + Thus, it is not practical to use current existing methods to create + a way that is 100% perfect for data safety and computation security. + What we actually need is to ensure that our data from either struct or + union wouldn't be modifies easily, not in C, but in Classify, the language + that rely on this very project, Compound. + */ + +typedef struct { + Memory data; + char SHA256[256]; +} RegItem; // 276 Bytes + +typedef union { + RegItem items[256]; +} RegTable256; // 4416 Bytes | 4.3125 KiB + +typedef union { + RegItem items[128]; +} RegTable128; // 2208 Bytes | 2.15625 KiB + +typedef union { + RegItem items[64]; +} RegTable64; // 1104 Bytes | 1.078125 KiB + +typedef union { + RegItem items[32]; +} RegTable32; // 552 Bytes + +typedef union { + RegItem items[16]; +} RegTable16; // 276 Bytes + +typedef union { + RegItem items[8]; +} RegTable8; // 138 Bytes + +bool Registry_Validate(const RegItem const *item, const RegResult const *result); +bool Registry_Calculate(const RegItem const *item, const RegResult const *result); +bool RegistryTable64_ + + + +#endif /* COMPOUND_SECURITY_REGISTRY_H */ diff --git a/type.h b/type.h new file mode 100644 index 0000000..d93f238 --- /dev/null +++ b/type.h @@ -0,0 +1,11 @@ +#ifndef COMPOUND_TYPE_H +# define COMPOUND_TYPE_H + +# include + +typedef struct { + char *identity; + Var data; +} Type; + +#endif /* COMPOUND_TYPE_H */