Example #1
0
void
po_message_check_all (po_message_t message, po_message_iterator_t iterator,
		      po_xerror_handler_t handler)
{
  message_ty *mp = (message_ty *) message;

  /* Establish error handler.  */
  po_xerror =
    (void (*) (int, const message_ty *, const char *, size_t, size_t, int, const char *))
    handler->xerror;
  po_xerror2 =
    (void (*) (int, const message_ty *, const char *, size_t, size_t, int, const char *, const message_ty *, const char *, size_t, size_t, int, const char *))
    handler->xerror2;

  /* For plural checking, combine the message and its header into a small,
     two-element message list.  */
  {
    message_ty *header;

    /* Find the header.  */
    {
      message_list_ty *mlp;
      size_t j;

      header = NULL;
      mlp =
	msgdomain_list_sublist (iterator->file->mdlp, iterator->domain, false);
      if (mlp != NULL)
	for (j = 0; j < mlp->nitems; j++)
	  if (is_header (mlp->item[j]) && !mlp->item[j]->obsolete)
	    {
	      header = mlp->item[j];
	      break;
	    }
    }

    {
      message_ty *items[2];
      struct message_list_ty ml;
      ml.item = items;
      ml.nitems = 0;
      ml.nitems_max = 2;
      ml.use_hashtable = false;

      if (header != NULL)
	message_list_append (&ml, header);
      if (mp != header)
	message_list_append (&ml, mp);

      check_message_list (&ml, 1, 1, 1, 0, 0, 0);
    }
  }

  /* Restore error handler.  */
  po_xerror  = textmode_xerror;
  po_xerror2 = textmode_xerror2;
}
void
read_resources_file (message_list_ty *mlp, const char *filename)
{
  const char *args[2];
  const char *gettextexedir;
  const char *gettextlibdir;
  char *assembly_path;
  const char *libdirs[1];
  struct locals locals;

  /* Prepare arguments.  */
  args[0] = filename;
  args[1] = NULL;

  /* Make it possible to override the .exe location.  This is
     necessary for running the testsuite before "make install".  */
  gettextexedir = getenv ("GETTEXTCSHARPEXEDIR");
  if (gettextexedir == NULL || gettextexedir[0] == '\0')
    gettextexedir = relocate (LIBDIR "/gettext");

  /* Make it possible to override the .dll location.  This is
     necessary for running the testsuite before "make install".  */
  gettextlibdir = getenv ("GETTEXTCSHARPLIBDIR");
  if (gettextlibdir == NULL || gettextlibdir[0] == '\0')
    gettextlibdir = relocate (LIBDIR);

  /* Dump the resource and retrieve the resulting output.  */
  assembly_path =
    xconcatenated_filename (gettextexedir, "msgunfmt.net", ".exe");
  libdirs[0] = gettextlibdir;
  if (execute_csharp_program (assembly_path, libdirs, 1,
                              args,
                              verbose, false,
                              execute_and_read_po_output, &locals))
    /* An error message should already have been provided.  */
    exit (EXIT_FAILURE);

  /* Add the output to mlp.  */
  {
    message_list_ty *read_mlp = locals.mdlp->item[0]->messages;
    size_t j;

    for (j = 0; j < read_mlp->nitems; j++)
      message_list_append (mlp, read_mlp->item[j]);
  }

  free (assembly_path);
}
message_list_ty *
message_list_copy (message_list_ty *mlp, int copy_level)
{
  message_list_ty *result;
  size_t j;

  result = message_list_alloc (mlp->use_hashtable);
  for (j = 0; j < mlp->nitems; j++)
    {
      message_ty *mp = mlp->item[j];

      message_list_append (result, copy_level ? mp : message_copy (mp));
    }

  return result;
}
Example #4
0
/* Reads an existing .mo file and adds the messages to mlp.  */
void
read_mo_file (message_list_ty *mlp, const char *filename)
{
  FILE *fp;
  struct binary_mo_file bf;
  struct mo_file_header header;
  unsigned int i;
  static lex_pos_ty pos = { __FILE__, __LINE__ };

  if (strcmp (filename, "-") == 0 || strcmp (filename, "/dev/stdin") == 0)
    {
      fp = stdin;
      SET_BINARY (fileno (fp));
    }
  else
    {
      fp = fopen (filename, "rb");
      if (fp == NULL)
	error (EXIT_FAILURE, errno,
	       _("error while opening \"%s\" for reading"), filename);
    }

  /* Read the file contents into memory.  */
  read_binary_mo_file (&bf, fp, filename);

  /* Get a 32-bit number from the file header.  */
# define GET_HEADER_FIELD(field) \
    get_uint32 (&bf, offsetof (struct mo_file_header, field))

  /* We must grope the file to determine which endian it is.
     Perversity of the universe tends towards maximum, so it will
     probably not match the currently executing architecture.  */
  bf.endian = MO_BIG_ENDIAN;
  header.magic = GET_HEADER_FIELD (magic);
  if (header.magic != _MAGIC)
    {
      bf.endian = MO_LITTLE_ENDIAN;
      header.magic = GET_HEADER_FIELD (magic);
      if (header.magic != _MAGIC)
	{
	unrecognised:
	  error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"),
		 filename);
	}
    }

  header.revision = GET_HEADER_FIELD (revision);

  /* We support only the major revisions 0 and 1.  */
  switch (header.revision >> 16)
    {
    case 0:
    case 1:
      /* Fill the header parts that apply to major revisions 0 and 1.  */
      header.nstrings = GET_HEADER_FIELD (nstrings);
      header.orig_tab_offset = GET_HEADER_FIELD (orig_tab_offset);
      header.trans_tab_offset = GET_HEADER_FIELD (trans_tab_offset);
      header.hash_tab_size = GET_HEADER_FIELD (hash_tab_size);
      header.hash_tab_offset = GET_HEADER_FIELD (hash_tab_offset);

      for (i = 0; i < header.nstrings; i++)
	{
	  message_ty *mp;
	  char *msgid;
	  size_t msgid_len;
	  char *msgstr;
	  size_t msgstr_len;

	  /* Read the msgid.  */
	  msgid = get_string (&bf, header.orig_tab_offset + i * 8,
			      &msgid_len);

	  /* Read the msgstr.  */
	  msgstr = get_string (&bf, header.trans_tab_offset + i * 8,
			       &msgstr_len);

	  mp = message_alloc (msgid,
			      (strlen (msgid) + 1 < msgid_len
			       ? msgid + strlen (msgid) + 1
			       : NULL),
			      msgstr, msgstr_len,
			      &pos);
	  message_list_append (mlp, mp);
	}

      switch (header.revision & 0xffff)
	{
	case 0:
	  break;
	case 1:
	default:
	  /* Fill the header parts that apply to minor revision >= 1.  */
	  header.n_sysdep_segments = GET_HEADER_FIELD (n_sysdep_segments);
	  header.sysdep_segments_offset =
	    GET_HEADER_FIELD (sysdep_segments_offset);
	  header.n_sysdep_strings = GET_HEADER_FIELD (n_sysdep_strings);
	  header.orig_sysdep_tab_offset =
	    GET_HEADER_FIELD (orig_sysdep_tab_offset);
	  header.trans_sysdep_tab_offset =
	    GET_HEADER_FIELD (trans_sysdep_tab_offset);

	  for (i = 0; i < header.n_sysdep_strings; i++)
	    {
	      message_ty *mp;
	      char *msgid;
	      size_t msgid_len;
	      char *msgstr;
	      size_t msgstr_len;
	      nls_uint32 offset;

	      /* Read the msgid.  */
	      offset = get_uint32 (&bf, header.orig_sysdep_tab_offset + i * 4);
	      msgid = get_sysdep_string (&bf, offset, &header, &msgid_len);

	      /* Read the msgstr.  */
	      offset = get_uint32 (&bf, header.trans_sysdep_tab_offset + i * 4);
	      msgstr = get_sysdep_string (&bf, offset, &header, &msgstr_len);

	      mp = message_alloc (msgid,
				  (strlen (msgid) + 1 < msgid_len
				   ? msgid + strlen (msgid) + 1
				   : NULL),
				  msgstr, msgstr_len,
				  &pos);
	      message_list_append (mlp, mp);
	    }
	  break;
	}
      break;

    default:
      goto unrecognised;
    }

  if (fp != stdin)
    fclose (fp);
}
/* Reads an existing .mo file and adds the messages to mlp.  */
void
read_mo_file (message_list_ty *mlp, const char *filename)
{
  FILE *fp;
  struct binary_mo_file bf;
  struct mo_file_header header;
  unsigned int i;
  static lex_pos_ty pos = { __FILE__, __LINE__ };

  if (strcmp (filename, "-") == 0 || strcmp (filename, "/dev/stdin") == 0)
    {
      fp = stdin;
      SET_BINARY (fileno (fp));
    }
  else
    {
      fp = fopen (filename, "rb");
      if (fp == NULL)
        error (EXIT_FAILURE, errno,
               _("error while opening \"%s\" for reading"), filename);
    }

  /* Read the file contents into memory.  */
  read_binary_mo_file (&bf, fp, filename);

  /* Get a 32-bit number from the file header.  */
# define GET_HEADER_FIELD(field) \
    get_uint32 (&bf, offsetof (struct mo_file_header, field))

  /* We must grope the file to determine which endian it is.
     Perversity of the universe tends towards maximum, so it will
     probably not match the currently executing architecture.  */
  bf.endian = MO_BIG_ENDIAN;
  header.magic = GET_HEADER_FIELD (magic);
  if (header.magic != _MAGIC)
    {
      bf.endian = MO_LITTLE_ENDIAN;
      header.magic = GET_HEADER_FIELD (magic);
      if (header.magic != _MAGIC)
        {
        unrecognised:
          error (EXIT_FAILURE, 0, _("file \"%s\" is not in GNU .mo format"),
                 filename);
        }
    }

  header.revision = GET_HEADER_FIELD (revision);

  /* We support only the major revisions 0 and 1.  */
  switch (header.revision >> 16)
    {
    case 0:
    case 1:
      /* Fill the header parts that apply to major revisions 0 and 1.  */
      header.nstrings = GET_HEADER_FIELD (nstrings);
      header.orig_tab_offset = GET_HEADER_FIELD (orig_tab_offset);
      header.trans_tab_offset = GET_HEADER_FIELD (trans_tab_offset);
      header.hash_tab_size = GET_HEADER_FIELD (hash_tab_size);
      header.hash_tab_offset = GET_HEADER_FIELD (hash_tab_offset);

      for (i = 0; i < header.nstrings; i++)
        {
          message_ty *mp;
          char *msgctxt;
          char *msgid;
          size_t msgid_len;
          char *separator;
          char *msgstr;
          size_t msgstr_len;

          /* Read the msgctxt and msgid.  */
          msgid = get_string (&bf, header.orig_tab_offset + i * 8,
                              &msgid_len);
          /* Split into msgctxt and msgid.  */
          separator = strchr (msgid, MSGCTXT_SEPARATOR);
          if (separator != NULL)
            {
              /* The part before the MSGCTXT_SEPARATOR is the msgctxt.  */
              *separator = '\0';
              msgctxt = msgid;
              msgid = separator + 1;
              msgid_len -= msgid - msgctxt;
            }
          else
            msgctxt = NULL;

          /* Read the msgstr.  */
          msgstr = get_string (&bf, header.trans_tab_offset + i * 8,
                               &msgstr_len);

          mp = message_alloc (msgctxt,
                              msgid,
                              (strlen (msgid) + 1 < msgid_len
                               ? msgid + strlen (msgid) + 1
                               : NULL),
                              msgstr, msgstr_len,
                              &pos);
          message_list_append (mlp, mp);
        }

      switch (header.revision & 0xffff)
        {
        case 0:
          break;
        case 1:
        default:
          /* Fill the header parts that apply to minor revision >= 1.  */
          header.n_sysdep_segments = GET_HEADER_FIELD (n_sysdep_segments);
          header.sysdep_segments_offset =
            GET_HEADER_FIELD (sysdep_segments_offset);
          header.n_sysdep_strings = GET_HEADER_FIELD (n_sysdep_strings);
          header.orig_sysdep_tab_offset =
            GET_HEADER_FIELD (orig_sysdep_tab_offset);
          header.trans_sysdep_tab_offset =
            GET_HEADER_FIELD (trans_sysdep_tab_offset);

          for (i = 0; i < header.n_sysdep_strings; i++)
            {
              message_ty *mp;
              char *msgctxt;
              char *msgid;
              size_t msgid_len;
              char *separator;
              char *msgstr;
              size_t msgstr_len;
              nls_uint32 offset;
              size_t f;

              /* Read the msgctxt and msgid.  */
              offset = get_uint32 (&bf, header.orig_sysdep_tab_offset + i * 4);
              msgid = get_sysdep_string (&bf, offset, &header, &msgid_len);
              /* Split into msgctxt and msgid.  */
              separator = strchr (msgid, MSGCTXT_SEPARATOR);
              if (separator != NULL)
                {
                  /* The part before the MSGCTXT_SEPARATOR is the msgctxt.  */
                  *separator = '\0';
                  msgctxt = msgid;
                  msgid = separator + 1;
                  msgid_len -= msgid - msgctxt;
                }
              else
                msgctxt = NULL;

              /* Read the msgstr.  */
              offset = get_uint32 (&bf, header.trans_sysdep_tab_offset + i * 4);
              msgstr = get_sysdep_string (&bf, offset, &header, &msgstr_len);

              mp = message_alloc (msgctxt,
                                  msgid,
                                  (strlen (msgid) + 1 < msgid_len
                                   ? msgid + strlen (msgid) + 1
                                   : NULL),
                                  msgstr, msgstr_len,
                                  &pos);

              /* Only messages with c-format or objc-format annotation are
                 recognized as having system-dependent strings by msgfmt.
                 Which one of the two, we don't know.  We have to guess,
                 assuming that c-format is more probable than objc-format and
                 that the .mo was likely produced by "msgfmt -c".  */
              for (f = format_c; ; f = format_objc)
                {
                  bool valid = true;
                  struct formatstring_parser *parser = formatstring_parsers[f];
                  const char *str_end;
                  const char *str;

                  str_end = msgid + msgid_len;
                  for (str = msgid; str < str_end; str += strlen (str) + 1)
                    {
                      char *invalid_reason = NULL;
                      void *descr =
                        parser->parse (str, false, NULL, &invalid_reason);

                      if (descr != NULL)
                        parser->free (descr);
                      else
                        {
                          free (invalid_reason);
                          valid = false;
                          break;
                        }
                    }
                  if (valid)
                    {
                      str_end = msgstr + msgstr_len;
                      for (str = msgstr; str < str_end; str += strlen (str) + 1)
                        {
                          char *invalid_reason = NULL;
                          void *descr =
                            parser->parse (str, true, NULL, &invalid_reason);

                          if (descr != NULL)
                            parser->free (descr);
                          else
                            {
                              free (invalid_reason);
                              valid = false;
                              break;
                            }
                        }
                    }

                  if (valid)
                    {
                      /* Found the most likely among c-format, objc-format.  */
                      mp->is_format[f] = yes;
                      break;
                    }

                  /* Try next f.  */
                  if (f == format_objc)
                    break;
                }

              message_list_append (mlp, mp);
            }
          break;
        }
      break;

    default:
      goto unrecognised;
    }

  if (fp != stdin)
    fclose (fp);
}