sourcepawn/compiler/sc5.c
author David Anderson <dvander@alliedmods.net>
Thu Jan 25 20:08:00 2007 +0000 (2007-01-25)
changeset 353 492a8d0d5f59
parent 27 764c6dd3dc25
child 365 d830b2b0414f
permissions -rw-r--r--
added linux support
dvander@27
     1
/*  Pawn compiler - Error message system
dvander@27
     2
 *  In fact a very simple system, using only 'panic mode'.
dvander@27
     3
 *
dvander@27
     4
 *  Copyright (c) ITB CompuPhase, 1997-2006
dvander@27
     5
 *
dvander@27
     6
 *  This software is provided "as-is", without any express or implied warranty.
dvander@27
     7
 *  In no event will the authors be held liable for any damages arising from
dvander@27
     8
 *  the use of this software.
dvander@27
     9
 *
dvander@27
    10
 *  Permission is granted to anyone to use this software for any purpose,
dvander@27
    11
 *  including commercial applications, and to alter it and redistribute it
dvander@27
    12
 *  freely, subject to the following restrictions:
dvander@27
    13
 *
dvander@27
    14
 *  1.  The origin of this software must not be misrepresented; you must not
dvander@27
    15
 *      claim that you wrote the original software. If you use this software in
dvander@27
    16
 *      a product, an acknowledgment in the product documentation would be
dvander@27
    17
 *      appreciated but is not required.
dvander@27
    18
 *  2.  Altered source versions must be plainly marked as such, and must not be
dvander@27
    19
 *      misrepresented as being the original software.
dvander@27
    20
 *  3.  This notice may not be removed or altered from any source distribution.
dvander@27
    21
 *
dvander@27
    22
 *  Version: $Id: sc5.c 3579 2006-06-06 13:35:29Z thiadmer $
dvander@27
    23
 */
dvander@27
    24
#include <assert.h>
dvander@27
    25
#if defined	__WIN32__ || defined _WIN32 || defined __MSDOS__
dvander@27
    26
  #include <io.h>
dvander@27
    27
#endif
dvander@27
    28
#if defined LINUX || defined __GNUC__
dvander@27
    29
  #include <unistd.h>
dvander@27
    30
#endif
dvander@27
    31
#include <stdio.h>
dvander@27
    32
#include <stdlib.h>
dvander@27
    33
#include <stdarg.h>     /* ANSI standardized variable argument list functions */
dvander@27
    34
#include <string.h>
dvander@27
    35
#if defined FORTIFY
dvander@27
    36
  #include <alloc/fortify.h>
dvander@27
    37
#endif
dvander@27
    38
#include "sc.h"
dvander@27
    39
dvander@27
    40
#if defined _MSC_VER
dvander@27
    41
  #pragma warning(push)
dvander@27
    42
  #pragma warning(disable:4125)  /* decimal digit terminates octal escape sequence */
dvander@27
    43
#endif
dvander@27
    44
dvander@27
    45
#include "sc5.scp"
dvander@27
    46
dvander@27
    47
#if defined _MSC_VER
dvander@27
    48
  #pragma warning(pop)
dvander@27
    49
#endif
dvander@27
    50
dvander@27
    51
#define NUM_WARNINGS    (sizeof warnmsg / sizeof warnmsg[0])
dvander@27
    52
static unsigned char warndisable[(NUM_WARNINGS + 7) / 8]; /* 8 flags in a char */
dvander@27
    53
dvander@27
    54
static int errflag;
dvander@27
    55
static int errstart;    /* line number at which the instruction started */
dvander@27
    56
static int errline;     /* forced line number for the error message */
dvander@27
    57
dvander@27
    58
/*  error
dvander@27
    59
 *
dvander@27
    60
 *  Outputs an error message (note: msg is passed optionally).
dvander@27
    61
 *  If an error is found, the variable "errflag" is set and subsequent
dvander@27
    62
 *  errors are ignored until lex() finds a semicolumn or a keyword
dvander@27
    63
 *  (lex() resets "errflag" in that case).
dvander@27
    64
 *
dvander@27
    65
 *  Global references: inpfname   (reffered to only)
dvander@27
    66
 *                     fline      (reffered to only)
dvander@27
    67
 *                     fcurrent   (reffered to only)
dvander@27
    68
 *                     errflag    (altered)
dvander@27
    69
 */
dvander@27
    70
SC_FUNC int error(int number,...)
dvander@27
    71
{
dvander@27
    72
static char *prefix[3]={ "error", "fatal error", "warning" };
dvander@27
    73
static int lastline,errorcount;
dvander@27
    74
static short lastfile;
dvander@27
    75
  char *msg,*pre;
dvander@27
    76
  va_list argptr;
dvander@27
    77
  char string[128];
dvander@27
    78
dvander@27
    79
  /* errflag is reset on each semicolon.
dvander@27
    80
   * In a two-pass compiler, an error should not be reported twice. Therefore
dvander@27
    81
   * the error reporting is enabled only in the second pass (and only when
dvander@27
    82
   * actually producing output). Fatal errors may never be ignored.
dvander@27
    83
   */
dvander@27
    84
  if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200))
dvander@27
    85
    return 0;
dvander@27
    86
dvander@27
    87
  /* also check for disabled warnings */
dvander@27
    88
  if (number>=200) {
dvander@27
    89
    int index=(number-200)/8;
dvander@27
    90
    int mask=1 << ((number-200)%8);
dvander@27
    91
    if ((warndisable[index] & mask)!=0)
dvander@27
    92
      return 0;
dvander@27
    93
  } /* if */
dvander@27
    94
dvander@27
    95
  if (number<100){
dvander@27
    96
    msg=errmsg[number-1];
dvander@27
    97
    pre=prefix[0];
dvander@27
    98
    errflag=TRUE;       /* set errflag (skip rest of erroneous expression) */
dvander@27
    99
    errnum++;
dvander@27
   100
  } else if (number<200){
dvander@27
   101
    msg=fatalmsg[number-100];
dvander@27
   102
    pre=prefix[1];
dvander@27
   103
    errnum++;           /* a fatal error also counts as an error */
dvander@27
   104
  } else {
dvander@27
   105
    msg=warnmsg[number-200];
dvander@27
   106
    pre=prefix[2];
dvander@27
   107
    warnnum++;
dvander@27
   108
  } /* if */
dvander@27
   109
dvander@27
   110
  strexpand(string,(unsigned char *)msg,sizeof string,SCPACK_TABLE);
dvander@27
   111
dvander@27
   112
  assert(errstart<=fline);
dvander@27
   113
  if (errline>0)
dvander@27
   114
    errstart=errline;
dvander@27
   115
  else
dvander@27
   116
    errline=fline;
dvander@27
   117
  assert(errstart<=errline);
dvander@27
   118
  va_start(argptr,number);
dvander@27
   119
  if (strlen(errfname)==0) {
dvander@27
   120
    int start= (errstart==errline) ? -1 : errstart;
dvander@27
   121
    if (pc_error(number,string,inpfname,start,errline,argptr)) {
dvander@27
   122
      if (outf!=NULL) {
dvander@27
   123
        pc_closeasm(outf,TRUE);
dvander@27
   124
        outf=NULL;
dvander@27
   125
      } /* if */
dvander@27
   126
      longjmp(errbuf,3);        /* user abort */
dvander@27
   127
    } /* if */
dvander@27
   128
  } else {
dvander@27
   129
    FILE *fp=fopen(errfname,"a");
dvander@27
   130
    if (fp!=NULL) {
dvander@27
   131
      if (errstart>=0 && errstart!=errline)
dvander@27
   132
        fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number);
dvander@27
   133
      else
dvander@27
   134
        fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number);
dvander@27
   135
      vfprintf(fp,string,argptr);
dvander@27
   136
      fclose(fp);
dvander@27
   137
    } /* if */
dvander@27
   138
  } /* if */
dvander@27
   139
  va_end(argptr);
dvander@27
   140
dvander@27
   141
  if (number>=100 && number<200 || errnum>25){
dvander@27
   142
    if (strlen(errfname)==0) {
dvander@27
   143
      va_start(argptr,number);
dvander@27
   144
      pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr);
dvander@27
   145
      va_end(argptr);
dvander@27
   146
    } /* if */
dvander@27
   147
    if (outf!=NULL) {
dvander@27
   148
      pc_closeasm(outf,TRUE);
dvander@27
   149
      outf=NULL;
dvander@27
   150
    } /* if */
dvander@27
   151
    longjmp(errbuf,2);          /* fatal error, quit */
dvander@27
   152
  } /* if */
dvander@27
   153
dvander@27
   154
  errline=-1;
dvander@27
   155
  /* check whether we are seeing many errors on the same line */
dvander@27
   156
  if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile)
dvander@27
   157
    errorcount=0;
dvander@27
   158
  lastline=fline;
dvander@27
   159
  lastfile=fcurrent;
dvander@27
   160
  if (number<200)
dvander@27
   161
    errorcount++;
dvander@27
   162
  if (errorcount>=3)
dvander@27
   163
    error(107);         /* too many error/warning messages on one line */
dvander@27
   164
dvander@27
   165
  return 0;
dvander@27
   166
}
dvander@27
   167
dvander@27
   168
SC_FUNC void errorset(int code,int line)
dvander@27
   169
{
dvander@27
   170
  switch (code) {
dvander@27
   171
  case sRESET:
dvander@27
   172
    errflag=FALSE;      /* start reporting errors */
dvander@27
   173
    break;
dvander@27
   174
  case sFORCESET:
dvander@27
   175
    errflag=TRUE;       /* stop reporting errors */
dvander@27
   176
    break;
dvander@27
   177
  case sEXPRMARK:
dvander@27
   178
    errstart=fline;     /* save start line number */
dvander@27
   179
    break;
dvander@27
   180
  case sEXPRRELEASE:
dvander@27
   181
    errstart=-1;        /* forget start line number */
dvander@27
   182
    errline=-1;
dvander@27
   183
    break;
dvander@27
   184
  case sSETPOS:
dvander@27
   185
    errline=line;
dvander@27
   186
    break;
dvander@27
   187
  } /* switch */
dvander@27
   188
}
dvander@27
   189
dvander@27
   190
/* sc_enablewarning()
dvander@27
   191
 * Enables or disables a warning (errors cannot be disabled).
dvander@27
   192
 * Initially all warnings are enabled. The compiler does this by setting bits
dvander@27
   193
 * for the *disabled* warnings and relying on the array to be zero-initialized.
dvander@27
   194
 *
dvander@27
   195
 * Parameter enable can be:
dvander@27
   196
 *  o  0 for disable
dvander@27
   197
 *  o  1 for enable
dvander@27
   198
 *  o  2 for toggle
dvander@27
   199
 */
dvander@27
   200
int pc_enablewarning(int number,int enable)
dvander@27
   201
{
dvander@27
   202
  int index;
dvander@27
   203
  unsigned char mask;
dvander@27
   204
dvander@27
   205
  if (number<200)
dvander@27
   206
    return FALSE;       /* errors and fatal errors cannot be disabled */
dvander@27
   207
  number -= 200;
dvander@27
   208
  if (number>=NUM_WARNINGS)
dvander@27
   209
    return FALSE;
dvander@27
   210
dvander@27
   211
  index=number/8;
dvander@27
   212
  mask=(unsigned char)(1 << (number%8));
dvander@27
   213
  switch (enable) {
dvander@27
   214
  case 0:
dvander@27
   215
    warndisable[index] |= mask;
dvander@27
   216
    break;
dvander@27
   217
  case 1:
dvander@27
   218
    warndisable[index] &= (unsigned char)~mask;
dvander@27
   219
    break;
dvander@27
   220
  case 2:
dvander@27
   221
    warndisable[index] ^= mask;
dvander@27
   222
    break;
dvander@27
   223
  } /* switch */
dvander@27
   224
dvander@27
   225
  return TRUE;
dvander@27
   226
}
dvander@27
   227
dvander@27
   228
#undef SCPACK_TABLE