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