Beispiel #1
0
static char *
eat_ws(CONF *conf, char *p)
{
	while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
		p++;
	return (p);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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';
}
Beispiel #4
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++;
		}
	}
Beispiel #5
0
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));
}
Beispiel #7
0
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;
}
Beispiel #8
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, &section, 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;
}
Beispiel #9
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);
}
Beispiel #10
0
/* 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);
}
Beispiel #11
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,&section,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
			{
Beispiel #12
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);

    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, &section, 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);
}
Beispiel #13
0
Datei: bvm.c Projekt: tkriik/bvm
/* 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;
		}
	}
}