Пример #1
0
void
html_ul(struct html_context *html_context, unsigned char *a,
        unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	unsigned char *al;

	/* dump_html_stack(html_context); */
	par_format.list_level++;
	par_format.list_number = 0;
	par_format.flags = P_DISC;

	al = get_attr_val(a, (unsigned char *)"type", html_context->doc_cp);
	if (al) {
		if (!c_strcasecmp((const char *)al, "disc"))
			par_format.flags = P_DISC;
		else if (!c_strcasecmp((const char *)al, "circle"))
			par_format.flags = P_O;
		else if (!c_strcasecmp((const char *)al, "square"))
			par_format.flags = P_SQUARE;
		mem_free(al);
	}
	par_format.leftmargin += 2 + (par_format.list_level > 1);
	if (!html_context->table_level)
		int_upper_bound(&par_format.leftmargin, par_format.width / 2);

	par_format.align = ALIGN_LEFT;
	html_top->type = ELEMENT_DONT_KILL;
}
Пример #2
0
/* Returns the encoding specified by ENCODING, which must be in one of the
   forms described at the top of encoding-guesser.h.  The returned string might
   be ENCODING itself or a suffix of it, or it might be a statically allocated
   string. */
const char *
encoding_guess_parse_encoding (const char *encoding)
{
  if (encoding == NULL
      || !c_strcasecmp (encoding, "auto")
      || !c_strcasecmp (encoding, "auto,locale")
      || !c_strcasecmp (encoding, "locale"))
    return locale_charset ();
  else if (!c_strncasecmp (encoding, "auto,", 5))
    return encoding + 5;
  else
    return encoding;
}
Пример #3
0
void
html_button(struct html_context *html_context, unsigned char *a,
            unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	unsigned char *al;
	struct form_control *fc;
	enum form_type type = FC_SUBMIT;
	int cp = html_context->doc_cp;

	html_focusable(html_context, a);

	al = get_attr_val(a, (unsigned char *)"type", cp);
	if (!al) goto no_type_attr;

	if (!c_strcasecmp((const char *)al, "button")) {
		type = FC_BUTTON;
	} else if (!c_strcasecmp((const char *)al, "reset")) {
		type = FC_RESET;
	} else if (c_strcasecmp((const char *)al, "submit")) {
		/* unknown type */
		mem_free(al);
		return;
	}
	mem_free(al);

no_type_attr:
	fc = init_form_control(type, a, html_context);
	if (!fc) return;

	fc->id = get_attr_val(a, (unsigned char *)"id", cp);
	fc->name = get_attr_val(a, (unsigned char *)"name", cp);
	fc->default_value = get_attr_val(a, (unsigned char *)"value", cp);
	if (!fc->default_value) {
		if (fc->type == FC_SUBMIT)
			fc->default_value = stracpy((const unsigned char *)"Submit");
		else if (fc->type == FC_RESET)
			fc->default_value = stracpy((const unsigned char *)"Reset");
		else if (fc->type == FC_BUTTON)
			fc->default_value = stracpy((const unsigned char *)"Button");
	}
	if (!fc->default_value)
		fc->default_value = stracpy((const unsigned char *)"");

	html_context->special_f(html_context, SP_CONTROL, fc);
	format.form = fc;
	format.style.attr |= AT_BOLD;
}
Пример #4
0
/* Canonicalize an encoding name.  */
const char *
po_charset_canonicalize (const char *charset)
{
  /* The list of charsets supported by glibc's iconv() and by the portable
     iconv() across platforms.  Taken from intl/config.charset.  */
  static const char *standard_charsets[] =
  {
    ascii, "ANSI_X3.4-1968", "US-ASCII",        /* i = 0..2 */
    "ISO-8859-1", "ISO_8859-1",                 /* i = 3, 4 */
    "ISO-8859-2", "ISO_8859-2",
    "ISO-8859-3", "ISO_8859-3",
    "ISO-8859-4", "ISO_8859-4",
    "ISO-8859-5", "ISO_8859-5",
    "ISO-8859-6", "ISO_8859-6",
    "ISO-8859-7", "ISO_8859-7",
    "ISO-8859-8", "ISO_8859-8",
    "ISO-8859-9", "ISO_8859-9",
    "ISO-8859-13", "ISO_8859-13",
    "ISO-8859-14", "ISO_8859-14",
    "ISO-8859-15", "ISO_8859-15",               /* i = 25, 26 */
    "KOI8-R",
    "KOI8-U",
    "KOI8-T",
    "CP850",
    "CP866",
    "CP874",
    "CP932",
    "CP949",
    "CP950",
    "CP1250",
    "CP1251",
    "CP1252",
    "CP1253",
    "CP1254",
    "CP1255",
    "CP1256",
    "CP1257",
    "GB2312",
    "EUC-JP",
    "EUC-KR",
    "EUC-TW",
    "BIG5",
    "BIG5-HKSCS",
    "GBK",
    "GB18030",
    "SHIFT_JIS",
    "JOHAB",
    "TIS-620",
    "VISCII",
    "GEORGIAN-PS",
    utf8
  };
  size_t i;

  for (i = 0; i < SIZEOF (standard_charsets); i++)
    if (c_strcasecmp (charset, standard_charsets[i]) == 0)
      return standard_charsets[i < 3 ? 0 : i < 27 ? ((i - 3) & ~1) + 3 : i];
  return NULL;
}
Пример #5
0
void
html_linebrk(struct html_context *html_context, unsigned char *a,
             unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	unsigned char *al = get_attr_val(a, (unsigned char *)"align", html_context->doc_cp);

	if (al) {
		if (!c_strcasecmp((const char *)al, "left")) par_format.align = ALIGN_LEFT;
		else if (!c_strcasecmp((const char *)al, "right")) par_format.align = ALIGN_RIGHT;
		else if (!c_strcasecmp((const char *)al, "center")) {
			par_format.align = ALIGN_CENTER;
			if (!html_context->table_level)
				par_format.leftmargin = par_format.rightmargin = 0;
		} else if (!c_strcasecmp((const char *)al, "justify")) par_format.align = ALIGN_JUSTIFY;
		mem_free(al);
	}
}
Пример #6
0
static widget_creation_function
find_in_table (const char *type, const widget_creation_entry *table)
{
  const widget_creation_entry* cur;
  for (cur = table; cur->type; cur++)
    if (!c_strcasecmp (type, cur->type))
      return cur->function;
  return NULL;
}
Пример #7
0
/* Parse a link and return results in @link.
 * It tries to identify known types. */
static int
html_link_parse(struct html_context *html_context, unsigned char *a,
                struct hlink *link)
{
	int i;

	assert(a && link);
	memset(link, 0, sizeof(*link));

	link->href = get_url_val(a, (unsigned char *)"href", html_context->doc_cp);
	if (!link->href) return 0;

	link->lang = get_attr_val(a, (unsigned char *)"lang", html_context->doc_cp);
	link->hreflang = get_attr_val(a, (unsigned char *)"hreflang", html_context->doc_cp);
	link->title = get_attr_val(a, (unsigned char *)"title", html_context->doc_cp);
	link->content_type = get_attr_val(a, (unsigned char *)"type", html_context->doc_cp);
	link->media = get_attr_val(a, (unsigned char *)"media", html_context->doc_cp);

	link->name = get_attr_val(a, (unsigned char *)"rel", html_context->doc_cp);
	if (link->name) {
		link->direction = LD_REL;
	} else {
		link->name = get_attr_val(a, (unsigned char *)"rev", html_context->doc_cp);
		if (link->name) link->direction = LD_REV;
	}

	if (!link->name) return 1;

	/* TODO: fastfind */
	for (i = 0; lt_names[i].str; i++)
		if (!c_strcasecmp((const char *)link->name, (const char *)lt_names[i].str)) {
			link->type = lt_names[i].type;
			return 1;
		}

	if (c_strcasestr((const char *)link->name, "icon") ||
	   (link->content_type && c_strcasestr((const char *)link->content_type, "icon"))) {
		link->type = LT_ICON;

	} else if (c_strcasestr((const char *)link->name, "alternate")) {
		link->type = LT_ALTERNATE;
		if (link->lang)
			link->type = LT_ALTERNATE_LANG;
		else if (c_strcasestr((const char *)link->name, "stylesheet") ||
			 (link->content_type && c_strcasestr((const char *)link->content_type, "css")))
			link->type = LT_ALTERNATE_STYLESHEET;
		else if (link->media)
			link->type = LT_ALTERNATE_MEDIA;

	} else if (link->content_type && c_strcasestr((const char *)link->content_type, "css")) {
		link->type = LT_STYLESHEET;
	}

	return 1;
}
Пример #8
0
int
name_to_language(const unsigned char *name)
{
	int i;

	for (i = 0; languages[i].name; i++) {
		if (c_strcasecmp(languages[i].name, name))
			continue;
		return i;
	}
	return 1;
}
Пример #9
0
int
compare_opt(struct document_options *o1, struct document_options *o2)
{
	return memcmp(o1, o2, offsetof(struct document_options, framename))
		|| c_strcasecmp(o1->framename, o2->framename)
		|| (o1->box.x != o2->box.x)
		|| (o1->box.y != o2->box.y)
		|| ((o1->needs_height || o2->needs_height)
		    && o1->box.height != o2->box.height)
		|| ((o1->needs_width || o2->needs_width)
		    && o1->box.width != o2->box.width);
}
Пример #10
0
char *
str_iconveha (const char *src,
              const char *from_codeset, const char *to_codeset,
              bool transliterate,
              enum iconv_ilseq_handler handler)
{
  if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
    {
      char *result = strdup (src);

      if (result == NULL)
        errno = ENOMEM;
      return result;
    }

  /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
     we want to use transliteration.  */
#if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
     && !defined __UCLIBC__) \
    || _LIBICONV_VERSION >= 0x0105
  if (transliterate)
    {
      char *result;
      size_t len = strlen (to_codeset);
      char *to_codeset_suffixed = (char *) malloca (len + 10 + 1);
      memcpy (to_codeset_suffixed, to_codeset, len);
      memcpy (to_codeset_suffixed + len, "//TRANSLIT", 10 + 1);

      result = str_iconveha_notranslit (src, from_codeset, to_codeset_suffixed,
                                        handler);

      freea (to_codeset_suffixed);

      return result;
    }
  else
#endif
    return str_iconveha_notranslit (src, from_codeset, to_codeset, handler);
}
Пример #11
0
/* ToUnicode().  May realloc() utf8in.  Will free utf8in unconditionally. */
static int
idna_to_unicode_internal (char *utf8in,
                          uint32_t * out, size_t * outlen, int flags)
{
    int rc;
    char tmpout[64];
    size_t utf8len = strlen (utf8in) + 1;
    size_t addlen = 0;

    /*
     * ToUnicode consists of the following steps:
     *
     * 1. If the sequence contains any code points outside the ASCII range
     * (0..7F) then proceed to step 2, otherwise skip to step 3.
     */

    {
        size_t i;
        int inasciirange;

        inasciirange = 1;
        for (i = 0; utf8in[i]; i++)
            if (utf8in[i] & ~0x7F)
                inasciirange = 0;
        if (inasciirange)
            goto step3;
    }

    /*
     * 2. Perform the steps specified in [NAMEPREP] and fail if there is an
     * error. (If step 3 of ToASCII is also performed here, it will not
     * affect the overall behavior of ToUnicode, but it is not
     * necessary.) The AllowUnassigned flag is used in [NAMEPREP].
     */
    do
    {
        char *newp = realloc (utf8in, utf8len + addlen);
        if (newp == NULL)
        {
            free (utf8in);
            return IDNA_MALLOC_ERROR;
        }
        utf8in = newp;
        if (flags & IDNA_ALLOW_UNASSIGNED)
            rc = stringprep_nameprep (utf8in, utf8len + addlen);
        else
            rc = stringprep_nameprep_no_unassigned (utf8in, utf8len + addlen);
        addlen += 1;
    }
    while (rc == STRINGPREP_TOO_SMALL_BUFFER);

    if (rc != STRINGPREP_OK)
    {
        free (utf8in);
        return IDNA_STRINGPREP_ERROR;
    }

    /* 3. Verify that the sequence begins with the ACE prefix, and save a
     * copy of the sequence.
     * ... The ToASCII and ToUnicode operations MUST recognize the ACE
     prefix in a case-insensitive manner.
     */

step3:
    if (c_strncasecmp (utf8in, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) != 0)
    {
        free (utf8in);
        return IDNA_NO_ACE_PREFIX;
    }

    /* 4. Remove the ACE prefix.
     */

    memmove (utf8in, &utf8in[strlen (IDNA_ACE_PREFIX)],
             strlen (utf8in) - strlen (IDNA_ACE_PREFIX) + 1);

    /* 5. Decode the sequence using the decoding algorithm in [PUNYCODE]
     * and fail if there is an error. Save a copy of the result of
     * this step.
     */

    (*outlen)--;			/* reserve one for the zero */

    rc = punycode_decode (strlen (utf8in), utf8in, outlen, out, NULL);
    if (rc != PUNYCODE_SUCCESS)
    {
        free (utf8in);
        return IDNA_PUNYCODE_ERROR;
    }

    out[*outlen] = 0;		/* add zero */

    /* 6. Apply ToASCII.
     */

    rc = idna_to_ascii_4i (out, *outlen, tmpout, flags);
    if (rc != IDNA_SUCCESS)
    {
        free (utf8in);
        return rc;
    }

    /* 7. Verify that the result of step 6 matches the saved copy from
     * step 3, using a case-insensitive ASCII comparison.
     */

    if (c_strcasecmp (utf8in, tmpout + strlen (IDNA_ACE_PREFIX)) != 0)
    {
        free (utf8in);
        return IDNA_ROUNDTRIP_VERIFY_ERROR;
    }

    /* 8. Return the saved copy from step 5.
     */

    free (utf8in);
    return IDNA_SUCCESS;
}
Пример #12
0
char *
str_iconv (const char *src, const char *from_codeset, const char *to_codeset)
{
  if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
    {
      char *result = strdup (src);

      if (result == NULL)
	errno = ENOMEM;
      return result;
    }
  else
    {
#if HAVE_ICONV
      iconv_t cd;
      char *result;

      /* Avoid glibc-2.1 bug with EUC-KR.  */
# if (__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) && !defined _LIBICONV_VERSION
      if (c_strcasecmp (from_codeset, "EUC-KR") == 0
	  || c_strcasecmp (to_codeset, "EUC-KR") == 0)
	{
	  errno = EINVAL;
	  return NULL;
	}
# endif
      cd = iconv_open (to_codeset, from_codeset);
      if (cd == (iconv_t) -1)
	return NULL;

      result = str_cd_iconv (src, cd);

      if (result == NULL)
	{
	  /* Close cd, but preserve the errno from str_cd_iconv.  */
	  int saved_errno = errno;
	  iconv_close (cd);
	  errno = saved_errno;
	}
      else
	{
	  if (iconv_close (cd) < 0)
	    {
	      /* Return NULL, but free the allocated memory, and while doing
		 that, preserve the errno from iconv_close.  */
	      int saved_errno = errno;
	      free (result);
	      errno = saved_errno;
	      return NULL;
	    }
	}
      return result;
#else
      /* This is a different error code than if iconv_open existed but didn't
	 support from_codeset and to_codeset, so that the caller can emit
	 an error message such as
	   "iconv() is not supported. Installing GNU libiconv and
	    then reinstalling this package would fix this."  */
      errno = ENOSYS;
      return NULL;
#endif
    }
}
Пример #13
0
static int
cmp_names(const void *item, void *data)
{
    return c_strcasecmp(item, data);
}
Пример #14
0
const char *
proper_name_utf8 (const char *name_ascii, const char *name_utf8)
{
  /* See whether there is a translation.   */
  const char *translation = gettext (name_ascii);

  /* Try to convert NAME_UTF8 to the locale encoding.  */
  const char *locale_code = locale_charset ();
  char *alloc_name_converted = NULL;
  char *alloc_name_converted_translit = NULL;
  const char *name_converted = NULL;
  const char *name_converted_translit = NULL;
  const char *name;

  if (c_strcasecmp (locale_code, "UTF-8") != 0)
    {
#if HAVE_ICONV
      name_converted = alloc_name_converted =
	xstr_iconv (name_utf8, "UTF-8", locale_code);

# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
     || _LIBICONV_VERSION >= 0x0105
      {
	size_t len = strlen (locale_code);
	char *locale_code_translit = (char *) xmalloc (len + 10 + 1);
	memcpy (locale_code_translit, locale_code, len);
	memcpy (locale_code_translit + len, "//TRANSLIT", 10 + 1);

	name_converted_translit = alloc_name_converted_translit =
	  xstr_iconv (name_utf8, "UTF-8", locale_code_translit);

	free (locale_code_translit);
      }
# endif
#endif
    }
  else
    {
      name_converted = name_utf8;
      name_converted_translit = name_utf8;
    }

  /* The name in locale encoding.  */
  name = (name_converted != NULL ? name_converted :
	  name_converted_translit != NULL ? name_converted_translit :
	  name_ascii);

  if (translation != name_ascii)
    {
      /* See whether the translation contains the original name.
	 A multibyte-aware strstr() is not absolutely necessary here.  */
      if (c_strstr (translation, name_ascii) != NULL
	  || (name_converted != NULL
	      && strstr (translation, name_converted) != NULL)
	  || (name_converted_translit != NULL
	      && strstr (translation, name_converted_translit) != NULL))
	{
	  if (alloc_name_converted != NULL)
	    free (alloc_name_converted);
	  if (alloc_name_converted_translit != NULL)
	    free (alloc_name_converted_translit);
	  return translation;
	}
      else
	{
	  /* Return "TRANSLATION (NAME)".  */
	  char *result =
	    (char *) xmalloc (strlen (translation) + 2 + strlen (name) + 1 + 1);

	  sprintf (result, "%s (%s)", translation, name);

	  if (alloc_name_converted != NULL)
	    free (alloc_name_converted);
	  if (alloc_name_converted_translit != NULL)
	    free (alloc_name_converted_translit);
	  return result;
	}
    }
  else
    {
      if (alloc_name_converted != NULL && alloc_name_converted != name)
	free (alloc_name_converted);
      if (alloc_name_converted_translit != NULL
	  && alloc_name_converted_translit != name)
	free (alloc_name_converted_translit);
      return name;
    }
}
Пример #15
0
static bool
is_encoding_utf32 (const char *encoding)
{
  return (!c_strcasecmp (encoding, "utf-32")
          || !c_strcasecmp (encoding, "utf32"));
}
Пример #16
0
int
iconveh_open (const char *to_codeset, const char *from_codeset, iconveh_t *cdp)
{
  iconv_t cd;
  iconv_t cd1;
  iconv_t cd2;

  /* Avoid glibc-2.1 bug with EUC-KR.  */
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
     && !defined _LIBICONV_VERSION
  if (c_strcasecmp (from_codeset, "EUC-KR") == 0
      || c_strcasecmp (to_codeset, "EUC-KR") == 0)
    {
      errno = EINVAL;
      return -1;
    }
# endif

  cd = iconv_open (to_codeset, from_codeset);

  if (STRCASEEQ (from_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
    cd1 = (iconv_t)(-1);
  else
    {
      cd1 = iconv_open ("UTF-8", from_codeset);
      if (cd1 == (iconv_t)(-1))
        {
          int saved_errno = errno;
          if (cd != (iconv_t)(-1))
            iconv_close (cdp->cd);
          errno = saved_errno;
          return -1;
        }
    }

  if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)
# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
      && !defined __UCLIBC__) \
     || _LIBICONV_VERSION >= 0x0105
      || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0
# endif
     )
    cd2 = (iconv_t)(-1);
  else
    {
      cd2 = iconv_open (to_codeset, "UTF-8");
      if (cd2 == (iconv_t)(-1))
        {
          int saved_errno = errno;
          if (cd1 != (iconv_t)(-1))
            iconv_close (cd1);
          if (cd != (iconv_t)(-1))
            iconv_close (cd);
          errno = saved_errno;
          return -1;
        }
    }

  cdp->cd = cd;
  cdp->cd1 = cd1;
  cdp->cd2 = cd2;
  return 0;
}
Пример #17
0
/* Parse all the aggregate functions. */
static bool
parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
			   struct agr_proc *agr)
{
  struct agr_var *tail; /* Tail of linked list starting at agr->vars. */

  /* Parse everything. */
  tail = NULL;
  for (;;)
    {
      char **dest;
      char **dest_label;
      size_t n_dest;
      struct string function_name;

      enum mv_class exclude;
      const struct agr_func *function;
      int func_index;

      union agr_argument arg[2];

      const struct variable **src;
      size_t n_src;

      size_t i;

      dest = NULL;
      dest_label = NULL;
      n_dest = 0;
      src = NULL;
      function = NULL;
      n_src = 0;
      arg[0].c = NULL;
      arg[1].c = NULL;
      ds_init_empty (&function_name);

      /* Parse the list of target variables. */
      while (!lex_match (lexer, T_EQUALS))
	{
	  size_t n_dest_prev = n_dest;

	  if (!parse_DATA_LIST_vars (lexer, dict, &dest, &n_dest,
                                     (PV_APPEND | PV_SINGLE | PV_NO_SCRATCH
                                      | PV_NO_DUPLICATE)))
	    goto error;

	  /* Assign empty labels. */
	  {
	    int j;

	    dest_label = xnrealloc (dest_label, n_dest, sizeof *dest_label);
	    for (j = n_dest_prev; j < n_dest; j++)
	      dest_label[j] = NULL;
	  }



	  if (lex_is_string (lexer))
	    {
	      dest_label[n_dest - 1] = xstrdup (lex_tokcstr (lexer));
	      lex_get (lexer);
	    }
	}

      /* Get the name of the aggregation function. */
      if (lex_token (lexer) != T_ID)
	{
	  lex_error (lexer, _("expecting aggregation function"));
	  goto error;
	}

      ds_assign_substring (&function_name, lex_tokss (lexer));
      exclude = ds_chomp_byte (&function_name, '.') ? MV_SYSTEM : MV_ANY;

      for (function = agr_func_tab; function->name; function++)
	if (!c_strcasecmp (function->name, ds_cstr (&function_name)))
	  break;
      if (NULL == function->name)
	{
	  msg (SE, _("Unknown aggregation function %s."),
	       ds_cstr (&function_name));
	  goto error;
	}
      ds_destroy (&function_name);
      func_index = function - agr_func_tab;
      lex_get (lexer);

      /* Check for leading lparen. */
      if (!lex_match (lexer, T_LPAREN))
	{
	  if (function->src_vars == AGR_SV_YES)
	    {
              lex_force_match (lexer, T_LPAREN);
	      goto error;
	    }
	}
      else
        {
	  /* Parse list of source variables. */
	  {
	    int pv_opts = PV_NO_SCRATCH;

	    if (func_index == SUM || func_index == MEAN || func_index == SD)
	      pv_opts |= PV_NUMERIC;
	    else if (function->n_args)
	      pv_opts |= PV_SAME_TYPE;

	    if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
	      goto error;
	  }

	  /* Parse function arguments, for those functions that
	     require arguments. */
	  if (function->n_args != 0)
	    for (i = 0; i < function->n_args; i++)
	      {
		int type;

		lex_match (lexer, T_COMMA);
		if (lex_is_string (lexer))
		  {
		    arg[i].c = recode_string (dict_get_encoding (agr->dict),
                                              "UTF-8", lex_tokcstr (lexer),
                                              -1);
		    type = VAL_STRING;
		  }
		else if (lex_is_number (lexer))
		  {
		    arg[i].f = lex_tokval (lexer);
		    type = VAL_NUMERIC;
		  }
                else
                  {
		    msg (SE, _("Missing argument %zu to %s."),
                         i + 1, function->name);
		    goto error;
		  }

		lex_get (lexer);

		if (type != var_get_type (src[0]))
		  {
		    msg (SE, _("Arguments to %s must be of same type as "
			       "source variables."),
			 function->name);
		    goto error;
		  }
	      }

	  /* Trailing rparen. */
	  if (!lex_force_match (lexer, T_RPAREN))
            goto error;

	  /* Now check that the number of source variables match
	     the number of target variables.  If we check earlier
	     than this, the user can get very misleading error
	     message, i.e. `AGGREGATE x=SUM(y t).' will get this
	     error message when a proper message would be more
	     like `unknown variable t'. */
	  if (n_src != n_dest)
	    {
	      msg (SE, _("Number of source variables (%zu) does not match "
			 "number of target variables (%zu)."),
		    n_src, n_dest);
	      goto error;
	    }

          if ((func_index == PIN || func_index == POUT
              || func_index == FIN || func_index == FOUT)
              && (var_is_numeric (src[0])
                  ? arg[0].f > arg[1].f
                  : str_compare_rpad (arg[0].c, arg[1].c) > 0))
            {
              union agr_argument t = arg[0];
              arg[0] = arg[1];
              arg[1] = t;

              msg (SW, _("The value arguments passed to the %s function "
                         "are out-of-order.  They will be treated as if "
                         "they had been specified in the correct order."),
                   function->name);
            }
	}

      /* Finally add these to the linked list of aggregation
         variables. */
      for (i = 0; i < n_dest; i++)
	{
	  struct agr_var *v = xzalloc (sizeof *v);

	  /* Add variable to chain. */
	  if (agr->agr_vars != NULL)
	    tail->next = v;
	  else
	    agr->agr_vars = v;
          tail = v;
	  tail->next = NULL;
          v->moments = NULL;

	  /* Create the target variable in the aggregate
             dictionary. */
	  {
	    struct variable *destvar;

	    v->function = func_index;

	    if (src)
	      {
		v->src = src[i];

		if (var_is_alpha (src[i]))
		  {
		    v->function |= FSTRING;
		    v->string = xmalloc (var_get_width (src[i]));
		  }

		if (function->alpha_type == VAL_STRING)
		  destvar = dict_clone_var_as (agr->dict, v->src, dest[i]);
		else
                  {
                    assert (var_is_numeric (v->src)
                            || function->alpha_type == VAL_NUMERIC);
                    destvar = dict_create_var (agr->dict, dest[i], 0);
                    if (destvar != NULL)
                      {
                        struct fmt_spec f;
                        if ((func_index == N || func_index == NMISS)
                            && dict_get_weight (dict) != NULL)
                          f = fmt_for_output (FMT_F, 8, 2);
                        else
                          f = function->format;
                        var_set_both_formats (destvar, &f);
                      }
                  }
	      } else {
                struct fmt_spec f;
		v->src = NULL;
		destvar = dict_create_var (agr->dict, dest[i], 0);
		if (destvar != NULL)
		  {
		    if ((func_index == N || func_index == NMISS)
			&& dict_get_weight (dict) != NULL)
		      f = fmt_for_output (FMT_F, 8, 2);
		    else
		      f = function->format;
		    var_set_both_formats (destvar, &f);
		  }
	    }

	    if (!destvar)
	      {
		msg (SE, _("Variable name %s is not unique within the "
			   "aggregate file dictionary, which contains "
			   "the aggregate variables and the break "
			   "variables."),
		     dest[i]);
		goto error;
	      }

	    free (dest[i]);
	    if (dest_label[i])
              var_set_label (destvar, dest_label[i]);

	    v->dest = destvar;
	  }

	  v->exclude = exclude;

	  if (v->src != NULL)
	    {
	      int j;

	      if (var_is_numeric (v->src))
		for (j = 0; j < function->n_args; j++)
		  v->arg[j].f = arg[j].f;
	      else
		for (j = 0; j < function->n_args; j++)
		  v->arg[j].c = xstrdup (arg[j].c);
	    }
	}

      if (src != NULL && var_is_alpha (src[0]))
	for (i = 0; i < function->n_args; i++)
	  {
	    free (arg[i].c);
	    arg[i].c = NULL;
	  }

      free (src);
      free (dest);
      free (dest_label);

      if (!lex_match (lexer, T_SLASH))
	{
	  if (lex_token (lexer) == T_ENDCMD)
	    return true;

	  lex_error (lexer, "expecting end of command");
	  return false;
	}
      continue;

    error:
      ds_destroy (&function_name);
      for (i = 0; i < n_dest; i++)
	{
	  free (dest[i]);
	  free (dest_label[i]);
	}
      free (dest);
      free (dest_label);
      free (arg[0].c);
      free (arg[1].c);
      if (src && n_src && var_is_alpha (src[0]))
	for (i = 0; i < function->n_args; i++)
	  {
	    free (arg[i].c);
	    arg[i].c = NULL;
	  }
      free (src);

      return false;
    }
}
Пример #18
0
void
html_input(struct html_context *html_context, unsigned char *a,
           unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	unsigned char *al;
	struct form_control *fc;
	int cp = html_context->doc_cp;

	fc = init_form_control(FC_TEXT, a, html_context);
	if (!fc) return;

	al = get_attr_val(a, (unsigned char *)"type", cp);
	if (al) {
		if (!c_strcasecmp((const char *)al, "text")) fc->type = FC_TEXT;
		else if (!c_strcasecmp((const char *)al, "hidden")) fc->type = FC_HIDDEN;
		else if (!c_strcasecmp((const char *)al, "button")) fc->type = FC_BUTTON;
		else if (!c_strcasecmp((const char *)al, "checkbox")) fc->type = FC_CHECKBOX;
		else if (!c_strcasecmp((const char *)al, "radio")) fc->type = FC_RADIO;
		else if (!c_strcasecmp((const char *)al, "password")) fc->type = FC_PASSWORD;
		else if (!c_strcasecmp((const char *)al, "submit")) fc->type = FC_SUBMIT;
		else if (!c_strcasecmp((const char *)al, "reset")) fc->type = FC_RESET;
		else if (!c_strcasecmp((const char *)al, "file")) fc->type = FC_FILE;
		else if (!c_strcasecmp((const char *)al, "image")) fc->type = FC_IMAGE;
		/* else unknown type, let it default to FC_TEXT. */
		mem_free(al);
	}

	if (fc->type == FC_HIDDEN)
		fc->default_value = get_lit_attr_val(a, (unsigned char *)"value", cp);
	else if (fc->type != FC_FILE)
		fc->default_value = get_attr_val(a, (unsigned char *)"value", cp);
	if (!fc->default_value) {
		if (fc->type == FC_CHECKBOX)
			fc->default_value = stracpy((const unsigned char *)"on");
		else if (fc->type == FC_SUBMIT)
			fc->default_value = stracpy((const unsigned char *)"Submit");
		else if (fc->type == FC_RESET)
			fc->default_value = stracpy((const unsigned char *)"Reset");
		else if (fc->type == FC_BUTTON)
			fc->default_value = stracpy((const unsigned char *)"Button");
	}
	if (!fc->default_value)
		fc->default_value = stracpy((const unsigned char *)"");

	fc->id = get_attr_val(a, (unsigned char *)"id", cp);
	fc->name = get_attr_val(a, (unsigned char *)"name", cp);

	fc->size = get_num(a, (unsigned char *)"size", cp);
	if (fc->size == -1)
		fc->size = html_context->options->default_form_input_size;
	fc->size++;
	if (fc->size > html_context->options->box.width)
		fc->size = html_context->options->box.width;
	fc->maxlength = get_num(a, (unsigned char *)"maxlength", cp);
	if (fc->maxlength == -1) fc->maxlength = INT_MAX;
	if (fc->type == FC_CHECKBOX || fc->type == FC_RADIO)
		fc->default_state = has_attr(a, (unsigned char *)"checked", cp);
	if (fc->type == FC_IMAGE)
		fc->alt = get_attr_val(a, (unsigned char *)"alt", cp);

	if (fc->type != FC_HIDDEN) {
		html_input_format(html_context, a, fc);
	}

	html_context->special_f(html_context, SP_CONTROL, fc);
}
Пример #19
0
static int
alias_compare(const struct alias_map *map1, const struct alias_map *map2)
{
	return c_strcasecmp(map1->alias, map2->alias);
}
Пример #20
0
void
html_textarea(struct html_context *html_context, unsigned char *attr,
              unsigned char *html, unsigned char *eof, unsigned char **end)
{
	struct form_control *fc;
	unsigned char *p, *t_name, *wrap_attr;
	int t_namelen;
	int cols, rows;
	int i;

	html_focusable(html_context, attr);
	while (html < eof && (*html == '\n' || *html == '\r')) html++;
	p = html;
	while (p < eof && *p != '<') {

pp:
		p++;
	}
	if (p >= eof) {
		*end = eof;
		return;
	}
	if (parse_element(p, eof, &t_name, &t_namelen, NULL, end)) goto pp;
	if (c_strlcasecmp(t_name, t_namelen, (const unsigned char *)"/TEXTAREA", 9)) goto pp;

	fc = init_form_control(FC_TEXTAREA, attr, html_context);
	if (!fc) return;

	fc->id = get_attr_val(attr, (unsigned char *)"id", html_context->doc_cp);
	fc->name = get_attr_val(attr, (unsigned char *)"name", html_context->doc_cp);
	fc->default_value = convert_string(NULL, html, p - html,
					   html_context->doc_cp,
					   CSM_DEFAULT, NULL, NULL, NULL);
	for (p = fc->default_value; p && p[0]; p++) {
		/* FIXME: We don't cope well with entities here. Bugzilla uses
		 * &#13; inside of textarea and we fail miserably upon that
		 * one.  --pasky */
		if (p[0] == '\r') {
			if (p[1] == '\n'
			    || (p > fc->default_value && p[-1] == '\n')) {
				memmove(p, p + 1, strlen((const char *)p));
				p--;
			} else {
				p[0] = '\n';
			}
		}
	}

	cols = get_num(attr, (unsigned char *)"cols", html_context->doc_cp);
	if (cols <= 0)
		cols = html_context->options->default_form_input_size;
	cols++; /* Add 1 column, other browsers may have different
		   behavior here (mozilla adds 2) --Zas */
	if (cols > html_context->options->box.width)
		cols = html_context->options->box.width;
	fc->cols = cols;

	rows = get_num(attr, (unsigned char *)"rows", html_context->doc_cp);
	if (rows <= 0) rows = 1;
	if (rows > html_context->options->box.height)
		rows = html_context->options->box.height;
	fc->rows = rows;
	html_context->options->needs_height = 1;

	wrap_attr = get_attr_val(attr, (unsigned char *)"wrap", html_context->doc_cp);
	if (wrap_attr) {
		if (!c_strcasecmp((const char *)wrap_attr, "hard")
		    || !c_strcasecmp((const char *)wrap_attr, "physical")) {
			fc->wrap = FORM_WRAP_HARD;
		} else if (!c_strcasecmp((const char *)wrap_attr, "soft")
			   || !c_strcasecmp((const char *)wrap_attr, "virtual")) {
			fc->wrap = FORM_WRAP_SOFT;
		} else if (!c_strcasecmp((const char *)wrap_attr, "none")
			   || !c_strcasecmp((const char *)wrap_attr, "off")) {
			fc->wrap = FORM_WRAP_NONE;
		}
		mem_free(wrap_attr);

	} else if (has_attr(attr, (unsigned char *)"nowrap", html_context->doc_cp)) {
		fc->wrap = FORM_WRAP_NONE;

	} else {
		fc->wrap = FORM_WRAP_SOFT;
	}

	fc->maxlength = get_num(attr, (unsigned char *)"maxlength", html_context->doc_cp);
	if (fc->maxlength == -1) fc->maxlength = INT_MAX;

	if (rows > 1) ln_break(html_context, 1);
	else put_chrs(html_context, (unsigned char *)" ", 1);

	html_stack_dup(html_context, ELEMENT_KILLABLE);
	format.form = fc;
	format.style.attr |= AT_BOLD;

	for (i = 0; i < rows; i++) {
		int j;

		for (j = 0; j < cols; j++)
			put_chrs(html_context, (unsigned char *)"_", 1);
		if (i < rows - 1)
			ln_break(html_context, 1);
	}

	pop_html_element(html_context);
	if (rows > 1)
		ln_break(html_context, 1);
	else
		put_chrs(html_context, (unsigned char *)" ", 1);
	html_context->special_f(html_context, SP_CONTROL, fc);
}
Пример #21
0
void
html_form(struct html_context *html_context, unsigned char *a,
          unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	unsigned char *al;
	struct form *form;

	html_context->was_br = 1;

	form = init_form();
	if (!form) return;

	form->method = FORM_METHOD_GET;
	form->form_num = a - html_context->startf;

	al = get_attr_val(a, (unsigned char *)"method", html_context->doc_cp);
	if (al) {
		if (!c_strcasecmp((const char *)al, "post")) {
			unsigned char *enctype;

			enctype  = get_attr_val(a, (unsigned char *)"enctype",
						html_context->doc_cp);

			form->method = FORM_METHOD_POST;
			if (enctype) {
				if (!c_strcasecmp((const char *)enctype, "multipart/form-data"))
					form->method = FORM_METHOD_POST_MP;
				else if (!c_strcasecmp((const char *)enctype, "text/plain"))
					form->method = FORM_METHOD_POST_TEXT_PLAIN;
				mem_free(enctype);
			}
		}
		mem_free(al);
	}
	form->onsubmit = get_attr_val(a, (unsigned char *)"onsubmit", html_context->doc_cp);
	al = get_attr_val(a, (unsigned char *)"name", html_context->doc_cp);
	if (al) form->name = al;

	al = get_attr_val(a, (unsigned char *)"action", html_context->doc_cp);
	/* The HTML specification at
	 * http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.3 states
	 * that the behavior of an empty action attribute should be undefined.
	 * Mozilla handles action="" as action="<current-URI>" which seems
	 * reasonable. (bug 615) */
	if (al && *al) {
		form->action = join_urls(html_context->base_href, trim_chars(al, ' ', NULL));
		mem_free(al);

	} else {
		enum uri_component components = URI_ORIGINAL;

		mem_free_if(al);

		/* We have to do following for GET method, because we would end
		 * up with two '?' otherwise. */
		if (form->method == FORM_METHOD_GET)
			components = URI_FORM_GET;

		form->action = get_uri_string(html_context->base_href, components);

		/* No action URI should contain post data */
		assert(!form->action || !strchr((char *)form->action, POST_CHAR));

		/* GET method URIs should not have '?'. */
		assert(!form->action
			|| form->method != FORM_METHOD_GET
			|| !strchr((char *)form->action, '?'));
	}

	al = get_target(html_context->options, a);
	form->target = al ? al : stracpy(html_context->base_target);

	html_context->special_f(html_context, SP_FORM, form);
}
Пример #22
0
int
main (int argc, char *argv[])
{
  if (argc > 1)
    {
      /* configure should already have checked that the locale is supported.  */
      if (setlocale (LC_ALL, "") == NULL)
	return 1;
    }

  ASSERT (c_strcasecmp ("paragraph", "Paragraph") == 0);

  ASSERT (c_strcasecmp ("paragrapH", "parAgRaph") == 0);

  ASSERT (c_strcasecmp ("paragraph", "paraLyzed") < 0);
  ASSERT (c_strcasecmp ("paraLyzed", "paragraph") > 0);

  ASSERT (c_strcasecmp ("para", "paragraph") < 0);
  ASSERT (c_strcasecmp ("paragraph", "para") > 0);

  /* The following tests shows how c_strcasecmp() is different from
     strcasecmp().  */

  ASSERT (c_strcasecmp ("\311mile", "\351mile") < 0);
  ASSERT (c_strcasecmp ("\351mile", "\311mile") > 0);

  /* The following tests shows how c_strcasecmp() is different from
     mbscasecmp().  */

  ASSERT (c_strcasecmp ("\303\266zg\303\274r", "\303\226ZG\303\234R") > 0); /* özgür */
  ASSERT (c_strcasecmp ("\303\226ZG\303\234R", "\303\266zg\303\274r") < 0); /* özgür */

  /* This test shows how strings of different size cannot compare equal.  */
  ASSERT (c_strcasecmp ("turkish", "TURK\304\260SH") < 0);
  ASSERT (c_strcasecmp ("TURK\304\260SH", "turkish") > 0);

  return 0;
}
Пример #23
0
void
html_link(struct html_context *html_context, unsigned char *a,
          unsigned char *xxx3, unsigned char *xxx4, unsigned char **xxx5)
{
	int link_display = html_context->options->meta_link_display;
	unsigned char *name;
	struct hlink link;
	struct string text;
	int name_neq_title = 0;
	int first = 1;

#ifndef CONFIG_CSS
	if (!link_display) return;
#endif
	if (!html_link_parse(html_context, a, &link)) return;
	if (!link.href) goto free_and_return;

#ifdef CONFIG_CSS
	if (link.type == LT_STYLESHEET
	    && supports_html_media_attr(link.media)) {
		int len = strlen((const char *)link.href);

		import_css_stylesheet(&html_context->css_styles,
				      html_context->base_href, link.href, len);
	}

	if (!link_display) goto free_and_return;
#endif

	/* Ignore few annoying links.. */
	if (link_display < 5 &&
	    (link.type == LT_ICON ||
	     link.type == LT_AUTHOR ||
	     link.type == LT_STYLESHEET ||
	     link.type == LT_ALTERNATE_STYLESHEET)) goto free_and_return;

	if (!link.name || link.type != LT_UNKNOWN)
		/* Give preference to our default names for known types. */
		name = get_lt_default_name(&link);
	else
		name = link.name;

	if (!name) goto free_and_return;
	if (!init_string(&text)) goto free_and_return;

	html_focusable(html_context, a);

	if (link.title) {
		add_to_string(&text, link.title);
		name_neq_title = strcmp((const char *)link.title, (const char *)name);
	} else
		add_to_string(&text, name);

	if (link_display == 1) goto put_link_line;	/* Only title */

#define APPEND(what) do { \
		add_to_string(&text, first ? (const unsigned char *)" (" : (const unsigned char *)", "); \
		add_to_string(&text, (what)); \
		first = 0; \
	} while (0)

	if (name_neq_title) {
		APPEND(name);
	}

	if (link_display >= 3 && link.hreflang) {
		APPEND(link.hreflang);
	}

	if (link_display >= 4 && link.content_type) {
		APPEND(link.content_type);
	}

	if (link.lang && link.type == LT_ALTERNATE_LANG &&
	    (link_display < 3 || (link.hreflang &&
				  c_strcasecmp((const char *)link.hreflang, (const char *)link.lang)))) {
		APPEND(link.lang);
	}

	if (link.media) {
		APPEND(link.media);
	}

#undef APPEND

	if (!first) add_char_to_string(&text, ')');

put_link_line:
	{
		unsigned char *prefix = (link.direction == LD_REL)
					? (unsigned char *)"Link: " : (unsigned char *)"Reverse link: ";
		unsigned char *link_name = (text.length)
					   ? text.source : name;

		put_link_line(prefix, link_name, link.href,
			      html_context->base_target, html_context);

		if (text.source) done_string(&text);
	}

free_and_return:
	html_link_clear(&link);
}
Пример #24
0
iconv_t
rpl_iconv_open (const char *tocode, const char *fromcode)
#undef iconv_open
{
  char fromcode_upper[32];
  char tocode_upper[32];
  char *fromcode_upper_end;
  char *tocode_upper_end;

#if REPLACE_ICONV_UTF
  /* Special handling of conversion between UTF-8 and UTF-{16,32}{BE,LE}.
     Do this here, before calling the real iconv_open(), because  OSF/1 5.1
     iconv() to these encoding inserts a BOM, which is wrong.
     We do not need to handle conversion between arbitrary encodings and
     UTF-{16,32}{BE,LE}, because the 'striconveh' module implements two-step
     conversion through UTF-8.
     The _ICONV_* constants are chosen to be disjoint from any iconv_t
     returned by the system's iconv_open() functions.  Recall that iconv_t
     is a scalar type.  */
  if (c_toupper (fromcode[0]) == 'U'
      && c_toupper (fromcode[1]) == 'T'
      && c_toupper (fromcode[2]) == 'F'
      && fromcode[3] == '-')
    {
      if (c_toupper (tocode[0]) == 'U'
          && c_toupper (tocode[1]) == 'T'
          && c_toupper (tocode[2]) == 'F'
          && tocode[3] == '-')
        {
          if (strcmp (fromcode + 4, "8") == 0)
            {
              if (c_strcasecmp (tocode + 4, "16BE") == 0)
                return _ICONV_UTF8_UTF16BE;
              if (c_strcasecmp (tocode + 4, "16LE") == 0)
                return _ICONV_UTF8_UTF16LE;
              if (c_strcasecmp (tocode + 4, "32BE") == 0)
                return _ICONV_UTF8_UTF32BE;
              if (c_strcasecmp (tocode + 4, "32LE") == 0)
                return _ICONV_UTF8_UTF32LE;
            }
          else if (strcmp (tocode + 4, "8") == 0)
            {
              if (c_strcasecmp (fromcode + 4, "16BE") == 0)
                return _ICONV_UTF16BE_UTF8;
              if (c_strcasecmp (fromcode + 4, "16LE") == 0)
                return _ICONV_UTF16LE_UTF8;
              if (c_strcasecmp (fromcode + 4, "32BE") == 0)
                return _ICONV_UTF32BE_UTF8;
              if (c_strcasecmp (fromcode + 4, "32LE") == 0)
                return _ICONV_UTF32LE_UTF8;
            }
        }
    }
#endif

  /* Do *not* add special support for 8-bit encodings like ASCII or ISO-8859-1
     here.  This would lead to programs that work in some locales (such as the
     "C" or "en_US" locales) but do not work in East Asian locales.  It is
     better if programmers make their programs depend on GNU libiconv (except
     on glibc systems), e.g. by using the AM_ICONV macro and documenting the
     dependency in an INSTALL or DEPENDENCIES file.  */

  /* Try with the original names first.
     This covers the case when fromcode or tocode is a lowercase encoding name
     that is understood by the system's iconv_open but not listed in our
     mappings table.  */
  {
    iconv_t cd = iconv_open (tocode, fromcode);
    if (cd != (iconv_t)(-1))
      return cd;
  }

  /* Convert the encodings to upper case, because
       1. in the arguments of iconv_open() on AIX, HP-UX, and OSF/1 the case
          matters,
       2. it makes searching in the table faster.  */
  {
    const char *p = fromcode;
    char *q = fromcode_upper;
    while ((*q = c_toupper (*p)) != '\0')
      {
        p++;
        q++;
        if (q == &fromcode_upper[SIZEOF (fromcode_upper)])
          {
            errno = EINVAL;
            return (iconv_t)(-1);
          }
      }
    fromcode_upper_end = q;
  }

  {
    const char *p = tocode;
    char *q = tocode_upper;
    while ((*q = c_toupper (*p)) != '\0')
      {
        p++;
        q++;
        if (q == &tocode_upper[SIZEOF (tocode_upper)])
          {
            errno = EINVAL;
            return (iconv_t)(-1);
          }
      }
    tocode_upper_end = q;
  }

#ifdef ICONV_FLAVOR
  /* Apply the mappings.  */
  {
    const struct mapping *m =
      mapping_lookup (fromcode_upper, fromcode_upper_end - fromcode_upper);

    fromcode = (m != NULL ? m->vendor_name : fromcode_upper);
  }
  {
    const struct mapping *m =
      mapping_lookup (tocode_upper, tocode_upper_end - tocode_upper);

    tocode = (m != NULL ? m->vendor_name : tocode_upper);
  }
#else
  fromcode = fromcode_upper;
  tocode = tocode_upper;
#endif

  return iconv_open (tocode, fromcode);
}
Пример #25
0
void
html_script(struct html_context *html_context, unsigned char *a,
            unsigned char *html, unsigned char *eof, unsigned char **end)
{
#ifdef CONFIG_ECMASCRIPT
	/* TODO: <noscript> processing. Well, same considerations apply as to
	 * CSS property display: none processing. */
	/* TODO: Charsets for external scripts. */
	unsigned char *type, *language, *src;
	int in_comment = 0;
#endif

	html_skip(html_context, a);

#ifdef CONFIG_ECMASCRIPT
	/* We try to process nested <script> if we didn't process the parent
	 * one. That's why's all the fuzz. */
	/* Ref:
	 * http://www.ietf.org/internet-drafts/draft-hoehrmann-script-types-03.txt
	 */
	type = get_attr_val(a, (unsigned char *)"type", html_context->doc_cp);
	if (type) {
		unsigned char *pos = type;

		if (!c_strncasecmp((const char *)type, "text/", 5)) {
			pos += 5;

		} else if (!c_strncasecmp((const char *)type, "application/", 12)) {
			pos += 12;

		} else {
			mem_free(type);
not_processed:
			/* Permit nested scripts and retreat. */
			html_top->invisible++;
			return;
		}

		if (!c_strncasecmp((const char *)pos, "javascript", 10)) {
			int len = strlen((const char *)pos);

			if (len > 10 && !isdigit(pos[10])) {
				mem_free(type);
				goto not_processed;
			}

		} else if (c_strcasecmp((const char *)pos, "ecmascript")
		    && c_strcasecmp((const char *)pos, "jscript")
		    && c_strcasecmp((const char *)pos, "livescript")
		    && c_strcasecmp((const char *)pos, "x-javascript")
		    && c_strcasecmp((const char *)pos, "x-ecmascript")) {
			mem_free(type);
			goto not_processed;
		}

		mem_free(type);
	}

	/* Check that the script content is ecmascript. The value of the
	 * language attribute can be JavaScript with optional version digits
	 * postfixed (like: ``JavaScript1.1'').
	 * That attribute is deprecated in favor of type by HTML 4.01 */
	language = get_attr_val(a, (unsigned char *)"language", html_context->doc_cp);
	if (language) {
		int languagelen = strlen((const char *)language);

		if (languagelen < 10
		    || (languagelen > 10 && !isdigit(language[10]))
		    || c_strncasecmp((const char *)language, "javascript", 10)) {
			mem_free(language);
			html_top->invisible++;
			return;
			//goto not_processed;
		}

		mem_free(language);
	}

	if (html_context->part->document
	    && (src = get_attr_val(a, (unsigned char *)"src", html_context->doc_cp))) {
		/* External reference. */

		unsigned char *import_url;
		struct uri *uri;

		if (!get_opt_bool((const unsigned char *)"ecmascript.enable", NULL)) {
			mem_free(src);
			html_top->invisible++;
			return;
			//goto not_processed;
		}

		/* HTML <head> urls should already be fine but we can.t detect them. */
		import_url = join_urls(html_context->base_href, src);
		mem_free(src);
		if (!import_url) goto imported;

		uri = get_uri(import_url, URI_BASE);
		if (!uri) goto imported;

		/* Request the imported script as part of the document ... */
		html_context->special_f(html_context, SP_SCRIPT, uri);
		done_uri(uri);

		/* Create URL reference onload snippet. */
		insert_in_string(&import_url, 0, (const unsigned char *)"^", 1);
		add_to_string_list(&html_context->part->document->onload_snippets,
		                   import_url, -1);

imported:
		/* Retreat. Do not permit nested scripts, tho'. */
		if (import_url) mem_free(import_url);
		return;
	}

	/* Positive, grab the rest and interpret it. */

	/* First position to the real script start. */
	while (html < eof && *html <= ' ') html++;
	if (eof - html > 4 && !strncmp((const char *)html, "<!--", 4)) {
		in_comment = 1;
		/* We either skip to the end of line or to -->. */
		for (; *html != '\n' && *html != '\r' && eof - html >= 3; html++) {
			if (!strncmp((const char *)html, "-->", 3)) {
				/* This means the document is probably broken.
				 * We will now try to process the rest of
				 * <script> contents, which is however likely
				 * to be empty. Should we try to process the
				 * comment too? Currently it seems safer but
				 * less tolerant to broken pages, if there are
				 * any like this. */
				html += 3;
				in_comment = 0;
				break;
			}
		}
	}

	*end = html;

	/* Now look ahead for the script end. The <script> contents is raw
	 * CDATA, so we just look for the ending tag and need not care for
	 * any quote marks counting etc - YET, we are more tolerant and permit
	 * </script> stuff inside of the script if the whole <script> element
	 * contents is wrapped in a comment. See i.e. Mozilla bug 26857 for fun
	 * reading regarding this. */
	for (; *end < eof; (*end)++) {
		unsigned char *name;
		int namelen;

		if (in_comment) {
			/* TODO: If we ever get some standards-quirk mode
			 * distinction, this should be disabled in the
			 * standards mode (and we should just look for CDATA
			 * end, which is "</"). --pasky */
			if (eof - *end >= 3 && !strncmp((const char *)*end, "-->", 3)) {
				/* Next iteration will jump passed the ending '>' */
				(*end) += 2;
				in_comment = 0;
			}
			continue;
			/* XXX: Scan for another comment? That's admittelly
			 * already stretching things a little bit to an
			 * extreme ;-). */
		}

		if (**end != '<')
			continue;
		/* We want to land before the closing element, that's why we
		 * don't pass @end also as the appropriate parse_element()
		 * argument. */
		if (parse_element(*end, eof, &name, &namelen, NULL, NULL))
			continue;
		if (c_strlcasecmp(name, namelen, (const unsigned char *)"/script", 7))
			continue;
		/* We have won! */
		break;
	}
	if (*end >= eof) {
		/* Either the document is not completely loaded yet or it's
		 * broken. At any rate, run away screaming. */
		*end = eof; /* Just for sanity. */
		return;
	}

	if (html_context->part->document && *html != '^') {
		add_to_string_list(&html_context->part->document->onload_snippets,
		                   html, *end - html);
	}
#endif
}