long file_length(filetype *fp) { long cur, length; cur = file_getpos(fp); file_setpos(fp, 0, seek_end); length = file_getpos(fp); file_setpos(fp, cur, seek_set); return length; }
void vm_process(VM *vm) { int a, b, opcode; opcode = vm->image[vm->ip]; switch(opcode) { case VM_NOP: break; case VM_LIT: vm->sp++; vm->ip++; TOS = vm->image[vm->ip]; break; case VM_DUP: vm->sp++; vm->data[vm->sp] = NOS; break; case VM_DROP: DROP break; case VM_SWAP: a = TOS; TOS = NOS; NOS = a; break; case VM_PUSH: vm->rsp++; TORS = TOS; DROP break; case VM_POP: vm->sp++; TOS = TORS; vm->rsp--; break; case VM_CALL: vm->ip++; vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_JUMP: vm->ip++; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_RETURN: vm->ip = TORS; vm->rsp--; break; case VM_GT_JUMP: vm->ip++; if(NOS > TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_LT_JUMP: vm->ip++; if(NOS < TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_NE_JUMP: vm->ip++; if(TOS != NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_EQ_JUMP: vm->ip++; if(TOS == NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_FETCH: TOS = vm->image[TOS]; break; case VM_STORE: vm->image[TOS] = NOS; DROP DROP break; case VM_ADD: NOS += TOS; DROP break; case VM_SUB: NOS -= TOS; DROP break; case VM_MUL: NOS *= TOS; DROP break; case VM_DIVMOD: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case VM_AND: a = TOS; b = NOS; DROP TOS = a & b; break; case VM_OR: a = TOS; b = NOS; DROP TOS = a | b; break; case VM_XOR: a = TOS; b = NOS; DROP TOS = a ^ b; break; case VM_SHL: a = TOS; b = NOS; DROP TOS = b << a; break; case VM_SHR: a = TOS; b = NOS; DROP TOS = b >>= a; break; case VM_ZERO_EXIT: if (TOS == 0) { DROP vm->ip = TORS; vm->rsp--; } break; case VM_INC: TOS += 1; break; case VM_DEC: TOS -= 1; break; case VM_IN: a = TOS; TOS = vm->ports[a]; vm->ports[a] = 0; break; case VM_OUT: vm->ports[0] = 0; vm->ports[TOS] = NOS; DROP DROP break; case VM_WAIT: if (vm->ports[0] == 1) break; /* Input */ if (vm->ports[0] == 0 && vm->ports[1] == 1) { vm->ports[1] = dev_getch(); vm->ports[0] = 1; } /* Output (character generator) */ if (vm->ports[2] == 1) { dev_putch(TOS); DROP vm->ports[2] = 0; vm->ports[0] = 1; } if (vm->ports[4] != 0) { vm->ports[0] = 1; switch (vm->ports[4]) { case 1: vm_save_image(vm, vm->filename); vm->ports[4] = 0; break; case 2: file_add(vm); vm->ports[4] = 0; break; case -1: vm->ports[4] = file_handle(vm); break; case -2: vm->ports[4] = file_readc(vm); break; case -3: vm->ports[4] = file_writec(vm); break; case -4: vm->ports[4] = file_closehandle(vm); break; case -5: vm->ports[4] = file_getpos(vm); break; case -6: vm->ports[4] = file_seek(vm); break; case -7: vm->ports[4] = file_size(vm); break; default: vm->ports[4] = 0; } } /* Capabilities */ if (vm->ports[5] != 0) { vm->ports[0] = 1; switch(vm->ports[5]) { case -1: vm->ports[5] = IMAGE_SIZE; break; case -2: vm->ports[5] = 0; break; case -3: vm->ports[5] = 0; break; case -4: vm->ports[5] = 0; break; case -5: vm->ports[5] = vm->sp; break; case -6: vm->ports[5] = vm->rsp; break; case -7: vm->ports[5] = 0; break; case -8: vm->ports[5] = time(NULL); break; case -9: vm->ports[5] = 0; vm->ip = IMAGE_SIZE; break; default: vm->ports[5] = 0; } } if (vm->ports[8] != 0) { vm->ports[0] = 1; switch (vm->ports[8]) { case -1: rsocket(vm); vm->ports[8] = 0; break; case -2: rbind(vm); vm->ports[8] = 0; break; case -3: rlisten(vm); vm->ports[8] = 0; break; case -4: raccept(vm); vm->ports[8] = 0; break; case -5: rclose(vm); vm->ports[8] = 0; break; case -6: rsend(vm); vm->ports[8] = 0; break; case -7: rrecv(vm); vm->ports[8] = 0; break; case -8: rconnect(vm); vm->ports[8] = 0; break; default: vm->ports[8] = 0; } vm->ports[8] = 0; } break; default: vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; } vm->ports[3] = 1; }
//! This function read the playlist's entry at a specific position //! //! @param u16_position Position in play list. //! @param sz_path The address of the string where is stored the information. //! @param u16_size_line The length of the path. //! bool pl_nav_readentry(uint16_t u16_position, FS_STRING *sz_path, uint16_t *u16_size_line ) { uint8_t nav_id_save; uint16_t u16_current_pos; uint32_t u32_file_pos; // Set output to NULL to specify if there is an error *sz_path = NULL; // Position out of range if ((0 == u16_position) || (pl_g_u16_list_size < u16_position)) { fs_g_status = FS_ERR_PL_OUT_LST; return false; } // Go to play list file navigator nav_id_save = nav_get(); nav_select(FS_NAV_ID_PLAYLIST); // Save current file position u32_file_pos = file_getpos(); if (pl_g_u16_list_sel > u16_position) { // Go to the beginning of the text file reader_txt_beg(); u16_current_pos = 0; } else { u16_current_pos = pl_g_u16_list_sel; } while(u16_current_pos != u16_position) { if (file_eof()) { // Restore file position file_seek(u32_file_pos, FS_SEEK_SET); // Reselect the previous navigator nav_select(nav_id_save); return false; } if (u16_current_pos+1 == u16_position) { if (pl_main_readline(PL_MAIN_READLINE_OPT_GOTOPATH, nav_id_save, sz_path, u16_size_line)) break; } else if (pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE, 0, NULL, NULL)) u16_current_pos++; // Add a file } // Restore file position file_seek(u32_file_pos, FS_SEEK_SET); // Reselect the previous navigator nav_select(nav_id_save); return true; }
//! This function reads and checks the next line //! //! @param opt PL_MAIN_READLINE_OPT_CHECKLINE to check the next line in the file.\n //! PL_MAIN_READLINE_OPT_READSTRING to read the string in the text file.\n //! PL_MAIN_READLINE_OPT_GOTOPATH to read, check and goto the path. //! @param id_nav ID navigator to update with the selected file (ignore if b_gotopatch == false) //! @param sz_path Address of the string returned. It is used only if PL_MAIN_READLINE_OPT_READSTRING or //! PL_MAIN_READLINE_OPT_GOTOPATH options are specified. //! @param u16_size_line The length of the path. If this parameter is NULL, then the length is not returned. //! //! @return true if a line with a correct path //! false line ignored or end of file //! bool pl_main_readline( readline_opt_t opt, uint8_t id_nav, FS_STRING *sz_path, uint16_t *u16_size_line ) { uint16_t line_beg[8]; // Contains first characters of the line uint32_t u32_file_pos; uint16_t u16_alt_length = 0; uint8_t u8_pos_path_in_line = 0; // Set output to NULL to specify if there is an error *sz_path = NULL; // Read the 3 first char in the line u32_file_pos = file_getpos(); if( E_PL_M3U == pl_g_list_type ) { // M3U path lines = "path\file" // M3U comment lines = "#..." u16_alt_length = reader_txt_get_line( true, (FS_STRING)line_beg, 2 ); if( (2 > u16_alt_length) // The line size is not correct || ('#' == line_beg[0]) ) // It is a comment line { return false; } u8_pos_path_in_line=0; } if( (E_PL_PLS == pl_g_list_type) || (E_PL_SMP == pl_g_list_type) ) { // PLS path lines = "Filexxx=path\file" // SMP path lines = "File=path\file" u16_alt_length = reader_txt_get_line( true, (FS_STRING)line_beg, 8 ); if(6 > u16_alt_length) // The line size can't contain a path line return false; // Check if it is a path line if( ('F' != line_beg[0]) || ('i' != line_beg[1]) || ('l' != line_beg[2]) || ('e' != line_beg[3]) ) { return false; } u8_pos_path_in_line=5; if('=' != line_beg[4]) { u8_pos_path_in_line++; if('=' != line_beg[5]) { u8_pos_path_in_line++; if('=' != line_beg[6]) { u8_pos_path_in_line++; if('=' != line_beg[7]) return false; } } } } // Here, the line contains a path // Store the length of the line if a buffer is set if (u16_size_line) *u16_size_line = u16_alt_length - u8_pos_path_in_line; if (opt == PL_MAIN_READLINE_OPT_CHECKLINE) return true; // else go to path // Read all characters in line file_seek( u32_file_pos, FS_SEEK_SET ); *sz_path = PLAYLIST_BUF_ALLOC( u16_alt_length * (Is_unicode? 2 : 1 ) ); if( NULL == *sz_path ) return false; // no enough memory, impossible to store the path but path present in line if( 0 == reader_txt_get_line( (FS_UNICODE==true), *sz_path, u16_alt_length ) ) return false; // Error during the read if( 0 != u8_pos_path_in_line ) { // Shift the path to the beginning of the buffer memmove(*sz_path, *sz_path + u8_pos_path_in_line * ((FS_UNICODE==true) ? 2 : 1), (u16_alt_length - u8_pos_path_in_line) * ((FS_UNICODE==true) ? 2 : 1)); } if (opt == PL_MAIN_READLINE_OPT_READSTRING) return true; // Update the navigator with the path of play list file, because the path is relative at this one nav_copy( id_nav ); nav_select( id_nav ); // Go to the path included in the line if( !nav_setcwd( (FS_STRING) *sz_path , false, false ) ) { // path no found then path is dead -> reset list to deselect a file nav_filelist_reset(); } nav_select( FS_NAV_ID_PLAYLIST ); return true; }
//! This function read the playlist's entry at a specific position.\n //! It is implemented as a non-blocking function. //! //! @param data This data has to be set to 0 if non-caching options are //! used. //! @param u16_position Position in play list. //! @param sz_path The address of the string where is stored the information. //! @param u16_size_line The length of the path. //! @param u16_n The number of line to read at one time //! bool pl_nav_readentry_non_blocking(pl_nav_readentry_context_t *data, uint16_t u16_position, FS_STRING *sz_path, uint16_t *u16_size_line, uint16_t u16_n) { ai_async_context_t ctx; uint16_t u16_current_n; typedef enum { STATE_INITIALIZATION = 0, STATE_SET_POS, STATE_READ_ENTRY } state_t; bool b_update; // If false, means it is the first call if (!ai_async_context_pop(&ctx)) ctx.state = (state_t) STATE_INITIALIZATION; // By default set the status to DONE ctx.status = CMD_DONE; switch((state_t) ctx.state) { // Initialization case STATE_INITIALIZATION: // Set output to NULL to specify if there is an error *sz_path = NULL; // Position out of range if (u16_position == 0) { fs_g_status = FS_ERR_PL_OUT_LST; return false; } // Go to play list file navigator data->nav_id_saved = nav_get(); nav_select(FS_NAV_ID_PLAYLIST); // Save current file position data->u32_file_pos_saved = file_getpos(); // In this case it means the context data is already filled with entry // information for this specific playlist. That is the reason why it is // important to fill this structure with zeros if non-caching options are // used. b_update = true; if (data->fs_entry.u8_open_mode) { if (data->u16_current_pos + 1 <= u16_position) b_update = false; } if (b_update) { // Go to the beginning of the text file reader_txt_beg(); data->u16_current_pos = 0; // Store the info of the entry memcpy(&(data->fs_entry), &fs_g_nav_entry, sizeof(data->fs_entry)); } ctx.status = CMD_EXECUTING; ctx.state = (state_t) STATE_SET_POS; break; case STATE_SET_POS: nav_select(FS_NAV_ID_PLAYLIST); // Restore the info of the entry memcpy(&fs_g_nav_entry, &(data->fs_entry), sizeof(fs_g_nav_entry)); // Look for the "u16_n"th next lines on the file u16_current_n = 0; while ((data->u16_current_pos + 1 != u16_position) && !file_eof() && u16_current_n < u16_n) { if (pl_main_readline(PL_MAIN_READLINE_OPT_CHECKLINE, 0, NULL, NULL)) data->u16_current_pos++; u16_current_n++; } // If end of file if (file_eof()) { // Restore file position file_seek(data->u32_file_pos_saved, FS_SEEK_SET); // Reselect the previous navigator nav_select(data->nav_id_saved); return false; } // If the file has been found ctx.status = CMD_EXECUTING; if (data->u16_current_pos + 1 == u16_position) ctx.state = (state_t) STATE_READ_ENTRY; // Else continue seeking... // Store the info of the entry memcpy(&(data->fs_entry), &fs_g_nav_entry, sizeof(data->fs_entry)); break; case STATE_READ_ENTRY: nav_select(FS_NAV_ID_PLAYLIST); u16_current_n = 0; b_update = false; while (!file_eof() && u16_current_n < u16_n) { if ((b_update = pl_main_readline(PL_MAIN_READLINE_OPT_GOTOPATH, data->nav_id_saved, sz_path, u16_size_line))) break; u16_current_n++; } // Need to retry if (u16_current_n >= u16_n) { ctx.status = CMD_EXECUTING; break; } // If it is the end of the file if (file_eof() && !b_update) { // Restore file position file_seek(data->u32_file_pos_saved, FS_SEEK_SET); // Reselect the previous navigator nav_select(data->nav_id_saved); return false; } // Store positions data->u16_current_pos = u16_position; // Store the info of the entry memcpy(&(data->fs_entry), &fs_g_nav_entry, sizeof(data->fs_entry)); // Restore file position file_seek(data->u32_file_pos_saved, FS_SEEK_SET); // Reselect the previous navigator nav_select(data->nav_id_saved); break; } if (ctx.status == CMD_EXECUTING) { if (!ai_async_context_push(&ctx)) return false; } return true; }