source: git/src/message.c @ 60f7018

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

Initial revision

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

  • Property mode set to 100644
File size: 24.4 KB
Line 
1/* message.c */
2
3/* loosely based on Survex's error.c, but uses SGML entities for accented
4 * characters, and is rather more generic */
5
6/* maps: */
7
8/* (perfect hash) entity name to &#nnn; code */
9
10/* (lookup table or switch) &#nnn; code to best rendition in each charset */
11
12
13/* filename.c split off with filename manipulation stuff */
14
15
16/* > error.c
17 * Fairly general purpose error routines and path handling code
18 * Copyright (C) 1993-1997 Olly Betts
19 */
20
21/*
221993.01.25 PC Compatibility OKed
231993.01.27 print newline before error messages
241993.02.17 changed #ifdef RISCOS to #if OS==...
251993.02.19 now look for ErrList in dir main exec was in
26           for PC ERRLIST -> ERRLIST.TXT
271993.02.23 now do exit(EXIT_FAILURE) or exit(EXIT_SUCCESS)
28           added guessed UNIX stuff
291993.03.12 Major recode to make it less crap. Especially:
30           Now copes with *any* undefined message number
31           Error file now has spaces, not underscores
321993.03.16 Merged 'PathCode.c' with this file. Updates for 'PathCode.c' were:
33>> 1993.02.19 written
34>> 1993.02.23 added guess at UNIX code
35>> 1993.02.24 (W) add (int) cast to suppress warning calculating lenpth
36>> 1993.02.25 Don't look for FNM_SEP_DRV if it's not defined
371993.03.18 Added LfFromFnm()
381993.03.19 Corrected bug which caused infinite loop for PC text error file
391993.04.06 slight fettles and copied fn headers to error.c
401993.04.07 Added UsePth()
41           #error Don't ... -> #error Do not ... for GCC's happiness
421993.04.22 added fopenWithPthAndExt()
43           added application name code
441993.04.25 added AMIGA version
451993.05.05 Slightly more elegant hack than Wook's to solve BC++ stderr bug
461993.05.12 (W) added FNTYPE for different DOS memory model proofing (non-ANSI)
471993.05.22 (W) removed stderr hack as it is not that simple???
48               improved 'error file not found' reporting
491993.05.27 removed commented out #define STDERR ...
50           actually improved 'error file not found' et al - personally I do
51            *not* regard caverot telling me 'SURVEX: <error message>' as an
52            improvement. Mind you, I'm fussy.
531993.05.28 added signal catching code
541993.05.29 errno printed when signal received
551993.06.04 moved #define FNM_SEP_XXX to filelist.h
56           added #ifdef SIGSTAK as unix GCC doesn't seem to have it
571993.06.05 removed 'superfluous' &'s in signal fns
58           signal catcher now uses strerror()
591993.06.07 Unix libraries don't have strerror() - so don't use it!
60           FNTYPE -> FAR to aid comprehension
611993.06.10 in report_sig() only print out errno if non-zero
621993.06.12 fixed bug in path&ext code: only added .ext when prepending path
631993.06.16 syserr() -> fatal(); osmalloc() added; char* -> sz
64           osrealloc() added; osfree() comment added
651993.06.28 fixed bug which lost first character of each error message on
66            big-endian machines
67           fixed fopenWithPthAndExt() to osfree() fnmFull
681993.07.19 "common.h" -> "osdepend.h"
691993.07.27 changed "error number %d" to "#%d" in output
701993.08.10 added '\n' before errors reported in report_sig
711993.08.12 added more bomb-proofing
721993.08.13 fettled header
731993.08.16 added fAbsoluteFnm & fAmbiguousFnm; recoded fopenWithPthAndExt
74           RISC OS version of fopenWithPthAndExt copes with "<My$Dir>.File"
75           added AddExt; added pfExtUsed arg to fopenWithPthAndExt
761993.08.19 ./ in DOS is ambiguous, not absolute
771993.09.21 (W)fixed relative paths without preceding .\ for .svc files
78           (W)changed DOS fAbsolute() so 'c:here' is returned as ambiguous
791993.09.22 (W)changed error functions for more general info line
80           (W)added function list
811993.09.23 (IH)DOS uses farmalloc,farrealloc,farfree; osmalloc() takes a long
821993.10.15 (BP)changed erroneous ifdef MSDOS's to if (OS==MSDOS)
831993.10.18 (W)fWarningGiven added
841993.10.23 corrected fFALSE to fFalse
851993.11.03 changed error routines
86           cWarnings rather than fWarningGiven
87           fettled a bit
881993.11.05 OSSIZE_T added
89           fixed problem with pth=="" in fopenWithPthAndExt
90           added msg() and msgPerm()
911993.11.07 merged out of memory code from osmalloc & osrealloc
921993.11.08 added code to deal with quoted messages
931993.11.14 fettled
941993.11.15 added xosmalloc (returns NULL if malloc fails)
951993.11.18 xosrealloc added as macro in error.h
96           added calls to fDirectory
971993.11.19 added TeX style escape sequences for accents; also ``,'' for "
981993.11.20 minor change to '' and `` code
99           \/O & \/o now used for slashed Os
100           extracted tables to tex.h
1011993.11.26 moved chOpenQuotes & chCloseQuotes to tex.h
1021993.11.28 added NO_TEX to turn it off for now
1031993.11.29 (IH) void * FAR -> void FAR * ; void * FILE -> void FILE *
104           use perror in UNIX version
105           extracted messages from here too! (except for signal ones)
1061993.11.30 corrected Wook's ungroks in function list
107           error now returns (it was wrong, but limp on); use fatal to abort
108           added cErrors
1091993.12.01 added error_summary()
110           most signals tell the user to report them as a bug (autograss?)
111           check version of messages.txt file
1121993.12.08 split off osdepend.c
1131993.12.09 now makes less explicit reference to OS
1141993.12.16 farmalloc use controlled by NO_FLATDOS macro
115           fixed error bootstrap code problem-ette
1161993.12.17 wr changed to send to stderr as it writes error info
1171994.01.05 added missing FAR to fix >128 eqns bug
118           and another
119           bug-fixed in outofmem
1201994.03.13 enabled TeX style characters
121           will deal with `` and '' even if NO_TEX is defined
1221994.03.14 altered fopenWithPthAndExt to give filename actually used
1231994.03.19 signals now reported as `fatal error' since they are
124           all error output to do with signals is now sent to stderr
1251994.03.20 added a putnl() at end of error_summary()
1261994.03.24 error summary to stderr too
1271994.04.27 cWarnings and cErrors now static
1281994.06.03 fixed so SunOS version should cope with DOS error message file
1291994.06.09 added home directory environmental variable
1301994.06.18 fixed Norcroft warning
1311994.06.20 added int argument to warning, error and fatal
1321994.08.31 added fputnl()
1331994.09.13 added fix for caverot signals being invisible under RISC OS
1341994.09.13 removed 'cos it doesn't work
1351994.09.20 fixed signal handler to longjmp back so it's now truely ANSI
136           miscellaneous fettling
1371994.09.21 rearranged signal handler code to minimize stack use
1381994.09.22 should now be able to read multi-language message file
1391994.09.28 xosmalloc is now a macro in error.h
1401994.10.04 no longer pass NULL for szExt to fopenWithPathAndExt
1411994.10.05 DEFAULTLANG and szLangVar added
1421994.10.08 sizeof -> ossizeof
1431994.11.16 errno.h wanted even if we're not signal handling
1441994.11.23 UsePth and AddExt now insert a separator if appropriate
145           fopenWithPthAndExt now uses UsePth and AddExt
1461994.12.03 added FNM_SEP_LEV2
1471994.12.06 stderr -> STDERR; STDERR #defined to stdout
1481994.12.10 fopenWithPthAndExt() copes with NULL for pth or ext
1491995.03.25 added osstrdup
1501995.06.26 fixed bug with UsePth("",leafname)
1511995.10.06 commented out some debug code
1521995.10.11 fixed getline to take a buffer length
1531996.02.10 pszTable entries can now be NULL, as can szSingTab
1541996.02.19 fixed 2 sizeof() to ossizeof()
1551996.03.22 fettled layout
1561996.05.05 added CDECL
1571997.01.19 started code to support multiple charsets at once
1581997.01.22 finished off up charset code (merged in tex.h):
159>1993.11.20 created
160>1993.11.26 moved chOpenQuotes and chCloseQuotes to here too
161>1994.03.13 characters 128-159 translated to \xXX codes to placate compilers
162>1994.03.23 added caveat comment about top-bit-set characters
163>1994.12.03 added -DISO8859_1 to makefile to force iso-8859-1
164>1995.02.14 changed "char foo[]=" to "char *foo="
165>1996.02.10 pszTable is now an array of char *, which can be NULL
166>          szSingTab can also be NULL
167*/
168
169/* Beware: This file contains top-bit-set characters (160-255), so be     */
170/* careful of mailers, ascii ftp, etc                                     */
171
172/* Tables for TeX style accented chars, etc for use with Survex           */
173/* Copyright (C) Olly Betts 1993-1996                                     */
174
175/* NB if (as in TeX) \o and \O mean slashed-o and slashed-O, we can't
176 * have \oe and \OE for linked-oe and linked-OE without cleverer code.
177 * Therefore, I've changed slashed-o and slashed-O to \/o and \/O.
178 */
179
180/*
181Function List
182xosmalloc:       malloc, but indirected so we can eg do DOS XMS malloc
183osmalloc:        ditto, but traps failure and gives fatal error
184xosrealloc:      realloc, but indirected so we can eg do DOS XMS malloc
185osrealloc:       ditto, but traps failure and gives fatal error
186osfree:          free, but indirected so we can eg do DOS XMS malloc
187report_sig:      catches signals and prints explanatory message
188ReadErrorFile:   initialisation function - should be called first (ish)
189warning:         report warning
190error:           report error
191fatal:           report fatal error and exit
192fAbsoluteFnm:    is fnm definitely absolute?
193fAmbiguousFnm:   could fnm be interpreted as both absolute and relative?
194PthFromFnm:      extract path from fnm
195LfFromFnm:       extract leafname from fnm
196UsePth:          concatenate path & leafname
197UseExt:          bung an extension on
198fopenWithPthAndExt:
199                 open file, passing back filename actually used
200safe_fopen:      like fopen, but returns NULL for directories under all OS
201*/
202
203#include <stdio.h>
204#include <stdlib.h>
205#include <string.h>
206#include <ctype.h>
207#include <limits.h>
208#include <errno.h>
209
210#include "whichos.h"
211#include "error.h"
212#include "osdepend.h"
213#include "filelist.h"
214#include "debug.h"
215#include "version.h"
216
217#ifdef HAVE_SIGNAL
218# ifdef HAVE_SETJMP
219#  include <setjmp.h>
220static jmp_buf jmpbufSignal;
221#  include <signal.h>
222# else
223#  undef HAVE_SIGNAL
224# endif
225#endif
226
227/* This is the name of the default language -- set like this so folks can
228 * add (for eg) -DDEFAULTLANG="fren" to UFLG in the makefile
229 */
230#ifndef DEFAULTLANG
231# define DEFAULTLANG "engi"
232#endif
233
234#define STDERR stdout
235
236/* For funcs which want to be immune from messing around with different
237 * calling conventions */
238#ifndef CDECL
239#define CDECL
240#endif
241
242/* These are English versions of messages which might be needed before the
243 * alternative language version has been read from the message file.
244 */
245static const char * ergBootstrap[]={
246   "",
247   "Out of memory (couldn't find %ul bytes).\n",
248   "\nFatal error from %s: ",
249   "\nError from %s: ",
250   "\nWarning from %s: ",
251   "Message file has incorrect format\n", /* was "Error message file ..." */
252   "Negative error numbers are not allowed\n",
253   NULL /* NULL marks end of list */
254};
255
256static const char **erg = ergBootstrap;
257static int enMac = 32; /* Initially, grows automatically */
258static const char *szBadEn = "???";
259
260static int cWarnings = 0; /* keep track of how many warnings we've given */
261static int cErrors = 0;   /* and how many (non-fatal) errors */
262
263extern int error_summary(void) {
264   fprintf(STDERR,msg(16),cWarnings,cErrors);
265   fputnl(STDERR);
266   return ( cErrors ? EXIT_FAILURE : EXIT_SUCCESS );
267}
268
269/* in case osmalloc() fails before szAppNameCopy is set up */
270static const char *szAppNameCopy="anonymous program";
271
272/* error code for failed osmalloc and osrealloc calls */
273static void outofmem(OSSIZE_T size) {
274   fprintf( STDERR, erg[2], szAppNameCopy );
275   fprintf( STDERR, erg[1], (unsigned long)size );
276   exit(EXIT_FAILURE);
277}
278
279/* malloc with error catching if it fails. Also allows us to write special
280 * versions easily eg for DOS EMS or MS Windows.
281 */
282extern void FAR * osmalloc( OSSIZE_T size ) {
283   void FAR *p;
284   p=xosmalloc( size );
285   if (p==NULL)
286      outofmem(size);
287   return p;
288}
289
290/* realloc with error catching if it fails. */
291extern void FAR * osrealloc( void *p, OSSIZE_T size ) {
292   p=xosrealloc(p,size);
293   if (p==NULL)
294      outofmem(size);
295   return p;
296}
297
298extern void FAR * osstrdup( const char *sz ) {
299   char *p;
300   int len;
301   len=strlen(sz)+1;
302   p=osmalloc(len);
303   memmove(p,sz,len);
304   return p;
305}
306
307/* osfree is currently a macro in error.h */
308
309#ifdef HAVE_SIGNAL
310
311static int sigReceived;
312
313/* for systems not using autoconf, assume the signal handler returns void
314 * unless specified elsewhere */
315#ifndef RETSIGTYPE
316#define RETSIGTYPE void
317#endif
318
319static CDECL RETSIGTYPE FAR report_sig( int sig ) {
320   sigReceived=sig;
321   longjmp(jmpbufSignal,1);
322}
323
324static void init_signals( void ) {
325   int en;
326   if (!setjmp(jmpbufSignal)) {
327      signal(SIGABRT,report_sig); /* abnormal termination eg abort() */
328      signal(SIGFPE ,report_sig); /* arithmetic error eg /0 or overflow */
329      signal(SIGILL ,report_sig); /* illegal function image eg illegal instruction */
330      signal(SIGINT ,report_sig); /* interactive attention eg interrupt */
331      signal(SIGSEGV,report_sig); /* illegal storage access eg access outside memory limits */
332      signal(SIGTERM,report_sig); /* termination request sent to program */
333# ifdef SIGSTAK /* only on RISC OS AFAIK */
334      signal(SIGSTAK,report_sig); /* stack overflow */
335# endif
336      return;
337   }
338   fprintf(STDERR,msg(2),szAppNameCopy);
339   switch (sigReceived) {
340    case SIGABRT: en=90; break;
341    case SIGFPE:  en=91; break;
342    case SIGILL:  en=92; break;
343    case SIGINT:  en=93; break;
344    case SIGSEGV: en=94; break;
345    case SIGTERM: en=95; break;
346# ifdef SIGSTAK
347    case SIGSTAK: en=96; break;
348# endif
349    default:      en=97; break;
350   }
351   fputsnl(msg(en),STDERR);
352   if (errno >= 0) {
353# ifdef HAVE_STRERROR
354      fputsnl(strerror(errno),STDERR);
355# elif defined(HAVE_SYS_ERRLIST)
356      if (errno < sys_nerr)
357         fputsnl( STDERR, sys_errlist[errno] );
358# elif defined(HAVE_PERROR)
359      perror(NULL); /* always goes to stderr */
360      /* if (arg!=NULL && *arg!='\0') fputs("<arg>: <err>\n",stderr); */
361      /* else fputs("<err>\n",stderr); */
362# else
363      fprintf( STDERR, "error code %d\n", errno );
364# endif
365   }
366   if (sigReceived!=SIGINT && sigReceived!=SIGTERM)
367      fatal(11,NULL,NULL,0); /* shouldn't get any others => bug */
368   exit(EXIT_FAILURE);
369}
370#endif
371
372/* write string and nl to STDERR */
373extern void wr( const char *sz, int n ) {
374   n=n; /* suppress warning */
375   fputsnl(sz,STDERR);
376}
377
378#define CHARSET_BAD       -1
379#define CHARSET_USASCII    0
380#define CHARSET_ISO_8859_1 1
381#define CHARSET_DOSCP850   2
382#define CHARSET_RISCOS31   3
383static int default_charset( void ) {
384#ifdef ISO8859_1
385   return CHARSET_ISO_8859_1;
386#elif (OS==RISCOS)
387/*
388RISCOS 3.1 and above
389CHARSET_RISCOS31 !HCAK!
390*/
391   return CHARSET_ISO_8859_1;
392#elif (OS==MSDOS)
393   return CHARSET_DOSCP850;
394#else
395   return CHARSET_ISO_8859_1; /*!HACK!*/
396#endif
397}
398
399static const char *pthMe=NULL, *lfErrs=NULL;
400static char prefix[5];
401static int prefix_len;
402
403static void parse_msg_file( int charset_code ) {
404  FILE *fh;
405  char estr[256], line[256];
406  int en;
407  int c;
408  bool fQuoted;
409#ifndef NO_ACCENTS
410  char chOpenQuotes, chCloseQuotes;
411  char *szSingles;
412  char *szSingTab;
413  char *szAccents;
414  char *szLetters;
415  char **pszTable;
416
417  switch (charset_code) {
418     case CHARSET_USASCII: {
419        /* US ASCII */
420        chOpenQuotes = '\"';
421        chCloseQuotes = '\"';
422        szSingles = "";
423        szSingTab = NULL;
424        szAccents = "";
425        szLetters = "";
426        pszTable = NULL;
427        break;
428     }
429     case CHARSET_ISO_8859_1: {
430        /* ISO 8859/1 (Latin 1) */
431        static char *my_pszTable[]={
432         "àèòÀìùÈÌÒÙ",
433         "áéóÁíúÉÍÓÚýÝ",
434         "âêôÂîûÊÎÔÛ",
435         "äëöÄïüËÏÖÜÿ",
436         "ã õà   Õ   ñÑ",
437         NULL,
438         NULL,
439         NULL,
440         NULL,
441         NULL,
442         NULL,
443         "              ç",
444         "               Ç",
445         NULL,
446         "ª º",
447         "åæ",
448         "   Å  Æ",
449         "                  ß",
450         NULL,
451         NULL,
452         "  ø     Ø"
453        };
454        chOpenQuotes = '\"';
455        chCloseQuotes = '\"';
456        szSingles = "";
457        szSingTab = NULL;
458        szAccents = "`'^\"~=.uvHtcCdbaAsOo/";
459        szLetters = "aeoAiuEIOUyYnNcCwWs";
460        pszTable = my_pszTable;
461        break;
462     }
463     case CHARSET_RISCOS31: {
464        /* Archimedes RISC OS 3.1 and above
465         * ISO 8859/1 (Latin 1) + extensions in 128-159 */
466        static char *my_pszTable[]={
467         "àèòÀìùÈÌÒÙ",
468         "áéóÁíúÉÍÓÚýÝ",
469         "âêôÂîûÊÎÔÛ\x86\x85    \x82\x81",
470         "äëöÄïüËÏÖÜÿ",
471         "ã õà   Õ   ñÑ",
472         NULL,
473         NULL,
474         NULL,
475         NULL,
476         NULL,
477         NULL,
478         "              ç",
479         "               Ç",
480         NULL,
481         "ª º",
482         "åæ",
483         "   Å  Æ",
484         "                  ß",
485         "      \x9a",
486         " \x9b",
487         "  ø     Ø"
488        };
489        chOpenQuotes='\x94';
490        chCloseQuotes='\x95';
491        szSingles="";
492        szSingTab=NULL;
493        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
494        szLetters="aeoAiuEIOUyYnNcCwWs";
495        pszTable = my_pszTable;
496        break;
497     }
498     case CHARSET_DOSCP850: {
499        /* MS DOS - Code page 850 */
500        static char *my_pszTable[]={
501         "\x85\x8A\x95·\x8D\x97Ô ãëìí",
502         " \x82¢µ¡£\x90Öàé",
503         "\x83\x88\x93¶\x8C\x96Ò×âê",
504         "\x84\x89\x94\x8E\x8B\x81ÓØ\x99\x9A\x98",
505         "Æ äÇ    å   ¤¥",
506         NULL,
507         NULL,
508         NULL,
509         NULL,
510         NULL,
511         NULL,
512         "              \x87",
513         "               \x80",
514         NULL,
515         "¦ §",
516         "\x86\x91",
517         "   \x8F  \x92",
518         "                  á",
519         NULL,
520         NULL,
521         "  \x9B     \x9D"
522        };
523        chOpenQuotes='\"';
524        chCloseQuotes='\"';
525        szSingles="lLij";
526        szSingTab="  Õ";
527        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
528        szLetters="aeoAiuEIOUyYnNcCwWs";
529        pszTable = my_pszTable;
530        break;
531     }
532#if 0
533/* MS DOS - PC-8 (code page 437?) */
534static char chOpenQuotes='\"', chCloseQuotes='\"';
535static char *szSingles="";
536static char *szSingTab=NULL;
537static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
538static char *szLetters="aeoAiuEIOUyYnNcCwWs";
539static char *pszTable[]={
540 "\x85\x8A\x95 \x8D\x97",
541 " \x82¢ ¡£\x90",
542 "\x83\x88\x93 \x8C\x96",
543 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
544 "            ¤¥",
545 NULL,
546 NULL,
547 NULL,
548 NULL,
549 NULL,
550 NULL,
551 "              \x87",
552 "               \x80",
553 NULL,
554 "¦ §",
555 "\x86\x91",
556 "   \x8F  \x92",
557 "                  á",
558 NULL,
559 NULL,
560 NULL
561};
562
563#elif 0
564/* MS DOS - PC-8 Denmark/Norway */
565static char chOpenQuotes='\"', chCloseQuotes='\"';
566static char *szSingles="";
567static char *szSingTab=NULL;
568static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
569static char *szLetters="aeoAiuEIOUyYnNcCwWs";
570static char *pszTable[]={
571 "\x85\x8A\x95 \x8D\x97",
572 " \x82¢ ¡£\x90     ¬",
573 "\x83\x88\x93 \x8C\x96",
574 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
575 "© ¦ª    §   ¤¥",
576 NULL,
577 NULL,
578 NULL,
579 NULL,
580 NULL,
581 NULL,
582 "              \x87",
583 "               \x80",
584 NULL,
585 NULL,
586 "\x86\x91",
587 "   \x8F  \x92",
588 "                  á",
589 NULL,
590 NULL,
591 NULL
592};
593#elif 0
594/* No special chars... */
595# define NO_TEX
596#endif
597default: /*!HACK! do something -- no_tex variable version of NO_TEX ? */
598printf("oops, bad charset...\n");
599(void)0;
600  }
601#endif
602
603#if 0
604printf("opening error file\n");
605printf("(%s %s)\n",pthMe,lfErrs);
606#endif
607  fh=fopenWithPthAndExt( pthMe, lfErrs, "", "rb", NULL );
608#if 0
609printf("opened error file\n");
610#endif
611  if (!fh) {
612    /* no point extracting this error, as it won't get used if file opens */
613    fprintf(STDERR, erg[3], szAppNameCopy );
614    fprintf(STDERR, "Can't open message file '%s' using path '%s'\n",
615            lfErrs,pthMe);
616    exit(EXIT_FAILURE);
617  }
618
619  { /* copy bootstrap erg[] which'll get overwritten by file entries */
620    const char **ergMalloc;
621    erg = ergBootstrap;
622    ergMalloc=osmalloc( enMac*ossizeof(char*) );
623    for ( en=0 ; erg[en] ; en++ )
624      ergMalloc[en]=erg[en]; /* NULL marks end of list */
625    for ( ; en<enMac ; en++ )
626      ergMalloc[en]=szBadEn;
627    erg=ergMalloc;
628  }
629
630  while (!feof( fh )) {
631    const char *p, *q;
632    getline( line, ossizeof(line), fh );
633    if (strncmp( line, prefix, prefix_len ) == 0) {
634      long val = strtol( line+prefix_len, &q, 0);
635      if (val < 0 || val > (unsigned long)INT_MAX) {
636        fprintf( STDERR, erg[3], szAppNameCopy );
637        fprintf( STDERR, erg[ (errno==ERANGE) ? 5 : 6 ] );
638        exit(EXIT_FAILURE);
639      }
640      en = (int)val;
641      while (isspace(*q)) q++;
642
643      p = q + strlen(q);
644      while (p > q && isspace(p[-1])) p--;
645
646      fQuoted = (p > q + 1 && *q == '\"' && *(p-1) == '\"');
647      if (fQuoted) {
648         q++;
649         p--;
650      }
651      *p = '\0';
652
653      c = 0;
654      while (*q) {
655         if (*q == '&') {
656            if (*(q+1) == '#') {
657               if (isdigit(*(q+2))) {
658                  unsigned long value = strtoul( q+2, &q, 10);
659                  if (*q == ';') q++;
660                  /* add entity number value at estr[c] */
661                  continue;
662               }
663            } else if (isalnum(*q+1)) { /* or isalpha? !HACK! */
664               const char *entity;
665               int entity_len;
666               entity = q+1;
667               q += 2;
668               while (isalnum(*q)) q++;
669               entity_len = q - entity;
670               if (*q == ';') q++;
671               if (/* add entity "entity" at estr[c] ok*/) continue;
672               q = entity - 1;
673            }
674         }
675         if (*q < 32 || *q >= 127) {
676            printf( STDERR, "Warning: literal character '%c' (value %d) "
677                    "in message %d\n", *q, (int)*q, en );
678         }
679         estr[c++] = *q++;
680      }
681      estr[c] = '\0';
682
683      if (en >= enMac) {
684         int enTmp;
685         enTmp = enMac;
686         enMac = enMac<<1;
687         erg = osrealloc( erg, enMac * ossizeof(char*) );
688         while (enTmp < enMac) erg[enTmp++] = szBadEn;
689      }
690      erg[en] = osmalloc(c+1);
691      strcpy( erg[en], estr ); /* !HACK! osstrdup? */
692/*printf("Error number %d: %s\n",en,erg[en]);*/
693    }
694  }
695  fclose(fh);
696}
697
698extern const char * FAR ReadErrorFile( const char *szAppName, const char *szEnvVar,
699                                       const char *szLangVar, const char *argv0,
700                                       const char *lfErrFile ) {
701  int  c;
702  char *szTmp;
703
704  lfErrs = osstrdup(lfErrFile);
705#ifdef HAVE_SIGNAL
706  init_signals();
707#endif
708  /* This code *should* be completely bomb-proof :) even if strcpy()
709   * generates a signal
710   */
711  szAppNameCopy=szAppName; /* ... in case the osstrdup() fails */
712  szAppNameCopy=osstrdup(szAppName);
713
714  /* Look for env. var. "SURVEXHOME" or the like */
715  if (szEnvVar && *szEnvVar && (szTmp=getenv(szEnvVar))!=NULL && *szTmp) {
716    pthMe = osstrdup(szTmp);
717  } else if (argv0) /* else try the path on argv[0] */
718    pthMe = PthFromFnm(argv0);
719  else /* otherwise, forget it - go for the current directory */
720    pthMe = "";
721
722  /* Look for env. var. "SURVEXLANG" or the like */
723  if ((szTmp=getenv(szLangVar))==0 || !*szTmp)
724    szTmp=DEFAULTLANG;
725  for( c=0 ; c<4 && szTmp[c] ; c++ )
726    prefix[c]=tolower(szTmp[c]);
727  prefix[c++]=':';
728  prefix[c]='\0';
729  prefix_len=strlen(prefix);
730
731  select_charset(default_charset());
732
733  if (erg[0]==szBadEn) {
734    fprintf(STDERR, erg[3], szAppName );
735    /* no point extracting this message */
736    fprintf(STDERR, "No messages in language '%s'\n",prefix);
737    exit(EXIT_FAILURE);
738  }
739  if (strcmp(MESSAGE_VERSION_MIN,erg[0])>0 || strcmp(VERSION,erg[0])<0)
740    /* a little tacky, but'll work */
741    fatal(191,wr,MESSAGE_VERSION_MIN" - "VERSION,0);
742
743  return pthMe;
744}
745
746extern const char *msg( int en ) /* message may be overwritten by next call */ {
747  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
748}
749
750extern const char *msgPerm( int en ) /* returns persistent copy of message */ {
751  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
752}
753
754static void FAR errdisp( int en, void (*fn)( const char *, int ), const char *szArg, int n,
755                         int type ) {
756  fputnl( STDERR );
757  fprintf( STDERR, erg[type], szAppNameCopy );
758  fputs( msg(en), STDERR);
759  fputnl( STDERR );
760  if (fn)
761    (fn)( szArg, n );
762}
763
764extern void FAR warning( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
765  cWarnings++; /* And another notch in the bedpost... */
766  errdisp( en, fn, szArg, n, 4 );
767}
768
769extern void FAR error( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
770  cErrors++; /* non-fatal errors now return... */
771  errdisp( en, fn, szArg, n, 3 );
772}
773
774extern void FAR fatal( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
775  errdisp( en, fn, szArg, n, 2 );
776  exit(EXIT_FAILURE);
777}
778
779#if 1
780/* Code to support switching character set at runtime (e.g. for a printer
781 * driver to support different character sets on screen and on the printer)
782 */
783typedef struct charset_li {
784   struct charset_li *next;
785   int code;
786   char **erg;
787} charset_li;
788
789static charset_li *charset_head = NULL;
790
791static int charset = CHARSET_BAD;
792
793int select_charset( int charset_code ) {
794   int old_charset = charset;
795   charset_li *p;
796
797   printf( "select_charset(%d), old charset = %d\n", charset_code, charset );
798
799   charset = charset_code;
800
801   /* check if we've already parsed messages for new charset */
802   for( p = charset_head ; p ; p = p->next ) {
803      printf("%p: code %d erg %p\n",p,p->code,p->erg);
804      if (p->code == charset) {
805         erg = p->erg;
806         goto found;
807      }
808   }
809
810   /* nope, got to reparse message file */
811   ParseErrorFile( charset_code );
812
813   /* add to list */
814   p = osnew(charset_li);
815/*   p = osmalloc(256); */
816   p->code = charset;
817   p->erg = erg;
818   p->next = charset_head;
819   charset_head = p;
820
821   found:
822   return old_charset;
823}
824#endif
Note: See TracBrowser for help on using the repository browser.