source: git/src/message.c @ 07a346f

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereostereo-2025walls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 07a346f was f1a5201, checked in by Olly Betts <olly@…>, 27 years ago

Fixed narrowing implicit cast warning on RISCOS

git-svn-id: file:///home/survex-svn/survex/trunk@36 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 29.2 KB
Line 
1/* message.c */
2
3/* ERRC show diffs to newer version of error.c - most that are left in here aren't relevant */
4
5/* loosely based on Survex's error.c, but uses SGML entities for accented
6 * characters, and is rather more generic */
7
8/* maps: */
9
10/* (perfect hash) entity name to &#nnn; code */
11
12/* (lookup table or switch) &#nnn; code to best rendition in each charset */
13
14
15/* filename.c split off with filename manipulation stuff */
16
17
18/* > error.c
19 * Fairly general purpose error routines and path handling code
20 * Copyright (C) 1993-1997 Olly Betts
21 */
22
23/*
241993.01.25 PC Compatibility OKed
251993.01.27 print newline before error messages
261993.02.17 changed #ifdef RISCOS to #if OS==...
271993.02.19 now look for ErrList in dir main exec was in
28           for PC ERRLIST -> ERRLIST.TXT
291993.02.23 now do exit(EXIT_FAILURE) or exit(EXIT_SUCCESS)
30           added guessed UNIX stuff
311993.03.12 Major recode to make it less crap. Especially:
32           Now copes with *any* undefined message number
33           Error file now has spaces, not underscores
341993.03.16 Merged 'PathCode.c' with this file. Updates for 'PathCode.c' were:
35>> 1993.02.19 written
36>> 1993.02.23 added guess at UNIX code
37>> 1993.02.24 (W) add (int) cast to suppress warning calculating lenpth
38>> 1993.02.25 Don't look for FNM_SEP_DRV if it's not defined
391993.03.18 Added LfFromFnm()
401993.03.19 Corrected bug which caused infinite loop for PC text error file
411993.04.06 slight fettles and copied fn headers to error.c
421993.04.07 Added UsePth()
43           #error Don't ... -> #error Do not ... for GCC's happiness
441993.04.22 added fopenWithPthAndExt()
45           added application name code
461993.04.25 added AMIGA version
471993.05.05 Slightly more elegant hack than Wook's to solve BC++ stderr bug
481993.05.12 (W) added FNTYPE for different DOS memory model proofing (non-ANSI)
491993.05.22 (W) removed stderr hack as it is not that simple???
50               improved 'error file not found' reporting
511993.05.27 removed commented out #define STDERR ...
52           actually improved 'error file not found' et al - personally I do
53            *not* regard caverot telling me 'SURVEX: <error message>' as an
54            improvement. Mind you, I'm fussy.
551993.05.28 added signal catching code
561993.05.29 errno printed when signal received
571993.06.04 moved #define FNM_SEP_XXX to filelist.h
58           added #ifdef SIGSTAK as unix GCC doesn't seem to have it
591993.06.05 removed 'superfluous' &'s in signal fns
60           signal catcher now uses strerror()
611993.06.07 Unix libraries don't have strerror() - so don't use it!
62           FNTYPE -> FAR to aid comprehension
631993.06.10 in report_sig() only print out errno if non-zero
641993.06.12 fixed bug in path&ext code: only added .ext when prepending path
651993.06.16 syserr() -> fatal(); osmalloc() added; char* -> sz
66           osrealloc() added; osfree() comment added
671993.06.28 fixed bug which lost first character of each error message on
68            big-endian machines
69           fixed fopenWithPthAndExt() to osfree() fnmFull
701993.07.19 "common.h" -> "osdepend.h"
711993.07.27 changed "error number %d" to "#%d" in output
721993.08.10 added '\n' before errors reported in report_sig
731993.08.12 added more bomb-proofing
741993.08.13 fettled header
751993.08.16 added fAbsoluteFnm & fAmbiguousFnm; recoded fopenWithPthAndExt
76           RISC OS version of fopenWithPthAndExt copes with "<My$Dir>.File"
77           added AddExt; added pfExtUsed arg to fopenWithPthAndExt
781993.08.19 ./ in DOS is ambiguous, not absolute
791993.09.21 (W)fixed relative paths without preceding .\ for .svc files
80           (W)changed DOS fAbsolute() so 'c:here' is returned as ambiguous
811993.09.22 (W)changed error functions for more general info line
82           (W)added function list
831993.09.23 (IH)DOS uses farmalloc,farrealloc,farfree; osmalloc() takes a long
841993.10.15 (BP)changed erroneous ifdef MSDOS's to if (OS==MSDOS)
851993.10.18 (W)fWarningGiven added
861993.10.23 corrected fFALSE to fFalse
871993.11.03 changed error routines
88           cWarnings rather than fWarningGiven
89           fettled a bit
901993.11.05 OSSIZE_T added
91           fixed problem with pth=="" in fopenWithPthAndExt
92           added msg() and msgPerm()
931993.11.07 merged out of memory code from osmalloc & osrealloc
941993.11.08 added code to deal with quoted messages
951993.11.14 fettled
961993.11.15 added xosmalloc (returns NULL if malloc fails)
971993.11.18 xosrealloc added as macro in error.h
98           added calls to fDirectory
991993.11.19 added TeX style escape sequences for accents; also ``,'' for "
1001993.11.20 minor change to '' and `` code
101           \/O & \/o now used for slashed Os
102           extracted tables to tex.h
1031993.11.26 moved chOpenQuotes & chCloseQuotes to tex.h
1041993.11.28 added NO_TEX to turn it off for now
1051993.11.29 (IH) void * FAR -> void FAR * ; void * FILE -> void FILE *
106           use perror in UNIX version
107           extracted messages from here too! (except for signal ones)
1081993.11.30 corrected Wook's ungroks in function list
109           error now returns (it was wrong, but limp on); use fatal to abort
110           added cErrors
1111993.12.01 added error_summary()
112           most signals tell the user to report them as a bug (autograss?)
113           check version of messages.txt file
1141993.12.08 split off osdepend.c
1151993.12.09 now makes less explicit reference to OS
1161993.12.16 farmalloc use controlled by NO_FLATDOS macro
117           fixed error bootstrap code problem-ette
1181993.12.17 wr changed to send to stderr as it writes error info
1191994.01.05 added missing FAR to fix >128 eqns bug
120           and another
121           bug-fixed in outofmem
1221994.03.13 enabled TeX style characters
123           will deal with `` and '' even if NO_TEX is defined
1241994.03.14 altered fopenWithPthAndExt to give filename actually used
1251994.03.19 signals now reported as `fatal error' since they are
126           all error output to do with signals is now sent to stderr
1271994.03.20 added a putnl() at end of error_summary()
1281994.03.24 error summary to stderr too
1291994.04.27 cWarnings and cErrors now static
1301994.06.03 fixed so SunOS version should cope with DOS error message file
1311994.06.09 added home directory environmental variable
1321994.06.18 fixed Norcroft warning
1331994.06.20 added int argument to warning, error and fatal
1341994.08.31 added fputnl()
1351994.09.13 added fix for caverot signals being invisible under RISC OS
1361994.09.13 removed 'cos it doesn't work
1371994.09.20 fixed signal handler to longjmp back so it's now truely ANSI
138           miscellaneous fettling
1391994.09.21 rearranged signal handler code to minimize stack use
1401994.09.22 should now be able to read multi-language message file
1411994.09.28 xosmalloc is now a macro in error.h
1421994.10.04 no longer pass NULL for szExt to fopenWithPathAndExt
1431994.10.05 DEFAULTLANG and szLangVar added
1441994.10.08 sizeof -> ossizeof
1451994.11.16 errno.h wanted even if we're not signal handling
1461994.11.23 UsePth and AddExt now insert a separator if appropriate
147           fopenWithPthAndExt now uses UsePth and AddExt
1481994.12.03 added FNM_SEP_LEV2
1491994.12.06 stderr -> STDERR; STDERR #defined to stdout
1501994.12.10 fopenWithPthAndExt() copes with NULL for pth or ext
1511995.03.25 added osstrdup
1521995.06.26 fixed bug with UsePth("",leafname)
1531995.10.06 commented out some debug code
1541995.10.11 fixed getline to take a buffer length
1551996.02.10 pszTable entries can now be NULL, as can szSingTab
1561996.02.19 fixed 2 sizeof() to ossizeof()
1571996.03.22 fettled layout
1581996.05.05 added CDECL
1591997.01.19 started code to support multiple charsets at once
1601997.01.22 finished off up charset code (merged in tex.h):
161>1993.11.20 created
162>1993.11.26 moved chOpenQuotes and chCloseQuotes to here too
163>1994.03.13 characters 128-159 translated to \xXX codes to placate compilers
164>1994.03.23 added caveat comment about top-bit-set characters
165>1994.12.03 added -DISO8859_1 to makefile to force iso-8859-1
166>1995.02.14 changed "char foo[]=" to "char *foo="
167>1996.02.10 pszTable is now an array of char *, which can be NULL
168>          szSingTab can also be NULL
1691997.06.05 added const
1701998.03.04 more const
1711998.03.21 fixed up to compile cleanly on Linux
172*/
173
174/* Beware: This file contains top-bit-set characters (160-255), so be     */
175/* careful of mailers, ascii ftp, etc                                     */
176
177/* Tables for TeX style accented chars, etc for use with Survex           */
178/* Copyright (C) Olly Betts 1993-1996                                     */
179
180/* NB if (as in TeX) \o and \O mean slashed-o and slashed-O, we can't
181 * have \oe and \OE for linked-oe and linked-OE without cleverer code.
182 * Therefore, I've changed slashed-o and slashed-O to \/o and \/O.
183 */
184
185/*
186Function List
187xosmalloc:       malloc, but indirected so we can eg do DOS XMS malloc
188osmalloc:        ditto, but traps failure and gives fatal error
189xosrealloc:      realloc, but indirected so we can eg do DOS XMS malloc
190osrealloc:       ditto, but traps failure and gives fatal error
191osfree:          free, but indirected so we can eg do DOS XMS malloc
192report_sig:      catches signals and prints explanatory message
193ReadErrorFile:   initialisation function - should be called first (ish)
194warning:         report warning
195error:           report error
196fatal:           report fatal error and exit
197fAbsoluteFnm:    is fnm definitely absolute?
198fAmbiguousFnm:   could fnm be interpreted as both absolute and relative?
199PthFromFnm:      extract path from fnm
200LfFromFnm:       extract leafname from fnm
201UsePth:          concatenate path & leafname
202UseExt:          bung an extension on
203fopenWithPthAndExt:
204                 open file, passing back filename actually used
205safe_fopen:      like fopen, but returns NULL for directories under all OS
206*/
207
208#include <stdio.h>
209#include <stdlib.h>
210#include <string.h>
211#include <ctype.h>
212#include <limits.h>
213#include <errno.h>
214
215#include "whichos.h"
216#include "filename.h"
217#include "message.h"
218#include "osdepend.h"
219#include "filelist.h"
220#include "debug.h"
221#include "version.h"
222
223#ifdef HAVE_SIGNAL
224# ifdef HAVE_SETJMP
225#  include <setjmp.h>
226static jmp_buf jmpbufSignal;
227#  include <signal.h>
228# else
229#  undef HAVE_SIGNAL
230# endif
231#endif
232
233/* This is the name of the default language -- set like this so folks can
234 * add (for eg) -DDEFAULTLANG="fr" to UFLG in the makefile
235 */
236#ifndef DEFAULTLANG
237# define DEFAULTLANG "en"
238#endif
239
240#define STDERR stdout
241
242/* For funcs which want to be immune from messing around with different
243 * calling conventions */
244#ifndef CDECL
245#define CDECL
246#endif
247
248/* These are English versions of messages which might be needed before the
249 * alternative language version has been read from the message file.
250 */
251static const char * ergBootstrap[]={
252   "",
253   "Out of memory (couldn't find %ul bytes).\n",
254   "\nFatal error from %s: ",
255   "\nError from %s: ",
256   "\nWarning from %s: ",
257   "Message file has incorrect format\n", /* was "Error message file ..." */
258   "Negative error numbers are not allowed\n",
259   NULL /* NULL marks end of list */
260};
261
262static const char **erg = ergBootstrap;
263static int enMac = 32; /* Initially, grows automatically */
264static const char *szBadEn = "???";
265
266static int cWarnings = 0; /* keep track of how many warnings we've given */
267static int cErrors = 0;   /* and how many (non-fatal) errors */
268
269extern int error_summary(void) {
270   fprintf(STDERR,msg(16),cWarnings,cErrors);
271   fputnl(STDERR);
272   return ( cErrors ? EXIT_FAILURE : EXIT_SUCCESS );
273}
274
275/* in case osmalloc() fails before szAppNameCopy is set up */
276static const char *szAppNameCopy="anonymous program";
277
278/* error code for failed osmalloc and osrealloc calls */
279static void outofmem(OSSIZE_T size) {
280   fprintf( STDERR, erg[2], szAppNameCopy );
281   fprintf( STDERR, erg[1], (unsigned long)size );
282   exit(EXIT_FAILURE);
283}
284
285/* malloc with error catching if it fails. Also allows us to write special
286 * versions easily eg for DOS EMS or MS Windows.
287 */
288extern void FAR * osmalloc( OSSIZE_T size ) {
289   void FAR *p;
290   p=xosmalloc( size );
291   if (p==NULL)
292      outofmem(size);
293   return p;
294}
295
296/* realloc with error catching if it fails. */
297extern void FAR * osrealloc( void *p, OSSIZE_T size ) {
298   p=xosrealloc(p,size);
299   if (p==NULL)
300      outofmem(size);
301   return p;
302}
303
304extern void FAR * osstrdup( const char *sz ) {
305   char *p;
306   int len;
307   len=strlen(sz)+1;
308   p=osmalloc(len);
309   memmove(p,sz,len);
310   return p;
311}
312
313/* osfree is currently a macro in error.h */
314
315#ifdef HAVE_SIGNAL
316
317static int sigReceived;
318
319/* for systems not using autoconf, assume the signal handler returns void
320 * unless specified elsewhere */
321#ifndef RETSIGTYPE
322#define RETSIGTYPE void
323#endif
324
325static CDECL RETSIGTYPE FAR report_sig( int sig ) {
326   sigReceived=sig;
327   longjmp(jmpbufSignal,1);
328}
329
330static void init_signals( void ) {
331   int en;
332   if (!setjmp(jmpbufSignal)) {
333      signal(SIGABRT,report_sig); /* abnormal termination eg abort() */
334      signal(SIGFPE ,report_sig); /* arithmetic error eg /0 or overflow */
335      signal(SIGILL ,report_sig); /* illegal function image eg illegal instruction */
336      signal(SIGINT ,report_sig); /* interactive attention eg interrupt */
337      signal(SIGSEGV,report_sig); /* illegal storage access eg access outside memory limits */
338      signal(SIGTERM,report_sig); /* termination request sent to program */
339# ifdef SIGSTAK /* only on RISC OS AFAIK */
340      signal(SIGSTAK,report_sig); /* stack overflow */
341# endif
342      return;
343   }
344   fprintf(STDERR,msg(2),szAppNameCopy);
345   switch (sigReceived) {
346    case SIGABRT: en=90; break;
347    case SIGFPE:  en=91; break;
348    case SIGILL:  en=92; break;
349    case SIGINT:  en=93; break;
350    case SIGSEGV: en=94; break;
351    case SIGTERM: en=95; break;
352# ifdef SIGSTAK
353    case SIGSTAK: en=96; break;
354# endif
355    default:      en=97; break;
356   }
357   fputsnl(msg(en),STDERR);
358   if (errno >= 0) {
359# ifdef HAVE_STRERROR
360      fputsnl(strerror(errno),STDERR);
361# elif defined(HAVE_SYS_ERRLIST)
362      if (errno < sys_nerr)
363         fputsnl( STDERR, sys_errlist[errno] );
364# elif defined(HAVE_PERROR)
365      perror(NULL); /* always goes to stderr */
366      /* if (arg!=NULL && *arg!='\0') fputs("<arg>: <err>\n",stderr); */
367      /* else fputs("<err>\n",stderr); */
368# else
369      fprintf( STDERR, "error code %d\n", errno );
370# endif
371   }
372   if (sigReceived!=SIGINT && sigReceived!=SIGTERM)
373      fatal(11,NULL,NULL,0); /* shouldn't get any others => bug */
374   exit(EXIT_FAILURE);
375}
376#endif
377
378/* write string and nl to STDERR */
379extern void wr( const char *sz, int n ) {
380   n=n; /* suppress warning */
381   fputsnl(sz,STDERR);
382}
383
384#define CHARSET_BAD       -1
385#define CHARSET_USASCII    0
386#define CHARSET_ISO_8859_1 1
387#define CHARSET_DOSCP850   2
388#define CHARSET_RISCOS31   3
389static int default_charset( void ) {
390#ifdef ISO8859_1
391   return CHARSET_ISO_8859_1;
392#elif (OS==RISCOS)
393/*
394RISCOS 3.1 and above
395CHARSET_RISCOS31 !HCAK!
396*/
397   return CHARSET_ISO_8859_1;
398#elif (OS==MSDOS)
399   return CHARSET_DOSCP850;
400#else
401   return CHARSET_ISO_8859_1; /*!HACK!*/
402#endif
403}
404
405static const char *pthMe = NULL, *lfErrs = NULL;
406static char prefix[32];
407static int prefix_len;
408
409static char prefix_root[32];
410static int prefix_root_len;
411
412static int add_unicode(int charset, char *p, int value) {
413   if (value == 0) return 0;
414   if (charset == CHARSET_ISO_8859_1 && value < 256) {
415      *p = value;
416      return 1;
417   }
418   return 0;
419}
420
421static int decode_entity(const char *entity, size_t len) {
422   unsigned long value = 0;
423   int i;
424   for (i = 0; i < 4 && i < len; i++) value = (value<<8) | entity[i];
425   switch (value) {
426    case 'nbsp': return 160;
427    case 'iexc': return 161;
428    case 'cent': return 162;
429    case 'poun': return 163;
430    case 'curr': return 164;
431    case 'yen': return 165;
432    case 'brvb': return 166;
433    case 'sect': return 167;
434    case 'uml': return 168;
435    case 'copy': return 169;
436    case 'ordf': return 170;
437    case 'laqu': return 171;
438    case 'not': return 172;
439    case 'shy': return 173;
440    case 'reg': return 174;
441    case 'macr': return 175;
442    case 'deg': return 176;
443    case 'plus': return 177;
444    case 'sup2': return 178;
445    case 'sup3': return 179;
446    case 'acut': return 180;
447    case 'micr': return 181;
448    case 'para': return 182;
449    case 'midd': return 183;
450    case 'cedi': return 184;
451    case 'sup1': return 185;
452    case 'ordm': return 186;
453    case 'raqu': return 187;
454#if 0
455    case 'frac': return 188;
456    case 'frac': return 189;
457    case 'frac': return 190;
458#endif
459    case 'ique': return 191;
460    case 'Agra': return 192;
461    case 'Aacu': return 193;
462    case 'Acir': return 194;
463    case 'Atil': return 195;
464    case 'Auml': return 196;
465    case 'Arin': return 197;
466    case 'AEli': return 198;
467    case 'Cced': return 199;
468    case 'Egra': return 200;
469    case 'Eacu': return 201;
470    case 'Ecir': return 202;
471    case 'Euml': return 203;
472    case 'Igra': return 204;
473    case 'Iacu': return 205;
474    case 'Icir': return 206;
475    case 'Iuml': return 207;
476    case 'ETH': return 208;
477    case 'Ntil': return 209;
478    case 'Ogra': return 210;
479    case 'Oacu': return 211;
480    case 'Ocir': return 212;
481    case 'Otil': return 213;
482    case 'Ouml': return 214;
483    case 'time': return 215;
484    case 'Osla': return 216;
485    case 'Ugra': return 217;
486    case 'Uacu': return 218;
487    case 'Ucir': return 219;
488    case 'Uuml': return 220;
489    case 'Yacu': return 221;
490    case 'THOR': return 222;
491    case 'szli': return 223;
492    case 'agra': return 224;
493    case 'aacu': return 225;
494    case 'acir': return 226;
495    case 'atil': return 227;
496    case 'auml': return 228;
497    case 'arin': return 229;
498    case 'aeli': return 230;
499    case 'cced': return 231;
500    case 'egra': return 232;
501    case 'eacu': return 233;
502    case 'ecir': return 234;
503    case 'euml': return 235;
504    case 'igra': return 236;
505    case 'iacu': return 237;
506    case 'icir': return 238;
507    case 'iuml': return 239;
508    case 'eth': return 240;
509    case 'ntil': return 241;
510    case 'ogra': return 242;
511    case 'oacu': return 243;
512    case 'ocir': return 244;
513    case 'otil': return 245;
514    case 'ouml': return 246;
515    case 'divi': return 247;
516    case 'osla': return 248;
517    case 'ugra': return 249;
518    case 'uacu': return 250;
519    case 'ucir': return 251;
520    case 'uuml': return 252;
521    case 'yacu': return 253;
522    case 'thor': return 254;
523    case 'yuml': return 255;
524   }
525   return 0;
526}
527
528static void parse_msg_file( int charset_code ) {
529  FILE *fh;
530  char estr[512], line[512];
531  int en;
532  int c;
533  bool fQuoted;
534#ifndef NO_ACCENTS
535  char chOpenQuotes, chCloseQuotes;
536  char *szSingles;
537  char *szSingTab;
538  char *szAccents;
539  char *szLetters;
540  char **pszTable;
541
542  switch (charset_code) {
543     case CHARSET_USASCII: {
544        /* US ASCII */
545        chOpenQuotes = '\"';
546        chCloseQuotes = '\"';
547        szSingles = "";
548        szSingTab = NULL;
549        szAccents = "";
550        szLetters = "";
551        pszTable = NULL;
552        break;
553     }
554     case CHARSET_ISO_8859_1: {
555        /* ISO 8859/1 (Latin 1) */
556        static char *my_pszTable[]={
557         "àèòÀìùÈÌÒÙ",
558         "áéóÁíúÉÍÓÚýÝ",
559         "âêôÂîûÊÎÔÛ",
560         "äëöÄïüËÏÖÜÿ",
561         "ã õà   Õ   ñÑ",
562         NULL,
563         NULL,
564         NULL,
565         NULL,
566         NULL,
567         NULL,
568         "              ç",
569         "               Ç",
570         NULL,
571         "ª º",
572         "åæ",
573         "   Å  Æ",
574         "                  ß",
575         NULL,
576         NULL,
577         "  ø     Ø"
578        };
579        chOpenQuotes = '\"';
580        chCloseQuotes = '\"';
581        szSingles = "";
582        szSingTab = NULL;
583        szAccents = "`'^\"~=.uvHtcCdbaAsOo/";
584        szLetters = "aeoAiuEIOUyYnNcCwWs";
585        pszTable = my_pszTable;
586        break;
587     }
588     case CHARSET_RISCOS31: {
589        /* Archimedes RISC OS 3.1 and above
590         * ISO 8859/1 (Latin 1) + extensions in 128-159 */
591        static char *my_pszTable[]={
592         "àèòÀìùÈÌÒÙ",
593         "áéóÁíúÉÍÓÚýÝ",
594         "âêôÂîûÊÎÔÛ\x86\x85    \x82\x81",
595         "äëöÄïüËÏÖÜÿ",
596         "ã õà   Õ   ñÑ",
597         NULL,
598         NULL,
599         NULL,
600         NULL,
601         NULL,
602         NULL,
603         "              ç",
604         "               Ç",
605         NULL,
606         "ª º",
607         "åæ",
608         "   Å  Æ",
609         "                  ß",
610         "      \x9a",
611         " \x9b",
612         "  ø     Ø"
613        };
614        chOpenQuotes='\x94';
615        chCloseQuotes='\x95';
616        szSingles="";
617        szSingTab=NULL;
618        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
619        szLetters="aeoAiuEIOUyYnNcCwWs";
620        pszTable = my_pszTable;
621        break;
622     }
623     case CHARSET_DOSCP850: {
624        /* MS DOS - Code page 850 */
625        static char *my_pszTable[]={
626         "\x85\x8A\x95·\x8D\x97Ô ãëìí",
627         " \x82¢µ¡£\x90Öàé",
628         "\x83\x88\x93¶\x8C\x96Ò×âê",
629         "\x84\x89\x94\x8E\x8B\x81ÓØ\x99\x9A\x98",
630         "Æ äÇ    å   ¤¥",
631         NULL,
632         NULL,
633         NULL,
634         NULL,
635         NULL,
636         NULL,
637         "              \x87",
638         "               \x80",
639         NULL,
640         "¦ §",
641         "\x86\x91",
642         "   \x8F  \x92",
643         "                  á",
644         NULL,
645         NULL,
646         "  \x9B     \x9D"
647        };
648        chOpenQuotes='\"';
649        chCloseQuotes='\"';
650        szSingles="lLij";
651        szSingTab="  Õ";
652        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
653        szLetters="aeoAiuEIOUyYnNcCwWs";
654        pszTable = my_pszTable;
655        break;
656     }
657#if 0
658/* MS DOS - PC-8 (code page 437?) */
659static char chOpenQuotes='\"', chCloseQuotes='\"';
660static char *szSingles="";
661static char *szSingTab=NULL;
662static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
663static char *szLetters="aeoAiuEIOUyYnNcCwWs";
664static char *pszTable[]={
665 "\x85\x8A\x95 \x8D\x97",
666 " \x82¢ ¡£\x90",
667 "\x83\x88\x93 \x8C\x96",
668 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
669 "            ¤¥",
670 NULL,
671 NULL,
672 NULL,
673 NULL,
674 NULL,
675 NULL,
676 "              \x87",
677 "               \x80",
678 NULL,
679 "¦ §",
680 "\x86\x91",
681 "   \x8F  \x92",
682 "                  á",
683 NULL,
684 NULL,
685 NULL
686};
687
688#elif 0
689/* MS DOS - PC-8 Denmark/Norway */
690static char chOpenQuotes='\"', chCloseQuotes='\"';
691static char *szSingles="";
692static char *szSingTab=NULL;
693static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
694static char *szLetters="aeoAiuEIOUyYnNcCwWs";
695static char *pszTable[]={
696 "\x85\x8A\x95 \x8D\x97",
697 " \x82¢ ¡£\x90     ¬",
698 "\x83\x88\x93 \x8C\x96",
699 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
700 "© ¦ª    §   ¤¥",
701 NULL,
702 NULL,
703 NULL,
704 NULL,
705 NULL,
706 NULL,
707 "              \x87",
708 "               \x80",
709 NULL,
710 NULL,
711 "\x86\x91",
712 "   \x8F  \x92",
713 "                  á",
714 NULL,
715 NULL,
716 NULL
717};
718#elif 0
719/* No special chars... */
720# define NO_TEX
721#endif
722default: /*!HACK! do something -- no_tex variable version of NO_TEX ? */
723printf("oops, bad charset...\n");
724(void)0;
725  }
726#endif
727
728#if 0
729printf("opening error file\n");
730printf("(%s %s)\n",pthMe,lfErrs);
731#endif
732  fh=fopenWithPthAndExt( pthMe, lfErrs, "", "rb", NULL );
733#if 0
734printf("opened error file\n");
735#endif
736  if (!fh) {
737    /* no point extracting this error, as it won't get used if file opens */
738    fprintf(STDERR, erg[3], szAppNameCopy );
739    fprintf(STDERR, "Can't open message file '%s' using path '%s'\n",
740            lfErrs, pthMe);
741    exit(EXIT_FAILURE);
742  }
743
744  { /* copy bootstrap erg[] which'll get overwritten by file entries */
745     const char **ergMalloc;
746     erg = ergBootstrap;
747     ergMalloc = osmalloc( enMac * ossizeof(char*) );
748     /* NULL marks end of list */
749     for ( en = 0 ; erg[en] ; en++ ) ergMalloc[en]=erg[en];
750     for ( ; en < enMac ; en++ ) ergMalloc[en] = szBadEn;
751     erg = ergMalloc;
752  }
753
754  while (!feof( fh )) {
755    char *p;
756    char *q;
757    int exact;
758    getline( line, ossizeof(line), fh );
759    if ((exact = (strncmp(line, prefix, prefix_len) == 0)) ||
760        (prefix_root_len && strncmp(line, prefix_root, prefix_root_len) == 0)) {
761      long val;
762      val = strtol( line + (exact?prefix_len:prefix_root_len), &q, 0);
763      if (val < 0 || val > (unsigned long)INT_MAX) {
764        fprintf( STDERR, erg[3], szAppNameCopy );
765        fprintf( STDERR, erg[ (errno==ERANGE) ? 5 : 6 ] );
766        exit(EXIT_FAILURE);
767      }
768      en = (int)val;
769      while (isspace(*q)) q++;
770
771      p = q + strlen(q);
772      while (p > q && isspace(p[-1])) p--;
773
774      fQuoted = (p > q + 1 && *q == '\"' && *(p-1) == '\"');
775      if (fQuoted) {
776         q++;
777         p--;
778      }
779      *p = '\0';
780
781      c = 0;
782      while (*q) {
783         if (*q == '&') {
784            if (*(q+1) == '#') {
785               if (isdigit(q[2])) {
786                  unsigned long value = strtoul( q+2, &q, 10);
787                  if (*q == ';') q++;
788                  if (value < 127) {
789                     estr[c++] = (char)value;
790                  } else {
791                     c += add_unicode(charset_code, estr+c, value);
792                  }
793                  continue;
794               }
795            } else if (isalnum(q[1])) { /* or isalpha? !HACK! */
796               /*const*/ char *entity;
797               int entity_len;
798               int len;
799               entity = q+1;
800               q += 2;
801               while (isalnum(*q)) q++;
802               entity_len = q - entity;
803               if (*q == ';') q++;
804               len = add_unicode(charset_code, estr+c, decode_entity(entity, entity_len));
805               if (len) {
806                  c += len;
807                  continue;
808               }
809               q = entity - 1;
810            }
811         }
812         if (*q < 32 || *q >= 127) {
813            fprintf(STDERR, "Warning: literal character '%c' (value %d) "
814                    "in message %d\n", *q, (int)*q, en);
815         }
816         estr[c++] = *q++;
817      }
818      estr[c] = '\0';
819
820      if (en >= enMac) {
821         int enTmp;
822         enTmp = enMac;
823         enMac = enMac<<1;
824         erg = osrealloc( erg, enMac * ossizeof(char*) );
825         while (enTmp < enMac) erg[enTmp++] = szBadEn;
826      }
827      erg[en] = osstrdup(estr);
828/*printf("Error number %d: %s\n",en,erg[en]);*/
829    }
830  }
831  fclose(fh);
832}
833
834extern const char * FAR ReadErrorFile( const char *szAppName, const char *szEnvVar,
835                                       const char *szLangVar, const char *argv0,
836                                       const char *lfErrFile ) {
837   int  c;
838   char *szTmp;
839
840   lfErrs = osstrdup(lfErrFile);
841#ifdef HAVE_SIGNAL
842   init_signals();
843#endif
844   /* This code *should* be completely bomb-proof even if strcpy
845    * generates a signal
846    */
847   szAppNameCopy = szAppName; /* ... in case the osstrdup() fails */
848   szAppNameCopy = osstrdup(szAppName);
849
850   /* Look for env. var. "SURVEXHOME" or the like */
851   if (szEnvVar && *szEnvVar && (szTmp=getenv(szEnvVar))!=NULL && *szTmp) {
852      pthMe = osstrdup(szTmp);
853   } else if (argv0) {
854      /* else try the path on argv[0] */
855      pthMe = PthFromFnm(argv0);
856   } else {
857      /* otherwise, forget it - go for the current directory */
858      pthMe = "";
859   }
860
861   /* Look for env. var. "SURVEXLANG" or the like */
862   if ((szTmp=getenv(szLangVar))==0 || !*szTmp) {
863      szTmp = DEFAULTLANG;
864   }
865   for (c = 0 ; c < 4 && szTmp[c] ; c++) prefix[c] = tolower(szTmp[c]);
866   prefix[c] = '\0';
867   if (c == 4) {
868      if (strcmp(prefix, "engi") == 0) {
869         strcpy(prefix, "en");
870      } else if (strcmp(prefix, "engu") == 0) {
871         strcpy(prefix, "en-us");
872      } else if (strcmp(prefix, "fren") == 0) {
873         strcpy(prefix, "fr");
874      } else if (strcmp(prefix, "germ") == 0) {
875         strcpy(prefix, "de");
876      } else if (strcmp(prefix, "ital") == 0) {
877         strcpy(prefix, "it");
878      } else if (strcmp(prefix, "span") == 0) {
879         strcpy(prefix, "es");
880      } else if (strcmp(prefix, "cata") == 0) {
881         strcpy(prefix, "ca");
882      } else if (strcmp(prefix, "port") == 0) {
883         strcpy(prefix, "pt");
884      } else {
885         while (szTmp[c] && c < sizeof(prefix)) {
886            prefix[c] = tolower(szTmp[c]);
887            c++;
888         }
889         prefix[c] = '\0';
890      }
891   }
892   strcat(prefix, ":");
893   prefix_len = strlen(prefix);
894
895   /* If the language is something like "en-us", fallback to "en" if we don't
896    * have an entry for en-us */
897   szTmp = strchr(prefix, '-');
898   if (szTmp) {
899      c = szTmp - prefix;
900      memcpy(prefix_root, prefix, c);
901      prefix_root[c++] = ':';
902      prefix_root[c] = '\0';
903      prefix_root_len = strlen(prefix_root);
904   } else {
905      prefix_root_len = 0;
906   }
907
908  select_charset(default_charset());
909
910  if (erg[0]==szBadEn) {
911    fprintf(STDERR, erg[3], szAppName );
912    /* no point extracting this message */
913    fprintf(STDERR, "No messages in language '%s'\n",prefix);
914    exit(EXIT_FAILURE);
915  }
916  if (strcmp(MESSAGE_VERSION_MIN,erg[0])>0 || strcmp(VERSION,erg[0])<0)
917    /* a little tacky, but'll work */
918    fatal(191,wr,MESSAGE_VERSION_MIN" - "VERSION,0);
919
920  return pthMe;
921}
922
923extern const char *msg( int en ) /* message may be overwritten by next call */ {
924  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
925}
926
927extern const char *msgPerm( int en ) /* returns persistent copy of message */ {
928  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
929}
930
931static void FAR errdisp( int en, void (*fn)( const char *, int ), const char *arg, int n,
932                         int type ) {
933   fputnl( STDERR );
934   fputnl( STDERR );
935   fprintf( STDERR, erg[type], szAppNameCopy );
936   fputs( msg(en), STDERR);
937   fputnl( STDERR );
938   if (fn) (fn)(arg, n);
939/*   if (fn) (fn)( (arg ? arg : "(null)"), n);*/
940}
941
942extern void FAR warning( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
943   cWarnings++;
944   errdisp( en, fn, szArg, n, 4 );
945}
946
947extern void FAR error( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
948   cErrors++;
949   errdisp( en, fn, szArg, n, 3 );
950   /* non-fatal errors now return... */
951}
952
953extern void FAR fatal( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
954   errdisp( en, fn, szArg, n, 2 );
955   exit(EXIT_FAILURE);
956}
957
958#if 1
959/* Code to support switching character set at runtime (e.g. for a printer
960 * driver to support different character sets on screen and on the printer)
961 */
962typedef struct charset_li {
963   struct charset_li *next;
964   int code;
965   const char **erg;
966} charset_li;
967
968static charset_li *charset_head = NULL;
969
970static int charset = CHARSET_BAD;
971
972int select_charset( int charset_code ) {
973   int old_charset = charset;
974   charset_li *p;
975
976/*   printf( "select_charset(%d), old charset = %d\n", charset_code, charset ); */
977
978   charset = charset_code;
979
980   /* check if we've already parsed messages for new charset */
981   for( p = charset_head ; p ; p = p->next ) {
982/*      printf("%p: code %d erg %p\n",p,p->code,p->erg); */
983      if (p->code == charset) {
984         erg = p->erg;
985         goto found;
986      }
987   }
988
989   /* nope, got to reparse message file */
990   parse_msg_file( charset_code );
991
992   /* add to list */
993   p = osnew(charset_li);
994/*   p = osmalloc(256); */
995   p->code = charset;
996   p->erg = erg;
997   p->next = charset_head;
998   charset_head = p;
999
1000   found:
1001   return old_charset;
1002}
1003#endif
Note: See TracBrowser for help on using the repository browser.