Skip to content

Instantly share code, notes, and snippets.

@ZenLiuCN
Last active February 3, 2023 08:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZenLiuCN/4e3649112edba353ad0c98b2f831e824 to your computer and use it in GitHub Desktop.
Save ZenLiuCN/4e3649112edba353ad0c98b2f831e824 to your computer and use it in GitHub Desktop.
C Units
//
// Created by ZenLiu, license MIT
//
#ifndef _MACRO_LOG_UNIT_H
#define _MACRO_LOG_UNIT_H
#ifdef MACRO_LOG_INTO_FILE
/**
* user's response to open and close file if defined _LOG_FILE_.
*/
#ifndef MACRO_LOG_FILE
#include <stdio.h>
#define _LOG_PRINT_(_p,...) FILE * f=fopen("%s.log",__FILE_NAME__,"a+");fprintf(f,_p,##__VA_ARGS__);fflush(f);fclose(f);
#else
#define _LOG_PRINT_(_p,...) fprintf(MACRO_LOG_FILE,_p,##__VA_ARGS__)
#endif
#else
#define _LOG_PRINT_(_p,...) printf(_p,##__VA_ARGS__)
#endif
#if defined(__LOG_WITH_TIME__) && !defined(_LOG_TIME_NOW)
#include <time.h>
#define _LOG_TIME_NOW { time_t ts = time(NULL);\
struct tm *tm = localtime(&ts);\
_LOG_PRINT_("%d-%02d-%02d %02d:%02d:%02d ",tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);}
#elif defined(__LOG_WITH_TIME__)&&defined(_LOG_TIME_NOW)
#define LOG_PRINT(p, ...) (_LOG_TIME_NOW, _LOG_PRINT_(p,##__VA_ARGS__))
#else
#define LOG_PRINT(_p, ...) _LOG_PRINT_(_p,##__VA_ARGS__)
#endif
//print ERROR message
#define LOG_ERROR(__p, ...) LOG_PRINT("\tERROR\t"__p,##__VA_ARGS__)
//print WARN message
#define LOG_WARN(__p, ...) LOG_PRINT("\tWARN\t"__p,##__VA_ARGS__)
//print INFO message
#define LOG_INFO(__p, ...) LOG_PRINT("\tINFO\t"__p,##__VA_ARGS__)
//print message with line feed
#define LOG_PRINT_LN(_p, ...) LOG_PRINT(_p"\n",##__VA_ARGS__)
//print ERROR message with line feed
#define LOG_ERROR_LN(_p, ...) LOG_PRINT_LN("\tERROR\t[%s:%d]"_p,__FILE__,__LINE__,##__VA_ARGS__)
//print WARN message with line feed
#define LOG_WARN_LN(_p, ...) LOG_PRINT_LN("\tWARN\t"_p,##__VA_ARGS__)
//print INFO message with line feed
#define LOG_INFO_LN(_p, ...) LOG_PRINT_LN("\tINFO\t"_p,##__VA_ARGS__)
#ifndef _DEBUG_
#define LOG_DEBUG(p, ...)
#define LOG_DEBUG_LN(p, ...)
#define ASSERT(cond, msg)
#else
//print DEBUG message (only exists with _DEBUG_ )
#define LOG_DEBUG(_p, ...) LOG_PRINT("\tDEBUG\t[%s:%d]"_p,__FILE__,__LINE__,##__VA_ARGS__)
//print DEBUG message with line feed (only exists with _DEBUG_ )
#define LOG_DEBUG_LN(_p, ...) LOG_PRINT_LN("\tDEBUG\t[%s:%d]"_p, __FILE__,__LINE__,##__VA_ARGS__)
//assert cond is positive else print ERROR (only exists with _DEBUG_ )
#define ASSERT(_cond, _msg) if(!(_cond)){LOG_ERROR_LN("ASSERT FAIL: %s.",_msg);}
#endif
#endif //_MACRO_LOG_UNIT_H
//
// Created by ZenLiu, license MIT
//
#ifndef _MACRO_VARARGS_UNIT_H
#define _MACRO_VARARGS_UNIT_H
//region Generated Macros
//region VA_NUM_ARGS
#ifndef _DISABLE_USE_VA_NUM_ARGS_
#define __VA_NUM_ARGS__(__1,__2,__3,__4,__5,__6,__7,__8,__9,__N,...)__N
//returns number of varargs maximum support is 10
#define VA_NUM_ARGS(...)__VA_NUM_ARGS__(__VA_ARGS__,9,8,7,6,5,4,3,2,1)
#endif
//endregion VA_NUM_ARGS
//region CONCAT
#ifndef _DISABLE_USE_CONCAT_
#ifdef VA_NUM_ARGS
#define __CONCAT2(__1,__2)__1##__2
#define __CONCAT3(__1,__2,__3)__1##__2##__3
#define __CONCAT4(__1,__2,__3,__4)__1##__2##__3##__4
#define __CONCAT5(__1,__2,__3,__4,__5)__1##__2##__3##__4##__5
#define __CONCAT6(__1,__2,__3,__4,__5,__6)__1##__2##__3##__4##__5##__6
#define __CONCAT7(__1,__2,__3,__4,__5,__6,__7)__1##__2##__3##__4##__5##__6##__7
#define __CONCAT8(__1,__2,__3,__4,__5,__6,__7,__8)__1##__2##__3##__4##__5##__6##__7##__8
#define __CONCAT9(__1,__2,__3,__4,__5,__6,__7,__8,__9)__1##__2##__3##__4##__5##__6##__7##__8##__9
#define __CONCAT10(__1,__2,__3,__4,__5,__6,__7,__8,__9,__10)__1##__2##__3##__4##__5##__6##__7##__8##__9##__10
#define CONCAT2(__1,__2) __CONCAT2(__1,__2)
#define CONCAT3(__1,__2,__3) __CONCAT3(__1,__2,__3)
#define CONCAT4(__1,__2,__3,__4) __CONCAT4(__1,__2,__3,__4)
#define CONCAT5(__1,__2,__3,__4,__5) __CONCAT5(__1,__2,__3,__4,__5)
#define CONCAT6(__1,__2,__3,__4,__5,__6) __CONCAT6(__1,__2,__3,__4,__5,__6)
#define CONCAT7(__1,__2,__3,__4,__5,__6,__7) __CONCAT7(__1,__2,__3,__4,__5,__6,__7)
#define CONCAT8(__1,__2,__3,__4,__5,__6,__7,__8) __CONCAT8(__1,__2,__3,__4,__5,__6,__7,__8)
#define CONCAT9(__1,__2,__3,__4,__5,__6,__7,__8,__9) __CONCAT9(__1,__2,__3,__4,__5,__6,__7,__8,__9)
#define CONCAT10(__1,__2,__3,__4,__5,__6,__7,__8,__9,__10) __CONCAT10(__1,__2,__3,__4,__5,__6,__7,__8,__9,__10)
//concat max to concat 10 as identifier
#define CONCAT(...) CONCAT2(__CONCAT,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
//create unique identifier with file lines, max 6 name parts
#define UNIQUE_NAME(...) CONCAT(__,__VA_ARGS__,__,__LINE__,__)
//create a identity name which recall with same arguments
#define ID_NAME(...) CONCAT(__,__VA_ARGS__,__)
#else
#error "VA_NUM_ARGS is required, but not found"
#endif
#endif
//endregion CONCAT
//region USING
#ifndef _DISABLE_USE_USING_
#if defined(UNIQUE_NAME) && defined(CONCAT2) && defined(VA_NUM_ARGS)
#define __USING1(__decl)\
for(__decl,*UNIQUE_NAME(__using1__,ptr)=NULL;UNIQUE_NAME(__using1__,ptr)++==NULL?1:0;)
#define __USING2(__decl, __on_exit)\
for(__decl,*UNIQUE_NAME(__using2__,ptr)=NULL;\
UNIQUE_NAME(__using2__,ptr)++==NULL?1:0;\
__on_exit)
#define __USING3(__decl, __on_enter, __on_exit)\
for(__decl,*UNIQUE_NAME(__using3__,ptr)=NULL;\
UNIQUE_NAME(__using3__,ptr)++==NULL?((__on_enter),1):0;\
__on_exit)
#define __USING4(__decl0,__decl1,__on_exit,__body)\
{ int *UNIQUE_NAME(__using3__,ptr)=NULL; __decl0;__decl1;\
do{\
__body}\
while(UNIQUE_NAME(__using3__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using3__,holder_for_semi_) UNIQUE_NAME(__using3__,_holder_for_semi_)
#define __USING5(__decl0,__decl1,__decl2,__on_exit,__body)\
{ int *UNIQUE_NAME(__using4__,ptr)=NULL; __decl0;__decl1;__decl2;\
do{\
__body}\
while(UNIQUE_NAME(__using4__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using4__,holder_for_semi_) UNIQUE_NAME(__using4__,_holder_for_semi_)
#define __USING6(__decl0,__decl1,__decl2,__decl3,__on_exit,__body)\
{ int *UNIQUE_NAME(__using5__,ptr)=NULL; __decl0;__decl1;__decl2;__decl3;\
do{\
__body}\
while(UNIQUE_NAME(__using5__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using5__,holder_for_semi_) UNIQUE_NAME(__using5__,_holder_for_semi_)
#define __USING7(__decl0,__decl1,__decl2,__decl3,__decl4,__on_exit,__body)\
{ int *UNIQUE_NAME(__using6__,ptr)=NULL; __decl0;__decl1;__decl2;__decl3;__decl4;\
do{\
__body}\
while(UNIQUE_NAME(__using6__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using6__,holder_for_semi_) UNIQUE_NAME(__using6__,_holder_for_semi_)
#define __USING8(__decl0,__decl1,__decl2,__decl3,__decl4,__decl5,__on_exit,__body)\
{ int *UNIQUE_NAME(__using7__,ptr)=NULL; __decl0;__decl1;__decl2;__decl3;__decl4;__decl5;\
do{\
__body}\
while(UNIQUE_NAME(__using7__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using7__,holder_for_semi_) UNIQUE_NAME(__using7__,_holder_for_semi_)
#define __USING9(__decl0,__decl1,__decl2,__decl3,__decl4,__decl5,__decl6,__on_exit,__body)\
{ int *UNIQUE_NAME(__using8__,ptr)=NULL; __decl0;__decl1;__decl2;__decl3;__decl4;__decl5;__decl6;\
do{\
__body}\
while(UNIQUE_NAME(__using8__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using8__,holder_for_semi_) UNIQUE_NAME(__using8__,_holder_for_semi_)
#define __USING10(__decl0,__decl1,__decl2,__decl3,__decl4,__decl5,__decl6,__decl7,__on_exit,__body)\
{ int *UNIQUE_NAME(__using9__,ptr)=NULL; __decl0;__decl1;__decl2;__decl3;__decl4;__decl5;__decl6;__decl7;\
do{\
__body}\
while(UNIQUE_NAME(__using9__,ptr)++!=NULL?((__on_exit),0):1);\
}\
typedef struct UNIQUE_NAME(__using9__,holder_for_semi_) UNIQUE_NAME(__using9__,_holder_for_semi_)
// USING(declare){ __body__ },USING(declare,on_exit){ __body__ },USING(declare,on_enter,on_exit){ __body__ }.
// USING(declare,declares...,on_exit,__body__) usable for more declares (up to 7).
#define USING(...)CONCAT2(__USING,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
//endregion USING
//region BLOCK USING
#define __USING_B1(__decl)\
for(__decl,*UNIQUE_NAME(__using_b1__,ptr)=NULL;UNIQUE_NAME(__using_b1__,ptr)++==NULL?1:0;)
#define __USING_B2(__decl, __on_exit)\
for(__decl,*UNIQUE_NAME(__using_b2__,ptr)=NULL;\
UNIQUE_NAME(__using_b2__,ptr)++==NULL?1:0;\
__on_exit)
#define __USING_B3(__decl, __on_enter, __on_exit)\
for(__decl,*UNIQUE_NAME(__using_b3__,ptr)=NULL;\
UNIQUE_NAME(__using_b3__,ptr)++==NULL?((__on_enter),1):0;\
__on_exit)
#define __USING_B4(__decl0,__decl1,__on_enter,__on_exit)\
{ __decl0;__decl1;\
for(int *UNIQUE_NAME(__using_b3__,ptr)=NULL;UNIQUE_NAME(__using_b3__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
#define __USING_B5(__decl0,__decl1,__decl2,__on_enter,__on_exit)\
{ __decl0;__decl1;__decl2;\
for(int *UNIQUE_NAME(__using_b4__,ptr)=NULL;UNIQUE_NAME(__using_b4__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
#define __USING_B6(__decl0,__decl1,__decl2,__decl3,__on_enter,__on_exit)\
{ __decl0;__decl1;__decl2;__decl3;\
for(int *UNIQUE_NAME(__using_b5__,ptr)=NULL;UNIQUE_NAME(__using_b5__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
#define __USING_B7(__decl0,__decl1,__decl2,__decl3,__decl4,__on_enter,__on_exit)\
{ __decl0;__decl1;__decl2;__decl3;__decl4;\
for(int *UNIQUE_NAME(__using_b6__,ptr)=NULL;UNIQUE_NAME(__using_b6__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
#define __USING_B8(__decl0,__decl1,__decl2,__decl3,__decl4,__decl5,__on_enter,__on_exit)\
{ __decl0;__decl1;__decl2;__decl3;__decl4;__decl5;\
for(int *UNIQUE_NAME(__using_b7__,ptr)=NULL;UNIQUE_NAME(__using_b7__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
#define __USING_B9(__decl0,__decl1,__decl2,__decl3,__decl4,__decl5,__decl6,__on_enter,__on_exit)\
{ __decl0;__decl1;__decl2;__decl3;__decl4;__decl5;__decl6;\
for(int *UNIQUE_NAME(__using_b8__,ptr)=NULL;UNIQUE_NAME(__using_b8__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
#define __USING_B10(__decl0,__decl1,__decl2,__decl3,__decl4,__decl5,__decl6,__decl7,__on_enter,__on_exit)\
{ __decl0;__decl1;__decl2;__decl3;__decl4;__decl5;__decl6;__decl7;\
for(int *UNIQUE_NAME(__using_b9__,ptr)=NULL;UNIQUE_NAME(__using_b9__,ptr)++==NULL?((__on_exit),1):0;__on_enter)
// USING_(declare){ __body__ },USING_(declare,on_exit){ __body__ },USING_(declare,on_enter,on_exit){ __body__ }.
// USING_(declare,declares...,on_enter,on_exit){__body__}} **NOTICE DOUBLE BRACKETS** for more declares (up to 7).
#define USING_(...)CONCAT2(__USING_B,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
#else
#error "UNIQUE_NAME , CONCAT2 and VA_NUM_ARGS required but not found all for USING."
#endif
#endif
//endregion BLOCK USING
//endregion Generated Macros
#endif //_MACRO_VARARGS_UNIT_H
#ifdef _GEN_MACRO_
#ifndef _GEN_MACRO_MAX_VARS_
#define _GEN_MACRO_MAX_VARS_ 10
#endif
void gen_varargs_num() {
int max = _GEN_MACRO_MAX_VARS_;
if (max <= 1) {
fprintf(stderr, "_GEN_MACRO_MAX_VARS_ should always greater than 2, current %d (better greater than 6)", max);
return;
}
printf("//region VA_NUM_ARGS \n");
printf("#ifndef _DISABLE_USE_VA_NUM_ARGS_\n");
printf("#define __VA_NUM_ARGS__(");
for (int j = 1; j < max; ++j)
printf("%s__%d", j > 1 ? "," : "", j);
printf(",__N,...)__N\n");
printf("//returns number of varargs maximum support is %d\n#define VA_NUM_ARGS(...)__VA_NUM_ARGS__(__VA_ARGS__",
max);
for (int j = max - 1; j >= 1; --j) printf(",%d", j);
printf(")\n#endif\n\n");
printf("//endregion VA_NUM_ARGS \n");
}
void gen_concat() {
int max = _GEN_MACRO_MAX_VARS_;
if (max <= 1) {
fprintf(stderr, "_GEN_MACRO_MAX_VARS_ should always greater than 2, current %d ", max);
return;
}
printf("//region CONCAT \n");
printf("#ifndef _DISABLE_USE_CONCAT_\n");
printf("#ifdef VA_NUM_ARGS \n ");
for (int i = 2; i <= max; ++i) {
printf("#define __CONCAT%d(", i);
for (int j = 1; j <= i; ++j) {
if (j != 1) printf(",");
printf("__%d", j);
}
printf(")");
for (int j = 1; j <= i; ++j) {
if (j != 1) printf("##");
printf("__%d", j);
}
printf("\n");
}
//generate protect for nest expanding
for (int i = 2; i <= max; ++i) {
printf("#define CONCAT%d(", i);
for (int j = 1; j <= i; ++j) {
if (j != 1) printf(",");
printf("__%d", j);
}
printf(") __CONCAT%d(", i);
for (int j = 1; j <= i; ++j) {
if (j != 1) printf(",");
printf("__%d", j);
}
printf(")\n");
}
printf("//concat max to concat %d as identifier\n"
"#define CONCAT(...) CONCAT2(__CONCAT,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)\n", max);
printf("//create unique identifier with file lines, max %d name parts\n"
"#define UNIQUE_NAME(...) CONCAT(__,__VA_ARGS__,__,__LINE__,__)\n"
"//create a identity name which recall with same arguments \n"
"#define ID_NAME(...) CONCAT(__,__VA_ARGS__,__)\n", max - 4);
printf("#else\n "
"#error \"VA_NUM_ARGS is required, but not found\" \n"
"#endif\n#endif\n\n");
printf("//endregion CONCAT \n");
}
void gen_using() {
int extra = _GEN_MACRO_MAX_VARS_ - 3;
if (extra < 0) {
fprintf(stderr, "using extra must greater or equals 0, got %d, check _GEN_MACRO_MAX_VARS_", extra);
return;
}
printf("//region USING \n");
printf("#ifndef _DISABLE_USE_USING_\n");
printf("#if defined(UNIQUE_NAME) && defined(CONCAT2) && defined(VA_NUM_ARGS)\n");
printf("#define __USING1(__decl)\\\nfor(__decl,*UNIQUE_NAME(__using1__,ptr)=NULL;UNIQUE_NAME(__using1__,ptr)++==NULL?1:0;)\n");
printf("#define __USING2(__decl, __on_exit)\\\nfor(__decl,*UNIQUE_NAME(__using2__,ptr)=NULL;\\\nUNIQUE_NAME(__using2__,ptr)++==NULL?1:0;\\\n__on_exit)\n");
printf("#define __USING3(__decl, __on_enter, __on_exit)\\\nfor(__decl,*UNIQUE_NAME(__using3__,ptr)=NULL;\\\nUNIQUE_NAME(__using3__,ptr)++==NULL?((__on_enter),1):0;\\\n__on_exit)\n");
for (int i = 1; i <= extra; ++i) {
printf("#define __USING%d(__decl0", i + 3);
for (int j = 1; j <= i; ++j) printf(",__decl%d", j);
printf(",__on_exit,__body)\\\n"
"{ int *UNIQUE_NAME(__using%d__,ptr)=NULL;"
" __decl0", i + 2);
for (int j = 1; j <= i; ++j) printf(";__decl%d", j);
printf(";\\\n"
"do{\\\n"
"__body}\\\nwhile(UNIQUE_NAME(__using%d__,ptr)++!=NULL?((__on_exit),0):1);\\\n}\\\n"
"typedef struct UNIQUE_NAME(__using%d__,holder_for_semi_) UNIQUE_NAME(__using%d__,_holder_for_semi_)\n\n",
i + 2, i + 2, i + 2);
}
printf("// USING(declare){ __body__ },USING(declare,on_exit){ __body__ },USING(declare,on_enter,on_exit){ __body__ }.\n");
printf("// USING(declare,declares...,on_exit,__body__) usable for more declares (up to %d).\n", extra);
printf("#define USING(...)CONCAT2(__USING,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)\n");
printf("#else\n#error \"UNIQUE_NAME , CONCAT2 and VA_NUM_ARGS required but not found all for USING.\"\n");
printf("#endif\n");
printf("#endif\n");
printf("//endregion USING ");
}
//this generated using should use an ugly }} to end the body party,but be better to debug the body
void gen_block_using() {
int extra = _GEN_MACRO_MAX_VARS_ - 3;
if (extra < 0) {
fprintf(stderr, "using extra must greater or equals 0, got %d, check _GEN_MACRO_MAX_VARS_", extra);
return;
}
printf("//region BLOCK USING \n");
printf("#ifndef _DISABLE_USE_USING_\n");
printf("#if defined(UNIQUE_NAME) && defined(CONCAT2) && defined(VA_NUM_ARGS)\n");
printf("#define __USING_B1(__decl)\\\nfor(__decl,*UNIQUE_NAME(__using_b1__,ptr)=NULL;UNIQUE_NAME(__using_b1__,ptr)++==NULL?1:0;)\n");
printf("#define __USING_B2(__decl, __on_exit)\\\nfor(__decl,*UNIQUE_NAME(__using_b2__,ptr)=NULL;\\\nUNIQUE_NAME(__using_b2__,ptr)++==NULL?1:0;\\\n__on_exit)\n");
printf("#define __USING_B3(__decl, __on_enter, __on_exit)\\\nfor(__decl,*UNIQUE_NAME(__using_b3__,ptr)=NULL;\\\nUNIQUE_NAME(__using_b3__,ptr)++==NULL?((__on_enter),1):0;\\\n__on_exit)\n");
for (int i = 1; i <= extra; ++i) {
printf("#define __USING_B%d(__decl0", i + 3);
for (int j = 1; j <= i; ++j) printf(",__decl%d", j);
printf(",__on_enter,__on_exit)\\\n"
"{ __decl0");
for (int j = 1; j <= i; ++j) printf(";__decl%d", j);
printf(";\\\n"
"for(int *UNIQUE_NAME(__using_b%d__,ptr)=NULL;UNIQUE_NAME(__using_b%d__,ptr)++==NULL?((__on_exit),1):0;__on_enter)\n\n",
i + 2, i + 2);
}
printf("// USING(declare){ __body__ },USING(declare,on_exit){ __body__ },USING(declare,on_enter,on_exit){ __body__ }.\n");
printf("// USING(declare,declares...,on_enter,on_exit){__body__}} **NOTICE DOUBLE BRACKETS** for more declares (up to %d).\n", extra);
printf("#define USING(...)CONCAT2(__USING_B,VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)\n");
printf("#else\n#error \"UNIQUE_NAME , CONCAT2 and VA_NUM_ARGS required but not found all for USING.\"\n");
printf("#endif\n");
printf("#endif\n");
printf("//endregion BLOCK USING\n");
}
void gen_macros(int use_block_using) {
printf("\n\n//region Generated Macros\n\n");
gen_varargs_num();
gen_concat();
if (use_block_using) gen_block_using();
else gen_using();
printf("\n\n//endregion Generated Macros\n\n");
}
#endif //_GEN_MACRO_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment