jiahuimbzuai/CoQuIR huggingface dataset:
//  [c]
mark_source_chains(const struct xt_table_info *newinfo,
		   unsigned int valid_hooks, void *entry0)
{
	unsigned int hook;

	/* No recursion; use packet counter to save back ptrs (reset
	   to 0 as we leave), and comefrom to save source hook bitmask */
	for (hook = 0; hook < NF_INET_NUMHOOKS; hook++) {
		unsigned int pos = newinfo->hook_entry[hook];
		struct ipt_entry *e = (struct ipt_entry *)(entry0 + pos);

		if (!(valid_hooks & (1 << hook)))
			continue;

		/* Set initial back pointer. */
		e->counters.pcnt = pos;

		for (;;) {
			const struct xt_standard_target *t
				= (void *)ipt_get_target_c(e);
			int visited = e->comefrom & (1 << hook);

			if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
				pr_err("iptables: loop hook %u pos %u %08X.\n",
				       hook, pos, e->comefrom);
				return 0;
			}
			e->comefrom |= ((1 << hook) | (1 << NF_INET_NUMHOOKS));

			/* Unconditional return/END. */
			if ((e->target_offset == sizeof(struct ipt_entry) &&
			     (strcmp(t->target.u.user.name,
				     XT_STANDARD_TARGET) == 0) &&
			     t->verdict < 0 && unconditional(&e->ip)) ||
			    visited) {
				unsigned int oldpos, size;

				if ((strcmp(t->target.u.user.name,
					    XT_STANDARD_TARGET) == 0) &&
				    t->verdict < -NF_MAX_VERDICT - 1) {
					duprintf("mark_source_chains: bad "
						"negative verdict (%i)\n",
								t->verdict);
					return 0;
				}

				/* Return: backtrack through the last
				   big jump. */
				do {
					e->comefrom ^= (1<<NF_INET_NUMHOOKS);
#ifdef DEBUG_IP_FIREWALL_USER
					if (e->comefrom
					    & (1 << NF_INET_NUMHOOKS)) {
						duprintf("Back unset "
							 "on hook %u "
							 "rule %u\n",
							 hook, pos);
					}
#endif
					oldpos = pos;
					pos = e->counters.pcnt;
					e->counters.pcnt = 0;

					/* We're at the start. */
					if (pos == oldpos)
						goto next;

					e = (struct ipt_entry *)
						(entry0 + pos);
				} while (oldpos == pos + e->next_offset);

				/* Move along one */
				size = e->next_offset;
				e = (struct ipt_entry *)
					(entry0 + pos + size);
				e->counters.pcnt = pos;
				pos += size;
			} else {
				int newpos = t->verdict;

				if (strcmp(t->target.u.user.name,
					   XT_STANDARD_TARGET) == 0 &&
				    newpos >= 0) {
					if (newpos > newinfo->size -
						sizeof(struct ipt_entry)) {
						duprintf("mark_source_chains: "
							"bad verdict (%i)\n",
								newpos);
						return 0;
					}
					/* This a jump; chase it. */
					duprintf("Jump rule %u -> %u\n",
						 pos, newpos);
				} else {
					/* ... this is a fallthru */
					newpos = pos + e->next_offset;
				}
				e = (struct ipt_entry *)
					(entry0 + newpos);
				e->counters.pcnt = pos;
				pos = newpos;
			}
		}
next:
		duprintf("Finished chain %u\n", hook);
	}
	return 1;
}
//  [c]
check_entry_size_and_hooks(struct ipt_entry *e,
			   struct xt_table_info *newinfo,
			   const unsigned char *base,
			   const unsigned char *limit,
			   const unsigned int *hook_entries,
			   const unsigned int *underflows,
			   unsigned int valid_hooks)
{
	unsigned int h;
	int err;

	if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
	    (unsigned char *)e + sizeof(struct ipt_entry) >= limit ||
	    (unsigned char *)e + e->next_offset > limit) {
		duprintf("Bad offset %p\n", e);
		return -EINVAL;
	}

	if (e->next_offset
	    < sizeof(struct ipt_entry) + sizeof(struct xt_entry_target)) {
		duprintf("checking: element %p size %u\n",
			 e, e->next_offset);
		return -EINVAL;
	}

	err = check_entry(e);
	if (err)
		return err;

	/* Check hooks & underflows */
	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
		if (!(valid_hooks & (1 << h)))
			continue;
		if ((unsigned char *)e - base == hook_entries[h])
			newinfo->hook_entry[h] = hook_entries[h];
		if ((unsigned char *)e - base == underflows[h]) {
			if (!check_underflow(e)) {
				pr_debug("Underflows must be unconditional and "
					 "use the STANDARD target with "
					 "ACCEPT/DROP\n");
				return -EINVAL;
			}
			newinfo->underflow[h] = underflows[h];
		}
	}

	/* Clear counters and comefrom */
	e->counters = ((struct xt_counters) { 0, 0 });
	e->comefrom = 0;
	return 0;
}
//  [c]
check_entry_size_and_hooks(struct ipt_entry *e,
			   struct xt_table_info *newinfo,
			   const unsigned char *base,
			   const unsigned char *limit,
			   const unsigned int *hook_entries,
			   const unsigned int *underflows,
			   unsigned int valid_hooks)
{
	unsigned int h;
	int err;

	if ((unsigned long)e % __alignof__(struct ipt_entry) != 0 ||
	    (unsigned char *)e + sizeof(struct ipt_entry) >= limit ||
	    (unsigned char *)e + e->next_offset > limit) {
		duprintf("Bad offset %p\n", e);
		return -EINVAL;
	}

	if (e->next_offset
	    < sizeof(struct ipt_entry) + sizeof(struct xt_entry_target)) {
		duprintf("checking: element %p size %u\n",
			 e, e->next_offset);
		return -EINVAL;
	}

	err = check_entry(e);
	if (err)
		return err;

	/* Check hooks & underflows */
	for (h = 0; h < NF_INET_NUMHOOKS; h++) {
		if (!(valid_hooks & (1 << h)))
			continue;
		if ((unsigned char *)e - base == hook_entries[h])
			newinfo->hook_entry[h] = hook_entries[h];
		if ((unsigned char *)e - base == underflows[h]) {
			if (!check_underflow(e)) {
				pr_err("Underflows must be unconditional and "
				       "use the STANDARD target with "
				       "ACCEPT/DROP\n");
				return -EINVAL;
			}
			newinfo->underflow[h] = underflows[h];
		}
	}

	/* Clear counters and comefrom */
	e->counters = ((struct xt_counters) { 0, 0 });
	e->comefrom = 0;
	return 0;
}
//  [c]
int yr_object_array_set_item(
    YR_OBJECT* object,
    YR_OBJECT* item,
    int index)
{
  YR_OBJECT_ARRAY* array;

  int i;
  int count;

  assert(index >= 0);
  assert(object->type == OBJECT_TYPE_ARRAY);

  array = object_as_array(object);

  if (array->items == NULL)
  {
    count = 64;

    while (count <= index)
      count *= 2;

    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
        sizeof(YR_ARRAY_ITEMS) + count * sizeof(YR_OBJECT*));

    if (array->items == NULL)
      return ERROR_INSUFFICIENT_MEMORY;

    memset(array->items->objects, 0, count * sizeof(YR_OBJECT*));

    array->items->count = count;
  }
  else if (index >= array->items->count)
  {
    count = array->items->count * 2;

    while (count <= index)
      count *= 2;

    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
        array->items,
        sizeof(YR_ARRAY_ITEMS) + count * sizeof(YR_OBJECT*));

    if (array->items == NULL)
      return ERROR_INSUFFICIENT_MEMORY;

    for (i = array->items->count; i < count; i++)
      array->items->objects[i] = NULL;

    array->items->count = count;
  }

  item->parent = object;
  array->items->objects[index] = item;

  return ERROR_SUCCESS;
}
//  [c]
int yr_object_array_set_item(
    YR_OBJECT* object,
    YR_OBJECT* item,
    int index)
{
  YR_OBJECT_ARRAY* array;

  int i;
  int count;

  assert(index >= 0);
  assert(object->type == OBJECT_TYPE_ARRAY);

  array = object_as_array(object);

  if (array->items == NULL)
  {
    count = yr_max(64, (index + 1) * 2);

    array->items = (YR_ARRAY_ITEMS*) yr_malloc(
        sizeof(YR_ARRAY_ITEMS) + count * sizeof(YR_OBJECT*));

    if (array->items == NULL)
      return ERROR_INSUFFICIENT_MEMORY;

    memset(array->items->objects, 0, count * sizeof(YR_OBJECT*));

    array->items->count = count;
  }
  else if (index >= array->items->count)
  {
    count = array->items->count * 2;
    array->items = (YR_ARRAY_ITEMS*) yr_realloc(
        array->items,
        sizeof(YR_ARRAY_ITEMS) + count * sizeof(YR_OBJECT*));

    if (array->items == NULL)
      return ERROR_INSUFFICIENT_MEMORY;

    for (i = array->items->count; i < count; i++)
      array->items->objects[i] = NULL;

    array->items->count = count;
  }

  item->parent = object;
  array->items->objects[index] = item;

  return ERROR_SUCCESS;
}
//  [c]
int _yr_scan_verify_re_match(
    YR_SCAN_CONTEXT* context,
    YR_AC_MATCH* ac_match,
    uint8_t* data,
    size_t data_size,
    size_t data_base,
    size_t offset)
{
  CALLBACK_ARGS callback_args;
  RE_EXEC_FUNC exec;

  int forward_matches = -1;
  int backward_matches = -1;
  int flags = 0;

  if (STRING_IS_GREEDY_REGEXP(ac_match->string))
    flags |= RE_FLAGS_GREEDY;

  if (STRING_IS_NO_CASE(ac_match->string))
    flags |= RE_FLAGS_NO_CASE;

  if (STRING_IS_DOT_ALL(ac_match->string))
    flags |= RE_FLAGS_DOT_ALL;

  if (STRING_IS_FAST_REGEXP(ac_match->string))
    exec = yr_re_fast_exec;
  else
    exec = yr_re_exec;

  if (STRING_IS_ASCII(ac_match->string))
  {
    forward_matches = exec(
        ac_match->forward_code,
        data + offset,
        data_size - offset,
        offset,
        flags,
        NULL,
        NULL);
  }

  if (STRING_IS_WIDE(ac_match->string) && forward_matches == -1)
  {
    flags |= RE_FLAGS_WIDE;
    forward_matches = exec(
        ac_match->forward_code,
        data + offset,
        data_size - offset,
        offset,
        flags,
        NULL,
        NULL);
  }

  switch(forward_matches)
  {
    case -1:
      return ERROR_SUCCESS;
    case -2:
      return ERROR_INSUFFICIENT_MEMORY;
    case -3:
      return ERROR_TOO_MANY_MATCHES;
    case -4:
      return ERROR_TOO_MANY_RE_FIBERS;
    case -5:
      return ERROR_INTERNAL_FATAL_ERROR;
  }

  if (forward_matches == 0 && ac_match->backward_code == NULL)
    return ERROR_SUCCESS;

  callback_args.string = ac_match->string;
  callback_args.context = context;
  callback_args.data = data;
  callback_args.data_size = data_size;
  callback_args.data_base = data_base;
  callback_args.forward_matches = forward_matches;
  callback_args.full_word = STRING_IS_FULL_WORD(ac_match->string);

  if (ac_match->backward_code != NULL)
  {
    backward_matches = exec(
        ac_match->backward_code,
        data + offset,
        data_size - offset,
        offset,
        flags | RE_FLAGS_BACKWARDS | RE_FLAGS_EXHAUSTIVE,
        _yr_scan_match_callback,
        (void*) &callback_args);

    switch(backward_matches)
    {
      case -2:
        return ERROR_INSUFFICIENT_MEMORY;
      case -3:
        return ERROR_TOO_MANY_MATCHES;
      case -4:
        return ERROR_TOO_MANY_RE_FIBERS;
      case -5:
        return ERROR_INTERNAL_FATAL_ERROR;
    }
  }
  else
  {
    FAIL_ON_ERROR(_yr_scan_match_callback(
        data + offset, 0, flags, &callback_args));
  }

  return ERROR_SUCCESS;
}
//  [c]
int _yr_scan_verify_re_match(
    YR_SCAN_CONTEXT* context,
    YR_AC_MATCH* ac_match,
    uint8_t* data,
    size_t data_size,
    size_t data_base,
    size_t offset)
{
  CALLBACK_ARGS callback_args;
  RE_EXEC_FUNC exec;

  int forward_matches = -1;
  int backward_matches = -1;
  int flags = 0;

  if (STRING_IS_GREEDY_REGEXP(ac_match->string))
    flags |= RE_FLAGS_GREEDY;

  if (STRING_IS_NO_CASE(ac_match->string))
    flags |= RE_FLAGS_NO_CASE;

  if (STRING_IS_DOT_ALL(ac_match->string))
    flags |= RE_FLAGS_DOT_ALL;

  if (STRING_IS_FAST_REGEXP(ac_match->string))
    exec = yr_re_fast_exec;
  else
    exec = yr_re_exec;

  if (STRING_IS_ASCII(ac_match->string))
  {
    forward_matches = exec(
        ac_match->forward_code,
        data + offset,
        data_size - offset,
        offset > 0 ? flags | RE_FLAGS_NOT_AT_START : flags,
        NULL,
        NULL);
  }

  if (STRING_IS_WIDE(ac_match->string) && forward_matches == -1)
  {
    flags |= RE_FLAGS_WIDE;
    forward_matches = exec(
        ac_match->forward_code,
        data + offset,
        data_size - offset,
        offset > 0 ? flags | RE_FLAGS_NOT_AT_START : flags,
        NULL,
        NULL);
  }

  switch(forward_matches)
  {
    case -1:
      return ERROR_SUCCESS;
    case -2:
      return ERROR_INSUFFICIENT_MEMORY;
    case -3:
      return ERROR_TOO_MANY_MATCHES;
    case -4:
      return ERROR_TOO_MANY_RE_FIBERS;
    case -5:
      return ERROR_INTERNAL_FATAL_ERROR;
  }

  if (forward_matches == 0 && ac_match->backward_code == NULL)
    return ERROR_SUCCESS;

  callback_args.string = ac_match->string;
  callback_args.context = context;
  callback_args.data = data;
  callback_args.data_size = data_size;
  callback_args.data_base = data_base;
  callback_args.forward_matches = forward_matches;
  callback_args.full_word = STRING_IS_FULL_WORD(ac_match->string);

  if (ac_match->backward_code != NULL)
  {
    backward_matches = exec(
        ac_match->backward_code,
        data + offset,
        offset,
        flags | RE_FLAGS_BACKWARDS | RE_FLAGS_EXHAUSTIVE,
        _yr_scan_match_callback,
        (void*) &callback_args);

    switch(backward_matches)
    {
      case -2:
        return ERROR_INSUFFICIENT_MEMORY;
      case -3:
        return ERROR_TOO_MANY_MATCHES;
      case -4:
        return ERROR_TOO_MANY_RE_FIBERS;
      case -5:
        return ERROR_INTERNAL_FATAL_ERROR;
    }
  }
  else
  {
    FAIL_ON_ERROR(_yr_scan_match_callback(
        data + offset, 0, flags, &callback_args));
  }

  return ERROR_SUCCESS;
}
//  [c]
error_t ipStringToAddr(const char_t *str, IpAddr *ipAddr)
{
   error_t error;

#if (IPV6_SUPPORT == ENABLED)
   //IPv6 address?
   if(osStrchr(str, ':') != NULL)
   {
      //IPv6 addresses are 16-byte long
      ipAddr->length = sizeof(Ipv6Addr);
      //Convert the string to IPv6 address
      error = ipv6StringToAddr(str, &ipAddr->ipv6Addr);
   }
   else
#endif
#if (IPV4_SUPPORT == ENABLED)
   //IPv4 address?
   if(osStrchr(str, '.') != NULL)
   {
      //IPv4 addresses are 4-byte long
      ipAddr->length = sizeof(Ipv4Addr);
      //Convert the string to IPv4 address
      error = ipv4StringToAddr(str, &ipAddr->ipv4Addr);
   }
   else
#endif
   //Invalid IP address?
   {
      //Report an error
      error = ERROR_FAILURE;
   }

   //Return status code
   return error;
}
//  [c]
error_t ipStringToAddr(const char_t *str, IpAddr *ipAddr)
{
   error_t error;

#if (IPV6_SUPPORT == ENABLED)
   //IPv6 address?
   if(strchr(str, ':'))
   {
      //IPv6 addresses are 16-byte long
      ipAddr->length = sizeof(Ipv6Addr);
      //Convert the string to IPv6 address
      error = ipv6StringToAddr(str, &ipAddr->ipv6Addr);
   }
   else
#endif
#if (IPV4_SUPPORT == ENABLED)
   //IPv4 address?
   if(strchr(str, '.'))
   {
      //IPv4 addresses are 4-byte long
      ipAddr->length = sizeof(Ipv4Addr);
      //Convert the string to IPv4 address
      error = ipv4StringToAddr(str, &ipAddr->ipv4Addr);
   }
   else
#endif
   //Invalid IP address?
   {
      //Report an error
      error = ERROR_FAILURE;
   }

   //Return status code
   return error;
}
//  [c]
static void gf_isom_write_tx3g(GF_Tx3gSampleEntryBox *_a, GF_BitStream *bs, u32 sidx, u32 sidx_offset)
{
	u32 size, j, fount_count;
	const char *qt_fontname = NULL;
	void gpp_write_rgba(GF_BitStream *bs, u32 col);
	void gpp_write_box(GF_BitStream *bs, GF_BoxRecord *rec);
	void gpp_write_style(GF_BitStream *bs, GF_StyleRecord *rec);

	GF_TextSampleEntryBox *qt = (_a->type==GF_ISOM_BOX_TYPE_TEXT) ? (GF_TextSampleEntryBox *)_a : NULL;
	GF_Tx3gSampleEntryBox *ttxt = (_a->type!=GF_ISOM_BOX_TYPE_TEXT) ? (GF_Tx3gSampleEntryBox *)_a : NULL;

	if (sidx_offset) gf_bs_write_u8(bs, sidx + sidx_offset);

	/*SINCE WINCE HAS A READONLY VERSION OF MP4 WE MUST DO IT BY HAND*/
	size = 8 + 18 + 8 + 12;
	size += 8 + 2;
	fount_count = 0;
	if (qt && qt->textName) {
		qt_fontname = qt->textName;
		fount_count = 1;
	} else if (ttxt && ttxt->font_table) {
		fount_count = ttxt->font_table->entry_count;
		for (j=0; j<fount_count; j++) {
			size += 3;
			if (ttxt->font_table->fonts[j].fontName)
				size += (u32) strlen(ttxt->font_table->fonts[j].fontName);
		}
	}
	/*write TextSampleEntry box*/
	gf_bs_write_u32(bs, size);
	gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_TX3G);
	gf_bs_write_data(bs, _a->reserved, 6);
	gf_bs_write_u16(bs, _a->dataReferenceIndex);
	gf_bs_write_u32(bs, _a->displayFlags);
	if (qt) {
		GF_StyleRecord sr;
		memset(&sr, 0, sizeof(GF_StyleRecord));
		gf_bs_write_u8(bs, qt->textJustification);
		gf_bs_write_u8(bs, (u8) -1);
		gpp_write_rgba(bs, rgb_48_to_32(qt->background_color) );
		gpp_write_box(bs, &qt->default_box);
		sr.text_color = rgb_48_to_32(qt->foreground_color);
		sr.style_flags = qt->fontFace;
		gpp_write_style(bs, &sr);
	} else {
		gf_bs_write_u8(bs, ttxt->horizontal_justification);
		gf_bs_write_u8(bs, ttxt->vertical_justification);
		gpp_write_rgba(bs, ttxt->back_color);
		gpp_write_box(bs, &ttxt->default_box);
		gpp_write_style(bs, &ttxt->default_style);
	}
	/*write font table box*/
	size -= (8 + 18 + 8 + 12);
	gf_bs_write_u32(bs, size);
	gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_FTAB);

	gf_bs_write_u16(bs, fount_count);
	for (j=0; j<fount_count; j++) {
		if (qt) {
			gf_bs_write_u16(bs, 0);
			if (qt_fontname) {
				u32 len = (u32) strlen(qt_fontname);
				gf_bs_write_u8(bs, len);
				gf_bs_write_data(bs, qt_fontname, len);
			} else {
				gf_bs_write_u8(bs, 0);
			}
		} else {
			gf_bs_write_u16(bs, ttxt->font_table->fonts[j].fontID);
			if (ttxt->font_table->fonts[j].fontName) {
				u32 len = (u32) strlen(ttxt->font_table->fonts[j].fontName);
				gf_bs_write_u8(bs, len);
				gf_bs_write_data(bs, ttxt->font_table->fonts[j].fontName, len);
			} else {
				gf_bs_write_u8(bs, 0);
			}
		}
	}
}
//  [c]
static void gf_isom_write_tx3g(GF_Tx3gSampleEntryBox *a, GF_BitStream *bs, u32 sidx, u32 sidx_offset)
{
	u32 size, j, fount_count;
	Bool is_qt_text = (a->type==GF_ISOM_BOX_TYPE_TEXT) ? GF_TRUE : GF_FALSE;
	const char *qt_fontname = NULL;
	void gpp_write_rgba(GF_BitStream *bs, u32 col);
	void gpp_write_box(GF_BitStream *bs, GF_BoxRecord *rec);
	void gpp_write_style(GF_BitStream *bs, GF_StyleRecord *rec);


	if (sidx_offset) gf_bs_write_u8(bs, sidx + sidx_offset);

	/*SINCE WINCE HAS A READONLY VERSION OF MP4 WE MUST DO IT BY HAND*/
	size = 8 + 18 + 8 + 12;
	size += 8 + 2;
	fount_count = 0;
	if (is_qt_text) {
		GF_TextSampleEntryBox *qt = (GF_TextSampleEntryBox *)a;
		if (qt->textName) {
			qt_fontname = qt->textName;
			fount_count = 1;
		}
	} else {
		if (a->font_table) {
			fount_count = a->font_table->entry_count;
			for (j=0; j<fount_count; j++) {
				size += 3;
				if (a->font_table->fonts[j].fontName) size += (u32) strlen(a->font_table->fonts[j].fontName);
			}
		}
	}
	/*write TextSampleEntry box*/
	gf_bs_write_u32(bs, size);
	gf_bs_write_u32(bs, a->type);
	gf_bs_write_data(bs, a->reserved, 6);
	gf_bs_write_u16(bs, a->dataReferenceIndex);
	gf_bs_write_u32(bs, a->displayFlags);
	gf_bs_write_u8(bs, a->horizontal_justification);
	gf_bs_write_u8(bs, a->vertical_justification);
	gpp_write_rgba(bs, a->back_color);
	gpp_write_box(bs, &a->default_box);
	gpp_write_style(bs, &a->default_style);
	/*write font table box*/
	size -= (8 + 18 + 8 + 12);
	gf_bs_write_u32(bs, size);
	gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_FTAB);

	gf_bs_write_u16(bs, fount_count);
	for (j=0; j<fount_count; j++) {
		if (is_qt_text) {
			gf_bs_write_u16(bs, 0);
			if (qt_fontname) {
				u32 len = (u32) strlen(qt_fontname);
				gf_bs_write_u8(bs, len);
				gf_bs_write_data(bs, qt_fontname, len);
			} else {
				gf_bs_write_u8(bs, 0);
			}
		} else {
			gf_bs_write_u16(bs, a->font_table->fonts[j].fontID);
			if (a->font_table->fonts[j].fontName) {
				u32 len = (u32) strlen(a->font_table->fonts[j].fontName);
				gf_bs_write_u8(bs, len);
				gf_bs_write_data(bs, a->font_table->fonts[j].fontName, len);
			} else {
				gf_bs_write_u8(bs, 0);
			}
		}
	}
}
//  [c]

static SDL_Surface *Create_Surface_Blended(int width, int height, SDL_Color fg, Uint32 *color)
{
    const int alignment = Get_Alignement() - 1;
    SDL_Surface *textbuf = NULL;
    Uint32 bgcolor;

    /* Background color */
    bgcolor = (fg.r << 16) | (fg.g << 8) | fg.b;

    /* Underline/Strikethrough color style */
    *color = bgcolor | (fg.a << 24);

    /* Create the target surface if required */
    if (width != 0) {
        /* Create a surface with memory:
         * - pitch is rounded to alignment
         * - adress is aligned
         */
        Sint64 size;
        void *pixels, *ptr;
        /* Worse case at the end of line pulling 'alignment' extra blank pixels */
        Sint64 pitch = ((Sint64)width + (Sint64)alignment) * 4;
        pitch += alignment;
        pitch &= ~alignment;
        size = height * pitch + sizeof (void *) + alignment;
        if (size < 0 || size > SDL_MAX_SINT32) {
            /* Overflow... */
            return NULL;
        }

        ptr = SDL_malloc((size_t)size);
        if (ptr == NULL) {
            return NULL;
        }

        /* address is aligned */
        pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
        ((void **)pixels)[-1] = ptr;

        textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_ARGB8888);
        if (textbuf == NULL) {
            SDL_free(ptr);
            return NULL;
        }

        /* Let SDL handle the memory allocation */
        textbuf->flags &= ~SDL_PREALLOC;
        textbuf->flags |= SDL_SIMD_ALIGNED;

        /* Initialize with fg and 0 alpha */
        SDL_memset4(pixels, bgcolor, (height * pitch) / 4);

        /* Support alpha blending */
        if (fg.a != SDL_ALPHA_OPAQUE) {
            SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
        }
    }

    return textbuf;
//  [c]

static SDL_Surface *Create_Surface_Blended(int width, int height, SDL_Color fg, Uint32 *color)
{
    const int alignment = Get_Alignement() - 1;
    SDL_Surface *textbuf = NULL;
    Uint32 bgcolor;

    /* Background color */
    bgcolor = (fg.r << 16) | (fg.g << 8) | fg.b;

    /* Underline/Strikethrough color style */
    *color = bgcolor | (fg.a << 24);

    /* Create the target surface if required */
    if (width != 0) {
        /* Create a surface with memory:
         * - pitch is rounded to alignment
         * - adress is aligned
         */
        Sint64 size;
        void *pixels, *ptr;
        /* Worse case at the end of line pulling 'alignment' extra blank pixels */
        Sint64 pitch = (width + alignment) * 4;
        pitch += alignment;
        pitch &= ~alignment;
        size = height * pitch + sizeof (void *) + alignment;
        if (size < 0 || size > SDL_MAX_SINT32) {
            /* Overflow... */
            return NULL;
        }

        ptr = SDL_malloc((size_t)size);
        if (ptr == NULL) {
            return NULL;
        }

        /* address is aligned */
        pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
        ((void **)pixels)[-1] = ptr;

        textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_ARGB8888);
        if (textbuf == NULL) {
            SDL_free(ptr);
            return NULL;
        }

        /* Let SDL handle the memory allocation */
        textbuf->flags &= ~SDL_PREALLOC;
        textbuf->flags |= SDL_SIMD_ALIGNED;

        /* Initialize with fg and 0 alpha */
        SDL_memset4(pixels, bgcolor, (height * pitch) / 4);

        /* Support alpha blending */
        if (fg.a != SDL_ALPHA_OPAQUE) {
            SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
        }
    }

    return textbuf;
//  [c]
GF_Err gf_isom_get_text_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_TextSampleDescriptor **out_desc)
{
	GF_TrackBox *trak;
	u32 i;
	GF_Tx3gSampleEntryBox *txt = NULL;
	GF_TextSampleEntryBox *qt_txt = NULL;
	if (!descriptionIndex || !out_desc) return GF_BAD_PARAM;

	trak = gf_isom_get_track_from_file(movie, trackNumber);
	if (!trak || !trak->Media) return GF_BAD_PARAM;

	switch (trak->Media->handler->handlerType) {
	case GF_ISOM_MEDIA_TEXT:
	case GF_ISOM_MEDIA_SUBT:
		break;
	default:
		return GF_BAD_PARAM;
	}

	txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex - 1);
	if (!txt) return GF_BAD_PARAM;
	switch (txt->type) {
	case GF_ISOM_BOX_TYPE_TX3G:
		break;
	case GF_ISOM_BOX_TYPE_TEXT:
		qt_txt = (GF_TextSampleEntryBox *)txt;
		txt = NULL;
		break;
	default:
		return GF_BAD_PARAM;
	}

	(*out_desc) = (GF_TextSampleDescriptor *) gf_odf_desc_new(GF_ODF_TX3G_TAG);
	if (! (*out_desc) ) return GF_OUT_OF_MEM;

	if (qt_txt) {
		(*out_desc)->back_color = rgb_48_to_32(qt_txt->background_color);
		(*out_desc)->default_pos = qt_txt->default_box;
		(*out_desc)->default_style.style_flags = qt_txt->fontFace;
		(*out_desc)->default_style.text_color = rgb_48_to_32(qt_txt->foreground_color);
		(*out_desc)->displayFlags = qt_txt->displayFlags;
		(*out_desc)->vert_justif = -1;
		(*out_desc)->horiz_justif = qt_txt->textJustification;
		if (qt_txt->textName) {
			(*out_desc)->font_count = 1;
			(*out_desc)->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord));
			(*out_desc)->fonts[0].fontName = gf_strdup(qt_txt->textName);
		}
	} else {
		(*out_desc)->back_color = txt->back_color;
		(*out_desc)->default_pos = txt->default_box;
		(*out_desc)->default_style = txt->default_style;
		(*out_desc)->displayFlags = txt->displayFlags;
		(*out_desc)->vert_justif = txt->vertical_justification;
		(*out_desc)->horiz_justif = txt->horizontal_justification;
		(*out_desc)->font_count = txt->font_table->entry_count;
		(*out_desc)->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * txt->font_table->entry_count);
		for (i=0; i<txt->font_table->entry_count; i++) {
			(*out_desc)->fonts[i].fontID = txt->font_table->fonts[i].fontID;
			if (txt->font_table->fonts[i].fontName)
				(*out_desc)->fonts[i].fontName = gf_strdup(txt->font_table->fonts[i].fontName);
		}
	}
	return GF_OK;
}
//  [c]
GF_Err gf_isom_get_text_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_TextSampleDescriptor **out_desc)
{
	GF_TrackBox *trak;
	u32 i;
	Bool is_qt_text = GF_FALSE;
	GF_Tx3gSampleEntryBox *txt;

	if (!descriptionIndex || !out_desc) return GF_BAD_PARAM;

	trak = gf_isom_get_track_from_file(movie, trackNumber);
	if (!trak || !trak->Media) return GF_BAD_PARAM;

	switch (trak->Media->handler->handlerType) {
	case GF_ISOM_MEDIA_TEXT:
	case GF_ISOM_MEDIA_SUBT:
		break;
	default:
		return GF_BAD_PARAM;
	}

	txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex - 1);
	if (!txt) return GF_BAD_PARAM;
	switch (txt->type) {
	case GF_ISOM_BOX_TYPE_TX3G:
		break;
	case GF_ISOM_BOX_TYPE_TEXT:
		is_qt_text = GF_TRUE;
		break;
	default:
		return GF_BAD_PARAM;
	}

	(*out_desc) = (GF_TextSampleDescriptor *) gf_odf_desc_new(GF_ODF_TX3G_TAG);
	if (! (*out_desc) ) return GF_OUT_OF_MEM;
	(*out_desc)->back_color = txt->back_color;
	(*out_desc)->default_pos = txt->default_box;
	(*out_desc)->default_style = txt->default_style;
	(*out_desc)->displayFlags = txt->displayFlags;
	(*out_desc)->vert_justif = txt->vertical_justification;
	(*out_desc)->horiz_justif = txt->horizontal_justification;
	if (is_qt_text) {
		GF_TextSampleEntryBox *qt_txt = (GF_TextSampleEntryBox *) txt;
		if (qt_txt->textName) {
			(*out_desc)->font_count = 1;
			(*out_desc)->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord));
			(*out_desc)->fonts[0].fontName = gf_strdup(qt_txt->textName);
		}
	} else {
		(*out_desc)->font_count = txt->font_table->entry_count;
		(*out_desc)->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * txt->font_table->entry_count);
		for (i=0; i<txt->font_table->entry_count; i++) {
			(*out_desc)->fonts[i].fontID = txt->font_table->fonts[i].fontID;
			if (txt->font_table->fonts[i].fontName)
				(*out_desc)->fonts[i].fontName = gf_strdup(txt->font_table->fonts[i].fontName);
		}
	}
	return GF_OK;
}
//  [c]
static inline bool unconditional(const struct ipt_entry *e)
{
	static const struct ipt_ip uncond;

	return e->target_offset == sizeof(struct ipt_entry) &&
	       memcmp(&e->ip, &uncond, sizeof(uncond)) == 0;
#undef FWINV
}
//  [c]
static inline bool unconditional(const struct ipt_ip *ip)
{
	static const struct ipt_ip uncond;

	return memcmp(ip, &uncond, sizeof(uncond)) == 0;
#undef FWINV
}
//  [c]

static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Uint32 *color)
{
    const int alignment = Get_Alignement() - 1;
    SDL_Surface *textbuf;
    Sint64 size;

    /* Create a surface with memory:
     * - pitch is rounded to alignment
     * - adress is aligned
     */
    void *pixels, *ptr;
    /* Worse case at the end of line pulling 'alignment' extra blank pixels */
    Sint64 pitch = (Sint64)width + (Sint64)alignment;
    pitch += alignment;
    pitch &= ~alignment;
    size = height * pitch + sizeof (void *) + alignment;
    if (size < 0 || size > SDL_MAX_SINT32) {
        /* Overflow... */
        return NULL;
    }

    ptr = SDL_malloc((size_t)size);
    if (ptr == NULL) {
        return NULL;
    }

    /* address is aligned */
    pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
    ((void **)pixels)[-1] = ptr;

    textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_INDEX8);
    if (textbuf == NULL) {
        SDL_free(ptr);
        return NULL;
    }

    /* Let SDL handle the memory allocation */
    textbuf->flags &= ~SDL_PREALLOC;
    textbuf->flags |= SDL_SIMD_ALIGNED;

    /* Initialize with background to 0 */
    SDL_memset(pixels, 0, height * pitch);

    /* Underline/Strikethrough color style */
    *color = 1;

    /* Fill the palette: 1 is foreground */
    {
        SDL_Palette *palette = textbuf->format->palette;
        palette->colors[0].r = 255 - fg.r;
        palette->colors[0].g = 255 - fg.g;
        palette->colors[0].b = 255 - fg.b;
        palette->colors[1].r = fg.r;
        palette->colors[1].g = fg.g;
        palette->colors[1].b = fg.b;
        palette->colors[1].a = fg.a;
    }

    SDL_SetColorKey(textbuf, SDL_TRUE, 0);

    return textbuf;
//  [c]

static SDL_Surface* Create_Surface_Solid(int width, int height, SDL_Color fg, Uint32 *color)
{
    const int alignment = Get_Alignement() - 1;
    SDL_Surface *textbuf;
    Sint64 size;

    /* Create a surface with memory:
     * - pitch is rounded to alignment
     * - adress is aligned
     */
    void *pixels, *ptr;
    /* Worse case at the end of line pulling 'alignment' extra blank pixels */
    Sint64 pitch = width + alignment;
    pitch += alignment;
    pitch &= ~alignment;
    size = height * pitch + sizeof (void *) + alignment;
    if (size < 0 || size > SDL_MAX_SINT32) {
        /* Overflow... */
        return NULL;
    }

    ptr = SDL_malloc((size_t)size);
    if (ptr == NULL) {
        return NULL;
    }

    /* address is aligned */
    pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
    ((void **)pixels)[-1] = ptr;

    textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_INDEX8);
    if (textbuf == NULL) {
        SDL_free(ptr);
        return NULL;
    }

    /* Let SDL handle the memory allocation */
    textbuf->flags &= ~SDL_PREALLOC;
    textbuf->flags |= SDL_SIMD_ALIGNED;

    /* Initialize with background to 0 */
    SDL_memset(pixels, 0, height * pitch);

    /* Underline/Strikethrough color style */
    *color = 1;

    /* Fill the palette: 1 is foreground */
    {
        SDL_Palette *palette = textbuf->format->palette;
        palette->colors[0].r = 255 - fg.r;
        palette->colors[0].g = 255 - fg.g;
        palette->colors[0].b = 255 - fg.b;
        palette->colors[1].r = fg.r;
        palette->colors[1].g = fg.g;
        palette->colors[1].b = fg.b;
        palette->colors[1].a = fg.a;
    }

    SDL_SetColorKey(textbuf, SDL_TRUE, 0);

    return textbuf;
//  [c]

static SDL_Surface* Create_Surface_Shaded(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color)
{
    const int alignment = Get_Alignement() - 1;
    SDL_Surface *textbuf;
    Sint64 size;
    Uint8 bg_alpha = bg.a;

    /* Create a surface with memory:
     * - pitch is rounded to alignment
     * - adress is aligned
     */
    void *pixels, *ptr;
    /* Worse case at the end of line pulling 'alignment' extra blank pixels */
    Sint64 pitch = (Sint64)width + (Sint64)alignment;
    pitch += alignment;
    pitch &= ~alignment;
    size = height * pitch + sizeof (void *) + alignment;
    if (size < 0 || size > SDL_MAX_SINT32) {
        /* Overflow... */
        return NULL;
    }

    ptr = SDL_malloc((size_t)size);
    if (ptr == NULL) {
        return NULL;
    }

    /* address is aligned */
    pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
    ((void **)pixels)[-1] = ptr;

    textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_INDEX8);
    if (textbuf == NULL) {
        SDL_free(ptr);
        return NULL;
    }

    /* Let SDL handle the memory allocation */
    textbuf->flags &= ~SDL_PREALLOC;
    textbuf->flags |= SDL_SIMD_ALIGNED;

    /* Initialize with background to 0 */
    SDL_memset(pixels, 0, height * pitch);

    /* Underline/Strikethrough color style */
    *color = NUM_GRAYS - 1;

    /* Support alpha blending */
    if (fg.a != SDL_ALPHA_OPAQUE || bg.a != SDL_ALPHA_OPAQUE) {
        SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);

        /* Would disturb alpha palette */
        if (bg.a == SDL_ALPHA_OPAQUE) {
            bg.a = 0;
        }
    }

    /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
    {
        SDL_Palette *palette = textbuf->format->palette;
        int rdiff  = fg.r - bg.r;
        int gdiff  = fg.g - bg.g;
        int bdiff  = fg.b - bg.b;
        int adiff  = fg.a - bg.a;
        int sign_r = (rdiff >= 0) ? 1 : 255;
        int sign_g = (gdiff >= 0) ? 1 : 255;
        int sign_b = (bdiff >= 0) ? 1 : 255;
        int sign_a = (adiff >= 0) ? 1 : 255;
        int i;

        for (i = 0; i < NUM_GRAYS; ++i) {
            /* Compute color[i] = (i * color_diff / 255) */
            int tmp_r = i * rdiff;
            int tmp_g = i * gdiff;
            int tmp_b = i * bdiff;
            int tmp_a = i * adiff;
            palette->colors[i].r = (Uint8)(bg.r + DIVIDE_BY_255_SIGNED(tmp_r, sign_r));
            palette->colors[i].g = (Uint8)(bg.g + DIVIDE_BY_255_SIGNED(tmp_g, sign_g));
            palette->colors[i].b = (Uint8)(bg.b + DIVIDE_BY_255_SIGNED(tmp_b, sign_b));
            palette->colors[i].a = (Uint8)(bg.a + DIVIDE_BY_255_SIGNED(tmp_a, sign_a));
        }

        /* Make sure background has the correct alpha value */
        palette->colors[0].a = bg_alpha;
    }

    return textbuf;
//  [c]

static SDL_Surface* Create_Surface_Shaded(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color)
{
    const int alignment = Get_Alignement() - 1;
    SDL_Surface *textbuf;
    Sint64 size;
    Uint8 bg_alpha = bg.a;

    /* Create a surface with memory:
     * - pitch is rounded to alignment
     * - adress is aligned
     */
    void *pixels, *ptr;
    /* Worse case at the end of line pulling 'alignment' extra blank pixels */
    Sint64 pitch = width + alignment;
    pitch += alignment;
    pitch &= ~alignment;
    size = height * pitch + sizeof (void *) + alignment;
    if (size < 0 || size > SDL_MAX_SINT32) {
        /* Overflow... */
        return NULL;
    }

    ptr = SDL_malloc((size_t)size);
    if (ptr == NULL) {
        return NULL;
    }

    /* address is aligned */
    pixels = (void *)(((uintptr_t)ptr + sizeof(void *) + alignment) & ~alignment);
    ((void **)pixels)[-1] = ptr;

    textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_INDEX8);
    if (textbuf == NULL) {
        SDL_free(ptr);
        return NULL;
    }

    /* Let SDL handle the memory allocation */
    textbuf->flags &= ~SDL_PREALLOC;
    textbuf->flags |= SDL_SIMD_ALIGNED;

    /* Initialize with background to 0 */
    SDL_memset(pixels, 0, height * pitch);

    /* Underline/Strikethrough color style */
    *color = NUM_GRAYS - 1;

    /* Support alpha blending */
    if (fg.a != SDL_ALPHA_OPAQUE || bg.a != SDL_ALPHA_OPAQUE) {
        SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);

        /* Would disturb alpha palette */
        if (bg.a == SDL_ALPHA_OPAQUE) {
            bg.a = 0;
        }
    }

    /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
    {
        SDL_Palette *palette = textbuf->format->palette;
        int rdiff  = fg.r - bg.r;
        int gdiff  = fg.g - bg.g;
        int bdiff  = fg.b - bg.b;
        int adiff  = fg.a - bg.a;
        int sign_r = (rdiff >= 0) ? 1 : 255;
        int sign_g = (gdiff >= 0) ? 1 : 255;
        int sign_b = (bdiff >= 0) ? 1 : 255;
        int sign_a = (adiff >= 0) ? 1 : 255;
        int i;

        for (i = 0; i < NUM_GRAYS; ++i) {
            /* Compute color[i] = (i * color_diff / 255) */
            int tmp_r = i * rdiff;
            int tmp_g = i * gdiff;
            int tmp_b = i * bdiff;
            int tmp_a = i * adiff;
            palette->colors[i].r = (Uint8)(bg.r + DIVIDE_BY_255_SIGNED(tmp_r, sign_r));
            palette->colors[i].g = (Uint8)(bg.g + DIVIDE_BY_255_SIGNED(tmp_g, sign_g));
            palette->colors[i].b = (Uint8)(bg.b + DIVIDE_BY_255_SIGNED(tmp_b, sign_b));
            palette->colors[i].a = (Uint8)(bg.a + DIVIDE_BY_255_SIGNED(tmp_a, sign_a));
        }

        /* Make sure background has the correct alpha value */
        palette->colors[0].a = bg_alpha;
    }

    return textbuf;
//  [c]
cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs,
    size_t len, const cdf_header_t *h, cdf_secid_t id)
{
	size_t ss = CDF_SHORT_SEC_SIZE(h);
	size_t pos = CDF_SHORT_SEC_POS(h, id);
	assert(ss == len);
	if (pos + len > CDF_SEC_SIZE(h) * sst->sst_len) {
		DPRINTF(("Out of bounds read %" SIZE_T_FORMAT "u > %"
		    SIZE_T_FORMAT "u\n",
		    pos + len, CDF_SEC_SIZE(h) * sst->sst_len));
		return -1;
	}
	(void)memcpy(((char *)buf) + offs,
	    ((const char *)sst->sst_tab) + pos, len);
	return len;
}
//  [c]
void enc28j60EventHandler(NetInterface *interface)
{
   error_t error;
   uint16_t status;
   uint16_t value;

   //Read interrupt status register
   status = enc28j60ReadReg(interface, ENC28J60_EIR);

   //Check whether the link state has changed
   if((status & ENC28J60_EIR_LINKIF) != 0)
   {
      //Clear PHY interrupts flags
      enc28j60ReadPhyReg(interface, ENC28J60_PHIR);
      //Clear interrupt flag
      enc28j60ClearBit(interface, ENC28J60_EIR, ENC28J60_EIR_LINKIF);
      //Read PHY status register
      value = enc28j60ReadPhyReg(interface, ENC28J60_PHSTAT2);

      //Check link state
      if((value & ENC28J60_PHSTAT2_LSTAT) != 0)
      {
         //Link speed
         interface->linkSpeed = NIC_LINK_SPEED_10MBPS;

#if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED)
         //Full-duplex mode
         interface->duplexMode = NIC_FULL_DUPLEX_MODE;
#else
         //Half-duplex mode
         interface->duplexMode = NIC_HALF_DUPLEX_MODE;
#endif
         //Link is up
         interface->linkState = TRUE;
      }
      else
      {
         //Link is down
         interface->linkState = FALSE;
      }

      //Process link state change event
      nicNotifyLinkChange(interface);
   }

   //Check whether a packet has been received?
   if(enc28j60ReadReg(interface, ENC28J60_EPKTCNT) != 0)
   {
      //Clear interrupt flag
      enc28j60ClearBit(interface, ENC28J60_EIR, ENC28J60_EIR_PKTIF);

      //Process all pending packets
      do
      {
         //Read incoming packet
         error = enc28j60ReceivePacket(interface);

         //No more data in the receive buffer?
      } while(error != ERROR_BUFFER_EMPTY);
   }

   //Re-enable LINKIE and PKTIE interrupts
   enc28j60SetBit(interface, ENC28J60_EIE, ENC28J60_EIE_LINKIE |
      ENC28J60_EIE_PKTIE);
}
//  [c]
void enc28j60EventHandler(NetInterface *interface)
{
   error_t error;
   uint16_t status;
   uint16_t value;

   //Read interrupt status register
   status = enc28j60ReadReg(interface, ENC28J60_REG_EIR);

   //Check whether the link state has changed
   if((status & EIR_LINKIF) != 0)
   {
      //Clear PHY interrupts flags
      enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHIR);
      //Clear interrupt flag
      enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_LINKIF);
      //Read PHY status register
      value = enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHSTAT2);

      //Check link state
      if((value & PHSTAT2_LSTAT) != 0)
      {
         //Link speed
         interface->linkSpeed = NIC_LINK_SPEED_10MBPS;

#if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED)
         //Full-duplex mode
         interface->duplexMode = NIC_FULL_DUPLEX_MODE;
#else
         //Half-duplex mode
         interface->duplexMode = NIC_HALF_DUPLEX_MODE;
#endif
         //Link is up
         interface->linkState = TRUE;
      }
      else
      {
         //Link is down
         interface->linkState = FALSE;
      }

      //Process link state change event
      nicNotifyLinkChange(interface);
   }

   //Check whether a packet has been received?
   if((status & EIR_PKTIF) != 0)
   {
      //Clear interrupt flag
      enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_PKTIF);

      //Process all pending packets
      do
      {
         //Read incoming packet
         error = enc28j60ReceivePacket(interface);

         //No more data in the receive buffer?
      } while(error != ERROR_BUFFER_EMPTY);
   }

   //Re-enable LINKIE and PKTIE interrupts
   enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_LINKIE | EIE_PKTIE);
}
//  [c]
njs_module_path(njs_vm_t *vm, const njs_str_t *dir, njs_module_info_t *info)
{
    char        *p;
    size_t      length;
    njs_bool_t  trail;
    char        src[NJS_MAX_PATH + 1];

    trail = 0;
    length = info->name.length;

    if (dir != NULL) {
        length += dir->length;

        if (length == 0) {
            return NJS_DECLINED;
        }

        trail = (dir->start[dir->length - 1] != '/');

        if (trail) {
            length++;
        }
    }

    if (njs_slow_path(length > NJS_MAX_PATH)) {
        return NJS_ERROR;
    }

    p = &src[0];

    if (dir != NULL) {
        p = (char *) njs_cpymem(p, dir->start, dir->length);

        if (trail) {
            *p++ = '/';
        }
    }

    p = (char *) njs_cpymem(p, info->name.start, info->name.length);
    *p = '\0';

    p = realpath(&src[0], &info->path[0]);
    if (p == NULL) {
        return NJS_DECLINED;
    }

    info->fd = open(&info->path[0], O_RDONLY);
    if (info->fd < 0) {
        return NJS_DECLINED;
    }


    info->file.start = (u_char *) &info->path[0];
    info->file.length = njs_strlen(info->file.start);

    return NJS_OK;
}
//  [c]
njs_module_path(njs_vm_t *vm, const njs_str_t *dir, njs_module_info_t *info)
{
    char        *p;
    size_t      length;
    njs_bool_t  trail;
    char        src[NJS_MAX_PATH + 1];

    trail = 0;
    length = info->name.length;

    if (dir != NULL) {
        length = dir->length;

        if (length == 0) {
            return NJS_DECLINED;
        }

        trail = (dir->start[dir->length - 1] != '/');

        if (trail) {
            length++;
        }
    }

    if (njs_slow_path(length > NJS_MAX_PATH)) {
        return NJS_ERROR;
    }

    p = &src[0];

    if (dir != NULL) {
        p = (char *) njs_cpymem(p, dir->start, dir->length);

        if (trail) {
            *p++ = '/';
        }
    }

    p = (char *) njs_cpymem(p, info->name.start, info->name.length);
    *p = '\0';

    p = realpath(&src[0], &info->path[0]);
    if (p == NULL) {
        return NJS_DECLINED;
    }

    info->fd = open(&info->path[0], O_RDONLY);
    if (info->fd < 0) {
        return NJS_DECLINED;
    }


    info->file.start = (u_char *) &info->path[0];
    info->file.length = njs_strlen(info->file.start);

    return NJS_OK;
}
//  [c]
static int get_debug_info(struct PE_(r_bin_pe_obj_t)* bin, PE_(image_debug_directory_entry)* dbg_dir_entry, ut8* dbg_data, int dbg_data_len, SDebugInfo* res) {
	#define SIZEOF_FILE_NAME 255
	int i = 0;
	const char* basename;
	if (!dbg_data) {
		return 0;
	}
	switch (dbg_dir_entry->Type) {
	case IMAGE_DEBUG_TYPE_CODEVIEW:
		if (!strncmp ((char*) dbg_data, "RSDS", 4)) {
			SCV_RSDS_HEADER rsds_hdr;
			init_rsdr_hdr (&rsds_hdr);
			if (!get_rsds (dbg_data, dbg_data_len, &rsds_hdr)) {
				bprintf ("Warning: Cannot read PE debug info\n");
				return 0;
			}
			snprintf (res->guidstr, GUIDSTR_LEN,
				"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x",
				rsds_hdr.guid.data1,
				rsds_hdr.guid.data2,
				rsds_hdr.guid.data3,
				rsds_hdr.guid.data4[0],
				rsds_hdr.guid.data4[1],
				rsds_hdr.guid.data4[2],
				rsds_hdr.guid.data4[3],
				rsds_hdr.guid.data4[4],
				rsds_hdr.guid.data4[5],
				rsds_hdr.guid.data4[6],
				rsds_hdr.guid.data4[7],
				rsds_hdr.age);
			basename = r_file_basename ((char*) rsds_hdr.file_name);
			strncpy (res->file_name, (const char*)
				basename, sizeof (res->file_name));
			res->file_name[sizeof (res->file_name) - 1] = 0;
			rsds_hdr.free ((struct SCV_RSDS_HEADER*) &rsds_hdr);
		} else if (strncmp ((const char*) dbg_data, "NB10", 4) == 0) {
			if (dbg_data_len < 20) {
				eprintf ("Truncated NB10 entry, not enough data to parse\n");
				return 0;
			}
			SCV_NB10_HEADER nb10_hdr = {{0}};
			init_cv_nb10_header (&nb10_hdr);
			get_nb10 (dbg_data, &nb10_hdr);
			snprintf (res->guidstr, sizeof (res->guidstr),
				"%x%x", nb10_hdr.timestamp, nb10_hdr.age);
			res->file_name[0] = 0;
			if (nb10_hdr.file_name) {
				strncpy (res->file_name, (const char*)
						nb10_hdr.file_name, sizeof (res->file_name) - 1);
			}
			res->file_name[sizeof (res->file_name) - 1] = 0;
			nb10_hdr.free ((struct SCV_NB10_HEADER*) &nb10_hdr);
		} else {
			bprintf ("CodeView section not NB10 or RSDS\n");
			return 0;
		}
		break;
	default:
		//bprintf("get_debug_info(): not supported type\n");
		return 0;
	}

	while (i < 33) {
		res->guidstr[i] = toupper ((int) res->guidstr[i]);
		i++;
	}

	return 1;
}
//  [c]
static int get_debug_info(struct PE_(r_bin_pe_obj_t)* bin, PE_(image_debug_directory_entry)* dbg_dir_entry, ut8* dbg_data, int dbg_data_len, SDebugInfo* res) {
	#define SIZEOF_FILE_NAME 255
	int i = 0;
	const char* basename;
	if (!dbg_data) {
		return 0;
	}
	switch (dbg_dir_entry->Type) {
	case IMAGE_DEBUG_TYPE_CODEVIEW:
		if (!strncmp ((char*) dbg_data, "RSDS", 4)) {
			SCV_RSDS_HEADER rsds_hdr;
			init_rsdr_hdr (&rsds_hdr);
			if (!get_rsds (dbg_data, dbg_data_len, &rsds_hdr)) {
				bprintf ("Warning: Cannot read PE debug info\n");
				return 0;
			}
			snprintf (res->guidstr, GUIDSTR_LEN,
				"%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x",
				rsds_hdr.guid.data1,
				rsds_hdr.guid.data2,
				rsds_hdr.guid.data3,
				rsds_hdr.guid.data4[0],
				rsds_hdr.guid.data4[1],
				rsds_hdr.guid.data4[2],
				rsds_hdr.guid.data4[3],
				rsds_hdr.guid.data4[4],
				rsds_hdr.guid.data4[5],
				rsds_hdr.guid.data4[6],
				rsds_hdr.guid.data4[7],
				rsds_hdr.age);
			basename = r_file_basename ((char*) rsds_hdr.file_name);
			strncpy (res->file_name, (const char*)
				basename, sizeof (res->file_name));
			res->file_name[sizeof (res->file_name) - 1] = 0;
			rsds_hdr.free ((struct SCV_RSDS_HEADER*) &rsds_hdr);
		} else if (strncmp ((const char*) dbg_data, "NB10", 4) == 0) {
			SCV_NB10_HEADER nb10_hdr;
			init_cv_nb10_header (&nb10_hdr);
			get_nb10 (dbg_data, &nb10_hdr);
			snprintf (res->guidstr, sizeof (res->guidstr),
				"%x%x", nb10_hdr.timestamp, nb10_hdr.age);
			strncpy (res->file_name, (const char*)
				nb10_hdr.file_name, sizeof(res->file_name) - 1);
			res->file_name[sizeof (res->file_name) - 1] = 0;
			nb10_hdr.free ((struct SCV_NB10_HEADER*) &nb10_hdr);
		} else {
			bprintf ("CodeView section not NB10 or RSDS\n");
			return 0;
		}
		break;
	default:
		//bprintf("get_debug_info(): not supported type\n");
		return 0;
	}

	while (i < 33) {
		res->guidstr[i] = toupper ((int) res->guidstr[i]);
		i++;
	}

	return 1;
}
//  [c]
uint16_t enc28j60ReadPhyReg(NetInterface *interface, uint16_t address)
{
   uint16_t data;

   //Write register address
   enc28j60WriteReg(interface, ENC28J60_MIREGADR, address & REG_ADDR_MASK);

   //Start read operation
   enc28j60WriteReg(interface, ENC28J60_MICMD, ENC28J60_MICMD_MIIRD);
   //Wait for the read operation to complete
   while((enc28j60ReadReg(interface, ENC28J60_MISTAT) & ENC28J60_MISTAT_BUSY) != 0)
   {
   }

   //Clear command register
   enc28j60WriteReg(interface, ENC28J60_MICMD, 0);

   //Read the lower 8 bits
   data = enc28j60ReadReg(interface, ENC28J60_MIRDL);
   //Read the upper 8 bits
   data |= enc28j60ReadReg(interface, ENC28J60_MIRDH) << 8;

   //Return register contents
   return data;
}