static char * eat_ws(CONF *conf, char *p) { while (IS_WS(conf, *p) && (!IS_EOF(conf, *p))) p++; return (p); }
static char *scan_quote(CONF *conf, char *p) { int q = *p; p++; while (!(IS_EOF(conf, *p)) && (*p != q)) { if (IS_ESC(conf, *p)) { p++; if (IS_EOF(conf, *p)) return p; } p++; } if (*p == q) p++; return p; }
static void trim_ws(CONF *conf, char *start) { char *p = start; while (!IS_EOF(conf, *p)) p++; p--; while ((p >= start) && IS_WS(conf, *p)) p--; p++; *p = '\0'; }
static void clear_comments(CONF *conf, char *p) { for (;;) { if (IS_FCOMMENT(conf,*p)) { *p='\0'; return; } if (!IS_WS(conf,*p)) { break; } p++; } for (;;) { if (IS_COMMENT(conf,*p)) { *p='\0'; return; } if (IS_DQUOTE(conf,*p)) { p=scan_dquote(conf, p); continue; } if (IS_QUOTE(conf,*p)) { p=scan_quote(conf, p); continue; } if (IS_ESC(conf,*p)) { p=scan_esc(conf,p); continue; } if (IS_EOF(conf,*p)) return; else p++; } }
static char *scan_dquote(CONF *conf, char *p) { int q = *p; p++; while (!(IS_EOF(conf, *p))) { if (*p == q) { if (*(p + 1) == q) { p++; } else { break; } } p++; } if (*p == q) p++; return p; }
void _gif_sw_codec( kal_int32 GIF_ox, kal_int32 GIF_oy, kal_int32 resized_width, kal_int32 resized_height, kal_uint16 transparent_index, gif_sw_image_struct *cache, kal_int32 frame_counter, kal_bool transparent_enable, kal_bool isResized, GIF_COLOR_FORMAT_ENUM gif_color_format, GIF_COLOR_FORMAT_ENUM palette_format) { /*----------------------------------------------------------------*/ /* Local Variables */ /*----------------------------------------------------------------*/ kal_int32 src_clipx1, src_clipy1, src_clipx2, src_clipy2; int image_rows; int image_cols; kal_bool is_interlace; GIF_STATUS_ENUM status; /*----------------------------------------------------------------*/ /* Code Body */ /*----------------------------------------------------------------*/ //kal_uint32 start, end; //start = drv_get_current_time(); //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec(): Enter. GIF(ox,oy)=(%d,%d), resized_width=%d, resized_height=%d\n", GIF_ox, GIF_oy, resized_width, resized_height); src_clipx1 = _get_data(FSAL_ACCESS_U16, pfsal_handle); /* X */ src_clipy1 = _get_data(FSAL_ACCESS_U16, pfsal_handle); /* Y */ image_cols = _get_data(FSAL_ACCESS_U16, pfsal_handle); /* W */ image_rows = _get_data(FSAL_ACCESS_U16, pfsal_handle); /* H */ src_clipx2 = src_clipx1 + image_cols - 1; src_clipy2 = src_clipy1 + image_rows - 1; // If need not to draw, still need to decode to get correct next frame position status = gif_sw_resizer_init( cache->image_width, cache->image_height, src_clipx1, src_clipy1, src_clipx2, src_clipy2, GIF_ox, GIF_oy, GIF_ox + resized_width - 1, GIF_oy + resized_height - 1, gif_color_format); if (status != GIF_STATUS_OK) { /* decode limitation, output width too large */ SW_GIF_TRACE(GIF_TRACE_MOD, "[gif] - _gif_sw_codec() Fail: output width too large \n"); //GIF_SW_RAISE(1); GIF_SW_RAISE(status); } cache->last_frame_x1 = (kal_int16) GIF_SW_RESIZER.want_dx1 - GIF_ox; cache->last_frame_y1 = (kal_int16) GIF_SW_RESIZER.want_dy1 - GIF_oy; cache->last_frame_x2 = (kal_int16) GIF_SW_RESIZER.want_dx2 - GIF_ox; cache->last_frame_y2 = (kal_int16) GIF_SW_RESIZER.want_dy2 - GIF_oy; { kal_int32 n; n = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; /* W05.39 Fix n value will be changed and the interlace attribute may be incorrect */ if (n & 0x40) { is_interlace = KAL_TRUE; } else { is_interlace = KAL_FALSE; } if (n & 0x80) { gif_sw_color_from_rgb_func palette_color_from_rgb; kal_int32 i; n = 1 << ((n & 0x7) + 1); g_gif_sw_current_palette = g_gif_sw_local_palette; if (gif_color_format == GIF_SW_COLOR_FORMAT_8) { #if defined(GIF_SUPPORT_SET_PALETTE_FORMAT) palette_color_from_rgb = gif_sw_color_from_rgb_array[palette_format]; #else palette_color_from_rgb = GIF_SW_PALETTE_COLOR_FROM_RGB; #endif } else { palette_color_from_rgb = g_gif_sw_act_color_from_rgb; } /* Read the local color palette */ if (n) { g_gif_sw_palette_size = n; } for (i = 0; i < n; i++) { kal_uint8 R, G, B; R = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; G = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; B = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; g_gif_sw_current_palette[i] = palette_color_from_rgb(0xFF, R, G, B); if ((g_gif_sw_dest_source_key_enable && g_gif_sw_current_palette[i] == g_gif_sw_dest_source_key) || (g_gif_sw_decoder_is_bypass_color && g_gif_sw_current_palette[i] == g_gif_sw_decoder_bypass_color)) { g_gif_sw_current_palette[i] ^= 1; } } /* current layer is index color layer */ if (gif_color_format == GIF_SW_COLOR_FORMAT_8) { for (i = 0; i < (kal_int32) n; i++) { if(g_gif_sw_layer_set_palette) { (*g_gif_sw_layer_set_palette)((kal_uint8) i, g_gif_sw_current_palette[i]); } g_gif_sw_current_palette[i] = i; } } } else /* use global palette */ { g_gif_sw_current_palette = cache->palette; } } { #define MaxStackSize 4096 #define NullCode (~0) int offset, y; register int x = 0; register unsigned char *c; register unsigned int datum; kal_uint32 consump_byte_cnt = 0; kal_uint32 read_byte_cnt = 0; kal_uint32 data_block_start_addr = 0; short *prefix; int count; unsigned char *packet, *pixel_stack, *suffix, *top_stack; unsigned int available, bits, clear, code, code_mask, code_size, data_size, first, end_of_information, in_code, old_code, pass; void (*put_pixel)(kal_int32* want_sx,gif_sw_color c,kal_bool want_draw); kal_int32 wantx = 0; kal_int32 wantx0 = 0; wantx0 = GIF_SW_RESIZER.want_start_sx;//(kal_int16)((((GIF_SW_RESIZER.want_start_dx - GIF_ox) * GIF_SW_RESIZER.src_width_range << 1) + GIF_SW_RESIZER.dest_width_range) / (GIF_SW_RESIZER.dest_width_range << 1)); put_pixel = put_pixel_with_transparent_enable; if (!transparent_enable) { put_pixel = put_pixel_with_transparent_disable; } /* allocate decoder tables */ { kal_uint8 *mem = (kal_uint8*) g_gif_sw_tree_buffer; prefix = (short*)mem; mem += MaxStackSize * sizeof(*prefix); suffix = (unsigned char*)mem; mem += MaxStackSize; pixel_stack = (unsigned char*)mem; /* use MaxStackSize+1 bytes; */ } /* Initialize GIF data stream decoder. */ data_size = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; if (data_size > 8) { SW_GIF_TRACE(GIF_TRACE_MOD, "[gif] - _gif_sw_codec() Fail: CorruptImage \n"); //GIF_SW_RAISE(1); /* CorruptImage */ GIF_SW_RAISE(GIF_STATUS_DEC_ERROR_INVALID_FILE); /* CorruptImage */ } clear = 1 << data_size; end_of_information = clear + 1; available = clear + 2; old_code = NullCode; code_size = data_size + 1; code_mask = (1 << code_size) - 1; for (code = 0; code < clear; code++) { prefix[code] = 0; suffix[code] = (unsigned char)code; } /* decode gif pixel stream */ datum = 0; bits = 0; c = 0; count = 0; first = 0; offset = 0; pass = 0; top_stack = pixel_stack; data_block_start_addr = _gif_fsal_tell(pfsal_handle); for (y = src_clipy1; y <= src_clipy2; y++) { if(g_gif_sw_image_progress_callback) { if(!(*g_gif_sw_image_progress_callback)()) { SW_GIF_TRACE(GIF_TRACE_MOD, "[gif] - _gif_sw_codec() Fail: GIF_SW_RET_DECODE_TIME_OUT. x=%d, y=%d \n", x, y); //GIF_SW_RAISE(GIF_SW_RET_DECODE_TIME_OUT); GIF_SW_RAISE(GIF_STATUS_DECODE_TIME_OUT); } } /* move to 0,offset */ wantx = wantx0; for (x = src_clipx1; x <= src_clipx2;) { kal_int32 decoded_pixel_count = 0; kal_int32 next_dst_data_distance = 0; /* ImageMagick Open Source Code Segment Start */ if (top_stack == pixel_stack) { if (bits < code_size) { /* Load bytes until there is enough bits for a code. */ if (count == 0) { /* Read a new data block. */ count = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; read_byte_cnt += count; if (count == 0) { break; } packet = (unsigned char*)g_gif_sw_stack; /* this will only use 256 bytes */ GETS(c, packet, count); } datum += ((unsigned int)(*c)) << bits; bits += 8; c++; count--; continue; } /* Get the next code. */ code = datum & code_mask; datum >>= code_size; bits -= code_size; /* Interpret the code */ if ((code > available) || (code == end_of_information)) { SW_GIF_TRACE(GIF_TRACE_MOD, "[gif] - _gif_sw_codec() Fail: Interpret the code \n"); FLUSH(count); while (!IS_EOF()) // skip he remaining data blocks of the frame. { count = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; if(count == 0) { break; } FLUSH(count); } return; } if (code == clear) { /* Reset decoder. */ code_size = data_size + 1; code_mask = (1 << code_size) - 1; available = clear + 2; old_code = NullCode; continue; } if (old_code == NullCode) { *top_stack++ = suffix[code]; old_code = code; first = code; continue; } in_code = code; if (code >= available) { *top_stack++ = (unsigned char)first; code = old_code; } while (code >= clear) { if ((top_stack - pixel_stack) >= MaxStackSize) { break; } *top_stack++ = suffix[code]; code = (unsigned int)prefix[code]; } first = (unsigned int)suffix[code]; /* Add a new string to the string table, */ if ((top_stack - pixel_stack) >= MaxStackSize) { SW_GIF_TRACE(GIF_TRACE_MOD, "[gif] - _gif_sw_codec() Fail: (top_stack - pixel_stack) >= MaxStackSize)\n"); break; } if (available >= MaxStackSize) { SW_GIF_TRACE(GIF_TRACE_MOD, "[gif] - _gif_sw_codec() Fail: available >= MaxStackSize\n"); break; } *top_stack++ = (unsigned char)first; prefix[available] = (short)old_code; suffix[available] = (unsigned char)first; available++; if (((available & code_mask) == 0) && (available < MaxStackSize)) { code_size++; code_mask += available; } old_code = in_code; } top_stack--; /* ImageMagick Open Source Code Segment End */ /* Pop a pixel off the pixel stack. */ if (isResized) { decoded_pixel_count = top_stack - pixel_stack; //how many decoded pixels if ((src_clipy1 + offset) == GIF_SW_RESIZER.want_sy) { if (wantx >= x) { next_dst_data_distance = wantx - x;// how long the distance including x } else { next_dst_data_distance = src_clipx2 - x; } if (decoded_pixel_count < next_dst_data_distance) { //it means all the decoded data this time shall be discarded. x += decoded_pixel_count; top_stack -= (decoded_pixel_count); } else { //some pixels in the decoded pixels shall be output to the dst image. x += next_dst_data_distance;//GIF_SW_RESIZER.want_sx; top_stack -= (next_dst_data_distance); } } else { //The source lineY shall be discarded for the resized image. //wantx shall be GIF_SW_RESIZER.want_sx_table for all x (no need to update wantx) if ((x + decoded_pixel_count) > src_clipx2) { next_dst_data_distance = src_clipx2 - x; } else { next_dst_data_distance = decoded_pixel_count; } x += next_dst_data_distance;//GIF_SW_RESIZER.want_sx; top_stack -= (next_dst_data_distance); } } if ((x == wantx) && ((src_clipy1 + offset) == GIF_SW_RESIZER.want_sy)) { kal_uint32 index = (kal_uint32) *top_stack; put_pixel(&wantx, ((gif_sw_color) g_gif_sw_current_palette[index]), ((kal_bool) (transparent_index != index))); } x++; } /* x loop */ gif_sw_resizer_update_wanty(&wantx, is_interlace); if (!is_interlace) { offset++; } else { switch (pass) { case 0: default: { offset += 8; if (offset >= image_rows) { pass++; offset = 4; } break; } case 1: { offset += 8; if (offset >= image_rows) { pass++; offset = 2; } break; } case 2: { offset += 4; if (offset >= image_rows) { pass++; offset = 1; } break; } case 3: { offset += 2; break; } } gif_sw_resizer_update_interlaced_want_sy(isResized, &wantx, src_clipy1 + offset); } if (x <= src_clipx2) { //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec() Fail: x:%d <= src_clipx2:%d \n", x, src_clipx2); break; } } /* y loop */ if (y <= src_clipy2) { //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec() Fail:y:%d <= src_clipy2:%d \n", y, src_clipy2); //GIF_SW_RAISE(1); GIF_SW_RAISE(GIF_STATUS_DEC_ERROR_PARSE); } //if (1) { kal_uint8 val; kal_int32 remaining_cnt; kal_uint32 len, curpos; curpos = _gif_fsal_tell(pfsal_handle); remaining_cnt = (data_block_start_addr + read_byte_cnt) - curpos; if (remaining_cnt > 0) { //kal_uint32 dbg_idx = 0; //for (dbg_idx = 0; dbg_idx < (remaining_cnt); dbg_idx++) //{ // val = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; // printf("Flush The Remaining %dth Byte = %d.\n", dbg_idx, val); //} FLUSH(remaining_cnt); //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec(): Flush1 %d bytes.\n", remaining_cnt); } } //if (1) { kal_uint32 len, curpos; kal_uint8 val; len = 0; //Flush the remaining data. while (1) // skip data blocks { count = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; curpos = _gif_fsal_tell(pfsal_handle); len += count; if (count == 0) //Block Terminator { //printf("Count = 0, Flush %d data.\n", len); break; } FLUSH(count); //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec(): Flush2 %d bytes.\n", count); //if (count > 0) //{ // kal_uint32 dbg_idx = 0; // for (dbg_idx = 0; dbg_idx < len; dbg_idx++) // { // val = _get_data(FSAL_ACCESS_U8, pfsal_handle) & 0xFF; // printf("Flush %dth byte = %d.\n", curpos+dbg_idx, val); // } //} } } } /* codec block */ //end = drv_get_current_time(); //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec() End. %d ticks \n", drv_get_duration_tick(start, end)); //SW_GIF_TRACE(MOD_MMI, "[gif] - _gif_sw_codec(): Leave. FileCurPos = %d\n", _gif_fsal_tell(pfsal_handle)); }
static int str_copy(CONF *conf, char *section, char **pto, char *from) { int q, r, rr = 0, to = 0, len = 0; char *s, *e, *rp, *p, *rrp, *np, *cp, v; BUF_MEM *buf; if ((buf = BUF_MEM_new()) == NULL) return 0; len = strlen(from) + 1; if (!BUF_MEM_grow(buf, len)) goto err; for (;;) { if (IS_QUOTE(conf, *from)) { q = *from; from++; while (!IS_EOF(conf, *from) && (*from != q)) { if (IS_ESC(conf, *from)) { from++; if (IS_EOF(conf, *from)) break; } buf->data[to++] = *(from++); } if (*from == q) from++; } else if (IS_DQUOTE(conf, *from)) { q = *from; from++; while (!IS_EOF(conf, *from)) { if (*from == q) { if (*(from + 1) == q) { from++; } else { break; } } buf->data[to++] = *(from++); } if (*from == q) from++; } else if (IS_ESC(conf, *from)) { from++; v = *(from++); if (IS_EOF(conf, v)) break; else if (v == 'r') v = '\r'; else if (v == 'n') v = '\n'; else if (v == 'b') v = '\b'; else if (v == 't') v = '\t'; buf->data[to++] = v; } else if (IS_EOF(conf, *from)) break; else if (*from == '$') { size_t newsize; /* try to expand it */ rrp = NULL; s = &(from[1]); if (*s == '{') q = '}'; else if (*s == '(') q = ')'; else q = 0; if (q) s++; cp = section; e = np = s; while (IS_ALNUM(conf, *e)) e++; if ((e[0] == ':') && (e[1] == ':')) { cp = np; rrp = e; rr = *e; *rrp = '\0'; e += 2; np = e; while (IS_ALNUM(conf, *e)) e++; } r = *e; *e = '\0'; rp = e; if (q) { if (r != q) { CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE); goto err; } e++; } /*- * So at this point we have * np which is the start of the name string which is * '\0' terminated. * cp which is the start of the section string which is * '\0' terminated. * e is the 'next point after'. * r and rr are the chars replaced by the '\0' * rp and rrp is where 'r' and 'rr' came from. */ p = _CONF_get_string(conf, cp, np); if (rrp != NULL) *rrp = rr; *rp = r; if (p == NULL) { CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE); goto err; } newsize = strlen(p) + buf->length - (e - from); if (newsize > MAX_CONF_VALUE_LENGTH) { CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG); goto err; } if (!BUF_MEM_grow_clean(buf, newsize)) { CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE); goto err; } while (*p) buf->data[to++] = *(p++); /* * Since we change the pointer 'from', we also have to change the * perceived length of the string it points at. /RL */ len -= e - from; from = e; /* * In case there were no braces or parenthesis around the * variable reference, we have to put back the character that was * replaced with a '\0'. /RL */ *rp = r; } else buf->data[to++] = *(from++); } buf->data[to] = '\0'; OPENSSL_free(*pto); *pto = buf->data; OPENSSL_free(buf); return 1; err: BUF_MEM_free(buf); return 0; }
static int def_load_bio(CONF *conf, BIO *in, long *line) { /* The macro BUFSIZE conflicts with a system macro in VxWorks */ #define CONFBUFSIZE 512 int bufnum = 0, i, ii; BUF_MEM *buff = NULL; char *s, *p, *end; int again; long eline = 0; char btmp[DECIMAL_SIZE(eline) + 1]; CONF_VALUE *v = NULL, *tv; CONF_VALUE *sv = NULL; char *section = NULL, *buf; char *start, *psection, *pname; void *h = (void *)(conf->data); STACK_OF(BIO) *biosk = NULL; #ifndef OPENSSL_NO_POSIX_IO char *dirpath = NULL; OPENSSL_DIR_CTX *dirctx = NULL; #endif if ((buff = BUF_MEM_new()) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); goto err; } section = OPENSSL_strdup("default"); if (section == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (_CONF_new_data(conf) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } sv = _CONF_new_section(conf, section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } bufnum = 0; again = 0; for (;;) { if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); goto err; } p = &(buff->data[bufnum]); *p = '\0'; read_retry: BIO_gets(in, p, CONFBUFSIZE - 1); p[CONFBUFSIZE - 1] = '\0'; ii = i = strlen(p); if (i == 0 && !again) { /* the currently processed BIO is at EOF */ BIO *parent; #ifndef OPENSSL_NO_POSIX_IO /* continue processing with the next file from directory */ if (dirctx != NULL) { BIO *next; if ((next = get_next_file(dirpath, &dirctx)) != NULL) { BIO_vfree(in); in = next; goto read_retry; } else { OPENSSL_free(dirpath); dirpath = NULL; } } #endif /* no more files in directory, continue with processing parent */ if ((parent = sk_BIO_pop(biosk)) == NULL) { /* everything processed get out of the loop */ break; } else { BIO_vfree(in); in = parent; goto read_retry; } } again = 0; while (i > 0) { if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) break; else i--; } /* * we removed some trailing stuff so there is a new line on the end. */ if (ii && i == ii) again = 1; /* long line */ else { p[i] = '\0'; eline++; /* another input line */ } /* we now have a line with trailing \r\n removed */ /* i is the number of bytes */ bufnum += i; v = NULL; /* check for line continuation */ if (bufnum >= 1) { /* * If we have bytes and the last char '\\' and second last char * is not '\\' */ p = &(buff->data[bufnum - 1]); if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { bufnum--; again = 1; } } if (again) continue; bufnum = 0; buf = buff->data; clear_comments(conf, buf); s = eat_ws(conf, buf); if (IS_EOF(conf, *s)) continue; /* blank line */ if (*s == '[') { char *ss; s++; start = eat_ws(conf, s); ss = start; again: end = eat_alpha_numeric(conf, ss); p = eat_ws(conf, end); if (*p != ']') { if (*p != '\0' && ss != p) { ss = p; goto again; } CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); goto err; } *end = '\0'; if (!str_copy(conf, NULL, §ion, start)) goto err; if ((sv = _CONF_get_section(conf, section)) == NULL) sv = _CONF_new_section(conf, section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } continue; } else { pname = s; end = eat_alpha_numeric(conf, s); if ((end[0] == ':') && (end[1] == ':')) { *end = '\0'; end += 2; psection = pname; pname = end; end = eat_alpha_numeric(conf, end); } else { psection = section; } p = eat_ws(conf, end); if (strncmp(pname, ".include", 8) == 0 && (p != pname + 8 || *p == '=')) { char *include = NULL; BIO *next; if (*p == '=') { p++; p = eat_ws(conf, p); } trim_ws(conf, p); if (!str_copy(conf, psection, &include, p)) goto err; /* get the BIO of the included file */ #ifndef OPENSSL_NO_POSIX_IO next = process_include(include, &dirctx, &dirpath); if (include != dirpath) { /* dirpath will contain include in case of a directory */ OPENSSL_free(include); } #else next = BIO_new_file(include, "r"); OPENSSL_free(include); #endif if (next != NULL) { /* push the currently processing BIO onto stack */ if (biosk == NULL) { if ((biosk = sk_BIO_new_null()) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } } if (!sk_BIO_push(biosk, in)) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } /* continue with reading from the included BIO */ in = next; } continue; } else if (*p != '=') { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN); goto err; } *end = '\0'; p++; start = eat_ws(conf, p); trim_ws(conf, start); if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } v->name = OPENSSL_strdup(pname); v->value = NULL; if (v->name == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (!str_copy(conf, psection, &(v->value), start)) goto err; if (strcmp(psection, section) != 0) { if ((tv = _CONF_get_section(conf, psection)) == NULL) tv = _CONF_new_section(conf, psection); if (tv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } } else tv = sv; if (_CONF_add_string(conf, tv, v) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } v = NULL; } } BUF_MEM_free(buff); OPENSSL_free(section); /* * No need to pop, since we only get here if the stack is empty. * If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE! */ sk_BIO_free(biosk); return 1; err: BUF_MEM_free(buff); OPENSSL_free(section); /* * Since |in| is the first element of the stack and should NOT be freed * here, we cannot use sk_BIO_pop_free(). Instead, we pop and free one * BIO at a time, making sure that the last one popped isn't. */ while (sk_BIO_num(biosk) > 0) { BIO *popped = sk_BIO_pop(biosk); BIO_vfree(in); in = popped; } sk_BIO_free(biosk); #ifndef OPENSSL_NO_POSIX_IO OPENSSL_free(dirpath); if (dirctx != NULL) OPENSSL_DIR_end(&dirctx); #endif if (line != NULL) *line = eline; BIO_snprintf(btmp, sizeof(btmp), "%ld", eline); ERR_add_error_data(2, "line ", btmp); if (h != conf->data) { CONF_free(conf->data); conf->data = NULL; } if (v != NULL) { OPENSSL_free(v->name); OPENSSL_free(v->value); OPENSSL_free(v); } return 0; }
int main(int argc, char **argv) { int n,sockfd, on=1,i,j,maxfdp,optval=1; char recvline[LINE_MAX], in_packet[PACKET_LEN]; client_config_t config; int num_ifi = 0; pthread_t tid; thread_arg* arg; bool done = FALSE, is_probe = FALSE, is_error = FALSE; unsigned int ack_seq, seq, timestamp; unsigned short curr_win; circ_buffer_t rcv_buffer; ifi_t *ifi_array[IFI_MAX]; read_client_config("client.in", &config); print_client_config(&config); num_ifi = get_ifi(ifi_array); print_ifi(ifi_array, num_ifi); srand(config.seed); init_circular_buffer(&rcv_buffer, config.window_size); rtt_init(&rttinfo); if (connection_setup(&sockfd, ifi_array, num_ifi, &rcv_buffer, &config) < 0) err_sys("[Error] Connection Setup Error, Terminating..\n"); /* TODO: Recv ACK and connect to the new port */ arg = (thread_arg*)calloc(1, sizeof(thread_arg)); arg->rcv_buf = &rcv_buffer; arg->config = &config; arg->sockfd = sockfd; Pthread_create(&tid, NULL, &consumer_thread, arg); /* Below is the Producer Logic which reads from the socket and fills * up the receive Buffer. */ while (!done) { if ((n = read(sockfd, in_packet, PACKET_LEN)) < 0) { if (errno == EINTR) continue; else err_sys("[Error] Unknown Read Error"); } packet_info_t *pkt_info = get_packet_info(in_packet, n); if (!IS_DATA(pkt_info) && !(is_probe = IS_PROBE(pkt_info)) && !(is_error = IS_ERR(pkt_info))) { free_pkt_info(pkt_info); continue; } if (consume_random_packet(pkt_info, config.prob_loss, TRUE)) { free_pkt_info(pkt_info); continue; } if(IS_EOF(pkt_info) || is_error) done = TRUE; Pthread_mutex_lock(&buf_mutex); /* Special Handling for Probes & Errors, send an ACK, don't store in buffer */ if(!is_probe && !is_error) { write_to_buffer(&rcv_buffer , pkt_info); } /* Save off these values as we are releasing the lock below */ curr_win = window_size(&rcv_buffer); ack_seq = NEXT_ACK(&rcv_buffer); seq = pkt_info->seq; timestamp = pkt_info->timestamp; Pthread_mutex_unlock(&buf_mutex); if(is_probe) printf("[Info] Persist Timer Response [Ack:%u] [Window Size:%hu]\n", ack_seq, curr_win); else printf("[Info] Received [Seq: %u] Responding with [Ack:%u] [Window Size:%hu]\n", seq, ack_seq, curr_win); send_ack(sockfd, curr_win, seq, ack_seq, timestamp, config.prob_loss); } pthread_exit(NULL); }
/* This is the Thread which will read data from the Circular buffer * and print out to the Console */ void* consumer_thread(void *arg) { circ_buffer_t *rcv_buf; double mean, smoothed_mean; int sockfd; packet_info_t *pkt_info; double get_rand; bool data_present, was_buf_full, done = FALSE; unsigned int ack_seq; unsigned short new_win; double prob_loss; assert(arg); assert(rcv_buf = ((thread_arg *)arg)->rcv_buf); assert(((thread_arg *)arg)->config); mean = smoothed_mean = ((thread_arg *)arg)->config->mean; prob_loss = ((thread_arg *)arg)->config->prob_loss; sockfd = ((thread_arg *)arg)->sockfd; free(arg); Pthread_detach(pthread_self()); while (!done) { get_rand = (double)rand()/RAND_MAX; smoothed_mean = -1.0 * mean * log(get_rand); printf("[Consumer Thread] Wake Up in %lf ms\n", smoothed_mean); usleep((useconds_t)(smoothed_mean * 1000)); data_present = FALSE; was_buf_full = FALSE; Pthread_mutex_lock(&buf_mutex); if (IS_BUFFER_FULL(rcv_buf)) was_buf_full = TRUE; while(read_from_buffer(rcv_buf, &pkt_info) >= 0) { data_present = TRUE; fprintf(stdout, "[Consumer thread] [seq:%u]\n%.*s\n", pkt_info->seq, pkt_info->data_len, pkt_info->data); if(IS_EOF(pkt_info)) { done = TRUE; break; } free_pkt_info(pkt_info); pkt_info = NULL; } /* Save off these values as we are releasing the lock below */ new_win = window_size(rcv_buf); ack_seq = NEXT_ACK(rcv_buf); Pthread_mutex_unlock(&buf_mutex); if (!data_present) printf("[Consumer Thread] No data this time around\n"); if(was_buf_full) { /* Advertise New Opened Up window */ send_ack(sockfd, new_win, 0, ack_seq, 0, prob_loss); } } exit(0); }
static int def_load_bio(CONF *conf, BIO *in, long *line) { /* The macro BUFSIZE conflicts with a system macro in VxWorks */ #define CONFBUFSIZE 512 int bufnum=0,i,ii; BUF_MEM *buff=NULL; char *s,*p,*end; int again; long eline=0; char btmp[DECIMAL_SIZE(eline)+1]; CONF_VALUE *v=NULL,*tv; CONF_VALUE *sv=NULL; char *section=NULL,*buf; STACK_OF(CONF_VALUE) *section_sk=NULL,*ts __UNUSED; char *start,*psection,*pname; void *h = (void *)(conf->data); if ((buff=BUF_MEM_new()) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_BUF_LIB); goto err; } section=(char *)OPENSSL_malloc(10); if (section == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_MALLOC_FAILURE); goto err; } BUF_strlcpy(section,"default",10); if (_CONF_new_data(conf) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_MALLOC_FAILURE); goto err; } sv=_CONF_new_section(conf,section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } section_sk=(STACK_OF(CONF_VALUE) *)sv->value; bufnum=0; again=0; for (;;) { if (!BUF_MEM_grow(buff,bufnum+CONFBUFSIZE)) { CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_BUF_LIB); goto err; } p= &(buff->data[bufnum]); *p='\0'; BIO_gets(in, p, CONFBUFSIZE-1); p[CONFBUFSIZE-1]='\0'; ii=i=strlen(p); if (i == 0 && !again) break; again=0; while (i > 0) { if ((p[i-1] != '\r') && (p[i-1] != '\n')) break; else i--; } /* we removed some trailing stuff so there is a new * line on the end. */ if (ii && i == ii) again=1; /* long line */ else { p[i]='\0'; eline++; /* another input line */ } /* we now have a line with trailing \r\n removed */ /* i is the number of bytes */ bufnum+=i; v=NULL; /* check for line continuation */ if (bufnum >= 1) { /* If we have bytes and the last char '\\' and * second last char is not '\\' */ p= &(buff->data[bufnum-1]); if (IS_ESC(conf,p[0]) && ((bufnum <= 1) || !IS_ESC(conf,p[-1]))) { bufnum--; again=1; } } if (again) continue; bufnum=0; buf=buff->data; clear_comments(conf, buf); s=eat_ws(conf, buf); if (IS_EOF(conf,*s)) continue; /* blank line */ if (*s == '[') { char *ss; s++; start=eat_ws(conf, s); ss=start; again: end=eat_alpha_numeric(conf, ss); p=eat_ws(conf, end); if (*p != ']') { if (*p != '\0') { ss=p; goto again; } CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); goto err; } *end='\0'; if (!str_copy(conf,NULL,§ion,start)) goto err; if ((sv=_CONF_get_section(conf,section)) == NULL) sv=_CONF_new_section(conf,section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } section_sk=(STACK_OF(CONF_VALUE) *)sv->value; continue; } else {
static int def_load_bio(CONF *conf, BIO *in, long *line) { /* The macro BUFSIZE conflicts with a system macro in VxWorks */ #define CONFBUFSIZE 512 int bufnum = 0, i, ii; BUF_MEM *buff = NULL; char *s, *p, *end; int again; long eline = 0; char btmp[DECIMAL_SIZE(eline) + 1]; CONF_VALUE *v = NULL, *tv; CONF_VALUE *sv = NULL; char *section = NULL, *buf; char *start, *psection, *pname; void *h = (void *)(conf->data); if ((buff = BUF_MEM_new()) == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); goto err; } section = (char *)OPENSSL_malloc(10); if (section == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } BUF_strlcpy(section, "default", 10); if (_CONF_new_data(conf) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } sv = _CONF_new_section(conf, section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } bufnum = 0; again = 0; for (;;) { if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB); goto err; } p = &(buff->data[bufnum]); *p = '\0'; BIO_gets(in, p, CONFBUFSIZE - 1); p[CONFBUFSIZE - 1] = '\0'; ii = i = sgx_strlen(p); if (i == 0 && !again) break; again = 0; while (i > 0) { if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) break; else i--; } /* * we removed some trailing stuff so there is a new line on the end. */ if (ii && i == ii) again = 1; /* long line */ else { p[i] = '\0'; eline++; /* another input line */ } /* we now have a line with trailing \r\n removed */ /* i is the number of bytes */ bufnum += i; v = NULL; /* check for line continuation */ if (bufnum >= 1) { /* * If we have bytes and the last char '\\' and second last char * is not '\\' */ p = &(buff->data[bufnum - 1]); if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { bufnum--; again = 1; } } if (again) continue; bufnum = 0; buf = buff->data; clear_comments(conf, buf); s = eat_ws(conf, buf); if (IS_EOF(conf, *s)) continue; /* blank line */ if (*s == '[') { char *ss; s++; start = eat_ws(conf, s); ss = start; again: end = eat_alpha_numeric(conf, ss); p = eat_ws(conf, end); if (*p != ']') { if (*p != '\0' && ss != p) { ss = p; goto again; } CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); goto err; } *end = '\0'; if (!str_copy(conf, NULL, §ion, start)) goto err; if ((sv = _CONF_get_section(conf, section)) == NULL) sv = _CONF_new_section(conf, section); if (sv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } continue; } else { pname = s; psection = NULL; end = eat_alpha_numeric(conf, s); if ((end[0] == ':') && (end[1] == ':')) { *end = '\0'; end += 2; psection = pname; pname = end; end = eat_alpha_numeric(conf, end); } p = eat_ws(conf, end); if (*p != '=') { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN); goto err; } *end = '\0'; p++; start = eat_ws(conf, p); while (!IS_EOF(conf, *p)) p++; p--; while ((p != start) && (IS_WS(conf, *p))) p--; p++; *p = '\0'; if (!(v = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } if (psection == NULL) psection = section; v->name = (char *)OPENSSL_malloc(strlen(pname) + 1); v->value = NULL; if (v->name == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } BUF_strlcpy(v->name, pname, sgx_strlen(pname) + 1); if (!str_copy(conf, psection, &(v->value), start)) goto err; if (sgx_strcmp(psection, section) != 0) { if ((tv = _CONF_get_section(conf, psection)) == NULL) tv = _CONF_new_section(conf, psection); if (tv == NULL) { CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); goto err; } } else tv = sv; #if 1 if (_CONF_add_string(conf, tv, v) == 0) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } #else v->section = tv->section; if (!sk_CONF_VALUE_push(ts, v)) { CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE); goto err; } vv = (CONF_VALUE *)lh_insert(conf->data, v); if (vv != NULL) { sk_CONF_VALUE_delete_ptr(ts, vv); OPENSSL_free(vv->name); OPENSSL_free(vv->value); OPENSSL_free(vv); } #endif v = NULL; } } if (buff != NULL) BUF_MEM_free(buff); if (section != NULL) OPENSSL_free(section); return (1); err: if (buff != NULL) BUF_MEM_free(buff); if (section != NULL) OPENSSL_free(section); if (line != NULL) *line = eline; BIO_snprintf(btmp, sizeof btmp, "%ld", eline); ERR_add_error_data(2, "line ", btmp); if ((h != conf->data) && (conf->data != NULL)) { CONF_free(conf->data); conf->data = NULL; } if (v != NULL) { if (v->name != NULL) OPENSSL_free(v->name); if (v->value != NULL) OPENSSL_free(v->value); if (v != NULL) OPENSSL_free(v); } return (0); }
/* Executes a program in a BVM instance until termination. * Returns a non-zero error code if an error occurred. */ int bvm_run(struct bvm *vm, const uint8_t *code, size_t code_size) { /* Code size must fit into BVM's memory. */ if (code_size > sizeof(vm->mem)) return BVM_PROGRAM_TOO_LARGE; /* Zero register file and memory. */ memset(vm->reg, 0, sizeof(vm->reg)); memset(vm->mem, 0, sizeof(vm->mem)); /* Load program code into memory. */ memcpy(vm->mem, code, code_size); /* Reset the clock. */ vm->clk = 0; while (1) { uint8_t op; uint8_t src, dst; int c; usleep(BVM_CYCLE); vm->clk++; op = pc_next(vm); switch (op) { case HALT: return 0; case MOV: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = vm->reg[src]; continue; case MOVN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = src; continue; case LOAD: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = vm->mem[vm->reg[src]]; continue; case LOADA: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] = vm->mem[src]; continue; case PUT: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->mem[vm->reg[dst]] = vm->reg[src]; continue; case PUTN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->mem[vm->reg[dst]] = src; continue; case PUTA: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->mem[dst] = vm->reg[src]; continue; case PUTNA: src = pc_next(vm); dst = pc_next(vm); vm->mem[dst] = src; continue; case PUSH: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[SP]--; vm->mem[vm->reg[SP]] = vm->reg[src]; continue; case PUSHN: src = pc_next(vm); vm->reg[SP]--; vm->mem[vm->reg[SP]] = src; continue; case POP: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src] = vm->mem[vm->reg[SP]]; vm->reg[SP]++; continue; case INC: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src]++; continue; case DEC: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src]--; continue; case ADD: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] += vm->reg[src]; continue; case ADDN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] += src; continue; case SUB: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] -= vm->reg[src]; continue; case SUBN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] -= src; continue; case AND: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] &= vm->reg[src]; continue; case ANDN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] &= src; continue; case OR: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] |= vm->reg[src]; continue; case ORN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] |= src; continue; case XOR: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] ^= vm->reg[src]; continue; case XORN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[dst] ^= src; continue; case NEG: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[src] = ~vm->reg[src]; continue; case CMP: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src) || !IS_REGISTER_VALID(dst)) return BVM_BAD_INSTRUCTION; vm->reg[CC] = 0; vm->reg[CC] |= (vm->reg[src] == vm->reg[dst]) << CC_EQ_SHIFT; vm->reg[CC] |= (vm->reg[src] < vm->reg[dst]) << CC_OF_SHIFT; continue; case CMPN: src = pc_next(vm); dst = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[CC] = 0; vm->reg[CC] |= (vm->reg[src] == dst) << CC_EQ_SHIFT; vm->reg[CC] |= (vm->reg[src] < dst) << CC_OF_SHIFT; continue; case TEST: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; vm->reg[CC] = 0; vm->reg[CC] |= (vm->reg[src] == 0) << CC_EQ_SHIFT; continue; case JMP: vm->reg[PC] = pc_next(vm); continue; case JE: src = pc_next(vm); if (IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JNE: src = pc_next(vm); if (!IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JL: src = pc_next(vm); if (IS_LT(vm->reg[CC])) vm->reg[PC] = src; continue; case JLE: src = pc_next(vm); if (IS_LT(vm->reg[CC]) || IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JG: src = pc_next(vm); if (!IS_LT(vm->reg[CC]) && !IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JGE: src = pc_next(vm); if (!IS_LT(vm->reg[CC]) || IS_EQ(vm->reg[CC])) vm->reg[PC] = src; continue; case JEOF: src = pc_next(vm); if (IS_EOF(vm->reg[CC])) vm->reg[PC] = src; continue; case JNEOF: src = pc_next(vm); if (!IS_EOF(vm->reg[CC])) vm->reg[PC] = src; continue; case CALL: vm->reg[SP]--; vm->mem[vm->reg[SP]] = vm->reg[PC] + 1; vm->reg[PC] = pc_next(vm); continue; case RET: vm->reg[PC] = vm->mem[vm->reg[SP]]; vm->reg[SP]++; continue; case NOP: continue; case IN: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; if ((c = fgetc(stdin)) == EOF) vm->reg[CC] = CC_EOF; vm->reg[src] = c; continue; case OUT: src = pc_next(vm); if (!IS_REGISTER_VALID(src)) return BVM_BAD_INSTRUCTION; if (fputc(vm->reg[src], stdout) == EOF) vm->reg[CC] = CC_EOF; continue; case OUTN: src = pc_next(vm); if (fputc(src, stdout) == EOF) vm->reg[CC] = CC_EOF; continue; default: return BVM_BAD_INSTRUCTION; } } }