source: git/src/message.c @ a3e49dc

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

Fettled in changes from error.c

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

  • Property mode set to 100644
File size: 27.5 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 "error.h"
217#include "osdepend.h"
218#include "filelist.h"
219#include "debug.h"
220#include "version.h"
221
222#ifdef HAVE_SIGNAL
223# ifdef HAVE_SETJMP
224#  include <setjmp.h>
225static jmp_buf jmpbufSignal;
226#  include <signal.h>
227# else
228#  undef HAVE_SIGNAL
229# endif
230#endif
231
232/* This is the name of the default language -- set like this so folks can
233 * add (for eg) -DDEFAULTLANG="fren" to UFLG in the makefile
234 */
235#ifndef DEFAULTLANG
236# define DEFAULTLANG "engi"
237#endif
238
239#define STDERR stdout
240
241/* For funcs which want to be immune from messing around with different
242 * calling conventions */
243#ifndef CDECL
244#define CDECL
245#endif
246
247/* These are English versions of messages which might be needed before the
248 * alternative language version has been read from the message file.
249 */
250static const char * ergBootstrap[]={
251   "",
252   "Out of memory (couldn't find %ul bytes).\n",
253   "\nFatal error from %s: ",
254   "\nError from %s: ",
255   "\nWarning from %s: ",
256   "Message file has incorrect format\n", /* was "Error message file ..." */
257   "Negative error numbers are not allowed\n",
258   NULL /* NULL marks end of list */
259};
260
261static const char **erg = ergBootstrap;
262static int enMac = 32; /* Initially, grows automatically */
263static const char *szBadEn = "???";
264
265static int cWarnings = 0; /* keep track of how many warnings we've given */
266static int cErrors = 0;   /* and how many (non-fatal) errors */
267
268extern int error_summary(void) {
269   fprintf(STDERR,msg(16),cWarnings,cErrors);
270   fputnl(STDERR);
271   return ( cErrors ? EXIT_FAILURE : EXIT_SUCCESS );
272}
273
274/* in case osmalloc() fails before szAppNameCopy is set up */
275static const char *szAppNameCopy="anonymous program";
276
277/* error code for failed osmalloc and osrealloc calls */
278static void outofmem(OSSIZE_T size) {
279   fprintf( STDERR, erg[2], szAppNameCopy );
280   fprintf( STDERR, erg[1], (unsigned long)size );
281   exit(EXIT_FAILURE);
282}
283
284/* malloc with error catching if it fails. Also allows us to write special
285 * versions easily eg for DOS EMS or MS Windows.
286 */
287extern void FAR * osmalloc( OSSIZE_T size ) {
288   void FAR *p;
289   p=xosmalloc( size );
290   if (p==NULL)
291      outofmem(size);
292   return p;
293}
294
295/* realloc with error catching if it fails. */
296extern void FAR * osrealloc( void *p, OSSIZE_T size ) {
297   p=xosrealloc(p,size);
298   if (p==NULL)
299      outofmem(size);
300   return p;
301}
302
303extern void FAR * osstrdup( const char *sz ) {
304   char *p;
305   int len;
306   len=strlen(sz)+1;
307   p=osmalloc(len);
308   memmove(p,sz,len);
309   return p;
310}
311
312/* osfree is currently a macro in error.h */
313
314#ifdef HAVE_SIGNAL
315
316static int sigReceived;
317
318/* for systems not using autoconf, assume the signal handler returns void
319 * unless specified elsewhere */
320#ifndef RETSIGTYPE
321#define RETSIGTYPE void
322#endif
323
324static CDECL RETSIGTYPE FAR report_sig( int sig ) {
325   sigReceived=sig;
326   longjmp(jmpbufSignal,1);
327}
328
329static void init_signals( void ) {
330   int en;
331   if (!setjmp(jmpbufSignal)) {
332      signal(SIGABRT,report_sig); /* abnormal termination eg abort() */
333      signal(SIGFPE ,report_sig); /* arithmetic error eg /0 or overflow */
334      signal(SIGILL ,report_sig); /* illegal function image eg illegal instruction */
335      signal(SIGINT ,report_sig); /* interactive attention eg interrupt */
336      signal(SIGSEGV,report_sig); /* illegal storage access eg access outside memory limits */
337      signal(SIGTERM,report_sig); /* termination request sent to program */
338# ifdef SIGSTAK /* only on RISC OS AFAIK */
339      signal(SIGSTAK,report_sig); /* stack overflow */
340# endif
341      return;
342   }
343   fprintf(STDERR,msg(2),szAppNameCopy);
344   switch (sigReceived) {
345    case SIGABRT: en=90; break;
346    case SIGFPE:  en=91; break;
347    case SIGILL:  en=92; break;
348    case SIGINT:  en=93; break;
349    case SIGSEGV: en=94; break;
350    case SIGTERM: en=95; break;
351# ifdef SIGSTAK
352    case SIGSTAK: en=96; break;
353# endif
354    default:      en=97; break;
355   }
356   fputsnl(msg(en),STDERR);
357   if (errno >= 0) {
358# ifdef HAVE_STRERROR
359      fputsnl(strerror(errno),STDERR);
360# elif defined(HAVE_SYS_ERRLIST)
361      if (errno < sys_nerr)
362         fputsnl( STDERR, sys_errlist[errno] );
363# elif defined(HAVE_PERROR)
364      perror(NULL); /* always goes to stderr */
365      /* if (arg!=NULL && *arg!='\0') fputs("<arg>: <err>\n",stderr); */
366      /* else fputs("<err>\n",stderr); */
367# else
368      fprintf( STDERR, "error code %d\n", errno );
369# endif
370   }
371   if (sigReceived!=SIGINT && sigReceived!=SIGTERM)
372      fatal(11,NULL,NULL,0); /* shouldn't get any others => bug */
373   exit(EXIT_FAILURE);
374}
375#endif
376
377/* write string and nl to STDERR */
378extern void wr( const char *sz, int n ) {
379   n=n; /* suppress warning */
380   fputsnl(sz,STDERR);
381}
382
383#define CHARSET_BAD       -1
384#define CHARSET_USASCII    0
385#define CHARSET_ISO_8859_1 1
386#define CHARSET_DOSCP850   2
387#define CHARSET_RISCOS31   3
388static int default_charset( void ) {
389#ifdef ISO8859_1
390   return CHARSET_ISO_8859_1;
391#elif (OS==RISCOS)
392/*
393RISCOS 3.1 and above
394CHARSET_RISCOS31 !HCAK!
395*/
396   return CHARSET_ISO_8859_1;
397#elif (OS==MSDOS)
398   return CHARSET_DOSCP850;
399#else
400   return CHARSET_ISO_8859_1; /*!HACK!*/
401#endif
402}
403
404static const char *pthMe=NULL, *lfErrs=NULL;
405static char prefix[5];
406static int prefix_len;
407
408static void parse_msg_file( int charset_code ) {
409  FILE *fh;
410  char estr[256], line[256];
411  int en;
412  int c;
413  bool fQuoted;
414#ifndef NO_ACCENTS
415  char chOpenQuotes, chCloseQuotes;
416  char *szSingles;
417  char *szSingTab;
418  char *szAccents;
419  char *szLetters;
420  char **pszTable;
421
422  switch (charset_code) {
423     case CHARSET_USASCII: {
424        /* US ASCII */
425        chOpenQuotes = '\"';
426        chCloseQuotes = '\"';
427        szSingles = "";
428        szSingTab = NULL;
429        szAccents = "";
430        szLetters = "";
431        pszTable = NULL;
432        break;
433     }
434     case CHARSET_ISO_8859_1: {
435        /* ISO 8859/1 (Latin 1) */
436        static char *my_pszTable[]={
437         "àèòÀìùÈÌÒÙ",
438         "áéóÁíúÉÍÓÚýÝ",
439         "âêôÂîûÊÎÔÛ",
440         "äëöÄïüËÏÖÜÿ",
441         "ã õà   Õ   ñÑ",
442         NULL,
443         NULL,
444         NULL,
445         NULL,
446         NULL,
447         NULL,
448         "              ç",
449         "               Ç",
450         NULL,
451         "ª º",
452         "åæ",
453         "   Å  Æ",
454         "                  ß",
455         NULL,
456         NULL,
457         "  ø     Ø"
458        };
459        chOpenQuotes = '\"';
460        chCloseQuotes = '\"';
461        szSingles = "";
462        szSingTab = NULL;
463        szAccents = "`'^\"~=.uvHtcCdbaAsOo/";
464        szLetters = "aeoAiuEIOUyYnNcCwWs";
465        pszTable = my_pszTable;
466        break;
467     }
468     case CHARSET_RISCOS31: {
469        /* Archimedes RISC OS 3.1 and above
470         * ISO 8859/1 (Latin 1) + extensions in 128-159 */
471        static char *my_pszTable[]={
472         "àèòÀìùÈÌÒÙ",
473         "áéóÁíúÉÍÓÚýÝ",
474         "âêôÂîûÊÎÔÛ\x86\x85    \x82\x81",
475         "äëöÄïüËÏÖÜÿ",
476         "ã õà   Õ   ñÑ",
477         NULL,
478         NULL,
479         NULL,
480         NULL,
481         NULL,
482         NULL,
483         "              ç",
484         "               Ç",
485         NULL,
486         "ª º",
487         "åæ",
488         "   Å  Æ",
489         "                  ß",
490         "      \x9a",
491         " \x9b",
492         "  ø     Ø"
493        };
494        chOpenQuotes='\x94';
495        chCloseQuotes='\x95';
496        szSingles="";
497        szSingTab=NULL;
498        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
499        szLetters="aeoAiuEIOUyYnNcCwWs";
500        pszTable = my_pszTable;
501        break;
502     }
503     case CHARSET_DOSCP850: {
504        /* MS DOS - Code page 850 */
505        static char *my_pszTable[]={
506         "\x85\x8A\x95·\x8D\x97Ô ãëìí",
507         " \x82¢µ¡£\x90Öàé",
508         "\x83\x88\x93¶\x8C\x96Ò×âê",
509         "\x84\x89\x94\x8E\x8B\x81ÓØ\x99\x9A\x98",
510         "Æ äÇ    å   ¤¥",
511         NULL,
512         NULL,
513         NULL,
514         NULL,
515         NULL,
516         NULL,
517         "              \x87",
518         "               \x80",
519         NULL,
520         "¦ §",
521         "\x86\x91",
522         "   \x8F  \x92",
523         "                  á",
524         NULL,
525         NULL,
526         "  \x9B     \x9D"
527        };
528        chOpenQuotes='\"';
529        chCloseQuotes='\"';
530        szSingles="lLij";
531        szSingTab="  Õ";
532        szAccents="`'^\"~=.uvHtcCdbaAsOo/";
533        szLetters="aeoAiuEIOUyYnNcCwWs";
534        pszTable = my_pszTable;
535        break;
536     }
537#if 0
538/* MS DOS - PC-8 (code page 437?) */
539static char chOpenQuotes='\"', chCloseQuotes='\"';
540static char *szSingles="";
541static char *szSingTab=NULL;
542static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
543static char *szLetters="aeoAiuEIOUyYnNcCwWs";
544static char *pszTable[]={
545 "\x85\x8A\x95 \x8D\x97",
546 " \x82¢ ¡£\x90",
547 "\x83\x88\x93 \x8C\x96",
548 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
549 "            ¤¥",
550 NULL,
551 NULL,
552 NULL,
553 NULL,
554 NULL,
555 NULL,
556 "              \x87",
557 "               \x80",
558 NULL,
559 "¦ §",
560 "\x86\x91",
561 "   \x8F  \x92",
562 "                  á",
563 NULL,
564 NULL,
565 NULL
566};
567
568#elif 0
569/* MS DOS - PC-8 Denmark/Norway */
570static char chOpenQuotes='\"', chCloseQuotes='\"';
571static char *szSingles="";
572static char *szSingTab=NULL;
573static char *szAccents="`'^\"~=.uvHtcCdbaAsOo/";
574static char *szLetters="aeoAiuEIOUyYnNcCwWs";
575static char *pszTable[]={
576 "\x85\x8A\x95 \x8D\x97",
577 " \x82¢ ¡£\x90     ¬",
578 "\x83\x88\x93 \x8C\x96",
579 "\x84\x89\x94\x8E\x8B\x81  \x99\x9A\x98",
580 "© ¦ª    §   ¤¥",
581 NULL,
582 NULL,
583 NULL,
584 NULL,
585 NULL,
586 NULL,
587 "              \x87",
588 "               \x80",
589 NULL,
590 NULL,
591 "\x86\x91",
592 "   \x8F  \x92",
593 "                  á",
594 NULL,
595 NULL,
596 NULL
597};
598#elif 0
599/* No special chars... */
600# define NO_TEX
601#endif
602default: /*!HACK! do something -- no_tex variable version of NO_TEX ? */
603printf("oops, bad charset...\n");
604(void)0;
605  }
606#endif
607
608#if 0
609printf("opening error file\n");
610printf("(%s %s)\n",pthMe,lfErrs);
611#endif
612  fh=fopenWithPthAndExt( pthMe, lfErrs, "", "rb", NULL );
613#if 0
614printf("opened error file\n");
615#endif
616  if (!fh) {
617    /* no point extracting this error, as it won't get used if file opens */
618    fprintf(STDERR, erg[3], szAppNameCopy );
619    fprintf(STDERR, "Can't open message file '%s' using path '%s'\n",
620            lfErrs, pthMe);
621    exit(EXIT_FAILURE);
622  }
623
624  { /* copy bootstrap erg[] which'll get overwritten by file entries */
625     const char **ergMalloc;
626     erg = ergBootstrap;
627     ergMalloc = osmalloc( enMac * ossizeof(char*) );
628     /* NULL marks end of list */
629     for ( en = 0 ; erg[en] ; en++ ) ergMalloc[en]=erg[en];
630     for ( ; en < enMac ; en++ ) ergMalloc[en] = szBadEn;
631     erg = ergMalloc;
632  }
633
634  while (!feof( fh )) {
635#ifndef ERRC
636    const char *p, *q;
637    getline( line, ossizeof(line), fh );
638    if (strncmp( line, prefix, prefix_len ) == 0) {
639      long val = strtol( line+prefix_len, &q, 0);
640      if (val < 0 || val > (unsigned long)INT_MAX) {
641        fprintf( STDERR, erg[3], szAppNameCopy );
642        fprintf( STDERR, erg[ (errno==ERANGE) ? 5 : 6 ] );
643#else /* ERRC */
644    char *q;
645    getline(line,ossizeof(line),fh);
646    if (strncmp(line,prefix,prefix_len)==0) {
647      long val=strtol(line+prefix_len,&q,0);
648      if (val<0 || val>(unsigned long)INT_MAX) {
649        fprintf(STDERR, erg[3], szAppNameCopy);
650        fprintf(STDERR,erg[ (errno==ERANGE)?5:6 ]);
651#endif /* ERRC */
652        exit(EXIT_FAILURE);
653      }
654#ifndef ERRC
655      en = (int)val;
656      while (isspace(*q)) q++;
657
658      p = q + strlen(q);
659      while (p > q && isspace(p[-1])) p--;
660
661      fQuoted = (p > q + 1 && *q == '\"' && *(p-1) == '\"');
662      if (fQuoted) {
663         q++;
664         p--;
665      }
666      *p = '\0';
667
668      c = 0;
669      while (*q) {
670         if (*q == '&') {
671            if (*(q+1) == '#') {
672               if (isdigit(*(q+2))) {
673                  unsigned long value = strtoul( q+2, &q, 10);
674                  if (*q == ';') q++;
675                  /* add entity number value at estr[c] */
676                  continue;
677               }
678            } else if (isalnum(*q+1)) { /* or isalpha? !HACK! */
679               const char *entity;
680               int entity_len;
681               entity = q+1;
682               q += 2;
683               while (isalnum(*q)) q++;
684               entity_len = q - entity;
685               if (*q == ';') q++;
686               if (/* add entity "entity" at estr[c] ok*/) continue;
687               q = entity - 1;
688#else /* ERRC */
689      en=(int)val;
690      while (isspace(*q))
691        q++;
692      fQuoted=(*q=='\"');
693      if (fQuoted)
694        q++;
695      c=0;
696      while (*q && !(fQuoted && *q=='\"') ) {
697        if (*q=='\'' || *q=='`') /* convert `` and '' to left/right " */ {
698          if (*q==*(q+1)) {
699#ifndef NO_TEX
700            estr[c++] = ( *q=='`' ? chOpenQuotes : chCloseQuotes );
701#else
702            estr[c++] = '\"';
703#endif /* !NO_TEX */
704            q+=2;
705            continue;
706          }
707        }
708        if (*q!='\\')
709          estr[c++]=*q;
710        else {
711          q++;
712          switch (*q) {
713            case 'n': /* '\n' */
714              estr[c++]='\n';
715              break;
716            case '\0': /* \ at end of line, so concatenate lines */
717              getline(line,ossizeof(line),fh);
718              if (strncmp(line,prefix,prefix_len)!=0) { /* bad format */
719                fprintf(STDERR, erg[3], szAppNameCopy);
720                fprintf(STDERR,erg[5]);
721                exit(EXIT_FAILURE);
722              }
723              q=line+prefix_len;
724              continue;
725#ifndef NO_TEX
726            default: {
727              char *p;
728              int i, accent;
729              p=strchr(szSingles,*q);
730              if (p && szSingTab) {
731                estr[c++]=szSingTab[p-szSingles];
732                break;
733              }
734              p=strchr(szAccents,*q);
735              if (!p) {
736                if (*q!='\\')
737                  estr[c++]='\\';
738                break; /* \\ becomes \ and \<unknown> is not translated */
739              }
740              accent=p-szAccents;
741              q++;
742              p=strchr(szLetters,*q);
743              if (!p) {
744                estr[c++]='\\';
745                estr[c++]=szAccents[accent];
746                break;
747              }
748              i=p-szLetters;
749              if (pszTable[accent] && i<strlen(pszTable[accent])) {
750                char ch;
751                ch=pszTable[accent][i];
752                if (ch!=32) {
753                  estr[c++]=ch;
754                  break;
755                }
756              }
757              estr[c++]='\\';
758              estr[c++]=szAccents[accent];
759              estr[c++]=szLetters[i];
760#endif /* ERRC */
761            }
762#ifndef ERRC
763         }
764         if (*q < 32 || *q >= 127) {
765            printf( STDERR, "Warning: literal character '%c' (value %d) "
766                    "in message %d\n", *q, (int)*q, en );
767         }
768         estr[c++] = *q++;
769#else /* ERRC */
770#endif /* !NO_TEX */
771          }
772        }
773        q++;
774#endif /* ERRC */
775      }
776#ifndef ERRC
777      estr[c] = '\0';
778#endif /* not ERRC */
779
780#ifndef ERRC
781      if (en >= enMac) {
782         int enTmp;
783         enTmp = enMac;
784         enMac = enMac<<1;
785         erg = osrealloc( erg, enMac * ossizeof(char*) );
786         while (enTmp < enMac) erg[enTmp++] = szBadEn;
787#else /* ERRC */
788      if (!fQuoted) /* if string wasn't quoted, trim off spaces... */
789        while (c>0 && estr[c-1]==' ')
790          c--;
791      estr[c]='\0';
792      if (en>=enMac) {
793        int enTmp;
794        enTmp=enMac;
795        enMac=enMac<<1;
796        erg = osrealloc(erg, enMac * ossizeof(char*) );
797        for ( ; enTmp < enMac ; enTmp++ ) erg[enTmp] = szBadEn;
798#endif /* ERRC */
799      }
800      erg[en] = osstrdup(estr);
801/*printf("Error number %d: %s\n",en,erg[en]);*/
802    }
803  }
804  fclose(fh);
805}
806
807extern const char * FAR ReadErrorFile( const char *szAppName, const char *szEnvVar,
808                                       const char *szLangVar, const char *argv0,
809                                       const char *lfErrFile ) {
810  int  c;
811  char *szTmp;
812
813  lfErrs = osstrdup(lfErrFile);
814#ifdef HAVE_SIGNAL
815  init_signals();
816#endif
817  /* This code *should* be completely bomb-proof :) even if strcpy()
818   * generates a signal
819   */
820  szAppNameCopy=szAppName; /* ... in case the osstrdup() fails */
821  szAppNameCopy=osstrdup(szAppName);
822
823  /* Look for env. var. "SURVEXHOME" or the like */
824  if (szEnvVar && *szEnvVar && (szTmp=getenv(szEnvVar))!=NULL && *szTmp) {
825    pthMe = osstrdup(szTmp);
826  } else if (argv0) /* else try the path on argv[0] */
827    pthMe = PthFromFnm(argv0);
828  else /* otherwise, forget it - go for the current directory */
829    pthMe = "";
830
831  /* Look for env. var. "SURVEXLANG" or the like */
832  if ((szTmp=getenv(szLangVar))==0 || !*szTmp)
833    szTmp=DEFAULTLANG;
834  for( c=0 ; c<4 && szTmp[c] ; c++ )
835    prefix[c]=tolower(szTmp[c]);
836  prefix[c++]=':';
837  prefix[c]='\0';
838  prefix_len=strlen(prefix);
839
840  select_charset(default_charset());
841
842  if (erg[0]==szBadEn) {
843    fprintf(STDERR, erg[3], szAppName );
844    /* no point extracting this message */
845    fprintf(STDERR, "No messages in language '%s'\n",prefix);
846    exit(EXIT_FAILURE);
847  }
848  if (strcmp(MESSAGE_VERSION_MIN,erg[0])>0 || strcmp(VERSION,erg[0])<0)
849    /* a little tacky, but'll work */
850    fatal(191,wr,MESSAGE_VERSION_MIN" - "VERSION,0);
851
852  return pthMe;
853}
854
855extern const char *msg( int en ) /* message may be overwritten by next call */ {
856  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
857}
858
859extern const char *msgPerm( int en ) /* returns persistent copy of message */ {
860  return ( (en<0||en>=enMac) ? szBadEn : erg[en] );
861}
862
863static void FAR errdisp( int en, void (*fn)( const char *, int ), const char *szArg, int n,
864                         int type ) {
865  fputnl( STDERR );
866  fprintf( STDERR, erg[type], szAppNameCopy );
867  fputs( msg(en), STDERR);
868  fputnl( STDERR );
869  if (fn)
870    (fn)( szArg, n );
871}
872
873extern void FAR warning( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
874  cWarnings++; /* And another notch in the bedpost... */
875  errdisp( en, fn, szArg, n, 4 );
876}
877
878extern void FAR error( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
879  cErrors++; /* non-fatal errors now return... */
880  errdisp( en, fn, szArg, n, 3 );
881}
882
883extern void FAR fatal( int en, void (*fn)( const char *, int ), const char *szArg, int n ) {
884  errdisp( en, fn, szArg, n, 2 );
885  exit(EXIT_FAILURE);
886}
887
888#if 1
889/* Code to support switching character set at runtime (e.g. for a printer
890 * driver to support different character sets on screen and on the printer)
891 */
892typedef struct charset_li {
893   struct charset_li *next;
894   int code;
895   const char **erg;
896} charset_li;
897
898static charset_li *charset_head = NULL;
899
900static int charset = CHARSET_BAD;
901
902int select_charset( int charset_code ) {
903   int old_charset = charset;
904   charset_li *p;
905
906/*   printf( "select_charset(%d), old charset = %d\n", charset_code, charset ); */
907
908   charset = charset_code;
909
910   /* check if we've already parsed messages for new charset */
911   for( p = charset_head ; p ; p = p->next ) {
912/*      printf("%p: code %d erg %p\n",p,p->code,p->erg); */
913      if (p->code == charset) {
914         erg = p->erg;
915         goto found;
916      }
917   }
918
919   /* nope, got to reparse message file */
920   parse_msg_file( charset_code );
921
922   /* add to list */
923   p = osnew(charset_li);
924/*   p = osmalloc(256); */
925   p->code = charset;
926   p->erg = erg;
927   p->next = charset_head;
928   charset_head = p;
929
930   found:
931   return old_charset;
932}
933#endif
Note: See TracBrowser for help on using the repository browser.