/* XTrkCad - Model Railroad CAD * Copyright (C) 2005 Dave Bullis * 2007 Martin Fischer * * 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 of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #ifdef WINDOWS #if _MSC_VER >=1400 #define strdup _strdup #endif #endif #define I18NHEADERFILE "i18n.h" typedef struct helpMsg_t * helpMsg_p; typedef struct helpMsg_t { char * key; char * title; char * help; } helpMsg_t; helpMsg_t helpMsgs[200]; int helpMsgCnt = 0; struct transTbl { char *inChar; char *outChar[]; }; /* ATTENTION: make sure that the characters are in the same order as the equivalent escape sequences below */ /* translation table for unicode sequences understood by Halibut */ struct transTbl toUnicode = { "\xB0\0", { "\\u00B0", "\\0" } }; /* translation table for escape sequences understood by C compiler */ struct transTbl toC = { "\n\\\"\0", { "\\n", "\\\\", "\\\"", "\\0" } }; char * TranslateString( char *srcString, struct transTbl *trTbl ) { char *destString; char *cp; char *cp2; size_t bufLen = strlen( srcString ) + 1; char *idx; /* calculate the expected result length */ for( cp = srcString; *cp; cp++ ) if( idx = strchr( trTbl->inChar, *cp )) /* does character need translation ? */ bufLen += strlen( (trTbl->outChar)[idx - trTbl->inChar ] ) - 1; /* yes, extend buffer accordingly */ /* allocate memory for result */ destString = malloc( bufLen ); if( destString ) { /* copy and translate characters as needed */ cp2 = destString; for( cp = srcString; *cp; cp++ ) { if( idx = strchr( trTbl->inChar, *cp )) { /* does character need translation ? */ strcpy( cp2, (trTbl->outChar)[idx - trTbl->inChar ] ); /* yes, copy the escaped character sequence */ cp2 += strlen((trTbl->outChar)[idx - trTbl->inChar ] ); } else { *cp2++ = *cp; /* no, just copy the character */ } } /* terminate string */ *cp2 = '\0'; } else { /* memory allocation failed */ exit(1); } return( destString ); } int cmpHelpMsg( const void * a, const void * b ) { helpMsg_p aa = (helpMsg_p)a; helpMsg_p bb = (helpMsg_p)b; return strcmp( aa->title, bb->title ); } void unescapeString( FILE * f, char * str ) { while (*str) { if (*str != '\\') fputc( *str, f ); str++; } } /** * Generate the file in help source format ( ie. the BUT file ) */ void dumpHelp( FILE *hlpsrcF ) { int inx; char *transStr; fputs( "\\#\n * DO NOT EDIT! This file has been automatically created by genmessages.\n * Changes to this file will be overwritten.\n", hlpsrcF ); fprintf( hlpsrcF, "\n\n\\H{messageList} Message Explanations\n\n" ); /* sort in alphabetical order */ qsort( helpMsgs, helpMsgCnt, sizeof helpMsgs[0], cmpHelpMsg ); /* now save all the help messages */ for ( inx=0; inx 4 ) { fprintf( stderr, "Usage: %s [-i18n] INFILE OUTFILE\n\n", argv[0] ); fprintf( stderr, " -i18n is used to generate a include file with gettext support.\n\n" ); exit(1); } /* check options */ if( argc == 4 ) { if( !strcmp(argv[ 1 ], "-i18n")){ i18n = 1; inFileIdx = 2; /* second argument is input file */ } /* inFileIdx = 2; skip over option argument */ } else { inFileIdx = 1; /* first argument is input file */ } /* open the file for reading */ inF = fopen( argv[ inFileIdx ], "r" ); if( !inF ) { fprintf( stderr, "Could not open %s for reading!\n", argv[ inFileIdx ] ); exit( 1 ); } /* open the include file to generate */ hdrF = fopen( "messages.h", "w" ); if( !hdrF ) { fprintf( stderr, "Could not open messages.h for writing!\n" ); exit( 1 ); } fputs( "/*\n * DO NOT EDIT! This file has been automatically created by genmessages.\n * Changes to this file will be overwritten.\n */\n", hdrF ); /* open the help file to generate */ outF = fopen( argv[ inFileIdx + 1 ], "w" ); if( !inF ) { fprintf( stderr, "Could not open %s for writing!\n", argv[ inFileIdx ] ); exit( 1 ); } /* Include i18n header, if needed */ if (i18n) fprintf( hdrF, "#include \"" I18NHEADERFILE "\"\n\n" ); while ( fgets( buff, sizeof buff, inF ) ) { /* skip comment lines */ if ( buff[0] == '#' ) continue; /* remove trailing whitespaces */ cp = buff+strlen(buff)-1; while( cp >= buff && isspace(*cp)) { *cp = '\0'; cp--; } if ( strncmp( buff, "MESSAGE ", 8 ) == 0 ) { /* skip any spaces */ cp = strchr( buff+8, ' ' ); if (cp) while (*cp == ' ') *cp++ = 0; #ifndef FLAGS if ( cp && *cp ) { flags = atoi(cp); } #endif /* save the name of the message */ strcpy( msgName, buff + 8 ); msgAlt[0] = 0; msgTitle[0] = 0; msgTitle1[0] = 0; msgHelp[0] = 0; mode = m_title; } else if ( strncmp( buff, "ALT", 3 ) == 0 ) { mode = m_alt; msgAlt[0] = 0; } else if ( strncmp( buff, "HELP", 4 ) == 0 ) { mode = m_help; } else if ( strncmp( buff, "END", 3 ) == 0 ) { /* the whole message has been read */ /* create escape sequences */ tName = TranslateString( msgName, &toC ); tTitle = TranslateString( msgTitle, &toC ); tAlt = TranslateString( msgAlt, &toC ); if (msgHelp[0]==0) { /* no help text is included */ if (i18n) fprintf( hdrF, "#define %s N_(\"%s\")\n", tName, tTitle ); else fprintf( hdrF, "#define %s \"%s\"\n", tName, tTitle ); } else if (msgAlt[0]) { /* a help text and an alternate description are included */ if (i18n) fprintf( hdrF, "#define %s N_(\"%s\\t%s\\t%s\")\n", tName, tName, tAlt, tTitle ); else fprintf( hdrF, "#define %s \"%s\\t%s\\t%s\"\n", tName, tName, tAlt, tTitle ); } else { /* a help text but no alternate description are included */ if (i18n) fprintf( hdrF, "#define %s N_(\"%s\\t%s\")\n", tName, tName, tTitle ); else fprintf( hdrF, "#define %s \"%s\\t%s\"\n", tName, tName, tTitle ); } /*free temp stzrings */ free( tName ); free( tTitle ); free( tAlt ); /* save the help text for later use */ if (msgHelp[0]) { helpMsgs[helpMsgCnt].key = strdup(msgName); if ( msgAlt[0] ) helpMsgs[helpMsgCnt].title = strdup(msgAlt); else helpMsgs[helpMsgCnt].title = strdup(msgTitle); helpMsgs[helpMsgCnt].help = strdup(msgHelp); helpMsgCnt++; } mode = 0; } else { /* are we currently reading the message text? */ if (mode == m_title) { /* yes, is the message text split over two lines ? */ if (msgTitle[0]) { /* if yes, keep the first part as the short text */ if (msgAlt[0] == 0) { strcpy( msgAlt, msgTitle ); strcat( msgAlt, "..." ); } /* add a newline to the first part */ strcat( msgTitle, "\n" ); } /* now save the buffer into the message title */ strcat( msgTitle, buff ); } else if (mode == m_alt) { /* an alternate text was explicitly specified, save */ if( msgAlt[ 0 ] ) { strcat( msgAlt, " " ); strcat( msgAlt, buff ); } else { strcpy( msgAlt, buff ); } } else if (mode == m_help) { /* we are reading the help text, save in buffer */ strcat( msgHelp, buff ); strcat( msgHelp, "\n" ); } } } dumpHelp( outF ); fclose( hdrF ); fclose( inF ); fclose( outF ); printf( "%d messages\n", helpMsgCnt ); return 0; }