mirror of
				https://github.com/CPunch/Cosmo.git
				synced 2025-10-31 04:50:12 +00:00 
			
		
		
		
	started cdump.c:cosmoD_dump()
This commit is contained in:
		
							
								
								
									
										179
									
								
								src/cdump.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								src/cdump.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | |||||||
|  | #include "cdump.h" | ||||||
|  |  | ||||||
|  | #include "cmem.h" | ||||||
|  | #include "cobj.h" | ||||||
|  | #include "cvalue.h" | ||||||
|  |  | ||||||
|  | typedef struct | ||||||
|  | { | ||||||
|  |     CState *state; | ||||||
|  |     const void *userData; | ||||||
|  |     cosmo_Writer writer; | ||||||
|  |     int writerStatus; | ||||||
|  | } DumpState; | ||||||
|  |  | ||||||
|  | static void writeCValue(DumpState *dstate, CValue val); | ||||||
|  |  | ||||||
|  | static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer, | ||||||
|  |                           const void *userData) | ||||||
|  | { | ||||||
|  |     dstate->state = state; | ||||||
|  |     dstate->userData = userData; | ||||||
|  |     dstate->writer = writer; | ||||||
|  |     dstate->writerStatus = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeBlock(DumpState *dstate, const void *data, size_t size) | ||||||
|  | { | ||||||
|  |     if (dstate->writerStatus == 0) { | ||||||
|  |         dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeu8(DumpState *dstate, uint8_t d) | ||||||
|  | { | ||||||
|  |     writeBlock(dstate, &d, sizeof(uint8_t)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeu32(DumpState *dstate, uint32_t d) | ||||||
|  | { | ||||||
|  |     writeBlock(dstate, &d, sizeof(uint32_t)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeSize(DumpState *dstate, size_t d) | ||||||
|  | { | ||||||
|  |     writeBlock(dstate, &d, sizeof(size_t)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeVector(DumpState *dstate, const void *data, size_t size) | ||||||
|  | { | ||||||
|  |     writeSize(dstate, size); | ||||||
|  |     writeBlock(dstate, data, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeHeader(DumpState *dstate) | ||||||
|  | { | ||||||
|  |     writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN); | ||||||
|  |  | ||||||
|  |     /* after the magic, we write some platform information */ | ||||||
|  |     writeu8(dstate, cosmoD_isBigEndian()); | ||||||
|  |     writeu8(dstate, sizeof(cosmo_Number)); | ||||||
|  |     writeu8(dstate, sizeof(size_t)); | ||||||
|  |     writeu8(dstate, sizeof(int)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeCObjString(DumpState *dstate, CObjString *obj) | ||||||
|  | { | ||||||
|  |     if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */ | ||||||
|  |         writeu32(dstate, 0); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* write string length */ | ||||||
|  |     writeu32(dstate, obj->length); | ||||||
|  |  | ||||||
|  |     /* write string data */ | ||||||
|  |     writeBlock(dstate, obj->str, obj->length); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeCObjFunction(DumpState *dstate, CObjFunction *obj) | ||||||
|  | { | ||||||
|  |     writeCObjString(dstate, obj->name); | ||||||
|  |     writeCObjString(dstate, obj->module); | ||||||
|  |  | ||||||
|  |     writeu32(dstate, obj->args); | ||||||
|  |     writeu32(dstate, obj->upvals); | ||||||
|  |     writeu8(dstate, obj->variadic); | ||||||
|  |  | ||||||
|  |     /* write chunk info */ | ||||||
|  |     writeVector(dstate, obj->chunk.buf, sizeof(uint8_t) * obj->chunk.count); | ||||||
|  |  | ||||||
|  |     /* write line info */ | ||||||
|  |     writeVector(dstate, obj->chunk.lineInfo, sizeof(int) * obj->chunk.count); | ||||||
|  |  | ||||||
|  |     /* write constants */ | ||||||
|  |     for (int i = 0; i < obj->chunk.constants.count; i++) { | ||||||
|  |         writeCValue(dstate, obj->chunk.constants.values[i]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define WRITE_VAR(dstate, type, expression)                                                        \ | ||||||
|  |     {                                                                                              \ | ||||||
|  |         type _tmp = expression;                                                                    \ | ||||||
|  |         writeBlock(dstate, &_tmp, sizeof(_tmp));                                                   \ | ||||||
|  |         break;                                                                                     \ | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | static void writeCObj(DumpState *dstate, CObj *obj) | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |         we can kind of cheat here since our parser only emits a few very limited CObjs... | ||||||
|  |         CChunks will only ever have the following CObj's in their constant table: | ||||||
|  |         - COBJ_STRING | ||||||
|  |         - COBJ_FUNCTION | ||||||
|  |  | ||||||
|  |         the rest of the objects are created during runtime. yay! | ||||||
|  |     */ | ||||||
|  |     CObjType t = cosmoO_readType(obj); | ||||||
|  |  | ||||||
|  |     /* write cobj type */ | ||||||
|  |     writeu8(dstate, t); | ||||||
|  |  | ||||||
|  |     /* write object payload/body */ | ||||||
|  |     switch (t) { | ||||||
|  |     case COBJ_STRING: | ||||||
|  |         writeCObjString(dstate, (CObjString *)obj); | ||||||
|  |         break; | ||||||
|  |     case COBJ_FUNCTION: | ||||||
|  |         writeCObjFunction(dstate, (CObjFunction *)obj); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void writeCValue(DumpState *dstate, CValue val) | ||||||
|  | { | ||||||
|  |     CosmoType t = GET_TYPE(val); | ||||||
|  |  | ||||||
|  |     /* write value type */ | ||||||
|  |     writeu8(dstate, t); | ||||||
|  |  | ||||||
|  |     /* write value payload/body */ | ||||||
|  |     switch (t) { | ||||||
|  |     case COSMO_TNUMBER: | ||||||
|  |         WRITE_VAR(dstate, cosmo_Number, cosmoV_readNumber(val)) | ||||||
|  |     case COSMO_TBOOLEAN: | ||||||
|  |         WRITE_VAR(dstate, bool, cosmoV_readBoolean(val)) | ||||||
|  |     case COSMO_TREF: | ||||||
|  |         writeCObj(dstate, cosmoV_readRef(val)); | ||||||
|  |         break; | ||||||
|  |     case COSMO_TNIL: /* fallthrough, no body */ | ||||||
|  |     default: | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #undef WRITE_VAR | ||||||
|  |  | ||||||
|  | bool cosmoD_isBigEndian() | ||||||
|  | { | ||||||
|  |     union | ||||||
|  |     { | ||||||
|  |         uint32_t i; | ||||||
|  |         uint8_t c[4]; | ||||||
|  |     } _indxint = {0xDEADB33F}; | ||||||
|  |  | ||||||
|  |     return _indxint.c[0] == 0xDE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData) | ||||||
|  | { | ||||||
|  |     DumpState dstate; | ||||||
|  |     initDumpState(state, &dstate, writer, userData); | ||||||
|  |  | ||||||
|  |     writeHeader(&dstate); | ||||||
|  |     writeCObjFunction(&dstate, func); | ||||||
|  |  | ||||||
|  |     return dstate.writerStatus; | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/cdump.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/cdump.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #ifndef COSMO_DUMP_H | ||||||
|  | #define COSMO_DUMP_H | ||||||
|  |  | ||||||
|  | #include "cobj.h" | ||||||
|  | #include "cosmo.h" | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #define COSMO_MAGIC     "COS\x12" | ||||||
|  | #define COSMO_MAGIC_LEN 4 | ||||||
|  |  | ||||||
|  | typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const void *ud); | ||||||
|  |  | ||||||
|  | bool cosmoD_isBigEndian(); | ||||||
|  |  | ||||||
|  | int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData); | ||||||
|  |  | ||||||
|  | #endif | ||||||
		Reference in New Issue
	
	Block a user