|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Verify that translations in the .po file have the same number and type of
|
|
Packit |
2fc92b |
* printf-style format strings.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Copyright 2007-2017 by Apple Inc.
|
|
Packit |
2fc92b |
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* These coded instructions, statements, and computer programs are the
|
|
Packit |
2fc92b |
* property of Apple Inc. and are protected by Federal copyright
|
|
Packit |
2fc92b |
* law. Distribution and use rights are outlined in the file "LICENSE.txt"
|
|
Packit |
2fc92b |
* which should have been included with this file. If this file is
|
|
Packit |
2fc92b |
* missing or damaged, see the license at "http://www.cups.org/".
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Usage:
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* checkpo filename.{po,strings} [... filenameN.{po,strings}]
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* Compile with:
|
|
Packit |
2fc92b |
*
|
|
Packit |
2fc92b |
* gcc -o checkpo checkpo.c `cups-config --libs`
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
#include <cups/cups-private.h>
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Local functions...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static char *abbreviate(const char *s, char *buf, int bufsize);
|
|
Packit |
2fc92b |
static cups_array_t *collect_formats(const char *id);
|
|
Packit |
2fc92b |
static cups_array_t *cups_load_strings(const char *filename);
|
|
Packit |
2fc92b |
static int cups_read_strings(cups_file_t *fp, char *buffer, size_t bufsize, char **id, char **str);
|
|
Packit |
2fc92b |
static char *cups_scan_strings(char *buffer);
|
|
Packit |
2fc92b |
static void free_formats(cups_array_t *fmts);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'main()' - Validate .po and .strings files.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
int /* O - Exit code */
|
|
Packit |
2fc92b |
main(int argc, /* I - Number of command-line args */
|
|
Packit |
2fc92b |
char *argv[]) /* I - Command-line arguments */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
int i; /* Looping var */
|
|
Packit |
2fc92b |
cups_array_t *po; /* .po file */
|
|
Packit |
2fc92b |
_cups_message_t *msg; /* Current message */
|
|
Packit |
2fc92b |
cups_array_t *idfmts, /* Format strings in msgid */
|
|
Packit |
2fc92b |
*strfmts; /* Format strings in msgstr */
|
|
Packit |
2fc92b |
char *idfmt, /* Current msgid format string */
|
|
Packit |
2fc92b |
*strfmt; /* Current msgstr format string */
|
|
Packit |
2fc92b |
int fmtidx; /* Format index */
|
|
Packit |
2fc92b |
int status, /* Exit status */
|
|
Packit |
2fc92b |
pass, /* Pass/fail status */
|
|
Packit |
2fc92b |
untranslated; /* Untranslated messages */
|
|
Packit |
2fc92b |
char idbuf[80], /* Abbreviated msgid */
|
|
Packit |
2fc92b |
strbuf[80]; /* Abbreviated msgstr */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (argc < 2)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
puts("Usage: checkpo filename.{po,strings} [... filenameN.{po,strings}]");
|
|
Packit |
2fc92b |
return (1);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Check every .po or .strings file on the command-line...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (i = 1, status = 0; i < argc; i ++)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Use the CUPS .po loader to get the message strings...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (strstr(argv[i], ".strings"))
|
|
Packit |
2fc92b |
po = cups_load_strings(argv[i]);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
po = _cupsMessageLoad(argv[i], 1);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!po)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
perror(argv[i]);
|
|
Packit |
2fc92b |
return (1);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (i > 1)
|
|
Packit |
2fc92b |
putchar('\n');
|
|
Packit |
2fc92b |
printf("%s: ", argv[i]);
|
|
Packit |
2fc92b |
fflush(stdout);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Scan every message for a % string and then match them up with
|
|
Packit |
2fc92b |
* the corresponding string in the translation...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pass = 1;
|
|
Packit |
2fc92b |
untranslated = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (msg = (_cups_message_t *)cupsArrayFirst(po);
|
|
Packit |
2fc92b |
msg;
|
|
Packit |
2fc92b |
msg = (_cups_message_t *)cupsArrayNext(po))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Make sure filter message prefixes are not translated...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!strncmp(msg->id, "ALERT:", 6) || !strncmp(msg->id, "CRIT:", 5) ||
|
|
Packit |
2fc92b |
!strncmp(msg->id, "DEBUG:", 6) || !strncmp(msg->id, "DEBUG2:", 7) ||
|
|
Packit |
2fc92b |
!strncmp(msg->id, "EMERG:", 6) || !strncmp(msg->id, "ERROR:", 6) ||
|
|
Packit |
2fc92b |
!strncmp(msg->id, "INFO:", 5) || !strncmp(msg->id, "NOTICE:", 7) ||
|
|
Packit |
2fc92b |
!strncmp(msg->id, "WARNING:", 8))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
printf(" Bad prefix on filter message \"%s\"\n",
|
|
Packit |
2fc92b |
abbreviate(msg->id, idbuf, sizeof(idbuf)));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
idfmt = msg->id + strlen(msg->id) - 1;
|
|
Packit |
2fc92b |
if (idfmt >= msg->id && *idfmt == '\n')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
printf(" Trailing newline in message \"%s\"\n",
|
|
Packit |
2fc92b |
abbreviate(msg->id, idbuf, sizeof(idbuf)));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (; idfmt >= msg->id; idfmt --)
|
|
Packit |
2fc92b |
if (!isspace(*idfmt & 255))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (idfmt >= msg->id && *idfmt == '!')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
printf(" Exclamation in message \"%s\"\n",
|
|
Packit |
2fc92b |
abbreviate(msg->id, idbuf, sizeof(idbuf)));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((idfmt - 2) >= msg->id && !strncmp(idfmt - 2, "...", 3))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
printf(" Ellipsis in message \"%s\"\n",
|
|
Packit |
2fc92b |
abbreviate(msg->id, idbuf, sizeof(idbuf)));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!msg->str || !msg->str[0])
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
untranslated ++;
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (strchr(msg->id, '%'))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
idfmts = collect_formats(msg->id);
|
|
Packit |
2fc92b |
strfmts = collect_formats(msg->str);
|
|
Packit |
2fc92b |
fmtidx = 0;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (strfmt = (char *)cupsArrayFirst(strfmts);
|
|
Packit |
2fc92b |
strfmt;
|
|
Packit |
2fc92b |
strfmt = (char *)cupsArrayNext(strfmts))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (isdigit(strfmt[1] & 255) && strfmt[2] == '$')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Handle positioned format stuff...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
fmtidx = strfmt[1] - '1';
|
|
Packit |
2fc92b |
strfmt += 3;
|
|
Packit |
2fc92b |
if ((idfmt = (char *)cupsArrayIndex(idfmts, fmtidx)) != NULL)
|
|
Packit |
2fc92b |
idfmt ++;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Compare against the current format...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
idfmt = (char *)cupsArrayIndex(idfmts, fmtidx);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
fmtidx ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!idfmt || strcmp(strfmt, idfmt))
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (cupsArrayCount(strfmts) != cupsArrayCount(idfmts) || strfmt)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
printf(" Bad translation string \"%s\"\n for \"%s\"\n",
|
|
Packit |
2fc92b |
abbreviate(msg->str, strbuf, sizeof(strbuf)),
|
|
Packit |
2fc92b |
abbreviate(msg->id, idbuf, sizeof(idbuf)));
|
|
Packit |
2fc92b |
fputs(" Translation formats:", stdout);
|
|
Packit |
2fc92b |
for (strfmt = (char *)cupsArrayFirst(strfmts);
|
|
Packit |
2fc92b |
strfmt;
|
|
Packit |
2fc92b |
strfmt = (char *)cupsArrayNext(strfmts))
|
|
Packit |
2fc92b |
printf(" %s", strfmt);
|
|
Packit |
2fc92b |
fputs("\n Original formats:", stdout);
|
|
Packit |
2fc92b |
for (idfmt = (char *)cupsArrayFirst(idfmts);
|
|
Packit |
2fc92b |
idfmt;
|
|
Packit |
2fc92b |
idfmt = (char *)cupsArrayNext(idfmts))
|
|
Packit |
2fc92b |
printf(" %s", idfmt);
|
|
Packit |
2fc92b |
putchar('\n');
|
|
Packit |
2fc92b |
putchar('\n');
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
free_formats(idfmts);
|
|
Packit |
2fc92b |
free_formats(strfmts);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Only allow \\, \n, \r, \t, \", and \### character escapes...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (strfmt = msg->str; *strfmt; strfmt ++)
|
|
Packit |
2fc92b |
if (*strfmt == '\\' &&
|
|
Packit |
2fc92b |
strfmt[1] != '\\' && strfmt[1] != 'n' && strfmt[1] != 'r' &&
|
|
Packit |
2fc92b |
strfmt[1] != 't' && strfmt[1] != '\"' && !isdigit(strfmt[1] & 255))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
printf(" Bad escape \\%c in filter message \"%s\"\n"
|
|
Packit |
2fc92b |
" for \"%s\"\n", strfmt[1],
|
|
Packit |
2fc92b |
abbreviate(msg->str, strbuf, sizeof(strbuf)),
|
|
Packit |
2fc92b |
abbreviate(msg->id, idbuf, sizeof(idbuf)));
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (pass)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if ((untranslated * 10) >= cupsArrayCount(po) &&
|
|
Packit |
2fc92b |
strcmp(argv[i], "cups.pot"))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Only allow 10% of messages to be untranslated before we fail...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
pass = 0;
|
|
Packit |
2fc92b |
puts("FAIL");
|
|
Packit |
2fc92b |
printf(" Too many untranslated messages (%d of %d)\n",
|
|
Packit |
2fc92b |
untranslated, cupsArrayCount(po));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (untranslated > 0)
|
|
Packit |
2fc92b |
printf("PASS (%d of %d untranslated)\n", untranslated,
|
|
Packit |
2fc92b |
cupsArrayCount(po));
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
puts("PASS");
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!pass)
|
|
Packit |
2fc92b |
status = 1;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
_cupsMessageFree(po);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (status);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'abbreviate()' - Abbreviate a message string as needed.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static char * /* O - Abbreviated string */
|
|
Packit |
2fc92b |
abbreviate(const char *s, /* I - String to abbreviate */
|
|
Packit |
2fc92b |
char *buf, /* I - Buffer */
|
|
Packit |
2fc92b |
int bufsize) /* I - Size of buffer */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
char *bufptr; /* Pointer into buffer */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (bufptr = buf, bufsize -= 4; *s && bufsize > 0; s ++)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (*s == '\n')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (bufsize < 2)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*bufptr++ = '\\';
|
|
Packit |
2fc92b |
*bufptr++ = 'n';
|
|
Packit |
2fc92b |
bufsize -= 2;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (*s == '\t')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (bufsize < 2)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*bufptr++ = '\\';
|
|
Packit |
2fc92b |
*bufptr++ = 't';
|
|
Packit |
2fc92b |
bufsize -= 2;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else if (*s >= 0 && *s < ' ')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (bufsize < 4)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
sprintf(bufptr, "\\%03o", *s);
|
|
Packit |
2fc92b |
bufptr += 4;
|
|
Packit |
2fc92b |
bufsize -= 4;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
*bufptr++ = *s;
|
|
Packit |
2fc92b |
bufsize --;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*s)
|
|
Packit |
2fc92b |
memcpy(bufptr, "...", 4);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
*bufptr = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (buf);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'collect_formats()' - Collect all of the format strings in the msgid.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static cups_array_t * /* O - Array of format strings */
|
|
Packit |
2fc92b |
collect_formats(const char *id) /* I - msgid string */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cups_array_t *fmts; /* Array of format strings */
|
|
Packit |
2fc92b |
char buf[255], /* Format string buffer */
|
|
Packit |
2fc92b |
*bufptr; /* Pointer into format string */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
fmts = cupsArrayNew(NULL, NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while ((id = strchr(id, '%')) != NULL)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (id[1] == '%')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Skip %%...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
id += 2;
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (bufptr = buf; *id && bufptr < (buf + sizeof(buf) - 1); id ++)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
*bufptr++ = *id;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (strchr("CDEFGIOSUXcdeifgopsux", *id))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
id ++;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*bufptr = '\0';
|
|
Packit |
2fc92b |
cupsArrayAdd(fmts, strdup(buf));
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (fmts);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cups_load_strings()' - Load a .strings file into a _cups_msg_t array.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static cups_array_t * /* O - CUPS array of _cups_msg_t values */
|
|
Packit |
2fc92b |
cups_load_strings(const char *filename) /* I - File to load */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
cups_file_t *fp; /* .strings file */
|
|
Packit |
2fc92b |
cups_array_t *po; /* Localization array */
|
|
Packit |
2fc92b |
_cups_message_t *m; /* Localization message */
|
|
Packit |
2fc92b |
char buffer[8192], /* Message buffer */
|
|
Packit |
2fc92b |
*id, /* ID string */
|
|
Packit |
2fc92b |
*str; /* Translated message */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if ((fp = cupsFileOpen(filename, "r")) == NULL)
|
|
Packit |
2fc92b |
return (NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
po = _cupsMessageNew(NULL);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (cups_read_strings(fp, buffer, sizeof(buffer), &id, &str))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if ((m = malloc(sizeof(_cups_message_t))) == NULL)
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
m->id = strdup(id);
|
|
Packit |
2fc92b |
m->str = strdup(str);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (m->id && m->str)
|
|
Packit |
2fc92b |
cupsArrayAdd(po, m);
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (m->id)
|
|
Packit |
2fc92b |
free(m->id);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (m->str)
|
|
Packit |
2fc92b |
free(m->str);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
free(m);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayDelete(po);
|
|
Packit |
2fc92b |
po = NULL;
|
|
Packit |
2fc92b |
break;
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsFileClose(fp);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (po);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cups_read_strings()' - Read a pair of strings from a .strings file.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static int /* O - 1 on success, 0 on failure */
|
|
Packit |
2fc92b |
cups_read_strings(cups_file_t *strings, /* I - .strings file */
|
|
Packit |
2fc92b |
char *buffer, /* I - Line buffer */
|
|
Packit |
2fc92b |
size_t bufsize, /* I - Size of line buffer */
|
|
Packit |
2fc92b |
char **id, /* O - Pointer to ID string */
|
|
Packit |
2fc92b |
char **str) /* O - Pointer to translation string */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
char *bufptr; /* Pointer into buffer */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (cupsFileGets(strings, buffer, bufsize))
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (buffer[0] != '\"')
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*id = buffer + 1;
|
|
Packit |
2fc92b |
bufptr = cups_scan_strings(buffer);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*bufptr != '\"')
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*bufptr++ = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
while (*bufptr && *bufptr != '\"')
|
|
Packit |
2fc92b |
bufptr ++;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (!*bufptr)
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*str = bufptr + 1;
|
|
Packit |
2fc92b |
bufptr = cups_scan_strings(bufptr);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
if (*bufptr != '\"')
|
|
Packit |
2fc92b |
continue;
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*bufptr = '\0';
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (1);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (0);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'cups_scan_strings()' - Scan a quoted string.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static char * /* O - End of string */
|
|
Packit |
2fc92b |
cups_scan_strings(char *buffer) /* I - Start of string */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
char *bufptr; /* Pointer into string */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (bufptr = buffer + 1; *bufptr && *bufptr != '\"'; bufptr ++)
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (*bufptr == '\\')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
if (bufptr[1] >= '0' && bufptr[1] <= '3' &&
|
|
Packit |
2fc92b |
bufptr[2] >= '0' && bufptr[2] <= '7' &&
|
|
Packit |
2fc92b |
bufptr[3] >= '0' && bufptr[3] <= '7')
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Decode \nnn octal escape...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
*bufptr = (char)(((((bufptr[1] - '0') << 3) | (bufptr[2] - '0')) << 3) | (bufptr[3] - '0'));
|
|
Packit |
2fc92b |
_cups_strcpy(bufptr + 1, bufptr + 4);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
else
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* Decode \C escape...
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
_cups_strcpy(bufptr, bufptr + 1);
|
|
Packit |
2fc92b |
if (*bufptr == 'n')
|
|
Packit |
2fc92b |
*bufptr = '\n';
|
|
Packit |
2fc92b |
else if (*bufptr == 'r')
|
|
Packit |
2fc92b |
*bufptr = '\r';
|
|
Packit |
2fc92b |
else if (*bufptr == 't')
|
|
Packit |
2fc92b |
*bufptr = '\t';
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
return (bufptr);
|
|
Packit |
2fc92b |
}
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
/*
|
|
Packit |
2fc92b |
* 'free_formats()' - Free all of the format strings.
|
|
Packit |
2fc92b |
*/
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
static void
|
|
Packit |
2fc92b |
free_formats(cups_array_t *fmts) /* I - Array of format strings */
|
|
Packit |
2fc92b |
{
|
|
Packit |
2fc92b |
char *s; /* Current string */
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
for (s = (char *)cupsArrayFirst(fmts); s; s = (char *)cupsArrayNext(fmts))
|
|
Packit |
2fc92b |
free(s);
|
|
Packit |
2fc92b |
|
|
Packit |
2fc92b |
cupsArrayDelete(fmts);
|
|
Packit |
2fc92b |
}
|