source: git/src/message.c @ c025994

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 c025994 was b8d27ca, checked in by Olly Betts <olly@…>, 27 years ago

Minor fettles

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

  • Property mode set to 100644
File size: 33.7 KB
RevLine 
[60f7018]1/* message.c */
2
[a3e49dc]3/* ERRC show diffs to newer version of error.c - most that are left in here aren't relevant */
4
[60f7018]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
[a3e49dc]1691997.06.05 added const
1701998.03.04 more const
1711998.03.21 fixed up to compile cleanly on Linux
[60f7018]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"
[4432f2e]216#include "filename.h"
217#include "message.h"
[60f7018]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
[4432f2e]234 * add (for eg) -DDEFAULTLANG="fr" to UFLG in the makefile
[60f7018]235 */
236#ifndef DEFAULTLANG
[4432f2e]237# define DEFAULTLANG "en"
[60f7018]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
[2ca296b]245# define CDECL
[60f7018]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) {
[2ca296b]270   fprintf(STDERR, msg(16), cWarnings, cErrors);
[60f7018]271   fputnl(STDERR);
272   return ( cErrors ? EXIT_FAILURE : EXIT_SUCCESS );
273}
274
275/* in case osmalloc() fails before szAppNameCopy is set up */
[b8d27ca]276const char *szAppNameCopy = "anonymous program";
[60f7018]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;
[2ca296b]290   p = xosmalloc( size );
291   if (p == NULL) outofmem(size);
[60f7018]292   return p;
293}
294
295/* realloc with error catching if it fails. */
296extern void FAR * osrealloc( void *p, OSSIZE_T size ) {
[2ca296b]297   p = xosrealloc(p,size);
298   if (p == NULL) outofmem(size);
[60f7018]299   return p;
300}
301
302extern void FAR * osstrdup( const char *sz ) {
303   char *p;
304   int len;
[2ca296b]305   len = strlen(sz)+1;
306   p = osmalloc(len);
307   memcpy(p, sz, len);
[60f7018]308   return p;
309}
310
311/* osfree is currently a macro in error.h */
312
313#ifdef HAVE_SIGNAL
314
315static int sigReceived;
316
317/* for systems not using autoconf, assume the signal handler returns void
318 * unless specified elsewhere */
319#ifndef RETSIGTYPE
[2ca296b]320# define RETSIGTYPE void
[60f7018]321#endif
322
323static CDECL RETSIGTYPE FAR report_sig( int sig ) {
324   sigReceived=sig;
[2ca296b]325   longjmp(jmpbufSignal, 1);
[60f7018]326}
327
328static void init_signals( void ) {
329   int en;
330   if (!setjmp(jmpbufSignal)) {
331      signal(SIGABRT,report_sig); /* abnormal termination eg abort() */
332      signal(SIGFPE ,report_sig); /* arithmetic error eg /0 or overflow */
333      signal(SIGILL ,report_sig); /* illegal function image eg illegal instruction */
334      signal(SIGINT ,report_sig); /* interactive attention eg interrupt */
335      signal(SIGSEGV,report_sig); /* illegal storage access eg access outside memory limits */
336      signal(SIGTERM,report_sig); /* termination request sent to program */
337# ifdef SIGSTAK /* only on RISC OS AFAIK */
338      signal(SIGSTAK,report_sig); /* stack overflow */
339# endif
340      return;
341   }
342   fprintf(STDERR,msg(2),szAppNameCopy);
343   switch (sigReceived) {
344    case SIGABRT: en=90; break;
345    case SIGFPE:  en=91; break;
346    case SIGILL:  en=92; break;
347    case SIGINT:  en=93; break;
348    case SIGSEGV: en=94; break;
349    case SIGTERM: en=95; break;
350# ifdef SIGSTAK
351    case SIGSTAK: en=96; break;
352# endif
353    default:      en=97; break;
354   }
355   fputsnl(msg(en),STDERR);
356   if (errno >= 0) {
357# ifdef HAVE_STRERROR
358      fputsnl(strerror(errno),STDERR);
359# elif defined(HAVE_SYS_ERRLIST)
360      if (errno < sys_nerr)
361         fputsnl( STDERR, sys_errlist[errno] );
362# elif defined(HAVE_PERROR)
363      perror(NULL); /* always goes to stderr */
364      /* if (arg!=NULL && *arg!='\0') fputs("<arg>: <err>\n",stderr); */
365      /* else fputs("<err>\n",stderr); */
366# else
367      fprintf( STDERR, "error code %d\n", errno );
368# endif
369   }
370   if (sigReceived!=SIGINT && sigReceived!=SIGTERM)
371      fatal(11,NULL,NULL,0); /* shouldn't get any others => bug */
372   exit(EXIT_FAILURE);
373}
374#endif
375
376/* write string and nl to STDERR */
377extern void wr( const char *sz, int n ) {
378   n=n; /* suppress warning */
379   fputsnl(sz,STDERR);
380}
381
382#define CHARSET_BAD       -1
383#define CHARSET_USASCII    0
384#define CHARSET_ISO_8859_1 1
385#define CHARSET_DOSCP850   2
386#define CHARSET_RISCOS31   3
387static int default_charset( void ) {
388#ifdef ISO8859_1
389   return CHARSET_ISO_8859_1;
390#elif (OS==RISCOS)
[2ca296b]391/* RISCOS 3.1 and above CHARSET_RISCOS31 (ISO_8859_1 + extras in 128-159)
392 * RISCOS < 3.1 is ISO_8859_1 !HACK! */
393   return CHARSET_RISCOS31;
[60f7018]394#elif (OS==MSDOS)
395   return CHARSET_DOSCP850;
396#else
[2ca296b]397   return CHARSET_ISO_8859_1; /* Look at env var CHARSET ? !HACK! */
[60f7018]398#endif
399}
400
[4432f2e]401static const char *pthMe = NULL, *lfErrs = NULL;
402static char prefix[32];
[60f7018]403static int prefix_len;
404
[4432f2e]405static char prefix_root[32];
406static int prefix_root_len;
407
[48e4121]408#if (OS==MSDOS)
409static int xlate_dos_cp850(int unicode) {
410   switch (unicode) {
411/*# include "unicode-to-dos-cp-default.tab"*/
412case 160: return 255;
413case 161: return 173;
414case 162: return 189;
415case 163: return 156;
416case 164: return 207;
417case 165: return 190;
418case 167: return 245;
419case 168: return 249;
420case 169: return 184;
421case 170: return 166;
422case 171: return 174;
423case 172: return 170;
424case 173: return 240;
425case 174: return 169;
[2ca296b]426#if 0 /* !HACK! ?? */
[48e4121]427case 175: return 223;
428case 175: return 238;
429#endif
430case 176: return 248;
431case 177: return 241;
432case 178: return 253;
433case 179: return 252;
434case 180: return 239;
435case 181: return 230;
436case 182: return 244;
437case 183: return 250;
438case 184: return 247;
439case 185: return 251;
440case 186: return 167;
441case 187: return 175;
442case 188: return 172;
443case 189: return 171;
444case 190: return 243;
445case 191: return 168;
446case 192: return 183;
447case 193: return 181;
448case 194: return 182;
449case 195: return 199;
450case 196: return 142;
451case 197: return 143;
452case 198: return 146;
453case 199: return 128;
454case 200: return 212;
455case 201: return 144;
456case 202: return 210;
457case 203: return 211;
458case 204: return 222;
459case 205: return 214;
460case 206: return 215;
461case 207: return 216;
462case 208: return 209;
463case 209: return 165;
464case 210: return 227;
465case 211: return 224;
466case 212: return 226;
467case 213: return 229;
468case 214: return 153;
469case 215: return 158;
470case 216: return 157;
471case 217: return 235;
472case 218: return 233;
473case 219: return 234;
474case 220: return 154;
475case 221: return 237;
476case 222: return 232;
477case 223: return 225;
478case 224: return 133;
479case 225: return 160;
480case 226: return 131;
481case 227: return 198;
482case 228: return 132;
483case 229: return 134;
484case 230: return 145;
485case 231: return 135;
486case 232: return 138;
487case 233: return 130;
488case 234: return 136;
489case 235: return 137;
490case 236: return 141;
491case 237: return 161;
492case 238: return 140;
493case 239: return 139;
494case 240: return 208;
495case 241: return 164;
496case 242: return 149;
497case 243: return 162;
498case 244: return 147;
499case 245: return 228;
500case 246: return 148;
501case 247: return 246;
502case 248: return 155;
503case 249: return 151;
504case 250: return 163;
505case 251: return 150;
506case 252: return 129;
507case 253: return 236;
508case 254: return 231;
509case 255: return 152;
510   }
511   return 0;
512}
513#endif
514
[4432f2e]515static int add_unicode(int charset, char *p, int value) {
516   if (value == 0) return 0;
[48e4121]517   switch (charset) {
518    case CHARSET_USASCII:
519      if (value < 128) {
520         *p = value;
521         return 1;
522      }
523      break;
524    case CHARSET_ISO_8859_1:
525#if (OS==RISCOS)
526    case CHARSET_RISCOS31: /* RISC OS 3.1 has a few extras in 128-159 */
527#endif
528      if (value < 256) {
529         *p = value;
530         return 1;
531      }
532#if (OS==RISCOS)
533      /* !HACK! handle extras here */
534#endif
535      break;
536#if (OS==MSDOS)
537    case CHARSET_DOSCP850:
538      value = xlate_dos_cp850(value);
539      if (value) {
540         *p = value;
541         return 1;
542      }
543      break;
544#endif
[4432f2e]545   }
[f1a5201]546   return 0;
[4432f2e]547}
548
549static int decode_entity(const char *entity, size_t len) {
[48e4121]550   unsigned long value;   
[4432f2e]551   int i;
[48e4121]552   
553   if (len > 6) return 0;
554   value = entity[0] - '0';
555   if (value >= 'a' - '0') {
556      value += 36 - ('a' - '0');
557   } else if (value >= 'A' - '0') {
558      value += 10 - ('A' - '0');
559   }
560   for (i = 1; i < 6 && i < len; i++) {
561      int c;
562      c = toupper(entity[i]) - '0';
563      if (c >= 'A' - '0') c += 10 - ('A' - '0');
564      value = value * 36 + c;
565   }
[4432f2e]566   switch (value) {
[48e4121]567    case 17477224u: return 198; /* AElig */
568    case 622057730u: return 193; /* Aacute */
569    case 17380344u: return 194; /* Acirc */
570    case 632809418u: return 192; /* Agrave */
571    case 18080044u: return 197; /* Aring */
572    case 654238130u: return 195; /* Atilde */
573    case 506253u: return 196; /* Auml */
574    case 746420205u: return 199; /* Ccedil */
575    case 19205u: return 208; /* ETH */
576    case 863922434u: return 201; /* Eacute */
577    case 24098808u: return 202; /* Ecirc */
578    case 874674122u: return 200; /* Egrave */
579    case 692877u: return 203; /* Euml */
580    case 1105787138u: return 205; /* Iacute */
581    case 30817272u: return 206; /* Icirc */
582    case 1116538826u: return 204; /* Igrave */
583    case 879501u: return 207; /* Iuml */
584    case 1440298418u: return 209; /* Ntilde */
585    case 1468584194u: return 211; /* Oacute */
586    case 40894968u: return 212; /* Ocirc */
587    case 1479335882u: return 210; /* Ograve */
588    case 1499211233u: return 216; /* Oslash */
589    case 1500764594u: return 213; /* Otilde */
590    case 1159437u: return 214; /* Ouml */
591    case 49534115u: return 222; /* THORN */
592    case 1831381250u: return 218; /* Uacute */
593    case 50972664u: return 219; /* Ucirc */
594    case 1842132938u: return 217; /* Ugrave */
595    case 1439373u: return 220; /* Uuml */
596    case 2073245954u: return 221; /* Yacute */
597    case 2194178306u: return 225; /* aacute */
598    case 61050360u: return 226; /* acirc */
599    case 61065986u: return 180; /* acute */
600    case 61147240u: return 230; /* aelig */
601    case 2204929994u: return 224; /* agrave */
602    case 61750060u: return 229; /* aring */
603    case 2226358706u: return 227; /* atilde */
604    case 1719309u: return 228; /* auml */
605    case 2284059123u: return 166; /* brvbar */
606    case 2318540781u: return 231; /* ccedil */
607    case 64496109u: return 184; /* cedil */
608    case 1791929u: return 162; /* cent */
609    case 1804966u: return 169; /* copy */
610    case 2349398399u: return 164; /* curren */
611    case 51064u: return 176; /* deg */
612    case 2389884098u: return 247; /* divide */
613    case 2436043010u: return 233; /* eacute */
614    case 67768824u: return 234; /* ecirc */
615    case 2446794698u: return 232; /* egrave */
616    case 52901u: return 240; /* eth */
617    case 1905933u: return 235; /* euml */
618    case 2524944998u: return 189; /* frac12 */
619    case 2524945000u: return 188; /* frac14 */
620    case 2524945072u: return 190; /* frac34 */
621    case 2677907714u: return 237; /* iacute */
622    case 74487288u: return 238; /* icirc */
623    case 74599509u: return 161; /* iexcl */
624    case 2688659402u: return 236; /* igrave */
625    case 2705600621u: return 191; /* iquest */
626    case 2092557u: return 239; /* iuml */
627    case 79443312u: return 171; /* laquo */
628    case 2252907u: return 175; /* macr */
629    case 81477924u: return 181; /* micro */
630    case 2933233805u: return 183; /* middot */
631    case 2301433u: return 160; /* nbsp */
632    case 64397u: return 172; /* not */
633    case 3012418994u: return 241; /* ntilde */
634    case 3040704770u: return 243; /* oacute */
635    case 84564984u: return 244; /* ocirc */
636    case 3051456458u: return 242; /* ograve */
637    case 2368275u: return 170; /* ordf */
638    case 2368282u: return 186; /* ordm */
639    case 3071331809u: return 248; /* oslash */
640    case 3072885170u: return 245; /* otilde */
641    case 2372493u: return 246; /* ouml */
642    case 2393398u: return 182; /* para */
643    case 3120483695u: return 177; /* plusmn */
644    case 86819881u: return 163; /* pound */
645    case 89521008u: return 187; /* raquo */
646    case 69208u: return 174; /* reg */
647    case 2538029u: return 167; /* sect */
648    case 70630u: return 173; /* shy */
649    case 2559205u: return 185; /* sup1 */
650    case 2559206u: return 178; /* sup2 */
651    case 2559207u: return 179; /* sup3 */
652    case 92360104u: return 223; /* szlig */
653    case 93204131u: return 254; /* thorn */
654    case 93247732u: return 215; /* times */
655    case 3403501826u: return 250; /* uacute */
656    case 94642680u: return 251; /* ucirc */
657    case 3414253514u: return 249; /* ugrave */
658    case 73389u: return 168; /* uml */
659    case 2652429u: return 252; /* uuml */
660    case 3645366530u: return 253; /* yacute */
661    case 78287u: return 165; /* yen */
662    case 2839053u: return 255; /* yuml */
[4432f2e]663   }
664   return 0;
665}
666
[60f7018]667static void parse_msg_file( int charset_code ) {
668  FILE *fh;
[4432f2e]669  char estr[512], line[512];
[60f7018]670  int en;
671  int c;
672  bool fQuoted;
673#ifndef NO_ACCENTS
674  char chOpenQuotes, chCloseQuotes;
675  char *szSingles;
676  char *szSingTab;
677  char *szAccents;
678  char *szLetters;
679  char **pszTable;
680
681  switch (charset_code) {
682     case CHARSET_USASCII: {
683        /* US ASCII */
684        chOpenQuotes = '\"';
685        chCloseQuotes = '\"';
686        szSingles = "";
687        szSingTab = NULL;
688        szAccents = "";
689        szLetters = "";
690        pszTable = NULL;
691        break;
692     }
693     case CHARSET_ISO_8859_1: {
694        /* ISO 8859/1 (Latin 1) */
695        static char *my_pszTable[]={
696         "àèòÀìùÈÌÒÙ",
697         "áéóÁíúÉÍÓÚýÝ",
698         "âêôÂîûÊÎÔÛ",
699         "äëöÄïüËÏÖÜÿ",
700         "ã õà   Õ   ñÑ",
701         NULL,
702         NULL,
703         NULL,
704         NULL,
705         NULL,
706         NULL,
707         "              ç",
708         "               Ç",
709         NULL,
710         "ª º",
711         "åæ",
712         "   Å  Æ",
713         "                  ß",
714         NULL,
715         NULL,
716         "  ø     Ø"
717        };
718        chOpenQuotes = '\"';
719        chCloseQuotes = '\"';
720        szSingles = "";
721        szSingTab = NULL;
722        szAccents = "`'^\"~=.uvHtcCdbaAsOo/";
723        szLetters = "aeoAiuEIOUyYnNcCwWs";
724        pszTable = my_pszTable;
725        break;
726     }
727     case CHARSET_RISCOS31: {
728        /* Archimedes RISC OS 3.1 and above
729         * ISO 8859/1 (Latin 1) + extensions in 128-159 */
730        static char *my_pszTable[]={
731         "àèòÀìùÈÌÒÙ",
732         "áéóÁíúÉÍÓÚýÝ",
733         "âêôÂîûÊÎÔÛ\x86\x85    \x82\x81",
734         "äëöÄïüËÏÖÜÿ",
735         "ã õà   Õ   ñÑ",
736         NULL,
737         NULL,
738         NULL,
739         NULL,
740         NULL,
741         NULL,
742         "              ç",
743         "               Ç",
744         NULL,
745         "ª º",
746         "åæ",
747         "   Å  Æ",
748         "                  ß",
749         "      \x9a",
750         " \x9b",
751         "  ø     Ø"
752        };
753        chOpenQuotes='\x94';
754        chCloseQuotes='\x95';
755        szSingles="";
756        szSingTab=NULL;
757        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
758        szLetters="aeoAiuEIOUyYnNcCwWs";
759        pszTable = my_pszTable;
760        break;
761     }
762     case CHARSET_DOSCP850: {
763        /* MS DOS - Code page 850 */
764        static char *my_pszTable[]={
765         "\x85\x8A\x95·\x8D\x97Ô ãëìí",
766         " \x82¢µ¡£\x90Öàé",
767         "\x83\x88\x93¶\x8C\x96Ò×âê",
768         "\x84\x89\x94\x8E\x8B\x81ÓØ\x99\x9A\x98",
769         "Æ äÇ    å   ¤¥",
770         NULL,
771         NULL,
772         NULL,
773         NULL,
774         NULL,
775         NULL,
776         "              \x87",
777         "               \x80",
778         NULL,
779         "¦ §",
780         "\x86\x91",
781         "   \x8F  \x92",
782         "                  á",
783         NULL,
784         NULL,
785         "  \x9B     \x9D"
786        };
787        chOpenQuotes='\"';
788        chCloseQuotes='\"';
789        szSingles="lLij";
790        szSingTab="  Õ";
791        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
792        szLetters="aeoAiuEIOUyYnNcCwWs";
793        pszTable = my_pszTable;
794        break;
795     }
796#if 0
797/* MS DOS - PC-8 (code page 437?) */
798static char chOpenQuotes='\"', chCloseQuotes='\"';
799static char *szSingles="";
800static char *szSingTab=NULL;
801static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
802static char *szLetters="aeoAiuEIOUyYnNcCwWs";
803static char *pszTable[]={
804 "\x85\x8A\x95 \x8D\x97",
805 " \x82¢ ¡£\x90",
806 "\x83\x88\x93 \x8C\x96",
807 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
808 "            ¤¥",
809 NULL,
810 NULL,
811 NULL,
812 NULL,
813 NULL,
814 NULL,
815 "              \x87",
816 "               \x80",
817 NULL,
818 "¦ §",
819 "\x86\x91",
820 "   \x8F  \x92",
821 "                  á",
822 NULL,
823 NULL,
824 NULL
825};
826
827#elif 0
828/* MS DOS - PC-8 Denmark/Norway */
829static char chOpenQuotes='\"', chCloseQuotes='\"';
830static char *szSingles="";
831static char *szSingTab=NULL;
832static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
833static char *szLetters="aeoAiuEIOUyYnNcCwWs";
834static char *pszTable[]={
835 "\x85\x8A\x95 \x8D\x97",
836 " \x82¢ ¡£\x90     ¬",
837 "\x83\x88\x93 \x8C\x96",
838 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
839 "© ¦ª    §   ¤¥",
840 NULL,
841 NULL,
842 NULL,
843 NULL,
844 NULL,
845 NULL,
846 "              \x87",
847 "               \x80",
848 NULL,
849 NULL,
850 "\x86\x91",
851 "   \x8F  \x92",
852 "                  á",
853 NULL,
854 NULL,
855 NULL
856};
857#elif 0
858/* No special chars... */
859# define NO_TEX
860#endif
861default: /*!HACK! do something -- no_tex variable version of NO_TEX ? */
862printf("oops, bad charset...\n");
863(void)0;
864  }
865#endif
866
867#if 0
868printf("opening error file\n");
869printf("(%s %s)\n",pthMe,lfErrs);
870#endif
871  fh=fopenWithPthAndExt( pthMe, lfErrs, "", "rb", NULL );
872#if 0
873printf("opened error file\n");
874#endif
875  if (!fh) {
876    /* no point extracting this error, as it won't get used if file opens */
877    fprintf(STDERR, erg[3], szAppNameCopy );
878    fprintf(STDERR, "Can't open message file '%s' using path '%s'\n",
[a3e49dc]879            lfErrs, pthMe);
[60f7018]880    exit(EXIT_FAILURE);
881  }
882
883  { /* copy bootstrap erg[] which'll get overwritten by file entries */
[a3e49dc]884     const char **ergMalloc;
885     erg = ergBootstrap;
886     ergMalloc = osmalloc( enMac * ossizeof(char*) );
887     /* NULL marks end of list */
888     for ( en = 0 ; erg[en] ; en++ ) ergMalloc[en]=erg[en];
889     for ( ; en < enMac ; en++ ) ergMalloc[en] = szBadEn;
890     erg = ergMalloc;
[60f7018]891  }
892
893  while (!feof( fh )) {
[4432f2e]894    char *p;
895    char *q;
896    int exact;
[60f7018]897    getline( line, ossizeof(line), fh );
[4432f2e]898    if ((exact = (strncmp(line, prefix, prefix_len) == 0)) ||
899        (prefix_root_len && strncmp(line, prefix_root, prefix_root_len) == 0)) {
900      long val;
901      val = strtol( line + (exact?prefix_len:prefix_root_len), &q, 0);
[60f7018]902      if (val < 0 || val > (unsigned long)INT_MAX) {
903        fprintf( STDERR, erg[3], szAppNameCopy );
904        fprintf( STDERR, erg[ (errno==ERANGE) ? 5 : 6 ] );
905        exit(EXIT_FAILURE);
906      }
907      en = (int)val;
908      while (isspace(*q)) q++;
909
910      p = q + strlen(q);
911      while (p > q && isspace(p[-1])) p--;
912
913      fQuoted = (p > q + 1 && *q == '\"' && *(p-1) == '\"');
914      if (fQuoted) {
915         q++;
916         p--;
917      }
918      *p = '\0';
919
920      c = 0;
921      while (*q) {
922         if (*q == '&') {
923            if (*(q+1) == '#') {
[4432f2e]924               if (isdigit(q[2])) {
[60f7018]925                  unsigned long value = strtoul( q+2, &q, 10);
926                  if (*q == ';') q++;
[4432f2e]927                  if (value < 127) {
[f1a5201]928                     estr[c++] = (char)value;
[4432f2e]929                  } else {
930                     c += add_unicode(charset_code, estr+c, value);
931                  }
[60f7018]932                  continue;
933               }
[4432f2e]934            } else if (isalnum(q[1])) { /* or isalpha? !HACK! */
935               /*const*/ char *entity;
[60f7018]936               int entity_len;
[4432f2e]937               int len;
[60f7018]938               entity = q+1;
939               q += 2;
940               while (isalnum(*q)) q++;
941               entity_len = q - entity;
942               if (*q == ';') q++;
[4432f2e]943               len = add_unicode(charset_code, estr+c, decode_entity(entity, entity_len));
944               if (len) {
945                  c += len;
946                  continue;
947               }
[60f7018]948               q = entity - 1;
949            }
950         }
951         if (*q < 32 || *q >= 127) {
[4432f2e]952            fprintf(STDERR, "Warning: literal character '%c' (value %d) "
953                    "in message %d\n", *q, (int)*q, en);
[60f7018]954         }
955         estr[c++] = *q++;
956      }
957      estr[c] = '\0';
958
959      if (en >= enMac) {
960         int enTmp;
961         enTmp = enMac;
962         enMac = enMac<<1;
963         erg = osrealloc( erg, enMac * ossizeof(char*) );
964         while (enTmp < enMac) erg[enTmp++] = szBadEn;
965      }
[a3e49dc]966      erg[en] = osstrdup(estr);
[60f7018]967/*printf("Error number %d: %s\n",en,erg[en]);*/
968    }
969  }
970  fclose(fh);
971}
972
973extern const char * FAR ReadErrorFile( const char *szAppName, const char *szEnvVar,
974                                       const char *szLangVar, const char *argv0,
975                                       const char *lfErrFile ) {
[4432f2e]976   int  c;
977   char *szTmp;
[60f7018]978
[4432f2e]979   lfErrs = osstrdup(lfErrFile);
[60f7018]980#ifdef HAVE_SIGNAL
[4432f2e]981   init_signals();
[60f7018]982#endif
[4432f2e]983   /* This code *should* be completely bomb-proof even if strcpy
984    * generates a signal
985    */
986   szAppNameCopy = szAppName; /* ... in case the osstrdup() fails */
987   szAppNameCopy = osstrdup(szAppName);
988
989   /* Look for env. var. "SURVEXHOME" or the like */
990   if (szEnvVar && *szEnvVar && (szTmp=getenv(szEnvVar))!=NULL && *szTmp) {
991      pthMe = osstrdup(szTmp);
992   } else if (argv0) {
993      /* else try the path on argv[0] */
994      pthMe = PthFromFnm(argv0);
995   } else {
996      /* otherwise, forget it - go for the current directory */
997      pthMe = "";
998   }
[f1a5201]999
[4432f2e]1000   /* Look for env. var. "SURVEXLANG" or the like */
1001   if ((szTmp=getenv(szLangVar))==0 || !*szTmp) {
1002      szTmp = DEFAULTLANG;
1003   }
1004   for (c = 0 ; c < 4 && szTmp[c] ; c++) prefix[c] = tolower(szTmp[c]);
1005   prefix[c] = '\0';
1006   if (c == 4) {
1007      if (strcmp(prefix, "engi") == 0) {
1008         strcpy(prefix, "en");
1009      } else if (strcmp(prefix, "engu") == 0) {
[f1a5201]1010         strcpy(prefix, "en-us");
[4432f2e]1011      } else if (strcmp(prefix, "fren") == 0) {
[f1a5201]1012         strcpy(prefix, "fr");
[4432f2e]1013      } else if (strcmp(prefix, "germ") == 0) {
[f1a5201]1014         strcpy(prefix, "de");
[4432f2e]1015      } else if (strcmp(prefix, "ital") == 0) {
[f1a5201]1016         strcpy(prefix, "it");
[4432f2e]1017      } else if (strcmp(prefix, "span") == 0) {
[f1a5201]1018         strcpy(prefix, "es");
[4432f2e]1019      } else if (strcmp(prefix, "cata") == 0) {
[f1a5201]1020         strcpy(prefix, "ca");
[4432f2e]1021      } else if (strcmp(prefix, "port") == 0) {
[f1a5201]1022         strcpy(prefix, "pt");
[4432f2e]1023      } else {
1024         while (szTmp[c] && c < sizeof(prefix)) {
1025            prefix[c] = tolower(szTmp[c]);
1026            c++;
1027         }
1028         prefix[c] = '\0';
1029      }
1030   }
1031   strcat(prefix, ":");
1032   prefix_len = strlen(prefix);
[f1a5201]1033
[4432f2e]1034   /* If the language is something like "en-us", fallback to "en" if we don't
1035    * have an entry for en-us */
1036   szTmp = strchr(prefix, '-');
1037   if (szTmp) {
1038      c = szTmp - prefix;
1039      memcpy(prefix_root, prefix, c);
1040      prefix_root[c++] = ':';
1041      prefix_root[c] = '\0';
1042      prefix_root_len = strlen(prefix_root);
1043   } else {
1044      prefix_root_len = 0;
1045   }
[60f7018]1046
1047  select_charset(default_charset());
1048
1049  if (erg[0]==szBadEn) {
1050    fprintf(STDERR, erg[3], szAppName );
1051    /* no point extracting this message */
1052    fprintf(STDERR, "No messages in language '%s'\n",prefix);
1053    exit(EXIT_FAILURE);
1054  }
1055  if (strcmp(MESSAGE_VERSION_MIN,erg[0])>0 || strcmp(VERSION,erg[0])<0)
1056    /* a little tacky, but'll work */
1057    fatal(191,wr,MESSAGE_VERSION_MIN" - "VERSION,0);
1058
1059  return pthMe;
1060}
1061
1062extern const char *msg( int en ) /* message may be overwritten by next call */ {
1063  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
1064}
1065
1066extern const char *msgPerm( int en ) /* returns persistent copy of message */ {
1067  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
1068}
1069
[4432f2e]1070static void FAR errdisp( int en, void (*fn)( const char *, int ), const char *arg, int n,
[60f7018]1071                         int type ) {
[4432f2e]1072   fputnl( STDERR );
1073   fputnl( STDERR );
1074   fprintf( STDERR, erg[type], szAppNameCopy );
1075   fputs( msg(en), STDERR);
1076   fputnl( STDERR );
1077   if (fn) (fn)(arg, n);
1078/*   if (fn) (fn)( (arg ? arg : "(null)"), n);*/
[60f7018]1079}
1080
1081extern void FAR warning( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
[4432f2e]1082   cWarnings++;
1083   errdisp( en, fn, szArg, n, 4 );
[60f7018]1084}
1085
1086extern void FAR error( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
[4432f2e]1087   cErrors++;
1088   errdisp( en, fn, szArg, n, 3 );
1089   /* non-fatal errors now return... */
[60f7018]1090}
1091
1092extern void FAR fatal( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
[4432f2e]1093   errdisp( en, fn, szArg, n, 2 );
1094   exit(EXIT_FAILURE);
[60f7018]1095}
1096
1097#if 1
1098/* Code to support switching character set at runtime (e.g. for a printer
1099 * driver to support different character sets on screen and on the printer)
1100 */
1101typedef struct charset_li {
1102   struct charset_li *next;
1103   int code;
[a3e49dc]1104   const char **erg;
[60f7018]1105} charset_li;
1106
1107static charset_li *charset_head = NULL;
1108
1109static int charset = CHARSET_BAD;
1110
1111int select_charset( int charset_code ) {
1112   int old_charset = charset;
1113   charset_li *p;
1114
[a3e49dc]1115/*   printf( "select_charset(%d), old charset = %d\n", charset_code, charset ); */
[60f7018]1116
1117   charset = charset_code;
1118
1119   /* check if we've already parsed messages for new charset */
1120   for( p = charset_head ; p ; p = p->next ) {
[a3e49dc]1121/*      printf("%p: code %d erg %p\n",p,p->code,p->erg); */
[60f7018]1122      if (p->code == charset) {
1123         erg = p->erg;
1124         goto found;
1125      }
1126   }
1127
1128   /* nope, got to reparse message file */
[a3e49dc]1129   parse_msg_file( charset_code );
[60f7018]1130
1131   /* add to list */
1132   p = osnew(charset_li);
1133/*   p = osmalloc(256); */
1134   p->code = charset;
1135   p->erg = erg;
1136   p->next = charset_head;
1137   charset_head = p;
1138
1139   found:
1140   return old_charset;
1141}
1142#endif
Note: See TracBrowser for help on using the repository browser.