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