[Po4a-commits] "po4a/extension/lib/Locale/Po4a Man.xs, NONE, 1.1 Po.h, NONE, 1.1 Po.xs, NONE, 1.1 TransTractor.xs, NONE, 1.1 hash.h, NONE, 1.1 message.h, NONE, 1.1 pos.h, NONE, 1.1 str-list.h, NONE, 1.1"

Nicolas FRANCOIS nekral-guest at alioth.debian.org
Sat Mar 24 13:04:46 CET 2007


Update of /cvsroot/po4a/po4a/extension/lib/Locale/Po4a
In directory alioth:/tmp/cvs-serv14975/extension/lib/Locale/Po4a

Added Files:
	Man.xs Po.h Po.xs TransTractor.xs hash.h message.h pos.h 
	str-list.h 
Log Message:
New C extension. Not built or distributed by default.


--- NEW FILE: pos.h ---
/* Source file positions.
   Copyright (C) 1995-1998, 2000-2001 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _POS_H
#define _POS_H

/* Get size_t.  */
#include <stddef.h>

/* Position of a message within a source file.
   Used for error reporting purposes.  */
typedef struct lex_pos_ty lex_pos_ty;
struct lex_pos_ty
{
  char *file_name;
  size_t line_number;
};

#endif /* _POS_H */

--- NEW FILE: hash.h ---
/* Copyright (C) 1995, 2000-2003, 2005-2006 Free Software Foundation, Inc.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public License as
   published by the Free Software Foundation; either version 2 of the
   License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with the GNU C Library; see the file COPYING.LIB.  If
   not, write to the Free Software Foundation, Inc., 51 Franklin Street,
   Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _HASH_H
#define _HASH_H

#include "obstack.h"

#ifdef __cplusplus
extern "C" {
#endif

struct hash_entry;

typedef struct hash_table
{
  unsigned long int size;   /* Number of allocated entries.  */
  unsigned long int filled; /* Number of used entries.  */
  struct hash_entry *first; /* Pointer to head of list of entries.  */
  struct hash_entry *table; /* Pointer to array of entries.  */
  struct obstack mem_pool;  /* Memory pool holding the keys.  */
}
hash_table;

/* Initialize a hash table.  INIT_SIZE > 1 is the initial number of available
   entries.
   Return 0 upon successful completion, -1 upon memory allocation error.  */
extern int hash_init (hash_table *htab, unsigned long int init_size);

/* Delete a hash table's contents.
   Return 0 always.  */
extern int hash_destroy (hash_table *htab);

/* Look up the value of a key in the given table.
   If found, return 0 and set *RESULT to it.  Otherwise return -1.  */
extern int hash_find_entry (hash_table *htab,
			    const void *key, size_t keylen,
			    void **result);

/* Try to insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table.
   Return non-NULL (more precisely, the address of the KEY inside the table's
   memory pool) if successful, or NULL if there is already an entry with the
   given key.  */
extern const void * hash_insert_entry (hash_table *htab,
				       const void *key, size_t keylen,
				       void *data);

/* Insert the pair (KEY[0..KEYLEN-1], DATA) in the hash table.
   Return 0.  */
extern int hash_set_value (hash_table *htab,
			   const void *key, size_t keylen,
			   void *data);

/* Steps *PTR forward to the next used entry in the given hash table.  *PTR
   should be initially set to NULL.  Store information about the next entry
   in *KEY, *KEYLEN, *DATA.
   Return 0 normally, -1 when the whole hash table has been traversed.  */
extern int hash_iterate (hash_table *htab, void **ptr,
			 const void **key, size_t *keylen,
			 void **data);

/* Steps *PTR forward to the next used entry in the given hash table.  *PTR
   should be initially set to NULL.  Store information about the next entry
   in *KEY, *KEYLEN, *DATAP.  *DATAP is set to point to the storage of the
   value; modifying **DATAP will modify the value of the entry.
   Return 0 normally, -1 when the whole hash table has been traversed.  */
extern int hash_iterate_modify (hash_table *htab, void **ptr,
				const void **key, size_t *keylen,
				void ***datap);

/* Given SEED > 1, return the smallest odd prime number >= SEED.  */
extern unsigned long int next_prime (unsigned long int seed);

#ifdef __cplusplus
}
#endif

#endif /* not _HASH_H */

--- NEW FILE: message.h ---
/* GNU gettext - internationalization aids
   Copyright (C) 1995-1998, 2000-2006 Free Software Foundation, Inc.

   This file was written by Peter Miller <millerp at canb.auug.org.au>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _MESSAGE_H
#define _MESSAGE_H

#include "str-list.h"
#include "pos.h"
#include "hash.h"

#include <stdbool.h>


#ifdef __cplusplus
extern "C" {
#endif


/* According to Sun's Uniforum proposal the default message domain is
   named 'messages'.  */
#define MESSAGE_DOMAIN_DEFAULT "messages"


/* Separator between msgctxt and msgid in .mo files.  */
#define MSGCTXT_SEPARATOR '\004'  /* EOT */


/* Kinds of format strings.  */
enum format_type
{
  format_c,
  format_objc,
  format_sh,
  format_python,
  format_lisp,
  format_elisp,
  format_librep,
  format_scheme,
  format_smalltalk,
  format_java,
  format_csharp,
  format_awk,
  format_pascal,
  format_ycp,
  format_tcl,
  format_perl,
  format_perl_brace,
  format_php,
  format_gcc_internal,
  format_qt,
  format_boost
};
#define NFORMATS 21	/* Number of format_type enum values.  */
//extern DLL_VARIABLE const char *const format_language[NFORMATS];
//extern DLL_VARIABLE const char *const format_language_pretty[NFORMATS];
extern const char *const format_language[NFORMATS];
extern const char *const format_language_pretty[NFORMATS];

/* Is current msgid a format string?  */
enum is_format
{
  undecided,
  yes,
  no,
  yes_according_to_context,
  possible,
  impossible
};

extern bool
       possible_format_p (enum is_format);


/* Is current msgid wrappable?  */
#if 0
enum is_wrap
{
  undecided,
  yes,
  no
};
#else /* HACK - C's enum concept is so stupid */
#define is_wrap is_format
#endif


typedef struct message_ty message_ty;
struct message_ty
{
  /* The msgctxt string, if present.  */
  const char *msgctxt;

  /* The msgid string.  */
  const char *msgid;

  /* The msgid's plural, if present.  */
  const char *msgid_plural;

  /* The msgstr strings.  */
  const char *msgstr;
  /* The number of bytes in msgstr, including the terminating NUL.  */
  size_t msgstr_len;

  /* Position in the source PO file.  */
  lex_pos_ty pos;

  /* Plain comments (#) appearing before the message.  */
  string_list_ty *comment;

  /* Extracted comments (#.) appearing before the message.  */
  string_list_ty *comment_dot;

  /* File position comments (#:) appearing before the message, one for
     each unique file position instance, sorted by file name and then
     by line.  */
  size_t filepos_count;
  lex_pos_ty *filepos;

  /* Informations from special comments (e.g. generated by msgmerge).  */
  bool is_fuzzy;
  enum is_format is_format[NFORMATS];

  /* Do we want the string to be wrapped in the emitted PO file?  */
  enum is_wrap do_wrap;

  /* The prev_msgctxt, prev_msgid and prev_msgid_plural strings appearing
     before the message, if present.  Generated by msgmerge.  */
  const char *prev_msgctxt;
  const char *prev_msgid;
  const char *prev_msgid_plural;

  /* If set the message is obsolete and while writing out it should be
     commented out.  */
  bool obsolete;

  /* Used for checking that messages have been used, in the msgcmp,
     msgmerge, msgcomm and msgcat programs.  */
  int used;

  /* Used for looking up the target message, in the msgcat program.  */
  message_ty *tmp;

  /* Used for combining alternative translations, in the msgcat program.  */
  int alternative_count;
  struct altstr
    {
      const char *msgstr;
      size_t msgstr_len;
      const char *msgstr_end;
      string_list_ty *comment;
      string_list_ty *comment_dot;
      char *id;
    }
    *alternative;
};

extern message_ty *
       message_alloc (const char *msgctxt,
		      const char *msgid, const char *msgid_plural,
		      const char *msgstr, size_t msgstr_len,
		      const lex_pos_ty *pp);
#define is_header(mp) ((mp)->msgctxt == NULL && (mp)->msgid[0] == '\0')
extern void
       message_free (message_ty *mp);
extern void
       message_comment_append (message_ty *mp, const char *comment);
extern void
       message_comment_dot_append (message_ty *mp, const char *comment);
extern void
       message_comment_filepos (message_ty *mp, const char *name, size_t line);
extern message_ty *
       message_copy (message_ty *mp);


typedef struct message_list_ty message_list_ty;
struct message_list_ty
{
  message_ty **item;
  size_t nitems;
  size_t nitems_max;
  bool use_hashtable;
  hash_table htable;	/* Table mapping msgid to 'message_ty *'.  */
};

/* Create a fresh message list.
   If USE_HASHTABLE is true, a hash table will be used to speed up
   message_list_search().  USE_HASHTABLE can only be set to true if it is
   known that the message list will not contain duplicate msgids.  */
extern message_list_ty *
       message_list_alloc (bool use_hashtable);
/* Free a message list.
   If keep_messages = 0, also free the messages.  If keep_messages = 1, don't
   free the messages.  */
extern void
       message_list_free (message_list_ty *mlp, int keep_messages);
extern void
       message_list_append (message_list_ty *mlp, message_ty *mp);
extern void
       message_list_prepend (message_list_ty *mlp, message_ty *mp);
extern void
       message_list_insert_at (message_list_ty *mlp, size_t n, message_ty *mp);
extern void
       message_list_delete_nth (message_list_ty *mlp, size_t n);
typedef bool message_predicate_ty (const message_ty *mp);
extern void
       message_list_remove_if_not (message_list_ty *mlp,
				   message_predicate_ty *predicate);
/* Recompute the hash table of a message list after the msgids or msgctxts
   changed.  */
extern bool
       message_list_msgids_changed (message_list_ty *mlp);
extern message_ty *
       message_list_search (message_list_ty *mlp,
			    const char *msgctxt, const char *msgid);
extern message_ty *
       message_list_search_fuzzy (message_list_ty *mlp,
				  const char *msgctxt, const char *msgid);


typedef struct message_list_list_ty message_list_list_ty;
struct message_list_list_ty
{
  message_list_ty **item;
  size_t nitems;
  size_t nitems_max;
};

extern message_list_list_ty *
       message_list_list_alloc (void);
/* Free a list of message lists.
   If keep_level = 0, also free the messages.  If keep_level = 1, don't free
   the messages but free the lists.  If keep_level = 2, don't free the
   the messages and the lists.  */
extern void
       message_list_list_free (message_list_list_ty *mllp, int keep_level);
extern void
       message_list_list_append (message_list_list_ty *mllp,
				 message_list_ty *mlp);
extern void
       message_list_list_append_list (message_list_list_ty *mllp,
				      message_list_list_ty *mllp2);
extern message_ty *
       message_list_list_search (message_list_list_ty *mllp,
				 const char *msgctxt, const char *msgid);
extern message_ty *
       message_list_list_search_fuzzy (message_list_list_ty *mllp,
				       const char *msgctxt, const char *msgid);


typedef struct msgdomain_ty msgdomain_ty;
struct msgdomain_ty
{
  const char *domain;
  message_list_ty *messages;
};

extern msgdomain_ty *
       msgdomain_alloc (const char *domain, bool use_hashtable);
extern void
       msgdomain_free (msgdomain_ty *mdp);


typedef struct msgdomain_list_ty msgdomain_list_ty;
struct msgdomain_list_ty
{
  msgdomain_ty **item;
  size_t nitems;
  size_t nitems_max;
  bool use_hashtable;
  const char *encoding;		/* canonicalized encoding or NULL if unknown */
};

extern msgdomain_list_ty *
       msgdomain_list_alloc (bool use_hashtable);
extern void
       msgdomain_list_free (msgdomain_list_ty *mdlp);
extern void
       msgdomain_list_append (msgdomain_list_ty *mdlp, msgdomain_ty *mdp);
extern void
       msgdomain_list_append_list (msgdomain_list_ty *mdlp,
				   msgdomain_list_ty *mdlp2);
extern message_list_ty *
       msgdomain_list_sublist (msgdomain_list_ty *mdlp, const char *domain,
			       bool create);
extern message_ty *
       msgdomain_list_search (msgdomain_list_ty *mdlp,
			      const char *msgctxt, const char *msgid);
extern message_ty *
       msgdomain_list_search_fuzzy (msgdomain_list_ty *mdlp,
				    const char *msgctxt, const char *msgid);


/* The goal function used in fuzzy search.
   Higher values indicate a closer match.  */
extern double
       fuzzy_search_goal_function (const message_ty *mp,
				   const char *msgctxt, const char *msgid);

/* The threshold for fuzzy-searching.
   A message is considered only if  fstrcmp (msg, given) > FUZZY_THRESHOLD.  */
#define FUZZY_THRESHOLD 0.6


#ifdef __cplusplus
}
#endif


#endif /* message.h */

--- NEW FILE: Po.xs ---
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

//#include "ppport.h"

//#include "const-c.inc"

#include "Po.h"

Locale_Po4a_Po Po_new(char *class)
{
    struct Po *ret;
    printf("Locale::Po4a::Po::new()\n");

    ret = (struct Po *)safemalloc(sizeof(struct Po));
//    ret->po_file = NULL;
    ret->mlp = NULL;

    return ret;
}

void Po_DESTROY(Locale_Po4a_Po self)
{
    printf("Locale::Po4a::Po::DESTROY\n");
//    if (NULL != self->po_file)
//        po_file_free(self->po_file);
    if (NULL != self->mlp)
        message_list_free(self->mlp, 0);
    safefree(self);
}

void Po_read(Locale_Po4a_Po self, char *filename)
{
    printf("Locale::Po4a::Po::read(%s)\n", filename);
//    self->po_file = po_file_read(filename, &default_xerror_handler);
    po_file_t po_file = po_file_read(filename, &default_xerror_handler);
    self->mlp = message_list_alloc (true);
#if 0
    FILE * fp = fopen(filename, "r");
    extract_po(fp,
               filename, /* real file name */
               filename, /* logical file name */
               NULL,     /* not applicable for PO files */
               self->mdlp);
    if (fp != stdin)
        fclose (fp);
#endif
    if (po_file == NULL)
        croak("Can't open the PO file %s", filename);
    else
    {
        po_message_iterator_t iterator = po_message_iterator (po_file, NULL);
        for (;;)
        {
            po_message_t message = po_next_message (iterator);
            if (message == NULL)
                break;
            else
                message_list_append (self->mlp, (message_ty *)message);
        }
        po_message_iterator_free (iterator);
    }
// No free, otherwise, the messages are freed.
//    po_file_free (po_file);
}

int debug(char *key, int klen)
{
    int ret = 0;

    HV* debug = get_hv("debug", FALSE);
    if (NULL != debug)
    {
        SV **svp = hv_fetch(debug, key, klen, FALSE);
        if (NULL != svp)
        {
            SV *sv = *svp;
            if (0 != SvIV(sv))
                ret = 1;
        }
    }

    return ret;
}

#define KEY(x) x, sizeof(x)-1

char *Po_escape_text(char *text)
{
    char *pc = text;
    unsigned int len = 0;
//    int need_escape = 0;
    char *ret;
    char *pc_ret;
    int debug_escape = debug(KEY("escape"));
    if (debug_escape)
        fprintf(stderr, "\nescape [%s]====", text);
    while (*pc != '\0')
    {
        switch (*pc)
        {
            case '\\':
            case '\"':
            case '\n':
            case '\t':
                len += 2;
//                need_escape = 1;
                break;
            default:
                len++;
        }
        pc++;
    }
//    if (0 == need_escape)
//        return text;

    Newx(ret, len+1, char);
    pc_ret = ret;
    pc = text;
    while (*pc != '\0')
    {
        switch (*pc)
        {
            case '\\':
                *pc_ret++ = '\\';
                *pc_ret++ = '\\';
                break;
            case '"':
                *pc_ret++ = '\\';
                *pc_ret++ = '"';
                break;
            case '\n':
                *pc_ret++ = '\\';
                *pc_ret++ = 'n';
                break;
            case '\t':
                *pc_ret++ = '\\';
                *pc_ret++ = 't';
                break;
            default:
                *pc_ret++ = *pc;
        }
        pc++;
    }
    *pc_ret = '\0';
    if (debug_escape)
        fprintf(stderr, ">%s<\n", ret);
    return ret;
}

char *Po_unescape_text(char *text)
{
    char *ret;
    char *pc = text;
    char *pc_ret;
    int debug_escape = debug(KEY("escape"));
    if (debug_escape)
        fprintf(stderr, "\nunescape [%s]====", text);
    Newx(ret, strlen(text)+1, char);
    pc_ret = ret;
    while (*pc != '\0')
    {
        if (*pc != '\\')
            *pc_ret++ = *pc++;
        else if (*pc == '\n')
            continue;
        else switch (pc[1])
        {
            case '\0':
                *pc_ret++ = *++pc;
                break;
            case 'n':
                *pc_ret++ = '\n';
                pc += 2;
                break;
            case 't':
                *pc_ret++ = '\t';
                pc += 2;
                break;
            case '"':
                *pc_ret++ = '"';
                pc += 2;
                break;
            case '\\':
                *pc_ret++ = '\\';
                pc += 2;
                break;
            default:
                printf("unescape sequence ?: '%c'\n", pc[1]);
        }
    }
    *pc_ret = '\0';

    if (debug_escape)
        fprintf(stderr, ">%s<\n", ret);
    return ret;
}

char *Po_unquote_text(char *text)
{
    char *ret;
    char *pc = text;
    char *pc_ret;
    int debug_quote = debug(KEY("quote"));
    if (debug_quote)
        fprintf(stderr, "\nunquote [%s]====\n", text);
    Newx(ret, strlen(text)+1, char);
    pc_ret = ret;
    if (pc[0] == '"' && pc[1] == '"' && pc[2] == '\n')
	pc += 3;
    if (pc[0] == '"')
	pc++;
    while (*pc != '\0')
    {
	if (pc[0] == '"' && pc[1] == '\0')
	    pc++;
	else if (pc[0] == '"' && pc[1] == '\n' && pc[2] == '"')
	    pc += 3;
	else if (pc[0] == '\\' && pc[1] == 'n' && pc[2] == '\n')
	{
	    *pc_ret++ = '\\';
	    *pc_ret++ = 'n';
	    pc += 3;
	}
	else
	{
	    *pc_ret++ = *pc++;
	}
    }
    *pc_ret = '\0';

    if (debug_quote)
        fprintf(stderr, ">%s<\n", ret);
    return ret;
}

char *Po_canonize(char *text)
{
    char *ret;
    char *pc = text;
    char *pc_ret;
    int len = strlen(text)+1;
    int debug_canonize = debug(KEY("canonize"));
    if (debug_canonize)
        fprintf(stderr, "\ncanonize [%s]====\n", text);
while(*pc != '\0')
{
    if (*pc == '.' || *pc == '(')
        len++;
    pc++;
}
pc = text;
Newx(ret, len, char);
pc_ret = ret;
    while (*pc == ' ')
        pc++;
/*
    if (*pc == '\t')
    {
        *pc_ret++ = ' ';
        *pc_ret++ = ' ';
        while (*pc == ' ' || *pc == '\t')
            pc++;
    }
*/
    while (*pc != '\0')
    {
        if (pc_ret != ret)
        {
            /* already one char in ret */
            if (pc[0] == '\n')
            {
                if (pc_ret[-1] == ')' || pc_ret[-1] == '.')
                {
                    *pc_ret++ = ' ';
                    *pc_ret++ = ' ';
                }
                else if (pc_ret[-1] != ' ' || pc_ret[-2] == ')' || pc_ret[-2] == '.')
                {
                    *pc_ret++ = ' ';
                }
                pc++;
            }
            else if (pc[0] == ' '/* || pc[0] == '\t'*/)
            {
                if (pc_ret[-1] == ' ')
                {
                    if (pc_ret >= ret+2 && (pc_ret[-2] == ')' || pc_ret[-2] == '.'))
                    {
                        *pc_ret++ = ' ';
                    }
                }
                else
                {
                    *pc_ret++ = ' ';
                }
                pc++;
            }
            else
                *pc_ret++ = *pc++;
        }
        else
            *pc_ret++ = *pc++;
    }

    do
    {
        *pc_ret-- = '\0';
    }
    while (*pc_ret == ' ');

    if (debug_canonize)
        fprintf(stderr, ">%s<\n", ret);
    return ret;
}

/*
char *quote_text(char *text)
{
    char *ret;
    int debug_escape = debug(KEY("escape"));
    if (debug_escape)
        fprintf(stderr, "\nquote [%s]====", text);

    if (debug_escape)
        fprintf(stderr, ">%s<\n", ret);
    return ret;
}
*/
char *Po_get_charset(SV* self)
{
    char *ret;
    char *header;
    STRLEN headerlen;
    SV* self_sv;
    SV** psv;
    SV* string;
    STRLEN header_len;
    if(!SvOK(self) || !SvROK(self)) goto error;
    self_sv = SvRV(self);
    if(SvTYPE(self_sv) != SVt_PVHV) goto error;
    psv = hv_fetch((HV *)self_sv, "header", 6, 0);
    if(psv == NULL) goto error;
    string = *psv;
//fprintf(stderr, "get_charset3 %p %s\n", string, SvPV_nolen(string));
    if(!SvPOK(string)) goto error;
//fprintf(stderr, "get_charset4\n");
    header = SvPV(string, headerlen);
    char *charset = strstr(header, "charset=");
    if (NULL == charset)
    {
        fprintf(stderr, "no charset found\n");
        ret = strdup("");
    }
    else
    {
        charset += 8; /* remove "charset=" */
        char *pc = charset;
        while (   pc < header + headerlen
               && *pc != ' '
               && *pc != '\t'
               && *pc != '\n'
               && *pc != '\\')
        {
            pc++;
        }
        Newx(ret, pc - charset+1, char);
        memcpy(ret, charset, pc - charset);
        ret[pc - charset] = '\0';
    }


    return ret;
error:
    croak("can't extract charset.");
}

/*
self new(this, options)
char *timezone()
initialize(self,options)
read(self, filename)
write(self, filename)
write_if_needed(self, filename)
move_po_if_needed(new_po, old_po, backup)
gettextize(this, class)
filter(self, filter)
to_utf8(self)
gettext(self, text, options)
stats_get(self)
stats_clear(self)
push(self, entry)
push_raw(self, entry)
int count_enties(self)
int count_entries_doc(self)
char *msgid(self, num)
char *msgid_doc(self, num)
set_charset(self, charset)
char *quote_text(string)
char *wrap(text)
char *format_comment(comment, c)
*/
MODULE = Locale::Po4a::Po		PACKAGE = Locale::Po4a::Po		PREFIX = Po_

char *
Po_escape_text(text)
	char *		text

char *
Po_unescape_text(text)
	char *		text

char *
Po_get_charset(self)
	SV *		self

char *
Po_unquote_text(text)
	char *		text

char *
Po_canonize(text)
	char *		text

Locale_Po4a_Po
Po_new(class)
	char *		class

void
Po_DESTROY(self)
	Locale_Po4a_Po	self

void 
Po_read(self, filename)
	Locale_Po4a_Po	self
	char *		filename

void
Po_push(self, ...)
	Locale_Po4a_Po	self
CODE:
    char *msgid     = NULL;
    char *msgstr    = NULL;
    char *reference = NULL;
    char *comment   = NULL;
    char *automatic = NULL;
    char *flags     = NULL;
    char *type      = NULL;
    int i = items;

    printf("Locale::Po4a::Po::push()\n");

    if ((items % 2) == 0)
        croak("Usage: Locale::Po4a::Po::push(self, k => v, ...)\n");

    for (i=1; i<items; i+=2)
    {
        char *key = SvPV_nolen(ST(i));
        if (strEQ(key, "msgid"))
            msgid     = SvPV_nolen(ST(i+1));
        else if (strEQ(key, "msgstr"))
            msgstr    = SvPV_nolen(ST(i+1));
        else if (strEQ(key, "reference"))
            reference = SvPV_nolen(ST(i+1));
        else if (strEQ(key, "comment"))
            comment   = SvPV_nolen(ST(i+1));
        else if (strEQ(key, "automatic"))
            automatic = SvPV_nolen(ST(i+1));
        else if (strEQ(key, "flags"))
            flags     = SvPV_nolen(ST(i+1));
        else if (strEQ(key, "type"))
            type      = SvPV_nolen(ST(i+1));
        else
            croak("Unknown key found in Locale::Po4a::Po::push: %s\n",
                  SvPV_nolen(ST(i)));
    }
    /* message_list_search, message_list_append, message_alloc */

    message_ty *mp1 = message_list_search(self->mlp, NULL, msgid);
    printf("push search: %p\n", mp1);
    lex_pos_ty pos = { "file", 0 /*line*/};
    message_ty *mp2 = message_alloc(NULL, /* msgctxt */
                                   msgid,
                                   NULL, /* No plural */
                                   msgstr,
                                   strlen (msgstr) + 1,
                                   &pos);

    if (NULL == mp1)
    {
        message_list_append(self->mlp, mp2);
    }
    else
    {
        if (!strEQ(msgstr, mp1->msgstr))
            printf("duplicate: msgid: \"%s\", msgstr: \"%s\"/\"%s\"\n",
                   msgid, msgstr, mp1->msgstr);
    }


--- NEW FILE: str-list.h ---
/* GNU gettext - internationalization aids
   Copyright (C) 1995-1996, 1998, 2000-2004 Free Software Foundation, Inc.

   This file was written by Peter Miller <millerp at canb.auug.org.au>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _STR_LIST_H
#define _STR_LIST_H 1

/* Get size_t and NULL.  */
#include <stddef.h>

/* Get bool.  */
#include <stdbool.h>


#ifdef __cplusplus
extern "C" {
#endif


/* Type describing list of immutable strings,
   implemented using a dynamic array.  */
typedef struct string_list_ty string_list_ty;
struct string_list_ty
{
  const char **item;
  size_t nitems;
  size_t nitems_max;
};

/* Initialize an empty list of strings.  */
extern void string_list_init (string_list_ty *slp);

/* Return a fresh, empty list of strings.  */
extern string_list_ty *string_list_alloc (void);

/* Append a single string to the end of a list of strings.  */
extern void string_list_append (string_list_ty *slp, const char *s);

/* Append a single string to the end of a list of strings, unless it is
   already contained in the list.  */
extern void string_list_append_unique (string_list_ty *slp, const char *s);

/* Destroy a list of strings.  */
extern void string_list_destroy (string_list_ty *slp);

/* Free a list of strings.  */
extern void string_list_free (string_list_ty *slp);

/* Return a freshly allocated string obtained by concatenating all the
   strings in the list.  */
extern char *string_list_concat (const string_list_ty *slp);

/* Return a freshly allocated string obtained by concatenating all the
   strings in the list, and destroy the list.  */
extern char *string_list_concat_destroy (string_list_ty *slp);

/* Return a freshly allocated string obtained by concatenating all the
   strings in the list, separated by the separator character, terminated
   by the terminator character.  The terminator character is not added if
   drop_redundant_terminator is true and the last string already ends with
   the terminator. */
extern char *string_list_join (const string_list_ty *slp, char separator,
			       char terminator, bool drop_redundant_terminator);

/* Return 1 if s is contained in the list of strings, 0 otherwise.  */
extern bool string_list_member (const string_list_ty *slp, const char *s);


#ifdef __cplusplus
}
#endif


#endif /* _STR_LIST_H */

--- NEW FILE: Man.xs ---
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

//#include "ppport.h"

//#include "const-c.inc"


static char *current_font = NULL;
static char *previous_font = NULL;
static char *regular_font = NULL;
void set_font(char *font)
{
//    fprintf(stderr, "   set_font(%s)\n", font);
    char *saved_previous;
    if (current_font == NULL)
        current_font = strdup("R");
    if (previous_font == NULL)
        previous_font = strdup("R");
    saved_previous = previous_font;
    previous_font = strdup(current_font);

    if (font[0] == '\0')
    {
        free(current_font);
        current_font = strdup("R");
    }
    else if (0 == strcmp(font, "P") ||
             0 == strcmp(font, "[]") ||
             0 == strcmp(font, "[P]"))
    {
        free(current_font);
        current_font = strdup(saved_previous);
    }
    else if (strlen(font) == 1)
    {
        free(current_font);
        current_font = strdup(font);
    }
    else if (strlen(font) == 2)
    {
        free(current_font);
        current_font = malloc(4);
        current_font[0] = '(';
        current_font[1] = font[0];
        current_font[2] = font[1];
        current_font[3] = '\0';
    }
    else
    {
        fprintf(stderr, "not implemented");
    }
//        fprintf(stderr, "my set_font => r:'%s', p:'%s', c:'%s'\n", regular_font, previous_font, current_font);
    free(saved_previous);
//    fprintf(stderr, "   end set_font()\n");
}
void set_regular(char *font)
{
//    fprintf(stderr, "   set_regular(%s)\n", font);
    set_font(font);
    free(regular_font);
    regular_font = strdup(current_font);
//    fprintf(stderr, "   end set_regular()\n");
}

char *do_fonts(char *string, char *ref)
{
//    fprintf(stderr, "do_fonts(%s)\n", string);
    char *tmp;
    char *pc = string;
    char *pc_tmp;
    char previous[10];
    char current[10];
    char new[10];
    char last[10];
    if (current_font == NULL)
        current_font = strdup("R");
    if (previous_font == NULL)
        previous_font = strdup("R");
    if (regular_font == NULL)
        regular_font = strdup("R");
    last[0] = '\0';
    Newx(tmp, strlen(string)*2, char);
    pc_tmp = tmp;
    strcpy(previous, previous_font);
    strcpy(current, current_font);
    if (strcmp(regular_font, current_font) != 0)
        strcpy(new, current_font);
    else
        new[0] = '\0';

    while (*pc != '\0')
    {
        if (pc[0] == 'E' && pc[1] == '<' && pc[2] == '.')
        {
            if (new[0] != '\0')
            {
                char *pc_new = new;
                while (*pc_new != '\0')
                    *pc_tmp++ = *pc_new++;
                *pc_tmp++ = '<';
                new[0] = '\0';
            }

            pc_tmp[0] = pc[0];
            pc_tmp[1] = pc[1];
            pc_tmp[2] = pc[2];
            pc_tmp+=3;
            pc+=3;

            int count = 0;
            while (*pc !='>' || count != 0)
            {
                if (*pc == '<')
                    count++;
                if (*pc == '>')
                    count--;
                *pc_tmp++ = *pc++;
            }
        }
        else if (pc[0] == '\\' && pc[1] == 'f')
        {
            /* We found a font modifier */
            char f[10];
            pc += 2;

            /* Extract the font */
            if (*pc == '[')
            {
                char *pc_f = f;
                pc++;
                while(*pc != ']' && (pc_f - f < 10))
                    *pc_f++ = *pc++;
                if (*pc != ']')
                    die("font too long: '%s%s'\n", f, pc);
                pc++;
                *pc_f = '\0';
            }
            else if (*pc == '(')
            {
                pc++;
                f[0] = *pc++;
                f[1] = *pc++;
                f[2] = '\0';
            }
            else
            {
                f[0] = *pc++;
                f[1] = '\0';
            }
//            fprintf(stderr, "found font: '%s'\n", f);

            /* Canonize the font */
            if (f[1] == '\0')
            {
                if (f[0] == '\0' || f[0] == 'P')
                {
                    strcpy(f,previous);
                }
                else if (f[0] == '1')
                    f[0] = 'R';
                else if (f[0] == '2')
                    f[0] = 'I';
                else if (f[0] == '3')
                    f[0] = 'B';
                else if (f[0] == '3')
                {
                    f[0] = 'B';
                    f[1] = 'I';
                    f[2] = '\0';
                }
            }

//            fprintf(stderr, "found font: '%s'\n", f);
            /*
            if ((pc[0] == 'P' && pc++) ||
                (pc[0] == '[' && pc[1] == ']' && (pc = pc + 2)) ||
                (pc[0] == '[' && pc[1] == 'P' && pc[2] == ']' && (pc = pc +3)))
            {
                if (0 == strcmp(previous, regular_font))
                {
                    strcpy(previous, current);
                    new[0] = '>';
                    new[1] = '\0';
                    strcpy(current, regular_font);
                }
                else
                {
                    strcpy(new, previous);
                    strcpy(previous, current);
                    strcpy(current, new);
                }
            }
            else */

            if (0 == strcmp(f, regular_font))
            {
//                printf("     regular\n");
                strcpy(previous, current);
//                if (0 != strcmp(current, regular_font))
//                {
                    new[0] = '>';
                    new[1] = '\0';
                    strcpy(current, regular_font);
//                }
            }
            else// if (pc[1] pc[0] == 'B' || pc[0] == 'I' || pc[0] == 'R')
            {
                strcpy(previous, current);
                strcpy(current, f);
                strcpy(new, current);
            }/*
            else
            {
                fprintf(stderr, "unrecognized font: '%s'\n", pc);
            }*/
        }
        else
        {
//            printf("%p %p\n", pc_tmp, pc);
            if (new[0] != '\0')
            {
                char *pc_new = new;
                if (strcmp(new, last) != 0 && last[0] != '\0')
                    *pc_tmp++ = '>';
                if (new[0] != '>')
                {
                    if (strcmp(new, last) != 0)
                    {
                    while (*pc_new != '\0')
                        *pc_tmp++ = *pc_new++;
                    *pc_tmp++ = '<';
                    strcpy(last, new);
                    }
                }
                else
                    last[0] = '\0';
                new[0] = '\0';
            }

            *pc_tmp++ = *pc++;
        }
    }
    if (last[0] != '\0')
    {
        if (pc_tmp[-1] == '\n')
        {
            if (pc_tmp[-2] == '<')
            {
                if (pc_tmp[-3] == 'B' || pc_tmp[-3] == 'I' || pc_tmp[-3] == 'R')
                {
                    pc_tmp -=3;
                }
                else if (pc_tmp[-3] == 'W' && pc_tmp[-4] == 'C')
                {
                    pc_tmp -=4;
                }
                else
                {
                    pc_tmp[-1] = '>';
                }
            }
            else
            {
                pc_tmp[-1] = '>';
            }
            *pc_tmp++ = '\n';
        }
        else
            *pc_tmp++ = '>';
    }
    *pc_tmp = '\0';
    strcpy(previous_font, previous);
    strcpy(current_font, current);
//    fprintf(stderr, "end do_fonts: '%s'\n", tmp);
    return tmp;
}

MODULE = Locale::Po4a::Man		PACKAGE = Locale::Po4a::Man		

char *
do_fonts(string, ref)
	char *		string
	char *		ref

void set_regular(font)
	char *		font

void set_font(font)
	char *		font



--- NEW FILE: TransTractor.xs ---
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

//#include "ppport.h"

//#include "const-c.inc"

char *TransTractor_write(SV* self, char *filename)
{
    FILE *out = NULL;

    if (NULL == filename)
        croak("Can't write to a file without filename");

    if (0 == strcmp(filename, "-"))
    {
        out = stdout;
    }
    else
    {
        int count;
        I32 i = 0;
        dSP;
        ENTER;

        out = fopen(filename, "w");
        if (NULL == out)
        {
            perror("fopen");
            croak("Can't create %s.\n", filename);
        }

        PUSHMARK(SP);
        XPUSHs(self);
        PUTBACK;
        count = call_method("docheader", G_ARRAY);

        SPAGAIN;

        for (i=0; i< count; i++)
        {
            fputs(POPp, out);
        }

        HV *hv = SvRV(self);
//        if (hv_exists(hv, "TT", 2))
//        {
            SV **psv = hv_fetch(hv, "TT", 2,0);
            if (NULL != psv)
            {
                SV *sv = *psv;
//                if (hv_exists(SvRV(sv), "doc_out", 7))
//                {
                    psv = hv_fetch(SvRV(sv), "doc_out", 7, 0);
                    sv = *psv;
                    AV *av = SvRV(sv);
                    for (i = 0; i < av_len(av); i++)
                    {
                        fputs(SvRV(*av_fetch(av, i, 0)), out);
                    }
//                }
//                else
//                {
//                    croak("No doc_out.\n");
//                }
            }
//        }
//        else
//        {
//            croak("No TT.\n");
//        }

fclose(out);
        PUTBACK;
        LEAVE;
    }
}

MODULE = Locale::Po4a::TransTractor	PACKAGE = Locale::Po4a::TransTractor	PREFIX = TransTractor_

void TransTractor_write(self, filename)
	SV *		self
	char *		filename


--- NEW FILE: Po.h ---
#ifndef _PO_H
#define _PO_H

#include <gettext-po.h>
#include "message.h"

extern void textmode_xerror (int severity,
                             po_message_t message,
                             const char *filename, size_t lineno, size_t column,                             int multiline_p, const char *message_text);
extern void textmode_xerror2 (int severity,
                              po_message_t message1,
                              const char *filename1, size_t lineno1, size_t column1,
                              int multiline_p1, const char *message_text1,
                              po_message_t message2,
                              const char *filename2, size_t lineno2, size_t column2,
                              int multiline_p2, const char *message_text2);
struct po_xerror_handler default_xerror_handler={textmode_xerror,
                                                 textmode_xerror2};

struct Po {
//    po_file_t po_file;
    message_list_ty *mlp;
};

typedef struct Po Locale__Po4a__Po;
typedef struct Po * Locale_Po4a_Po;

#endif




More information about the Po4a-commits mailing list