Annotation of pgp/src/language.c, revision 1.1.1.8

1.1.1.8 ! root        1: /*
        !             2:    language.c - Foreign language translation for PGP
        !             3:    Finds foreign language "subtitles" for English phrases 
        !             4:    in external foriegn language text file.
        !             5: 
        !             6:    (c) Copyright 1990-1996 by Philip Zimmermann.  All rights reserved.
        !             7:    The author assumes no liability for damages resulting from the use
        !             8:    of this software, even if the damage results from defects in this
        !             9:    software.  No warranty is expressed or implied.
        !            10: 
        !            11:    Note that while most PGP source modules bear Philip Zimmermann's
        !            12:    copyright notice, many of them have been revised or entirely written
        !            13:    by contributors who frequently failed to put their names in their
        !            14:    code.  Code that has been incorporated into PGP from other authors
        !            15:    was either originally published in the public domain or is used with
        !            16:    permission from the various authors.
        !            17: 
        !            18:    PGP is available for free to the public under certain restrictions.
        !            19:    See the PGP User's Guide (included in the release package) for
        !            20:    important information about licensing, patent restrictions on
        !            21:    certain algorithms, trademarks, copyrights, and export controls.
        !            22:  */
        !            23: 
        !            24: #include <stdio.h>
        !            25: #include <stdlib.h>
        !            26: #include <string.h>
        !            27: #include <ctype.h>
        !            28: #include "usuals.h"
        !            29: #include "fileio.h"
        !            30: #include "language.h"
        !            31: #include "pgp.h"
        !            32: #include "charset.h"
        !            33: #include "armor.h"
        !            34: 
        !            35: #define SUBTITLES_FILE "language.txt"
        !            36: #define LANG_INDEXFILE "language.idx"
        !            37: 
        !            38: #define        STRBUFSIZE              2048
        !            39: 
        !            40: char language[16] = "en";      /* The language code, defaults to English */
        !            41: static char *strbuf;
        !            42: static char lang[16];          /* readstr sets this to the language id of
        !            43:                                   the msg it last read */
        !            44: static int subtitles_available = 0;
        !            45: static int line = 0;
        !            46: /*      subtitles_available is used to determine if we know whether the special
        !            47:    subtitles_file exists.  subtitles_available has the following values:
        !            48:    0  = first time thru, we don't yet know if subtitles_file exists.
        !            49:    1  = we have already determined that subtitles_file exists.
        !            50:    -1 = we have already determined that subtitles_file does not exist.
        !            51:  */
        !            52: 
        !            53: #define        NEWLINE         0
        !            54: #define        COMMENT         1
        !            55: #define        INSTRING        2
        !            56: #define        ESCAPE          3
        !            57: #define        IDENT           4
        !            58: #define        DONE            5
        !            59: #define        ERROR           6
        !            60: #define        ERR1            7
        !            61: 
        !            62: /* Look for and return a quoted string from the file.
        !            63:  * If nlabort is true, return failure if we find a blank line
        !            64:  * before we find the opening quote.
        !            65:  */
        !            66: static char *
        !            67:  readstr(FILE * f, char *buf, int nlabort)
        !            68: {
        !            69:     int c, d;
        !            70:     char *p = buf;
        !            71:     int state = NEWLINE;
        !            72:     int i = 0;
        !            73: 
        !            74:     while ((c = getc(f)) != EOF) {
        !            75:        if (c == '\r')
        !            76:            continue;
        !            77:        /* line numbers are only incremented when creating index file */
        !            78:        if (line && c == '\n')
        !            79:            ++line;
        !            80:        switch (state) {
        !            81:        case NEWLINE:
        !            82:            switch (c) {
        !            83:            case '#':
        !            84:                state = COMMENT;
        !            85:                break;
        !            86:            case '"':
        !            87:                state = INSTRING;
        !            88:                break;
        !            89:            case '\n':
        !            90:                if (nlabort) {
        !            91:                    *buf = '\0';
        !            92:                    return buf;
        !            93:                }
        !            94:            default:
        !            95:                if (i == 0 && isalnum(c)) {
        !            96:                    state = IDENT;
        !            97:                    lang[i++] = c;
        !            98:                    break;
        !            99:                }
        !           100:                if (!isspace(c)) {
        !           101:                    fprintf(stderr, "language.txt:%d: syntax error\n", line);
        !           102:                    state = ERROR;
        !           103:                }
        !           104:            }
        !           105:            break;
        !           106:        case COMMENT:
        !           107:            if (c == '\n')
        !           108:                state = NEWLINE;
        !           109:            break;
        !           110:        case INSTRING:
        !           111:            switch (c) {
        !           112:            case '\\':
        !           113:                state = ESCAPE;
        !           114:                break;
        !           115:            case '"':
        !           116:                state = DONE;
        !           117:                break;
        !           118:            default:
        !           119:                *p++ = c;
        !           120:            }
        !           121:            break;
        !           122:        case ESCAPE:
        !           123:            switch (c) {
        !           124:            case 'n':
        !           125:                *p++ = '\n';
        !           126:                break;
        !           127:            case 'r':
        !           128:                *p++ = '\r';
        !           129:                break;
        !           130:            case 't':
        !           131:                *p++ = '\t';
        !           132:                break;
        !           133:            case 'e':
        !           134: #ifdef EBCDIC
        !           135:                *p++ = ESC;
        !           136: #else
        !           137:                *p++ = '\033';
        !           138: #endif
        !           139:                break;
        !           140:            case 'a':
        !           141: #ifdef EBCDIC
        !           142:                *p++ = '\a';
        !           143: #else
        !           144:                *p++ = '\007';
        !           145: #endif
        !           146:                break;
        !           147:            case '#':
        !           148:            case '"':
        !           149:            case '\\':
        !           150:                *p++ = c;
        !           151:                break;
        !           152:            case '\n':
        !           153:                break;
        !           154:            case '0':
        !           155:            case '1':
        !           156:            case '2':
        !           157:            case '3':
        !           158:            case '4':
        !           159:            case '5':
        !           160:            case '6':
        !           161:            case '7':
        !           162:                d = c - '0';
        !           163:                while ((c = fgetc(f)) >= '0' && c <= '7')
        !           164:                    d = 8 * d + c - '0';
        !           165: #ifdef EBCDIC
        !           166: /* dirty hack for \007 chars in LANG:    LANG("\n\007....")
        !           167:    The right way is to replace all \007 by \a in the args of LANG() */
        !           168:                if (d == 7) d = '\a';
        !           169: #endif
        !           170:                *p++ = d;
        !           171:                ungetc(c, f);
        !           172:                break;
        !           173:            default:
        !           174:                fprintf(stderr,
        !           175:                        "language.txt:%d: illegal escape sequence: '\\%c'\n",
        !           176:                        line, c);
        !           177:                break;
        !           178:            }
        !           179:            state = INSTRING;
        !           180:            break;
        !           181:        case IDENT:             /* language identifier */
        !           182:            if (c == ':') {
        !           183:                state = NEWLINE;
        !           184:                break;
        !           185:            }
        !           186:            if (c == '\n' && strncmp(lang, "No translation", 14) == 0) {
        !           187:                i = 0;
        !           188:                state = NEWLINE;
        !           189:                break;
        !           190:            }
        !           191:            lang[i++] = c;
        !           192:            if (i == 15 || !isalnum(c) && !isspace(c)) {
        !           193:                lang[i] = '\0';
        !           194:                fprintf(stderr,
        !           195:                        "language.txt:%d: bad language identifier: '%s'\n",
        !           196:                        line, lang);
        !           197:                state = ERROR;
        !           198:                i = 0;
        !           199:            }
        !           200:            break;
        !           201:        case DONE:
        !           202:            if (c == '\n') {
        !           203:                lang[i] = '\0';
        !           204:                *p = '\0';
        !           205:                return buf;
        !           206:            }
        !           207:            if (!isspace(c)) {
        !           208:                fprintf(stderr,
        !           209:                        "language.txt:%d: extra characters after '\"'\n",
        !           210:                        line);
        !           211:                state = ERROR;
        !           212:            }
        !           213:            break;
        !           214:        case ERROR:
        !           215:            if (c == '\n')
        !           216:                state = ERR1;
        !           217:            break;
        !           218:        case ERR1:
        !           219:            state = (c == '\n' ? NEWLINE : ERROR);
        !           220:            break;
        !           221:        }
        !           222:     }
        !           223:     if (state != NEWLINE)
        !           224:        fprintf(stderr, "language.txt: unexpected EOF\n");
        !           225:     return NULL;
        !           226: }
        !           227: 
        !           228: #ifdef TEST
        !           229: main()
        !           230: {
        !           231:     char buf[2048];
        !           232: 
        !           233:     line = 1;
        !           234:     while (readstr(stdin, buf, 0)) {
        !           235:        printf("\nen: <%s>\n", buf);
        !           236:        while (readstr(stdin, buf, 1) && *buf != '\0')
        !           237:            printf("%s: <%s>\n", lang, buf);
        !           238:     }
        !           239:     exit(0);
        !           240: }
        !           241: #else
        !           242: 
        !           243: static struct indx_ent {
        !           244:     word32 crc;
        !           245:     long offset;
        !           246: } *indx_tbl = NULL;
        !           247: 
        !           248: static int max_msgs = 0;
        !           249: static long nmsg = 0;
        !           250: 
        !           251: static FILE *langf;
        !           252: 
        !           253: static void init_lang(void);
        !           254: 
        !           255: static int make_indexfile(char *);
        !           256: 
        !           257: /*
        !           258:  * uses 24-bit CRC function from armor.c
        !           259:  */
        !           260: static word32
        !           261:  message_crc(char *s)
        !           262: {
        !           263:     return crcbytes((byte *) s, strlen(s), (word32) 0);
        !           264: }
        !           265: 
        !           266: /*
        !           267:  * lookup file offset in indx_tbl
        !           268:  */
        !           269: static long lookup_offset(word32 crc)
        !           270: {
        !           271:     int i;
        !           272: 
        !           273:     for (i = 0; i < nmsg; ++i)
        !           274:        if (indx_tbl[i].crc == crc)
        !           275:            return indx_tbl[i].offset;
        !           276:     return -1;
        !           277: }
        !           278: 
        !           279: 
        !           280: /*
        !           281:  * return foreign translation of s
        !           282:  */
        !           283: char *
        !           284:  LANG(char *s)
        !           285: {
        !           286:     long filepos;
        !           287: #ifdef MACTC5
        !           288:        extern Boolean contains_yesNo, contains_enough, contains_badpass;
        !           289:        contains_yesNo = (((void *) strstr(s, "(Y/n)?") != NULL) ||
        !           290:            ((void *) strstr(s, "(y/N)?") != NULL));
        !           291:        contains_enough = ((void *) strstr(s, "Enough") != NULL);
        !           292:        contains_badpass = (strstr(s, "Bad pass phrase.") != NULL);
        !           293: #endif /* MACTC5 */
        !           294:     if (subtitles_available == 0)
        !           295:        init_lang();
        !           296:     if (subtitles_available < 0)
        !           297:        return s;
        !           298: 
        !           299:     filepos = lookup_offset(message_crc(s));
        !           300:     if (filepos == -1) {
        !           301:        return s;
        !           302:     } else {
        !           303:        fseek(langf, filepos, SEEK_SET);
        !           304:        readstr(langf, strbuf, 1);
        !           305:     }
        !           306: 
        !           307:     if (strbuf[0] == '\0')
        !           308:        return s;
        !           309: 
        !           310: #ifndef EBCDIC /* no conversion for ebcdic printf() messages needed */
        !           311:     for (s = strbuf; *s; ++s)
        !           312:        *s = EXT_C(*s);
        !           313: #endif
        !           314:     return strbuf;
        !           315: }
        !           316: 
        !           317: 
        !           318: static struct {
        !           319:     long lang_fsize;           /* size of language.txt */
        !           320:     char lang[16];             /* language identifier */
        !           321:     long nmsg;                 /* number of messages */
        !           322: } indx_hdr;
        !           323: 
        !           324: 
        !           325: /*
        !           326:  * initialize the index table: read it from language.idx or create
        !           327:  * a new one and write it to the index file. A new index file is
        !           328:  * created if the language set in config.pgp doesn't match the one
        !           329:  * in language.idx or if the size of language.txt has changed.
        !           330:  */
        !           331: static void init_lang()
        !           332: {
        !           333:     char indexfile[MAX_PATH];
        !           334:     char subtitles_file[MAX_PATH];
        !           335:     FILE *indexf;
        !           336: #ifdef PGP_SYSTEM_DIR 
        !           337:     int use_system_wide_lang = 0; 
        !           338: #endif 
        !           339: 
        !           340:     if (strcmp(language, "en") == 0) {
        !           341:        subtitles_available = -1;
        !           342:        return;                 /* use default messages */
        !           343:     }
        !           344:     buildfilename(subtitles_file, SUBTITLES_FILE);
        !           345:     langf = fopen(subtitles_file, FOPRBIN); /* Open file in binary mode... */
        !           346:     if (langf == NULL) {
        !           347: #ifdef PGP_SYSTEM_DIR
        !           348:        strcpy(subtitles_file, PGP_SYSTEM_DIR);
        !           349:        strcat(subtitles_file, SUBTITLES_FILE);
        !           350:        langf = fopen(subtitles_file, FOPRBIN); /* Open file in binary mode... */
        !           351:        use_system_wide_lang = 1;
        !           352:        if (langf == NULL)
        !           353: #endif
        !           354:        {
        !           355:            subtitles_available = -1;
        !           356:            return;
        !           357:        }
        !           358:     }
        !           359:     init_crc();
        !           360:     strbuf = (char *) malloc(STRBUFSIZE);
        !           361:     if (strbuf == NULL) {
        !           362:        fprintf(stderr, "Not enough memory for foreign subtitles\n");
        !           363:        fclose(langf);
        !           364:        subtitles_available = -1;
        !           365:        return;
        !           366:     }
        !           367: #ifdef PGP_SYSTEM_DIR
        !           368:     if (use_system_wide_lang) {
        !           369:        strcpy(indexfile, PGP_SYSTEM_DIR);
        !           370:        strcat(indexfile, LANG_INDEXFILE);
        !           371:     } else
        !           372: #endif
        !           373:     buildfilename(indexfile, LANG_INDEXFILE);
        !           374:     indexf = fopen(indexfile, FOPRBIN);
        !           375:     if (indexf != NULL) {
        !           376:        if (fread(&indx_hdr, 1, sizeof(indx_hdr),
        !           377:                  indexf) == sizeof(indx_hdr) &&
        !           378:            indx_hdr.lang_fsize == fsize(langf) &&
        !           379:            strcmp(indx_hdr.lang, language) == 0) {
        !           380:            nmsg = indx_hdr.nmsg;
        !           381:            indx_tbl = (struct indx_ent *) malloc(nmsg *
        !           382:                                                  sizeof(struct indx_ent));
        !           383:            if (indx_tbl == NULL) {
        !           384:                fprintf(stderr, "Not enough memory for foreign subtitles\n");
        !           385:                fclose(indexf);
        !           386:                fclose(langf);
        !           387:                subtitles_available = -1;
        !           388:                return;
        !           389:            }
        !           390:            if (fread(indx_tbl,
        !           391:                      sizeof(struct indx_ent), nmsg, indexf) != nmsg) {
        !           392:                free(indx_tbl); /* create a new one */
        !           393:                indx_tbl = NULL;
        !           394:            }
        !           395:        }
        !           396:        fclose(indexf);
        !           397:     }
        !           398:     if (indx_tbl == NULL && make_indexfile(indexfile) < 0) {
        !           399:        fclose(langf);
        !           400:        subtitles_available = -1;
        !           401:     } else {
        !           402:        subtitles_available = 1;
        !           403:     }
        !           404: }
        !           405: 
        !           406: 
        !           407: static int make_indexfile(char *indexfile)
        !           408: {
        !           409:     FILE *indexf;
        !           410:     long filepos;
        !           411:     int total_msgs = 0;
        !           412:     char *res;
        !           413: 
        !           414:     if (verbose)               /* must be set in config.pgp */
        !           415:        fprintf(stderr,
        !           416:                "Creating language index file '%s' for language \"%s\"\n",
        !           417:                indexfile, language);
        !           418:     rewind(langf);
        !           419:     indx_hdr.lang_fsize = fsize(langf);
        !           420:     strncpy(indx_hdr.lang, language, 15);
        !           421:     init_crc();
        !           422:     line = 1;
        !           423:     nmsg = 0;
        !           424:     while (readstr(langf, strbuf, 0)) {
        !           425:        if (nmsg == max_msgs) {
        !           426:            if (max_msgs) {
        !           427:                max_msgs *= 2;
        !           428:                indx_tbl = (struct indx_ent *) realloc(indx_tbl, max_msgs *
        !           429:                                                sizeof(struct indx_ent));
        !           430:            } else {
        !           431:                max_msgs = 400;
        !           432:                indx_tbl = (struct indx_ent *) malloc(max_msgs *
        !           433:                                                sizeof(struct indx_ent));
        !           434:            }
        !           435:            if (indx_tbl == NULL) {
        !           436:                fprintf(stderr, "Not enough memory for foreign subtitles\n");
        !           437:                return -1;
        !           438:            }
        !           439:        }
        !           440:        ++total_msgs;
        !           441:        indx_tbl[nmsg].crc = message_crc(strbuf);
        !           442:        if (lookup_offset(indx_tbl[nmsg].crc) != -1)
        !           443:            fprintf(stderr,
        !           444:                    "language.txt:%d: Message CRC not unique: \"%s\"\n",
        !           445:                    line, strbuf);
        !           446:        do {
        !           447:            filepos = ftell(langf);
        !           448:            res = readstr(langf, strbuf, 1);    /* Abort if find newline
        !           449:                                                   first */
        !           450:        } while (res && strbuf[0] != '\0' && strcmp(language, lang) != 0);
        !           451: 
        !           452:        if (res == NULL)
        !           453:            break;
        !           454:        if (strbuf[0] == '\0')  /* No translation */
        !           455:            continue;
        !           456: 
        !           457:        indx_tbl[nmsg].offset = filepos;
        !           458:        ++nmsg;
        !           459:        do
        !           460:            res = readstr(langf, strbuf, 1);    /* Abort if find newline
        !           461:                                                   first */
        !           462:        while (res && strbuf[0] != '\0');
        !           463:     }
        !           464:     line = 0;
        !           465:     indx_hdr.nmsg = nmsg;
        !           466:     if (nmsg == 0) {
        !           467:        fprintf(stderr, "No translations available for language \"%s\"\n\n",
        !           468:                language);
        !           469:        return -1;
        !           470:     }
        !           471:     if (verbose || total_msgs != nmsg)
        !           472:        fprintf(stderr, "%d messages, %d translations\n\n", total_msgs, nmsg);
        !           473: 
        !           474:     if ((indexf = fopen(indexfile, FOPWBIN)) == NULL) {
        !           475:        fprintf(stderr, "Cannot create %s\n", indexfile);
        !           476:     } else {
        !           477:        fwrite(&indx_hdr, 1, sizeof(indx_hdr), indexf);
        !           478:        fwrite(indx_tbl, sizeof(struct indx_ent), nmsg, indexf);
        !           479:        if (ferror(indexf) || fclose(indexf))
        !           480:            fprintf(stderr, "error writing %s\n", indexfile);
        !           481:     }
        !           482:     return 0;
        !           483: }
        !           484: #endif                         /* TEST */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.