PikaCompiler.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. /*
  2. * This file is part of the PikaPython project.
  3. * http://github.com/pikastech/pikapython
  4. *
  5. * MIT License
  6. *
  7. * Copyright (c) 2021 lyon liang6516@outlook.com
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a
  10. * copy of this software and associated documentation files (the "Software"),
  11. * to deal in the Software without restriction, including without limitation
  12. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13. * and/or sell copies of the Software, and to permit persons to whom the
  14. * Software is furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25. * DEALINGS IN THE SOFTWARE.
  26. */
  27. #include "PikaCompiler.h"
  28. #include "BaseObj.h"
  29. #include "PikaObj.h"
  30. #include "PikaParser.h"
  31. #include "dataQueue.h"
  32. #include "dataQueueObj.h"
  33. #include "dataStack.h"
  34. #include "dataStrs.h"
  35. const char magic_code_pyo[] = {0x0f, 'p', 'y', 'o'};
  36. /*
  37. * @brief check magic code of pyo file
  38. * @param bytecode
  39. * @return pika_true or pika_false
  40. */
  41. static pika_bool _check_magic_code_pyo(uint8_t* bytecode) {
  42. char* data = (char*)bytecode;
  43. if (data[0] == magic_code_pyo[0] && data[1] == magic_code_pyo[1] &&
  44. data[2] == magic_code_pyo[2] && data[3] == magic_code_pyo[3]) {
  45. return pika_true;
  46. }
  47. return pika_false;
  48. }
  49. /*
  50. * @brief get bytecode from bytes arg
  51. * @param self bytes arg
  52. * @return bytecode
  53. */
  54. static uint8_t* arg_getBytecode(Arg* self) {
  55. uint8_t* bytecode_file = arg_getBytes(self);
  56. if (_check_magic_code_pyo(bytecode_file)) {
  57. return bytecode_file + sizeof(magic_code_pyo) + sizeof(uint32_t);
  58. }
  59. return bytecode_file;
  60. }
  61. /*
  62. * @brief get bytecode size from bytes arg
  63. * @param self bytes arg
  64. * @return bytecode size
  65. */
  66. static size_t arg_getBytecodeSize(Arg* self) {
  67. size_t size_all = arg_getBytesSize(self);
  68. uint8_t* bytecode_file = arg_getBytes(self);
  69. if (_check_magic_code_pyo(bytecode_file)) {
  70. return size_all - sizeof(magic_code_pyo) - sizeof(uint32_t);
  71. }
  72. return size_all;
  73. }
  74. /* const Pool output redirect */
  75. static void __handler_constPool_output_file(ConstPool* self, char* content) {
  76. /* to ram */
  77. uint16_t size = strGetSize(content) + 1;
  78. self->arg_buff = arg_append(self->arg_buff, content, size);
  79. /* to flash */
  80. pika_platform_fwrite(content, 1, size, self->output_f);
  81. }
  82. /* instruct array output redirect */
  83. static void __handler_instructArray_output_none(InstructArray* self,
  84. InstructUnit* ins_unit) {
  85. /* none */
  86. }
  87. static void __handler_instructArray_output_file(InstructArray* self,
  88. InstructUnit* ins_unit) {
  89. /* to flash */
  90. pika_platform_fwrite(ins_unit, 1, instructUnit_getSize(), self->output_f);
  91. }
  92. /*
  93. need implament :
  94. pika_platform_fopen()
  95. pika_platform_fwrite()
  96. pika_platform_fclose()
  97. */
  98. PIKA_RES pikaCompile(char* output_file_name, char* py_lines) {
  99. PIKA_RES res = PIKA_RES_OK;
  100. ByteCodeFrame bytecode_frame = {0};
  101. uint32_t const_pool_size = 0;
  102. uint32_t instruct_array_size = 0;
  103. uint32_t bytecode_size = 0;
  104. char void_ = 0;
  105. FILE* bytecode_f = pika_platform_fopen(output_file_name, "wb+");
  106. if (NULL == bytecode_f) {
  107. pika_platform_printf("Error: open file %s failed.\r\n",
  108. output_file_name);
  109. res = PIKA_RES_ERR_IO_ERROR;
  110. goto __exit;
  111. }
  112. /* main process */
  113. /* step 1, get size of const pool and instruct array */
  114. byteCodeFrame_init(&bytecode_frame);
  115. bytecode_frame.const_pool.output_f = bytecode_f;
  116. bytecode_frame.instruct_array.output_f = bytecode_f;
  117. bytecode_frame.instruct_array.output_redirect_fun =
  118. __handler_instructArray_output_none;
  119. res = pika_lines2Bytes(&bytecode_frame, py_lines);
  120. if (PIKA_RES_OK != res) {
  121. pika_platform_printf(" Error: Syntax error.\r\n");
  122. goto __exit;
  123. }
  124. const_pool_size = bytecode_frame.const_pool.size;
  125. instruct_array_size = bytecode_frame.instruct_array.size;
  126. bytecode_size = const_pool_size + instruct_array_size +
  127. sizeof(const_pool_size) + sizeof(instruct_array_size);
  128. byteCodeFrame_deinit(&bytecode_frame);
  129. /* step 2, write instruct array to file */
  130. /* write magic code */
  131. pika_platform_fwrite(magic_code_pyo, 1, sizeof(magic_code_pyo), bytecode_f);
  132. /* write bytecode size */
  133. pika_platform_fwrite(&bytecode_size, 1, sizeof(bytecode_size), bytecode_f);
  134. /* write ins array size */
  135. pika_platform_fwrite(&instruct_array_size, 1, sizeof(instruct_array_size),
  136. bytecode_f);
  137. byteCodeFrame_init(&bytecode_frame);
  138. bytecode_frame.const_pool.output_f = bytecode_f;
  139. bytecode_frame.instruct_array.output_f = bytecode_f;
  140. /* instruct array to file */
  141. bytecode_frame.instruct_array.output_redirect_fun =
  142. __handler_instructArray_output_file;
  143. pika_lines2Bytes(&bytecode_frame, py_lines);
  144. byteCodeFrame_deinit(&bytecode_frame);
  145. /* step 3, write const pool to file */
  146. pika_platform_fwrite(&const_pool_size, 1, sizeof(const_pool_size),
  147. bytecode_f);
  148. void_ = 0;
  149. /* add \0 at the start */
  150. pika_platform_fwrite(&void_, 1, 1, bytecode_f);
  151. byteCodeFrame_init(&bytecode_frame);
  152. bytecode_frame.const_pool.output_f = bytecode_f;
  153. bytecode_frame.instruct_array.output_f = bytecode_f;
  154. /* const pool to file */
  155. bytecode_frame.const_pool.output_redirect_fun =
  156. __handler_constPool_output_file;
  157. /* instruct array to none */
  158. bytecode_frame.instruct_array.output_redirect_fun =
  159. __handler_instructArray_output_none;
  160. pika_lines2Bytes(&bytecode_frame, py_lines);
  161. /* deinit */
  162. __exit:
  163. byteCodeFrame_deinit(&bytecode_frame);
  164. if (NULL != bytecode_f) {
  165. pika_platform_fclose(bytecode_f);
  166. }
  167. /* succeed */
  168. return res;
  169. };
  170. /*
  171. need implament :
  172. pika_platform_fopen()
  173. pika_platform_fread()
  174. pika_platform_fwrite()
  175. pika_platform_fclose()
  176. */
  177. PIKA_RES pikaCompileFileWithOutputName(char* output_file_name,
  178. char* input_file_name) {
  179. Args buffs = {0};
  180. Arg* input_file_arg = arg_loadFile(NULL, input_file_name);
  181. if (NULL == input_file_arg) {
  182. pika_platform_printf("Error: Could not load file '%s'\n",
  183. input_file_name);
  184. return PIKA_RES_ERR_IO_ERROR;
  185. }
  186. char* lines = (char*)arg_getBytes(input_file_arg);
  187. lines = strsFilePreProcess(&buffs, lines);
  188. PIKA_RES res = pikaCompile(output_file_name, lines);
  189. arg_deinit(input_file_arg);
  190. strsDeinit(&buffs);
  191. return res;
  192. }
  193. PIKA_RES pikaCompileFile(char* input_file_name) {
  194. Args buffs = {0};
  195. char* output_file_name = strsGetFirstToken(&buffs, input_file_name, '.');
  196. output_file_name = strsAppend(&buffs, input_file_name, ".o");
  197. PIKA_RES res =
  198. pikaCompileFileWithOutputName(output_file_name, input_file_name);
  199. strsDeinit(&buffs);
  200. return res;
  201. }
  202. LibObj* New_LibObj(Args* args) {
  203. LibObj* self = New_PikaObj(NULL);
  204. return self;
  205. }
  206. void LibObj_deinit(LibObj* self) {
  207. obj_deinit(self);
  208. }
  209. /* add bytecode to lib, not copy the bytecode */
  210. void LibObj_dynamicLink(LibObj* self, char* module_name, uint8_t* bytecode) {
  211. Args buffs = {0};
  212. char* module_obj_name = strsReplace(&buffs, module_name, ".", "|");
  213. if (!obj_isArgExist(self, module_obj_name)) {
  214. obj_newObj(self, module_obj_name, "", New_TinyObj);
  215. }
  216. PikaObj* module_obj = obj_getObj(self, module_obj_name);
  217. obj_setStr(module_obj, "name", module_name);
  218. obj_setPtr(module_obj, "bytecode", bytecode);
  219. strsDeinit(&buffs);
  220. }
  221. /*
  222. * @brief add bytecode to lib, and copy the bytecode to the buff in the lib
  223. * @param self the lib obj
  224. * @param module_name the module name
  225. * @param bytecode the bytecode
  226. * @param size the size of the bytecode
  227. * @return error code
  228. */
  229. int LibObj_staticLink(LibObj* self,
  230. char* module_name,
  231. uint8_t* bytecode,
  232. size_t size) {
  233. Args buffs = {0};
  234. char* module_obj_name = strsReplace(&buffs, module_name, ".", "|");
  235. if (!obj_isArgExist(self, module_obj_name)) {
  236. obj_newObj(self, module_obj_name, "", New_TinyObj);
  237. }
  238. PikaObj* module_obj = obj_getObj(self, module_obj_name);
  239. uint16_t name_len = strGetSize(module_name);
  240. /* copy bytecode to buff */
  241. obj_setBytes(module_obj, "buff", bytecode, size);
  242. obj_setInt(module_obj, "namelen", name_len);
  243. obj_setInt(module_obj, "bytesize", size);
  244. /* link to buff */
  245. LibObj_dynamicLink(self, module_name, obj_getBytes(module_obj, "buff"));
  246. strsDeinit(&buffs);
  247. return 0;
  248. }
  249. int LibObj_staticLinkFileWithPath(LibObj* self,
  250. char* input_file_name,
  251. char* path) {
  252. Args buffs = {0};
  253. /* read file */
  254. Arg* input_file_arg = arg_loadFile(NULL, input_file_name);
  255. if (NULL == input_file_arg) {
  256. pika_platform_printf("Error: can't open file %s\r\n", input_file_name);
  257. return -1;
  258. }
  259. char* module_name = strsGetLastToken(&buffs, input_file_name, '/');
  260. size_t module_name_len = strlen(module_name);
  261. /* cut off '.py.o' */
  262. if (module_name[module_name_len - 1] == 'o' &&
  263. module_name[module_name_len - 2] == '.' &&
  264. module_name[module_name_len - 3] == 'y' &&
  265. module_name[module_name_len - 4] == 'p' &&
  266. module_name[module_name_len - 5] == '.') {
  267. module_name[module_name_len - 5] = 0;
  268. } else {
  269. // pika_platform_printf("linking raw %s:%s:%ld\r\n", input_file_name,
  270. // module_name, arg_getBytecodeSize(input_file_arg));
  271. /* replace . to | */
  272. module_name = strsReplace(&buffs, module_name, ".", "|");
  273. }
  274. char* module_name_new = strsPathJoin(&buffs, path, module_name);
  275. /* push bytecode */
  276. uint8_t* byte_code = arg_getBytecode(input_file_arg);
  277. size_t code_size = arg_getBytecodeSize(input_file_arg);
  278. LibObj_staticLink(self, module_name_new, byte_code, code_size);
  279. /* deinit */
  280. strsDeinit(&buffs);
  281. arg_deinit(input_file_arg);
  282. return 0;
  283. }
  284. int LibObj_staticLinkFile(LibObj* self, char* input_file_name) {
  285. return LibObj_staticLinkFileWithPath(self, input_file_name, "");
  286. }
  287. static int32_t __foreach_handler_listModules(Arg* argEach, void* context) {
  288. if (arg_isObject(argEach)) {
  289. PikaObj* module_obj = arg_getPtr(argEach);
  290. pika_platform_printf("%s\r\n", obj_getStr(module_obj, "name"));
  291. }
  292. return 0;
  293. }
  294. void LibObj_listModules(LibObj* self) {
  295. args_foreach(self->list, __foreach_handler_listModules, NULL);
  296. }
  297. typedef struct {
  298. FILE* out_file;
  299. uint32_t module_num;
  300. uint32_t sum_size;
  301. uint32_t block_size;
  302. size_t written_size;
  303. } PikaLinker;
  304. static void linker_fwrite(PikaLinker* context, uint8_t* bytes, size_t size) {
  305. size_t write_size = pika_platform_fwrite(bytes, 1, size, context->out_file);
  306. context->written_size += write_size;
  307. }
  308. static int32_t __foreach_handler_libWriteBytecode(Arg* argEach,
  309. PikaLinker* context) {
  310. if (arg_isObject(argEach)) {
  311. PikaObj* module_obj = arg_getPtr(argEach);
  312. pika_assert_obj_alive(module_obj);
  313. uint8_t* bytecode = obj_getPtr(module_obj, "bytecode");
  314. size_t bytecode_size = obj_getBytesSize(module_obj, "buff");
  315. /* align by 4 bytes */
  316. size_t align_size =
  317. align_by(bytecode_size, sizeof(uint32_t)) - bytecode_size;
  318. uint8_t aline_buff[sizeof(uint32_t)] = {0};
  319. // pika_platform_printf(" linking %s:%ld\r\n", obj_getStr(module_obj,
  320. // "name"),
  321. // bytecode_size);
  322. linker_fwrite(context, bytecode, bytecode_size);
  323. linker_fwrite(context, aline_buff, align_size);
  324. // printf("link success:%s\r\n", obj_getStr(module_obj, "name"));
  325. }
  326. return 0;
  327. }
  328. // #define NAME_BUFF_SIZE LIB_INFO_BLOCK_SIZE - sizeof(uint32_t)
  329. static int32_t __foreach_handler_libWriteIndex(Arg* argEach,
  330. PikaLinker* linker) {
  331. Args buffs = {0};
  332. if (arg_isObject(argEach)) {
  333. PikaObj* module_obj = arg_getPtr(argEach);
  334. uint32_t bytecode_size = obj_getInt(module_obj, "bytesize");
  335. char* module_name = obj_getStr(module_obj, "name");
  336. module_name = strsReplace(&buffs, module_name, "|", ".");
  337. uint32_t name_size = strGetSize(module_name);
  338. char* block_buff = (char*)pikaMalloc(linker->block_size);
  339. pika_platform_memset(block_buff, 0x00, linker->block_size);
  340. /*
  341. *create the block as [name][bytecode_size]
  342. * the space of name is LIB_INFO_BLOCK_SIZE - sizeof(bytecode_size)
  343. */
  344. pika_platform_memcpy(block_buff, module_name,
  345. name_size + 1); /* add '\0' after name */
  346. /* should write the size without align */
  347. pika_platform_memcpy(block_buff + linker->block_size - sizeof(uint32_t),
  348. &bytecode_size, sizeof(uint32_t));
  349. /* write the block to file */
  350. linker_fwrite(linker, (uint8_t*)block_buff, linker->block_size);
  351. pikaFree(block_buff, linker->block_size);
  352. }
  353. strsDeinit(&buffs);
  354. return 0;
  355. }
  356. static int32_t __foreach_handler_selectBlockSize(Arg* argEach,
  357. PikaLinker* linker) {
  358. uint32_t block_size = 0; /* block_size is the size of file info */
  359. if (arg_isObject(argEach)) {
  360. PikaObj* module_obj = arg_getPtr(argEach);
  361. /* namelen(aligned by 4bytes) and bytecode_size(uint32_t) */
  362. block_size =
  363. align_by(obj_getInt(module_obj, "namelen"), 4) + sizeof(uint32_t);
  364. if (block_size > linker->block_size) {
  365. // block_size should support the langest module name
  366. linker->block_size = block_size;
  367. }
  368. }
  369. return 0;
  370. }
  371. static int32_t __foreach_handler_libSumSize(Arg* argEach, PikaLinker* linker) {
  372. if (arg_isObject(argEach)) {
  373. PikaObj* module_obj = arg_getPtr(argEach);
  374. /* namelen(aligned by 4bytes) and bytecode_size(uint32_t) */
  375. uint32_t bytecode_size =
  376. obj_getInt(module_obj, "bytesize"); /* size of every module obj */
  377. /* align the bytecode_size by 4 bytes */
  378. linker->sum_size += align_by(bytecode_size, 4);
  379. }
  380. return 0;
  381. }
  382. static int32_t __foreach_handler_getModuleNum(Arg* argEach,
  383. PikaLinker* linker) {
  384. if (arg_isObject(argEach)) {
  385. linker->module_num++;
  386. }
  387. return 0;
  388. }
  389. int LibObj_linkFile(LibObj* self, char* output_file_name) {
  390. FILE* out_file = pika_platform_fopen(output_file_name, "wb+");
  391. PikaLinker linker = {0};
  392. linker.block_size = 64; /* 64 is the default block size */
  393. linker.out_file = out_file;
  394. /* write meta information */
  395. args_foreach(self->list, (fn_args_foreach)__foreach_handler_getModuleNum,
  396. &linker);
  397. /* select block size of pya */
  398. args_foreach(self->list, (fn_args_foreach)__foreach_handler_selectBlockSize,
  399. &linker);
  400. /* get sum size of pya */
  401. args_foreach(self->list, (fn_args_foreach)__foreach_handler_libSumSize,
  402. &linker);
  403. /* meta info */
  404. char magic_code[] = {0x0f, 'p', 'y', 'a'};
  405. uint32_t version_num = LIB_VERSION_NUMBER;
  406. uint32_t module_num = linker.module_num;
  407. uint32_t modules_size = linker.sum_size;
  408. uint32_t block_size = linker.block_size;
  409. uint32_t totle_size = block_size * (module_num + 1) + modules_size;
  410. uint8_t* meta_block_buff = pikaMalloc(block_size);
  411. pika_platform_memset(meta_block_buff, 0, block_size);
  412. /* write meta info */
  413. const uint32_t magic_code_offset =
  414. sizeof(uint32_t) * PIKA_APP_MAGIC_CODE_OFFSET;
  415. const uint32_t totle_size_offset =
  416. sizeof(uint32_t) * PIKA_APP_MODULE_SIZE_OFFSET;
  417. const uint32_t version_offset = sizeof(uint32_t) * PIKA_APP_VERSION_OFFSET;
  418. const uint32_t module_num_offset =
  419. sizeof(uint32_t) * PIKA_APP_MODULE_NUM_OFFSET;
  420. const uint32_t info_block_size_offset =
  421. sizeof(uint32_t) * PIKA_APP_INFO_BLOCK_SIZE_OFFSET;
  422. // the meta info is the first block
  423. pika_platform_memcpy(meta_block_buff + magic_code_offset, &magic_code,
  424. sizeof(uint32_t));
  425. pika_platform_memcpy(meta_block_buff + version_offset, &version_num,
  426. sizeof(uint32_t));
  427. /* write module_num to the file */
  428. pika_platform_memcpy(meta_block_buff + module_num_offset, &module_num,
  429. sizeof(uint32_t));
  430. /* write modules_size to the file */
  431. pika_platform_memcpy(meta_block_buff + totle_size_offset, &totle_size,
  432. sizeof(uint32_t));
  433. /* write block_size to the file */
  434. pika_platform_memcpy(meta_block_buff + info_block_size_offset, &block_size,
  435. sizeof(uint32_t));
  436. linker_fwrite(&linker, meta_block_buff, block_size);
  437. /* write module index to file */
  438. args_foreach(self->list, (fn_args_foreach)__foreach_handler_libWriteIndex,
  439. &linker);
  440. /* write module bytecode to file */
  441. args_foreach(self->list,
  442. (fn_args_foreach)__foreach_handler_libWriteBytecode, &linker);
  443. /* main process */
  444. /* deinit */
  445. pika_platform_fclose(out_file);
  446. pikaFree(meta_block_buff, block_size);
  447. pika_assert(totle_size == linker.written_size);
  448. return 0;
  449. }
  450. static int _getModuleNum(uint8_t* library_bytes) {
  451. if (0 != ((intptr_t)library_bytes & 0x03)) {
  452. return PIKA_RES_ERR_UNALIGNED_PTR;
  453. }
  454. char* magic_code = (char*)library_bytes;
  455. uint32_t* library_info = (uint32_t*)library_bytes;
  456. uint32_t version_num = library_info[PIKA_APP_VERSION_OFFSET];
  457. uint32_t module_num = library_info[PIKA_APP_MODULE_NUM_OFFSET];
  458. /* check magic_code */
  459. if (!((magic_code[0] == 0x0f) && (magic_code[1] == 'p') &&
  460. (magic_code[2] == 'y') && (magic_code[3] == 'a'))) {
  461. pika_platform_printf("Error: invalid magic code.\r\n");
  462. return PIKA_RES_ERR_ILLEGAL_MAGIC_CODE;
  463. }
  464. /* check version num */
  465. if (version_num != LIB_VERSION_NUMBER) {
  466. pika_platform_printf(
  467. "Error: invalid version number. Expected %d, got %d\r\n",
  468. LIB_VERSION_NUMBER, version_num);
  469. pika_platform_printf(
  470. "Please run the 'rus-msc-latest-win10.exe' again to update the "
  471. "version of compiled library.\r\n");
  472. return PIKA_RES_ERR_INVALID_VERSION_NUMBER;
  473. }
  474. return module_num;
  475. }
  476. #define MOD_NAMELEN_OFFSET 0
  477. #define MOD_NAME_OFFSET 4
  478. #define MOD_SIZE_OFFSET (name_len + 5) /* 5 = 4 + 1*/
  479. static PIKA_RES _loadModuleDataWithIndex(uint8_t* library_bytes,
  480. int module_num,
  481. int module_index,
  482. char** name_p,
  483. uint8_t** addr_p,
  484. size_t* size) {
  485. uint32_t block_size = *(uint32_t*)(library_bytes + 4 * sizeof(uint32_t));
  486. uint8_t* file_info_block_start = library_bytes + block_size;
  487. uint8_t* bytecode_ptr = file_info_block_start + block_size * module_num;
  488. uint8_t* bytecode_ptr_next = bytecode_ptr;
  489. uint32_t module_size = 0;
  490. char* module_name = NULL;
  491. uintptr_t offset = 0;
  492. for (uint32_t i = 0; i < module_index + 1; i++) {
  493. uint8_t* file_info_block = file_info_block_start + offset;
  494. module_name = (char*)(file_info_block);
  495. module_size =
  496. *(uint32_t*)(file_info_block + block_size - sizeof(uint32_t));
  497. bytecode_ptr = bytecode_ptr_next;
  498. offset += block_size;
  499. /* next module ptr, align by 4 bytes */
  500. bytecode_ptr_next += align_by(module_size, 4);
  501. }
  502. *name_p = module_name;
  503. *addr_p = bytecode_ptr;
  504. *size = module_size;
  505. /* fix size for string */
  506. PIKA_BOOL bIsString = PIKA_TRUE;
  507. for (size_t i = 0; i < module_size - 1; ++i) {
  508. if (bytecode_ptr[i] == 0) {
  509. bIsString = PIKA_FALSE;
  510. break;
  511. }
  512. }
  513. if (bIsString) {
  514. /* remove the last '\0' for stirng */
  515. if (bytecode_ptr[module_size - 1] == 0) {
  516. *size -= 1;
  517. }
  518. }
  519. return PIKA_RES_OK;
  520. }
  521. PIKA_RES _loadModuleDataWithName(uint8_t* library_bytes,
  522. char* module_name,
  523. uint8_t** addr_p,
  524. size_t* size_p) {
  525. int module_num = _getModuleNum(library_bytes);
  526. if (module_num < 0) {
  527. return (PIKA_RES)module_num;
  528. }
  529. Args buffs = {0};
  530. for (int i = 0; i < module_num; i++) {
  531. char* name = NULL;
  532. uint8_t* addr = NULL;
  533. size_t size = 0;
  534. _loadModuleDataWithIndex(library_bytes, module_num, i, &name, &addr,
  535. &size);
  536. name = strsGetLastToken(&buffs, name, '/');
  537. if (strEqu(module_name, name)) {
  538. *addr_p = addr;
  539. *size_p = size;
  540. strsDeinit(&buffs);
  541. return PIKA_RES_OK;
  542. }
  543. }
  544. strsDeinit(&buffs);
  545. return PIKA_RES_ERR_ARG_NO_FOUND;
  546. }
  547. Arg* _getPack_libraryBytes(char* pack_name) {
  548. if (NULL == pack_name) {
  549. pika_platform_printf(
  550. "[%s - %d]What I freakin' need is a damn pack file name! Why the "
  551. "hell did you give me a goddamn NULL?!\r\n",
  552. __FILE__, __LINE__);
  553. return NULL;
  554. }
  555. Arg* f_arg = NULL;
  556. f_arg = arg_loadFile(NULL, pack_name);
  557. if (NULL == f_arg) {
  558. pika_platform_printf("Error: Could not load file \'%s\'\r\n",
  559. pack_name);
  560. // pikaFree(*fp, sizeof(pikafs_FILE));
  561. // arg_deinit(f_arg);
  562. return NULL;
  563. }
  564. return f_arg;
  565. }
  566. typedef struct {
  567. char* module_name;
  568. PikaObj* module;
  569. } Context_LibObj_getModule;
  570. int32_t _handler_LibObj_getModule(Arg* argEach, void* context) {
  571. Context_LibObj_getModule* ctx = context;
  572. if (NULL != ctx->module) {
  573. return 0;
  574. }
  575. if (arg_isObject(argEach)) {
  576. PikaObj* module_obj = arg_getPtr(argEach);
  577. if (strEqu(obj_getStr(module_obj, "name"), ctx->module_name)) {
  578. ctx->module = module_obj;
  579. return 0;
  580. }
  581. }
  582. return 0;
  583. }
  584. PikaObj* LibObj_getModule(LibObj* self, char* module_name) {
  585. Context_LibObj_getModule context = {0};
  586. context.module_name = module_name;
  587. args_foreach(self->list, _handler_LibObj_getModule, &context);
  588. return context.module;
  589. }
  590. /*
  591. redirect import to module
  592. example:
  593. when IMP XXX.YYY.ZZZ and ZZZ is a calss
  594. then redirect to IMP XXX.YYY
  595. */
  596. char* LibObj_redirectModule(LibObj* self, Args* buffs_out, char* module_name) {
  597. if (NULL == self) {
  598. return NULL;
  599. }
  600. char* module_name_new = NULL;
  601. PikaObj* module_obj = NULL;
  602. Args buffs = {0};
  603. size_t token_num = strCountSign(module_name, '.');
  604. if (0 == token_num) {
  605. goto __exit;
  606. }
  607. module_obj = LibObj_getModule(self, module_name);
  608. if (NULL != module_obj) {
  609. module_name_new = module_name;
  610. goto __exit;
  611. }
  612. module_name_new = strsCopy(&buffs, module_name);
  613. for (int i = 0; i < token_num + 1; i++) {
  614. PikaObj* module_obj = LibObj_getModule(self, module_name_new);
  615. if (NULL != module_obj) {
  616. goto __exit;
  617. }
  618. strPopLastToken(module_name_new, '.');
  619. }
  620. __exit:
  621. if (NULL != module_name_new) {
  622. module_name_new = strsCopy(buffs_out, module_name_new);
  623. }
  624. strsDeinit(&buffs);
  625. return module_name_new;
  626. }
  627. int LibObj_loadLibrary(LibObj* self, uint8_t* library_bytes) {
  628. int module_num = _getModuleNum(library_bytes);
  629. if (module_num < 0) {
  630. /* load error */
  631. return module_num;
  632. }
  633. for (uint32_t i = 0; i < module_num; i++) {
  634. char* module_name = NULL;
  635. uint8_t* bytecode_addr = NULL;
  636. size_t bytecode_size = 0;
  637. _loadModuleDataWithIndex(library_bytes, module_num, i, &module_name,
  638. &bytecode_addr, &bytecode_size);
  639. LibObj_dynamicLink(self, module_name, bytecode_addr);
  640. }
  641. obj_setPtr(self, "@libraw", library_bytes);
  642. return PIKA_RES_OK;
  643. }
  644. int32_t __foreach_handler_printModule(Arg* argEach, void* context) {
  645. if (arg_isObject(argEach)) {
  646. PikaObj* module_obj = arg_getPtr(argEach);
  647. char* module_name = obj_getStr(module_obj, "name");
  648. if (NULL != module_name) {
  649. pika_platform_printf(module_name);
  650. pika_platform_printf("\r\n");
  651. }
  652. }
  653. return 0;
  654. }
  655. void LibObj_printModules(LibObj* self) {
  656. args_foreach(self->list, __foreach_handler_printModule, NULL);
  657. }
  658. int LibObj_loadLibraryFile(LibObj* self, char* lib_file_name) {
  659. Arg* aFile = arg_loadFile(NULL, lib_file_name);
  660. if (NULL == aFile) {
  661. pika_platform_printf("Error: Could not load library file '%s'\n",
  662. lib_file_name);
  663. return PIKA_RES_ERR_IO_ERROR;
  664. }
  665. /* save file_arg as @lib_buf to libObj */
  666. obj_setArg_noCopy(self, "@lib_buf", aFile);
  667. if (0 != LibObj_loadLibrary(self, arg_getBytes(aFile))) {
  668. pika_platform_printf("Error: Could not load library from '%s'\n",
  669. lib_file_name);
  670. return PIKA_RES_ERR_OPERATION_FAILED;
  671. }
  672. return PIKA_RES_OK;
  673. }
  674. /**
  675. * @brief unpack *.pack file to Specified path
  676. *
  677. * @param pack_name the name of *.pack file
  678. * @param out_path output path
  679. * @return
  680. */
  681. PIKA_RES pikafs_unpack_files(char* pack_name, char* out_path) {
  682. PIKA_RES stat = PIKA_RES_OK;
  683. Arg* file_arg = NULL;
  684. uint8_t* library_bytes = NULL;
  685. pikafs_FILE* fptr = NULL;
  686. if (NULL == out_path) {
  687. out_path = "./packout/";
  688. }
  689. file_arg = _getPack_libraryBytes(pack_name);
  690. if (NULL != file_arg) {
  691. library_bytes = arg_getBytes(file_arg);
  692. } else {
  693. return PIKA_RES_ERR_IO_ERROR;
  694. }
  695. int module_num = _getModuleNum(library_bytes);
  696. if (module_num < 0) {
  697. return (PIKA_RES)module_num;
  698. }
  699. Args buffs = {0};
  700. char* output_file_path = NULL;
  701. FILE* new_fp = NULL;
  702. char* name = NULL;
  703. uint8_t* addr = NULL;
  704. size_t size = 0;
  705. for (int i = 0; i < module_num; ++i) {
  706. size = 0;
  707. stat = _loadModuleDataWithIndex(library_bytes, module_num, i, &name,
  708. &addr, &size);
  709. name = strsGetLastToken(&buffs, name, '/');
  710. output_file_path = strsPathJoin(&buffs, out_path, name);
  711. pika_platform_printf("output_file_path: %s\r\n", output_file_path);
  712. new_fp = pika_platform_fopen(output_file_path, "wb+");
  713. if (NULL != new_fp) {
  714. pika_platform_fwrite(addr, size, 1, new_fp);
  715. pika_platform_fclose(new_fp);
  716. pika_platform_printf("unpack %s to %s\r\n", name, output_file_path);
  717. } else {
  718. pika_platform_printf("can't open %s\r\n", output_file_path);
  719. stat = PIKA_RES_ERR_IO_ERROR;
  720. break;
  721. }
  722. }
  723. arg_deinit(file_arg);
  724. strsDeinit(&buffs);
  725. pikaFree(fptr, sizeof(pikafs_FILE));
  726. return stat;
  727. }
  728. size_t pika_fputs(char* str, FILE* fp) {
  729. size_t size = strGetSize(str);
  730. return pika_platform_fwrite(str, 1, size, fp);
  731. }
  732. int Lib_loadLibraryFileToArray(char* origin_file_name, char* out_folder) {
  733. Args buffs = {0};
  734. Arg* file_arg = arg_loadFile(NULL, origin_file_name);
  735. int res = 0;
  736. if (NULL == file_arg) {
  737. pika_platform_printf("Error: Could not load file '%s'\n",
  738. origin_file_name);
  739. return 1;
  740. }
  741. char* output_file_name = NULL;
  742. output_file_name = strsGetLastToken(&buffs, origin_file_name, '/');
  743. output_file_name = strsAppend(&buffs, "__asset_", output_file_name);
  744. output_file_name = strsReplace(&buffs, output_file_name, ".", "_");
  745. output_file_name = strsAppend(&buffs, output_file_name, ".c");
  746. char* output_file_path = strsPathJoin(&buffs, out_folder, output_file_name);
  747. FILE* fp = pika_platform_fopen(output_file_path, "wb+");
  748. char* array_name = strsGetLastToken(&buffs, origin_file_name, '/');
  749. array_name = strsReplace(&buffs, array_name, ".", "_");
  750. pika_platform_printf(" loading %s[]...\n", array_name);
  751. pika_fputs("#include \"PikaPlatform.h\"\n", fp);
  752. pika_fputs("/* warning: auto generated file, please do not modify */\n",
  753. fp);
  754. pika_fputs("PIKA_BYTECODE_ALIGN const unsigned char ", fp);
  755. pika_fputs(array_name, fp);
  756. pika_fputs("[] = {", fp);
  757. char byte_buff[32] = {0};
  758. uint8_t* array = arg_getBytes(file_arg);
  759. for (size_t i = 0; i < arg_getBytesSize(file_arg); i++) {
  760. if (i % 12 == 0) {
  761. pika_fputs("\n ", fp);
  762. }
  763. pika_sprintf(byte_buff, "0x%02x, ", array[i]);
  764. pika_fputs(byte_buff, fp);
  765. }
  766. pika_fputs("\n};\n", fp);
  767. res = 0;
  768. goto __exit;
  769. __exit:
  770. pika_platform_fclose(fp);
  771. strsDeinit(&buffs);
  772. arg_deinit(file_arg);
  773. return res;
  774. }
  775. static PIKA_RES __Maker_compileModuleWithInfo(PikaMaker* self,
  776. char* module_name) {
  777. Args buffs = {0};
  778. char* input_file_name = strsReplace(&buffs, module_name, ".", "/");
  779. input_file_name = strsAppend(&buffs, input_file_name, ".py");
  780. char* input_file_path =
  781. strsPathJoin(&buffs, obj_getStr(self, "pwd"), input_file_name);
  782. pika_platform_printf(" compiling %s...\r\n", input_file_name);
  783. char* output_file_name = strsAppend(&buffs, module_name, ".py.o");
  784. char* output_file_path = NULL;
  785. output_file_path =
  786. strsPathJoin(&buffs, obj_getStr(self, "pwd"), "pikascript-api");
  787. output_file_path = strsPathJoin(&buffs, output_file_path, output_file_name);
  788. PIKA_RES res =
  789. pikaCompileFileWithOutputName(output_file_path, input_file_path);
  790. strsDeinit(&buffs);
  791. return res;
  792. }
  793. PikaMaker* New_PikaMaker(void) {
  794. PikaMaker* self = New_PikaObj(NULL);
  795. obj_setStr(self, "pwd", "");
  796. obj_setInt(self, "err", 0);
  797. LibObj* lib = New_LibObj(NULL);
  798. obj_setPtr(self, "lib", lib);
  799. return self;
  800. }
  801. /*
  802. * @brief: deinit PikaMaker
  803. * @param: self PikaMaker
  804. * @return: void
  805. */
  806. void pikaMaker_deinit(PikaMaker* self) {
  807. LibObj* lib = obj_getPtr(self, "lib");
  808. LibObj_deinit(lib);
  809. obj_deinit(self);
  810. }
  811. /*
  812. * @brief: set pwd
  813. * @param: self PikaMaker
  814. * @param: pwd
  815. * @return: void
  816. */
  817. void pikaMaker_setPWD(PikaMaker* self, char* pwd) {
  818. obj_setStr(self, "pwd", pwd);
  819. }
  820. /*
  821. * @brief: set state
  822. * @param: self PikaMaker
  823. * @param: module_name
  824. * @param: state
  825. * @return: void
  826. */
  827. void pikaMaker_setState(PikaMaker* self, char* module_name, char* state) {
  828. Args buffs = {0};
  829. char* module_obj_name = strsReplace(&buffs, module_name, ".", "|");
  830. obj_newMetaObj(self, module_obj_name, New_TinyObj);
  831. PikaObj* module_obj = obj_getObj(self, module_obj_name);
  832. obj_setStr(module_obj, "name", module_name);
  833. obj_setStr(module_obj, "state", state);
  834. strsDeinit(&buffs);
  835. }
  836. char* pikaMaker_getState(PikaMaker* self, char* module_name) {
  837. PikaObj* module_obj = obj_getObj(self, module_name);
  838. if (NULL == module_obj) {
  839. return "nocompiled";
  840. }
  841. return obj_getStr(module_obj, "state");
  842. }
  843. /*
  844. * @brief: compile module
  845. * @param: self PikaMaker
  846. * @param: module_name
  847. * @return: PIKA_RES
  848. */
  849. PIKA_RES pikaMaker_compileModule(PikaMaker* self, char* module_name) {
  850. PIKA_RES res = __Maker_compileModuleWithInfo(self, module_name);
  851. /* update compile info */
  852. if (PIKA_RES_OK == res) {
  853. pikaMaker_setState(self, module_name, "compiled");
  854. } else {
  855. pikaMaker_setState(self, module_name, "failed");
  856. }
  857. return res;
  858. }
  859. enum PIKA_MODULE_TYPE {
  860. PIKA_MODULE_TYPE_UNKNOWN,
  861. PIKA_MODULE_TYPE_PY,
  862. PIKA_MODULE_TYPE_PYI,
  863. PIKA_MODULE_TYPE_PYO
  864. };
  865. static enum PIKA_MODULE_TYPE _checkModuleType(char* module_path) {
  866. Args buffs = {0};
  867. enum PIKA_MODULE_TYPE module_type = PIKA_MODULE_TYPE_UNKNOWN;
  868. /* module info is not exist */
  869. /* set module to be compile */
  870. FILE* imp_file_py =
  871. pika_platform_fopen(strsAppend(&buffs, module_path, ".py"), "rb");
  872. FILE* imp_file_pyi =
  873. pika_platform_fopen(strsAppend(&buffs, module_path, ".pyi"), "rb");
  874. FILE* imp_file_pyo =
  875. pika_platform_fopen(strsAppend(&buffs, module_path, ".py.o"), "rb");
  876. if (NULL != imp_file_pyo) {
  877. module_type = PIKA_MODULE_TYPE_PYO;
  878. goto __exit;
  879. }
  880. if (NULL != imp_file_py) {
  881. module_type = PIKA_MODULE_TYPE_PY;
  882. goto __exit;
  883. }
  884. if (NULL != imp_file_pyi) {
  885. module_type = PIKA_MODULE_TYPE_PYI;
  886. goto __exit;
  887. }
  888. __exit:
  889. if (NULL != imp_file_pyo) {
  890. pika_platform_fclose(imp_file_pyo);
  891. }
  892. if (NULL != imp_file_pyi) {
  893. pika_platform_fclose(imp_file_pyi);
  894. }
  895. if (NULL != imp_file_py) {
  896. pika_platform_fclose(imp_file_py);
  897. }
  898. strsDeinit(&buffs);
  899. return module_type;
  900. }
  901. static char* _redirectModuleFromFs(Args* buffs_out,
  902. char* module_path,
  903. char* module_name) {
  904. Args buffs = {0};
  905. size_t token_num = strCountSign(module_name, '.');
  906. char* module_name_new = NULL;
  907. char* module_try = NULL;
  908. if (0 == token_num) {
  909. goto __exit;
  910. }
  911. module_try = strsCopy(&buffs, module_path);
  912. module_name_new = strsCopy(&buffs, module_name);
  913. for (int i = 0; i < token_num + 1; i++) {
  914. enum PIKA_MODULE_TYPE module_type = _checkModuleType(module_try);
  915. if (module_type != PIKA_MODULE_TYPE_UNKNOWN) {
  916. char* module_name = module_try;
  917. if (NULL != module_name) {
  918. goto __exit;
  919. }
  920. }
  921. strPopLastToken(module_try, '/');
  922. strPopLastToken(module_name_new, '.');
  923. }
  924. module_path = NULL;
  925. __exit:
  926. if (NULL != module_name_new) {
  927. module_name_new = strsCopy(buffs_out, module_name_new);
  928. }
  929. strsDeinit(&buffs);
  930. return module_name_new;
  931. }
  932. FILE* _openModuleFile(char* module_path, enum PIKA_MODULE_TYPE module_type) {
  933. Args buffs = {0};
  934. FILE* fp = NULL;
  935. switch (module_type) {
  936. case PIKA_MODULE_TYPE_PY:
  937. fp = pika_platform_fopen(strsAppend(&buffs, module_path, ".py"),
  938. "rb");
  939. break;
  940. case PIKA_MODULE_TYPE_PYI:
  941. fp = pika_platform_fopen(strsAppend(&buffs, module_path, ".pyi"),
  942. "rb");
  943. break;
  944. case PIKA_MODULE_TYPE_PYO:
  945. fp = pika_platform_fopen(strsAppend(&buffs, module_path, ".py.o"),
  946. "rb");
  947. break;
  948. default:
  949. break;
  950. }
  951. strsDeinit(&buffs);
  952. return fp;
  953. }
  954. int pikaMaker_linkByteocdeFile(PikaMaker* self, char* imp_module_name) {
  955. Args buffs = {0};
  956. char* imp_module_path =
  957. strsPathJoin(&buffs, obj_getStr(self, "pwd"), imp_module_name);
  958. FILE* imp_file = _openModuleFile(imp_module_path, PIKA_MODULE_TYPE_PYO);
  959. pika_platform_printf(" loading %s.py.o...\r\n", imp_module_path);
  960. /* found *.py.o, push to compiled list */
  961. pikaMaker_setState(self, imp_module_name, "compiled");
  962. char* imp_api_path =
  963. strsPathJoin(&buffs, obj_getStr(self, "pwd"), "pikascript-api/");
  964. imp_api_path = strsPathJoin(&buffs, imp_api_path, imp_module_name);
  965. FILE* imp_file_pyo_api =
  966. pika_platform_fopen(strsAppend(&buffs, imp_api_path, ".py.o"), "wb+");
  967. pika_assert(imp_file_pyo_api != NULL);
  968. /* copy imp_file_pyo to imp_api_path */
  969. uint8_t* buff = (uint8_t*)pika_platform_malloc(128);
  970. size_t read_size = 0;
  971. while (1) {
  972. read_size = pika_platform_fread(buff, 1, 128, imp_file);
  973. if (read_size > 0) {
  974. pika_platform_fwrite(buff, 1, read_size, imp_file_pyo_api);
  975. } else {
  976. break;
  977. }
  978. }
  979. pika_platform_free(buff);
  980. pika_platform_fclose(imp_file_pyo_api);
  981. pika_platform_fclose(imp_file);
  982. strsDeinit(&buffs);
  983. return 0;
  984. }
  985. int pikaMaker_getDependencies(PikaMaker* self, char* module_name) {
  986. int res = 0;
  987. ByteCodeFrame bf = {0};
  988. Args buffs = {0};
  989. byteCodeFrame_init(&bf);
  990. ConstPool* const_pool = NULL;
  991. InstructArray* ins_array = NULL;
  992. char* module_path =
  993. strsPathJoin(&buffs, obj_getStr(self, "pwd"), "pikascript-api/");
  994. module_path = strsPathJoin(&buffs, module_path, module_name);
  995. char* file_path = strsAppend(&buffs, module_path, ".py.o");
  996. Arg* file_arg = arg_loadFile(NULL, file_path);
  997. uint8_t offset_befor = 0;
  998. if (NULL == file_arg) {
  999. pika_platform_printf("Error: Could not load file '%s'\n", file_path);
  1000. res = 1;
  1001. goto __exit;
  1002. }
  1003. byteCodeFrame_loadByteCode(&bf, arg_getBytes(file_arg));
  1004. const_pool = &bf.const_pool;
  1005. ins_array = &bf.instruct_array;
  1006. offset_befor = ins_array->content_offset_now;
  1007. ins_array->content_offset_now = 0;
  1008. while (1) {
  1009. InstructUnit* ins_unit = instructArray_getNow(ins_array);
  1010. if (NULL == ins_unit) {
  1011. goto __exit;
  1012. }
  1013. if (instructUnit_getInstructIndex(ins_unit) == PIKA_INS(IMP) ||
  1014. instructUnit_getInstructIndex(ins_unit) == PIKA_INS(INH)) {
  1015. char* imp_module_name =
  1016. constPool_getByOffset(const_pool, ins_unit->const_pool_index);
  1017. char* imp_module_name_fs =
  1018. strsReplace(&buffs, imp_module_name, ".", "/");
  1019. char* imp_module_path = strsPathJoin(
  1020. &buffs, obj_getStr(self, "pwd"), imp_module_name_fs);
  1021. char* imp_module_name_redirect =
  1022. _redirectModuleFromFs(&buffs, imp_module_path, imp_module_name);
  1023. if (NULL != imp_module_name_redirect) {
  1024. /* redirect to real module */
  1025. imp_module_name = imp_module_name_redirect;
  1026. imp_module_name_fs =
  1027. strsReplace(&buffs, imp_module_name, ".", "/");
  1028. imp_module_path = strsPathJoin(&buffs, obj_getStr(self, "pwd"),
  1029. imp_module_name_fs);
  1030. }
  1031. /* check if compiled the module */
  1032. if (args_isArgExist(self->list, imp_module_name)) {
  1033. /* module info is exist, do nothing */
  1034. } else {
  1035. /* module info is not exist */
  1036. /* set module to be compile */
  1037. enum PIKA_MODULE_TYPE module_type =
  1038. _checkModuleType(imp_module_path);
  1039. if (module_type == PIKA_MODULE_TYPE_PYO) {
  1040. pikaMaker_linkByteocdeFile(self, imp_module_path);
  1041. } else if (module_type == PIKA_MODULE_TYPE_PY) {
  1042. /* found *.py, push to nocompiled list */
  1043. pikaMaker_setState(self, imp_module_name, "nocompiled");
  1044. } else if (module_type == PIKA_MODULE_TYPE_PYI) {
  1045. /* found *.py, push to nocompiled list */
  1046. pikaMaker_setState(self, imp_module_name, "cmodule");
  1047. } else {
  1048. pika_platform_printf(
  1049. " [warning]: file: '%s.pyi', '%s.py' or '%s.py.o' "
  1050. "no found\n",
  1051. imp_module_name_fs, imp_module_name_fs,
  1052. imp_module_name_fs);
  1053. }
  1054. }
  1055. }
  1056. instructArray_getNext(ins_array);
  1057. }
  1058. __exit:
  1059. if (NULL != ins_array) {
  1060. ins_array->content_offset_now = offset_befor;
  1061. }
  1062. if (NULL != file_arg) {
  1063. arg_deinit(file_arg);
  1064. }
  1065. strsDeinit(&buffs);
  1066. byteCodeFrame_deinit(&bf);
  1067. return res;
  1068. }
  1069. int32_t __foreach_handler_printStates(Arg* argEach, void* context) {
  1070. if (arg_isObject(argEach)) {
  1071. PikaObj* module_obj = arg_getPtr(argEach);
  1072. pika_platform_printf("%s: %s\r\n", obj_getStr(module_obj, "name"),
  1073. obj_getStr(module_obj, "state"));
  1074. }
  1075. return 0;
  1076. }
  1077. void pikaMaker_printStates(PikaMaker* self) {
  1078. args_foreach(self->list, __foreach_handler_printStates, NULL);
  1079. }
  1080. int32_t __foreach_handler_getFirstNocompiled(Arg* argEach, void* context) {
  1081. if (arg_isObject(argEach)) {
  1082. PikaObj* module_obj = arg_getPtr(argEach);
  1083. char* state = obj_getStr(module_obj, "state");
  1084. if (args_isArgExist((Args*)context, "res")) {
  1085. /* already get method */
  1086. return 0;
  1087. }
  1088. if (strEqu("nocompiled", state)) {
  1089. /* push module */
  1090. args_setStr((Args*)context, "res", obj_getStr(module_obj, "name"));
  1091. return 0;
  1092. }
  1093. }
  1094. return 0;
  1095. }
  1096. char* pikaMaker_getFirstNocompiled(PikaMaker* self) {
  1097. Args context = {0};
  1098. args_foreach(self->list, __foreach_handler_getFirstNocompiled, &context);
  1099. char* res = args_getStr(&context, "res");
  1100. if (NULL == res) {
  1101. /* remove res in maker */
  1102. obj_removeArg(self, "res");
  1103. } else {
  1104. obj_setStr(self, "res", res);
  1105. }
  1106. args_deinit_stack(&context);
  1107. return obj_getStr(self, "res");
  1108. }
  1109. /*
  1110. * @brief compile module with depends
  1111. * @param self PikaMaker
  1112. * @param module_name
  1113. * @return PIKA_RES
  1114. */
  1115. PIKA_RES pikaMaker_compileModuleWithDepends(PikaMaker* self,
  1116. char* module_name) {
  1117. PIKA_RES res = PIKA_RES_OK;
  1118. if (!strEqu("nocompiled", pikaMaker_getState(self, module_name))) {
  1119. return PIKA_RES_OK;
  1120. }
  1121. res = pikaMaker_compileModule(self, module_name);
  1122. if (PIKA_RES_OK != res) {
  1123. obj_setInt(self, "err", res);
  1124. return res;
  1125. }
  1126. pikaMaker_getDependencies(self, module_name);
  1127. while (1) {
  1128. char* uncompiled = pikaMaker_getFirstNocompiled(self);
  1129. /* compiled all modules */
  1130. if (NULL == uncompiled) {
  1131. break;
  1132. }
  1133. res = pikaMaker_compileModule(self, uncompiled);
  1134. if (PIKA_RES_OK != res) {
  1135. obj_setInt(self, "err", res);
  1136. return res;
  1137. }
  1138. pikaMaker_getDependencies(self, uncompiled);
  1139. }
  1140. return PIKA_RES_OK;
  1141. }
  1142. PIKA_RES pikaMaker_compileModuleWithList(PikaMaker* self, char* list_content) {
  1143. PIKA_RES res = PIKA_RES_OK;
  1144. Args buffs = {0};
  1145. char* module_name = NULL;
  1146. char* module_name_start = list_content;
  1147. char* module_name_end = NULL;
  1148. pika_platform_printf(" <module list>\r\n");
  1149. while (1) {
  1150. module_name_end = strFind(module_name_start, '\n');
  1151. if (NULL == module_name_end) {
  1152. break;
  1153. }
  1154. module_name = strsSubStr(&buffs, module_name_start, module_name_end);
  1155. if (!strIsBlank(module_name)) {
  1156. pika_platform_printf(" - %s\r\n", module_name);
  1157. }
  1158. module_name_start = module_name_end + 1;
  1159. }
  1160. module_name_start = list_content;
  1161. while (1) {
  1162. module_name_end = strFind(module_name_start, '\n');
  1163. if (NULL == module_name_end) {
  1164. break;
  1165. }
  1166. module_name = strsSubStr(&buffs, module_name_start, module_name_end);
  1167. if (!strIsBlank(module_name)) {
  1168. char* module_name_fs = strsReplace(&buffs, module_name, ".", "/");
  1169. enum PIKA_MODULE_TYPE module_type =
  1170. _checkModuleType(module_name_fs);
  1171. if (module_type == PIKA_MODULE_TYPE_PY) {
  1172. res = pikaMaker_compileModuleWithDepends(self, module_name);
  1173. if (PIKA_RES_OK != res) {
  1174. obj_setInt(self, "err", res);
  1175. goto __exit;
  1176. }
  1177. }
  1178. if (module_type == PIKA_MODULE_TYPE_PYO) {
  1179. pikaMaker_linkByteocdeFile(self, module_name);
  1180. }
  1181. if (module_type == PIKA_MODULE_TYPE_UNKNOWN) {
  1182. pika_platform_printf(
  1183. " [warning]: file: '%s.pyi', '%s.py' or '%s.py.o' "
  1184. "no found\n",
  1185. module_name, module_name, module_name);
  1186. }
  1187. }
  1188. module_name_start = module_name_end + 1;
  1189. }
  1190. __exit:
  1191. strsDeinit(&buffs);
  1192. return PIKA_RES_OK;
  1193. }
  1194. PIKA_RES pikaMaker_compileModuleWithListFile(PikaMaker* self,
  1195. char* list_file_name) {
  1196. Args buffs = {0};
  1197. PIKA_RES res = PIKA_RES_OK;
  1198. char* folder_path =
  1199. strsPathJoin(&buffs, obj_getStr(self, "pwd"), "pikascript-api/");
  1200. char* list_file_path = strsPathJoin(&buffs, folder_path, list_file_name);
  1201. char* list_file_content = NULL;
  1202. pika_platform_printf(" loading %s...\r\n", list_file_name);
  1203. Arg* list_file_arg = arg_loadFile(NULL, list_file_path);
  1204. if (NULL == list_file_arg) {
  1205. pika_platform_printf("Error: Could not load file '%s'\n",
  1206. list_file_path);
  1207. res = PIKA_RES_ERR_IO_ERROR;
  1208. goto __exit;
  1209. }
  1210. list_file_content = (char*)arg_getBytes(list_file_arg);
  1211. list_file_content = strsFilePreProcess_ex(&buffs, list_file_content, "\n");
  1212. res = pikaMaker_compileModuleWithList(self, list_file_content);
  1213. goto __exit;
  1214. __exit:
  1215. strsDeinit(&buffs);
  1216. return res;
  1217. }
  1218. int32_t __foreach_handler_linkCompiledModules(Arg* argEach, void* context) {
  1219. Args buffs = {0};
  1220. if (arg_isObject(argEach)) {
  1221. LibObj* lib = args_getPtr((Args*)context, "@lib");
  1222. PikaMaker* maker = args_getPtr((Args*)context, "__maker");
  1223. PikaObj* module_obj = arg_getPtr(argEach);
  1224. char* module_name = obj_getStr(module_obj, "name");
  1225. char* state = obj_getStr(module_obj, "state");
  1226. if (strEqu(state, "compiled")) {
  1227. char* pwd = obj_getStr(maker, "pwd");
  1228. char* folder_path = strsPathJoin(&buffs, pwd, "pikascript-api/");
  1229. char* module_file_name = strsAppend(&buffs, module_name, ".py.o");
  1230. char* module_file_path =
  1231. strsPathJoin(&buffs, folder_path, module_file_name);
  1232. LibObj_staticLinkFile(lib, module_file_path);
  1233. }
  1234. }
  1235. strsDeinit(&buffs);
  1236. return 0;
  1237. }
  1238. PIKA_RES _do_pikaMaker_linkCompiledModulesFullPath(PikaMaker* self,
  1239. char* lib_path,
  1240. pika_bool gen_c_array) {
  1241. PIKA_RES compile_err = (PIKA_RES)obj_getInt(self, "err");
  1242. if (PIKA_RES_OK != compile_err) {
  1243. pika_platform_printf(" Error: compile failed, link aborted.\r\n");
  1244. return compile_err;
  1245. }
  1246. Args context = {0};
  1247. Args buffs = {0};
  1248. pika_platform_printf(" linking %s...\n", lib_path);
  1249. LibObj* lib = obj_getPtr(self, "lib");
  1250. args_setPtr(&context, "@lib", lib);
  1251. args_setPtr(&context, "__maker", self);
  1252. args_foreach(self->list, __foreach_handler_linkCompiledModules, &context);
  1253. args_deinit_stack(&context);
  1254. char* pwd = obj_getStr(self, "pwd");
  1255. char* lib_path_folder = strsPathGetFolder(&buffs, lib_path);
  1256. char* folder_path = strsPathJoin(&buffs, pwd, lib_path_folder);
  1257. char* lib_file_path = strsPathJoin(&buffs, pwd, lib_path);
  1258. LibObj_linkFile(lib, lib_file_path);
  1259. if (gen_c_array) {
  1260. Lib_loadLibraryFileToArray(lib_file_path, folder_path);
  1261. }
  1262. strsDeinit(&buffs);
  1263. return PIKA_RES_OK;
  1264. }
  1265. PIKA_RES pikaMaker_linkCompiledModulesFullPath(PikaMaker* self,
  1266. char* lib_path) {
  1267. return _do_pikaMaker_linkCompiledModulesFullPath(self, lib_path, pika_true);
  1268. }
  1269. PIKA_RES _do_pikaMaker_linkCompiledModules(PikaMaker* self,
  1270. char* lib_name,
  1271. pika_bool gen_c_array) {
  1272. Args buffs = {0};
  1273. char* lib_file_path = strsPathJoin(&buffs, "pikascript-api/", lib_name);
  1274. PIKA_RES res = _do_pikaMaker_linkCompiledModulesFullPath(
  1275. self, lib_file_path, gen_c_array);
  1276. strsDeinit(&buffs);
  1277. return res;
  1278. }
  1279. PIKA_RES pikaMaker_linkCompiledModules(PikaMaker* self, char* lib_name) {
  1280. return _do_pikaMaker_linkCompiledModules(self, lib_name, pika_true);
  1281. }
  1282. /*
  1283. * @brief link raw file to library
  1284. * @param self PikaMaker
  1285. * @param file_path
  1286. * @return PIKA_RES
  1287. */
  1288. PIKA_RES pikaMaker_linkRaw(PikaMaker* self, char* file_path) {
  1289. LibObj* lib = obj_getPtr(self, "lib");
  1290. LibObj_staticLinkFile(lib, file_path);
  1291. return PIKA_RES_OK;
  1292. }
  1293. /*
  1294. * @brief link raw file to library
  1295. * @param self PikaMaker
  1296. * @param path of the file to be packed
  1297. * @param path of the file in pikafs
  1298. * @return PIKA_RES
  1299. */
  1300. PIKA_RES pikaMaker_linkRawWithPath(PikaMaker* self,
  1301. char* file_path,
  1302. char* pack_path) {
  1303. LibObj* lib = obj_getPtr(self, "lib");
  1304. PIKA_RES ret =
  1305. (PIKA_RES)LibObj_staticLinkFileWithPath(lib, file_path, pack_path);
  1306. return ret;
  1307. }
  1308. /*
  1309. * @brief open file from library
  1310. * @param file_name
  1311. * @param mode "r" or "rb"
  1312. * @return pikafs_FILE* or NULL if failed
  1313. */
  1314. pikafs_FILE* pikafs_fopen(char* file_name, char* mode) {
  1315. pikafs_FILE* f = (pikafs_FILE*)pikaMalloc(sizeof(pikafs_FILE));
  1316. if (NULL == f) {
  1317. return NULL;
  1318. }
  1319. memset(f, 0, sizeof(pikafs_FILE));
  1320. uint8_t* library_bytes = obj_getPtr(pika_getLibObj(), "@libraw");
  1321. if (NULL == library_bytes) {
  1322. goto __error;
  1323. }
  1324. if (PIKA_RES_OK !=
  1325. _loadModuleDataWithName(library_bytes, file_name, &f->addr, &f->size)) {
  1326. goto __error;
  1327. }
  1328. return f;
  1329. __error:
  1330. pikaFree(f, sizeof(pikafs_FILE));
  1331. return NULL;
  1332. }
  1333. pikafs_FILE* pikafs_fopen_pack(char* pack_name, char* file_name) {
  1334. pikafs_FILE* f = NULL;
  1335. Arg* file_arg = NULL;
  1336. uint8_t* library_bytes = NULL;
  1337. f = (pikafs_FILE*)pikaMalloc(sizeof(pikafs_FILE));
  1338. if (NULL == f) {
  1339. pika_platform_printf("Error: malloc failed \r\n");
  1340. goto __malloc_err;
  1341. // return PIKA_RES_ERR_OUT_OF_RANGE;
  1342. }
  1343. memset(f, 0, sizeof(pikafs_FILE));
  1344. file_arg = _getPack_libraryBytes(pack_name);
  1345. if (NULL != file_arg) {
  1346. library_bytes = arg_getBytes(file_arg);
  1347. } else {
  1348. goto __getpack_err;
  1349. }
  1350. if (PIKA_RES_OK !=
  1351. _loadModuleDataWithName(library_bytes, file_name, &f->addr, &f->size)) {
  1352. goto __exit;
  1353. }
  1354. f->farg = file_arg;
  1355. return f;
  1356. __exit:
  1357. if (NULL != f->farg) {
  1358. arg_deinit(f->farg);
  1359. }
  1360. __getpack_err:
  1361. pikaFree(f, sizeof(pikafs_FILE));
  1362. __malloc_err:
  1363. return NULL;
  1364. }
  1365. /*
  1366. * @brief read file
  1367. * @param buf the buffer to read
  1368. * @param size size of each item
  1369. * @param count count of items
  1370. * @param f file
  1371. * @return read count
  1372. */
  1373. int pikafs_fread(void* buf, size_t size, size_t count, pikafs_FILE* f) {
  1374. size_t read_len = size * count;
  1375. if (f->pos >= f->size) {
  1376. return 0;
  1377. }
  1378. if (f->pos + read_len > f->size) {
  1379. read_len = f->size;
  1380. }
  1381. __platform_memcpy(buf, f->addr + f->pos, read_len);
  1382. f->pos += read_len;
  1383. size_t actual_count = read_len / size;
  1384. return actual_count;
  1385. }
  1386. /*
  1387. * @brief write file
  1388. * @param buf the buffer to write
  1389. * @param size size of each item
  1390. * @param count count of items
  1391. * @param f file
  1392. * @return write count or -1 if failed
  1393. */
  1394. int pikafs_fwrite(void* buf, size_t size, size_t count, pikafs_FILE* file) {
  1395. return -1;
  1396. }
  1397. /*
  1398. * @brief close file
  1399. * @param f file
  1400. * @return 0 if success
  1401. */
  1402. int pikafs_fclose(pikafs_FILE* file) {
  1403. if (file->need_free) {
  1404. pikaFree(file->addr, file->size);
  1405. }
  1406. if (NULL != file->farg) {
  1407. arg_deinit(file->farg);
  1408. }
  1409. pikaFree(file, sizeof(pikafs_FILE));
  1410. return 0;
  1411. }