~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to tads/tads3/tcmain.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifdef RCSID
 
2
static char RCSid[] =
 
3
"$Header: d:/cvsroot/tads/tads3/TCMAIN.CPP,v 1.4 1999/07/11 00:46:53 MJRoberts Exp $";
 
4
#endif
 
5
 
 
6
/* 
 
7
 *   Copyright (c) 1999, 2002 Michael J. Roberts.  All Rights Reserved.
 
8
 *   
 
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
 
10
 *   on using and copying this software.  
 
11
 */
 
12
/*
 
13
Name
 
14
  tcmain.cpp - TADS 3 Compiler - main compiler driver
 
15
Function
 
16
  
 
17
Notes
 
18
  
 
19
Modified
 
20
  04/22/99 MJRoberts  - Creation
 
21
*/
 
22
 
 
23
#include "t3std.h"
 
24
#include "vmerr.h"
 
25
#include "tcglob.h"
 
26
#include "tcmain.h"
 
27
#include "tcerr.h"
 
28
#include "tctok.h"
 
29
#include "utf8.h"
 
30
#include "charmap.h"
 
31
#include "tchost.h"
 
32
#include "tcprs.h"
 
33
#include "tcgen.h"
 
34
#include "tctarg.h"
 
35
#include "charmap.h"
 
36
#include "resload.h"
 
37
#include "tcunas.h"
 
38
 
 
39
 
 
40
/* ------------------------------------------------------------------------ */
 
41
/*
 
42
 *   statics 
 
43
 */
 
44
 
 
45
/* references to the error subsystem */
 
46
int CTcMain::err_refs_ = 0;
 
47
 
 
48
/* flag: we have failed to load external messages */
 
49
int CTcMain::err_no_extern_messages_ = FALSE;
 
50
 
 
51
/* console output character mapper */
 
52
CCharmapToLocal *CTcMain::console_mapper_ = 0;
 
53
 
 
54
 
 
55
/* ------------------------------------------------------------------------ */
 
56
/*
 
57
 *   Initialize the error subsystem for the compiler 
 
58
 */
 
59
void CTcMain::tc_err_init(size_t param_stack_size,
 
60
                          CResLoader *res_loader)
 
61
{
 
62
    /* initialize the error stack */
 
63
    err_init(1024);
 
64
 
 
65
    /* if this is the first initializer, set things up */
 
66
    if (err_refs_ == 0)
 
67
    {
 
68
        /* if we haven't loaded external compiler messages, load them */
 
69
        if (!err_no_extern_messages_
 
70
            && tc_messages == &tc_messages_english[0])
 
71
        {
 
72
            osfildef *fp;
 
73
            
 
74
            /* try finding a message file */
 
75
            fp = res_loader->open_res_file("t3make.msg", 0, "XMSG");
 
76
            if (fp != 0)
 
77
            {
 
78
                /* try loading it */
 
79
                err_load_message_file(fp, &tc_messages, &tc_message_count,
 
80
                                      &tc_messages_english[0],
 
81
                                      tc_message_count_english);
 
82
                
 
83
                /* done with the file */
 
84
                osfcls(fp);
 
85
            }
 
86
            else
 
87
            {
 
88
                /* note the failure, so we don't try again */
 
89
                err_no_extern_messages_ = FALSE;
 
90
            }
 
91
        }
 
92
    }
 
93
 
 
94
    /* count the reference depth */
 
95
    ++err_refs_;
 
96
}
 
97
 
 
98
/*
 
99
 *   terminate the error subsystem for the compiler 
 
100
 */
 
101
void CTcMain::tc_err_term()
 
102
{
 
103
    /* reduce the reference count */
 
104
    --err_refs_;
 
105
 
 
106
    /* delete the error stack */
 
107
    err_terminate();
 
108
 
 
109
    /* if this is the last reference, clean things up */
 
110
    if (err_refs_ == 0)
 
111
    {
 
112
        /* if we loaded an external message file, unload it */
 
113
        err_delete_message_array(&tc_messages, &tc_message_count,
 
114
                                 &tc_messages_english[0],
 
115
                                 tc_message_count_english);
 
116
    }
 
117
}
 
118
 
 
119
/* ------------------------------------------------------------------------ */
 
120
/*
 
121
 *   Initialize the compiler 
 
122
 */
 
123
void CTcMain::init(CTcHostIfc *hostifc, CResLoader *res_loader,
 
124
                   const char *default_charset)
 
125
{
 
126
    /* initialize the error subsystem */
 
127
    tc_err_init(1024, res_loader);
 
128
    
 
129
    /* remember the host interface */
 
130
    G_hostifc = hostifc;
 
131
 
 
132
    /* perform static initializations on the parser symbol table class */
 
133
    CTcPrsSymtab::s_init();
 
134
 
 
135
    /* create the compiler main object */
 
136
    G_tcmain = new CTcMain(res_loader, default_charset);
 
137
}
 
138
 
 
139
/*
 
140
 *   Terminate the compiler 
 
141
 */
 
142
void CTcMain::terminate()
 
143
{
 
144
    /* delete the tokenizer */
 
145
    delete G_tok;
 
146
    G_tok = 0;
 
147
 
 
148
    /* delete the compiler main object */
 
149
    delete G_tcmain;
 
150
    G_tcmain = 0;
 
151
 
 
152
    /* forget any object and property fixups */
 
153
    G_objfixup = 0;
 
154
    G_propfixup = 0;
 
155
    G_enumfixup = 0;
 
156
 
 
157
    /* 
 
158
     *   make sure we explicitly turn the fixup flags on again if we want
 
159
     *   them in a future run 
 
160
     */
 
161
    G_keep_objfixups = FALSE;
 
162
    G_keep_propfixups = FALSE;
 
163
    G_keep_enumfixups = FALSE;
 
164
 
 
165
    /* perform static termination on the parser symbol table class */
 
166
    CTcPrsSymtab::s_terminate();
 
167
 
 
168
    /* forget the host interface */
 
169
    G_hostifc = 0;
 
170
 
 
171
    /* terminate the error subsystem */
 
172
    tc_err_term();
 
173
}
 
174
 
 
175
/* ------------------------------------------------------------------------ */
 
176
/*
 
177
 *   set up the compiler 
 
178
 */
 
179
CTcMain::CTcMain(CResLoader *res_loader, const char *default_charset)
 
180
{
 
181
    char csbuf[OSFNMAX];
 
182
    
 
183
    /* 
 
184
     *   if the caller didn't provide a default character set, ask the OS
 
185
     *   what we should use
 
186
     */
 
187
    if (default_charset == 0)
 
188
    {
 
189
        /* 
 
190
         *   ask the OS what to use for file contents, since we use this
 
191
         *   character set to translate the text we read from source files 
 
192
         */
 
193
        os_get_charmap(csbuf, OS_CHARMAP_FILECONTENTS);
 
194
        
 
195
        /* use our OS-provided character set */
 
196
        default_charset = csbuf;
 
197
    }
 
198
 
 
199
    /* if there's no static console output character map, create one */
 
200
    if (console_mapper_ == 0)
 
201
    {
 
202
        char mapname[32];
 
203
 
 
204
        /* get the console character set name */
 
205
        os_get_charmap(mapname, OS_CHARMAP_DISPLAY);
 
206
 
 
207
        /* create a resource loader for the console character map */
 
208
        console_mapper_ = CCharmapToLocal::load(res_loader, mapname);
 
209
 
 
210
        /* if that failed, create an ASCII mapper */
 
211
        if (console_mapper_ == 0)
 
212
            console_mapper_ = CCharmapToLocal::load(res_loader, "us-ascii");
 
213
    }
 
214
    
 
215
    /* remember our resource loader */
 
216
    res_loader_ = res_loader;
 
217
    
 
218
    /* 
 
219
     *   set default options - minimum verbosity, no numeric error codes,
 
220
     *   show standard warnings but not pedantic warnings, not test mode 
 
221
     */
 
222
    err_options_ = TCMAIN_ERR_WARNINGS;
 
223
 
 
224
    /* we have no warning suppression list yet */
 
225
    suppress_list_ = 0;
 
226
    suppress_cnt_ = 0;
 
227
 
 
228
    /* remember our default character set */
 
229
    default_charset_ = lib_copy_str(default_charset);
 
230
 
 
231
    /* create the tokenizer */
 
232
    G_tok = new CTcTokenizer(res_loader_, default_charset_);
 
233
    
 
234
    /* 
 
235
     *   Create the parser and node memory pool.  Create the memory pool
 
236
     *   first, because the parser allocates objects out of the pool. 
 
237
     */
 
238
    G_prsmem = new CTcPrsMem();
 
239
    G_prs = new CTcParser();
 
240
 
 
241
    /* create the generator data stream (for constant data) */
 
242
    G_ds = new CTcDataStream(TCGEN_DATA_STREAM);
 
243
 
 
244
    /* create the primary generator code stream */
 
245
    G_cs_main = new CTcCodeStream(TCGEN_CODE_STREAM);
 
246
 
 
247
    /* create the static initializer code stream */
 
248
    G_cs_static = new CTcCodeStream(TCGEN_STATIC_CODE_STREAM);
 
249
 
 
250
    /* make the primary code stream active */
 
251
    G_cs = G_cs_main;
 
252
 
 
253
    /* create the generator object data stream */
 
254
    G_os = new CTcDataStream(TCGEN_OBJECT_STREAM);
 
255
 
 
256
    /* create the intrinsic class modifier object data stream */
 
257
    G_icmod_stream = new CTcDataStream(TCGEN_ICMOD_STREAM);
 
258
 
 
259
    /* create the dictionary object data stream */
 
260
    G_dict_stream = new CTcDataStream(TCGEN_DICT_STREAM);
 
261
 
 
262
    /* create the grammar-production object data stream */
 
263
    G_gramprod_stream = new CTcDataStream(TCGEN_GRAMPROD_STREAM);
 
264
 
 
265
    /* create the BigNumber object data stream */
 
266
    G_bignum_stream = new CTcDataStream(TCGEN_BIGNUM_STREAM);
 
267
 
 
268
    /* create the IntrinsicClass object data stream */
 
269
    G_int_class_stream = new CTcDataStream(TCGEN_INTCLASS_STREAM);
 
270
 
 
271
    /* create the static initializer identifier stream */
 
272
    G_static_init_id_stream = new CTcDataStream(TCGEN_STATIC_INIT_ID_STREAM);
 
273
 
 
274
    /* create the target-specific code generator */
 
275
    G_cg = new CTcGenTarg();
 
276
 
 
277
    /* initialize the parser */
 
278
    G_prs->init();
 
279
 
 
280
    /* no errors or warnings yet */
 
281
    error_count_ = 0;
 
282
    warning_count_ = 0;
 
283
    first_error_ = 0;
 
284
    first_warning_ = 0;
 
285
 
 
286
    /* set a fairly liberal maximum error limit */
 
287
    max_error_count_ = 100;
 
288
 
 
289
    /* there's no disassembly output stream yet */
 
290
    G_disasm_out = 0;
 
291
}
 
292
 
 
293
 
 
294
/* ------------------------------------------------------------------------ */
 
295
/*
 
296
 *   delete the compiler driver 
 
297
 */
 
298
CTcMain::~CTcMain()
 
299
{
 
300
    /* if there's a disassembly stream, delete it */
 
301
    if (G_disasm_out != 0)
 
302
        delete G_disasm_out;
 
303
 
 
304
    /* delete the various data streams */
 
305
    delete G_cs_main;
 
306
    delete G_cs_static;
 
307
    delete G_ds;
 
308
    delete G_os;
 
309
    delete G_icmod_stream;
 
310
    delete G_dict_stream;
 
311
    delete G_gramprod_stream;
 
312
    delete G_bignum_stream;
 
313
    delete G_int_class_stream;
 
314
    delete G_static_init_id_stream;
 
315
 
 
316
    /* delete the console output character map, if there is one */
 
317
    if (console_mapper_ != 0)
 
318
    {
 
319
        /* release our reference on it */
 
320
        console_mapper_->release_ref();
 
321
 
 
322
        /* forget it (since it's static) */
 
323
        console_mapper_ = 0;
 
324
    }
 
325
 
 
326
    /* delete the target-specific code generator */
 
327
    delete G_cg;
 
328
 
 
329
    /* delete the parser and node memory pool */
 
330
    delete G_prs;
 
331
    delete G_prsmem;
 
332
 
 
333
    /* delete the parser */
 
334
    delete G_tok;
 
335
 
 
336
    /* delete our default character set name string */
 
337
    lib_free_str(default_charset_);
 
338
}
 
339
 
 
340
 
 
341
/* ------------------------------------------------------------------------ */
 
342
/*
 
343
 *   Log an error, part 1: show the message prefix.  This should be called
 
344
 *   before formatting the text of the message, and part 2 should be called
 
345
 *   after formatting the message text.  Returns a pointer to the message
 
346
 *   template text.  
 
347
 */
 
348
static const char *log_msg_internal_1(
 
349
    CTcTokFileDesc *linedesc, long linenum,
 
350
    int *err_counter, int *warn_counter, int *first_error, int *first_warning,
 
351
    unsigned long options, const int *suppress_list, size_t suppress_cnt,
 
352
    tc_severity_t severity, int err)
 
353
{
 
354
    const char *msg;
 
355
    const char *prefix;
 
356
 
 
357
    /*
 
358
     *   If this is a warning or a pedantic warning, and it's in the list of
 
359
     *   suppressed messages, ignore it entirely.  
 
360
     */
 
361
    if (severity == TC_SEV_PEDANTIC || severity == TC_SEV_WARNING)
 
362
    {
 
363
        size_t rem;
 
364
        const int *p;
 
365
 
 
366
        /* scan the suppress list */
 
367
        for (p = suppress_list, rem = suppress_cnt ; rem != 0 ; ++p, --rem)
 
368
        {
 
369
            /* check for a match */
 
370
            if (*p == err)
 
371
            {
 
372
                /* it's in the suppress list - ignore the error */
 
373
                return 0;
 
374
            }
 
375
        }
 
376
    }
 
377
 
 
378
    /* increment the appropriate counter */
 
379
    switch(severity)
 
380
    {
 
381
    case TC_SEV_INFO:
 
382
        /* 
 
383
         *   we don't need to count informational messages, and no prefix is
 
384
         *   required 
 
385
         */
 
386
        prefix = "";
 
387
        break;
 
388
 
 
389
    case TC_SEV_PEDANTIC:
 
390
        /* 
 
391
         *   if we're not in "pedantic" mode, or we're not even showing
 
392
         *   regular errors, ignore it 
 
393
         */
 
394
        if (!(options & TCMAIN_ERR_PEDANTIC)
 
395
            || !(options & TCMAIN_ERR_WARNINGS))
 
396
            return 0;
 
397
 
 
398
        /* if this is the first warning, remember the code */
 
399
        if (*warn_counter == 0 && first_warning != 0)
 
400
            *first_warning = err;
 
401
 
 
402
        /* count it */
 
403
        ++(*warn_counter);
 
404
 
 
405
        /* set the prefix */
 
406
        prefix = "warning";
 
407
        break;
 
408
 
 
409
    case TC_SEV_WARNING:
 
410
        /* if we're suppressing warnings, ignore it */
 
411
        if (!(options & TCMAIN_ERR_WARNINGS))
 
412
            return 0;
 
413
 
 
414
        /* if this is the first warning, remember the code */
 
415
        if (*warn_counter == 0 && first_warning != 0)
 
416
            *first_warning = err;
 
417
 
 
418
        /* count the warning */
 
419
        ++(*warn_counter);
 
420
 
 
421
        /* use an appropriate prefix */
 
422
        prefix = "warning";
 
423
        break;
 
424
 
 
425
    case TC_SEV_ERROR:
 
426
        /* if this is the first error, remember the code */
 
427
        if (*err_counter == 0 && first_error != 0)
 
428
            *first_error = err;
 
429
 
 
430
        /* count the error */
 
431
        ++(*err_counter);
 
432
 
 
433
        /* use an appropriate prefix */
 
434
        prefix = "error";
 
435
        break;
 
436
 
 
437
    case TC_SEV_FATAL:
 
438
        /* if this is the first error, remember the code */
 
439
        if (*err_counter == 0 && first_error != 0)
 
440
            *first_error = err;
 
441
 
 
442
        /* count this as an error */
 
443
        ++(*err_counter);
 
444
 
 
445
        /* use an appropriate prefix */
 
446
        prefix = "fatal error";
 
447
        break;
 
448
 
 
449
    case TC_SEV_INTERNAL:
 
450
        /* if this is the first error, remember the code */
 
451
        if (*err_counter == 0 && first_error != 0)
 
452
            *first_error = err;
 
453
 
 
454
        /* count this as an error */
 
455
        ++(*err_counter);
 
456
 
 
457
        /* use an appropriate prefix */
 
458
        prefix = "internal error";
 
459
        break;
 
460
    }
 
461
 
 
462
    /* display the current parsing position, if available */
 
463
    if (linedesc != 0)
 
464
    {
 
465
        const char *fname;
 
466
        char qu_buf[OSFNMAX*2 + 2];
 
467
 
 
468
        /* get the filename from the source descriptor */
 
469
        fname = linedesc->get_fname();
 
470
 
 
471
        /* 
 
472
         *   if we're in test reporting mode, show only the root part of the
 
473
         *   filename 
 
474
         */
 
475
        if ((options & TCMAIN_ERR_TESTMODE) != 0)
 
476
            fname = os_get_root_name((char *)fname);
 
477
 
 
478
        /* if they want quoted filenames, quote the filename */
 
479
        if ((options & TCMAIN_ERR_FNAME_QU) != 0)
 
480
        {
 
481
            const char *src;
 
482
            char *dst;
 
483
 
 
484
            /* quote each character of the filename */
 
485
            for (src = fname, qu_buf[0] = '"', dst = qu_buf + 1 ;
 
486
                 *src != '\0' ; )
 
487
            {
 
488
                /* if this is a quote character, stutter it */
 
489
                if (*src == '"')
 
490
                    *dst++ = '"';
 
491
 
 
492
                /* add this character */
 
493
                *dst++ = *src++;
 
494
            }
 
495
 
 
496
            /* add a closing quote and trailing null */
 
497
            *dst++ = '"';
 
498
            *dst = '\0';
 
499
 
 
500
            /* use the quoted version of the filename */
 
501
            fname = qu_buf;
 
502
        }
 
503
 
 
504
        /* show the filename and line number prefix */
 
505
        G_hostifc->print_err("%s(%ld): ", fname, linenum);
 
506
    }
 
507
 
 
508
    /* display the error type prefix */
 
509
    G_hostifc->print_err("%s", prefix);
 
510
 
 
511
    /* add the error number, if we're showing error numbers */
 
512
    if ((options & TCMAIN_ERR_NUMBERS) != 0 && severity != TC_SEV_INFO)
 
513
        G_hostifc->print_err(" %u", (unsigned int)err);
 
514
 
 
515
    /* add a colon and a space for separation */
 
516
    G_hostifc->print_err(": ");
 
517
 
 
518
    /* get the error message */
 
519
    msg = tcerr_get_msg(err, (options & TCMAIN_ERR_VERBOSE) != 0);
 
520
    if (msg == 0)
 
521
        msg = "[Unable to find message text for this error code.  "
 
522
              "This might indicate an internal problem with the compiler, "
 
523
              "or it might be caused by an installation problem that is "
 
524
              "preventing the compiler from finding an external message "
 
525
              "file that it requires.]";
 
526
 
 
527
    /* return the message text, so the caller can format it with arguments */
 
528
    return msg;
 
529
}
 
530
 
 
531
/*
 
532
 *   Log an error, part 2: show the message suffix.
 
533
 */
 
534
static void log_msg_internal_2(unsigned long options, tc_severity_t severity)
 
535
{
 
536
    /* 
 
537
     *   if we're in verbose mode, and this is an internal error, add the
 
538
     *   internal error explanation text 
 
539
     */
 
540
    if (severity == TC_SEV_INTERNAL && (options & TCMAIN_ERR_VERBOSE) != 0)
 
541
    {
 
542
        const char *msg;
 
543
        
 
544
        /* get the internal error explanation text and display it */
 
545
        msg = tcerr_get_msg(TCERR_INTERNAL_EXPLAN, TRUE);
 
546
        if (msg != 0)
 
547
            G_hostifc->print_err("\n%s", msg);
 
548
    }
 
549
 
 
550
    /* end the line */
 
551
    G_hostifc->print_err((options & TCMAIN_ERR_VERBOSE) != 0 ? "\n\n" : "\n");
 
552
}
 
553
 
 
554
/* ------------------------------------------------------------------------ */
 
555
/*
 
556
 *   Print an error message.  Word-wrap the message if we're in verbose mode.
 
557
 */
 
558
static void format_message(const char *msg, unsigned long options)
 
559
{
 
560
    /*
 
561
     *   if we're in verbose mode, word-wrap to 80 columns; otherwise just
 
562
     *   print it as-is 
 
563
     */
 
564
    if ((options & TCMAIN_ERR_VERBOSE) != 0)
 
565
    {
 
566
        const char *p;
 
567
        const int line_wid = 79;
 
568
 
 
569
        /* start on a new line, to skip any prefix text */
 
570
        G_hostifc->print_err("\n");
 
571
 
 
572
        /* word-wrap to 80 columns */
 
573
        for (p = msg ; *p != '\0' ; )
 
574
        {
 
575
            const char *start;
 
576
            const char *sp;
 
577
 
 
578
            /* find the next word break */
 
579
            for (sp = 0, start = p ; ; )
 
580
            {
 
581
                /* if this is a space, note it */
 
582
                if (*p == ' ')
 
583
                    sp = p;
 
584
 
 
585
                /* 
 
586
                 *   if we're at the end of the line, or we're over the line
 
587
                 *   width and we found a space, break here 
 
588
                 */
 
589
                if (*p == '\0' || p - start >= line_wid && sp != 0)
 
590
                {
 
591
                    /* if we've reached the end, print the rest */
 
592
                    if (*p == '\0')
 
593
                        sp = p;
 
594
 
 
595
                    /* trim off trailing spaces */
 
596
                    for ( ; sp > start && *(sp-1) == ' ' ; --sp) ;
 
597
 
 
598
                    /* show this part */
 
599
                    G_hostifc->print_err("%.*s\n", sp - start, start);
 
600
 
 
601
                    /* skip leading spaces */
 
602
                    for ( ; *sp == ' ' ; ++sp) ;
 
603
 
 
604
                    /* if this is the end of the line, we're done */
 
605
                    if (*p == '\0')
 
606
                        break;
 
607
 
 
608
                    /* start over here */
 
609
                    start = p = sp;
 
610
                }
 
611
                else
 
612
                {
 
613
                    /* this one fits - skip it */
 
614
                    ++p;
 
615
                }
 
616
            }
 
617
        }
 
618
    }
 
619
    else
 
620
    {
 
621
        /* display it */
 
622
        G_hostifc->print_err("%s", msg);
 
623
    }
 
624
}
 
625
 
 
626
/* ------------------------------------------------------------------------ */
 
627
/*
 
628
 *   log an error from an exception object 
 
629
 */
 
630
void CTcMain::S_log_error(CTcTokFileDesc *linedesc, long linenum,
 
631
                          int *err_counter, int *warn_counter,
 
632
                          unsigned long options,
 
633
                          const int *suppress_list, size_t suppress_cnt,
 
634
                          tc_severity_t severity, CVmException *exc)
 
635
{
 
636
    const char *msg;
 
637
    char msgbuf[1024];
 
638
    
 
639
    /* show the prefix */
 
640
    msg = log_msg_internal_1(linedesc, linenum, err_counter, warn_counter,
 
641
                             0, 0, options, suppress_list, suppress_cnt,
 
642
                             severity, exc->get_error_code());
 
643
 
 
644
    /* if the message is suppressed, we're done */
 
645
    if (msg == 0)
 
646
        return;
 
647
 
 
648
    /* format the message using arguments stored in the exception */
 
649
    err_format_msg(msgbuf, sizeof(msgbuf), msg, exc);
 
650
 
 
651
    /* print the error */
 
652
    format_message(msgbuf, options);
 
653
 
 
654
    /* show the suffix */
 
655
    log_msg_internal_2(options, severity);
 
656
}
 
657
 
 
658
/* ------------------------------------------------------------------------ */
 
659
/*
 
660
 *   Log an error using va_list arguments
 
661
 */
 
662
void CTcMain::S_v_log_error(CTcTokFileDesc *linedesc, long linenum,
 
663
                            int *err_counter, int *warn_counter,
 
664
                            int *first_error, int *first_warning,
 
665
                            unsigned long options,
 
666
                            const int *suppress_list, size_t suppress_cnt,
 
667
                            tc_severity_t severity, int err, va_list args)
 
668
{
 
669
    const char *msg;
 
670
    char msgbuf[2048];
 
671
 
 
672
    /* show the prefix */
 
673
    msg = log_msg_internal_1(linedesc, linenum, err_counter, warn_counter,
 
674
                             first_error, first_warning, options,
 
675
                             suppress_list, suppress_cnt, severity, err);
 
676
 
 
677
    /* if the message is suppressed, we're done */
 
678
    if (msg == 0)
 
679
        return;
 
680
 
 
681
    /* format the message using the va_list argument */
 
682
    t3vsprintf(msgbuf, sizeof(msgbuf), msg, args);
 
683
 
 
684
    /* display it */
 
685
    format_message(msgbuf, options);
 
686
 
 
687
    /* show the suffix */
 
688
    log_msg_internal_2(options, severity);
 
689
}
 
690
 
 
691
/* ------------------------------------------------------------------------ */
 
692
/*
 
693
 *   Check the current error count against the maximum error limit, and throw
 
694
 *   a fatal error if we've reached the limit.  
 
695
 */
 
696
void CTcMain::check_error_limit()
 
697
{
 
698
    /* check the error count against the limit */
 
699
    if (error_count_ > max_error_count_)
 
700
    {
 
701
        /* 
 
702
         *   raise the maximum error count a bit so that we don't encounter
 
703
         *   another maximum error situation and loop on flagging the
 
704
         *   too-many-errors error while trying to display a too-many-errors
 
705
         *   error 
 
706
         */
 
707
        max_error_count_ = error_count_ + 100;
 
708
 
 
709
        /* display a message explaining the problem */
 
710
        log_error(G_tok->get_last_desc(), G_tok->get_last_linenum(),
 
711
                  TC_SEV_FATAL, TCERR_TOO_MANY_ERRORS);
 
712
 
 
713
        /* throw the generic fatal error, since we've logged this */
 
714
        err_throw(TCERR_FATAL_ERROR);
 
715
    }
 
716
}
 
717