/* Checks the po file for C format correctness. To compile it you need the gettext package installed with its development files. Compilation commandline: gcc -lgettextpo -o msgcheckformat msgcheckformat.c Usage: msgcheckformat ---------------------------------------------------------------------------- Copyright (C) 2004 Szymon Stefanek (pragma at kvirc dot net) 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. */ #include #include #include #include #include #include int total_errors = 0; int total_warnings = 0; static void replace_crlf(const char * msg,char * buf) { while(*msg) { if(*msg == '\r') { *buf++ = '\\'; *buf++ = 'r'; msg++; } else if(*msg == '\n') { *buf++ = '\\'; *buf++ = 'n'; msg++; } else *buf++ = *msg++; } } static void print_error(po_message_t m,const char * msgid,const char * msgstr,const char * error) { char bufferid[16000]; char bufferstr[16000]; int is_fuzzy = po_message_is_fuzzy(m) ? 1 : 0; replace_crlf(msgid,bufferid); replace_crlf(msgstr,bufferstr); fprintf(stderr,"%s in %s:\n msgid: %s\n msgstr: %s\n reason: %s\n\n", is_fuzzy ? "Warning" : "Error", is_fuzzy ? "fuzzy entry" : "entry", bufferid,bufferstr,error); if(is_fuzzy)total_warnings++; else total_errors++; } static void process_message(po_message_t m) { const char * msgstr = po_message_msgstr(m); const char * msgid = po_message_msgid(m); const char *p; const char *q; if(msgid[0] == '\0')return; if(strlen(msgid) < 1)return; if(strlen(msgstr) < 1)return; if(msgstr[0] == '\0')return; p = msgid; q = msgstr; while(*p && *q) { while(*p && (*p != '%'))p++; while(*q && (*q != '%'))q++; if(*q && *p) { q++; p++; if(*p != *q) { char buff[200]; sprintf(buff,"Mismatched format character (%c != %c)",*p,*q); print_error(m,msgid,msgstr,buff); } } } if(*p || *q) { print_error(m,msgid,msgstr,"Mismatched number of format characters"); } } static void process_messages(po_message_iterator_t it) { po_message_t m = po_next_message(it); while(m) { process_message(m); m = po_next_message(it); } } int main(int argc, char **argv) { po_file_t po; po_message_iterator_t it; const char * const * domains; if(!*argv[1]) { fprintf(stderr,"usage: %s \n",argv[0]); return 0; } po = po_file_read(argv[1]); if(!po) { fprintf(stderr,"Couldn't read the input po file\n"); return 0; } domains = po_file_domains(po); if(!domains) { fprintf(stderr,"Couldn't find the message domains in the po file\n"); return 0; } while(*domains) { it = po_message_iterator(po,*domains); process_messages(it); po_message_iterator_free(it); domains++; } po_file_free(po); if(total_errors == 0 && total_warnings == 0)fprintf(stderr,"No errors found\n"); else fprintf(stderr,"%d warnings, %d errors\n",total_warnings,total_errors); return 0; }