static void abort_compiler() { if (strlen(errfname)==0) { fprintf(stdout, "\nCompilation aborted."); } /* if */ if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,2); /* fatal error, quit */ }
/* error * * Outputs an error message (note: msg is passed optionally). * If an error is found, the variable "errflag" is set and subsequent * errors are ignored until lex() finds a semicolon or a keyword * (lex() resets "errflag" in that case). * * Global references: inpfname (reffered to only) * fline (reffered to only) * fcurrent (reffered to only) * errflag (altered) */ SC_FUNC int error(long number,...) { static char *prefix[3]={ "error", "fatal error", "warning" }; static int lastline,errorcount; static short lastfile; char *msg,*pre,*filename; va_list argptr; char string[256]; int notice; /* split the error field between the real error/warning number and an optional * "notice" number */ notice=number >> (sizeof(long)*4); number&=((unsigned long)~0) >> (sizeof(long)*4); assert(number>0 && number<300); /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore * the error reporting is enabled only in the second pass (and only when * actually producing output). Fatal errors may never be ignored. */ if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200)) return 0; /* also check for disabled warnings */ if (number>=200) { int index=(number-200)/8; int mask=1 << ((number-200)%8); if ((warndisable[index] & mask)!=0) { errline=-1; errfile=-1; return 0; } /* if */ } /* if */ if (number<100){ assert(number>0 && number<sizearray(errmsg)); msg=errmsg[number]; pre=prefix[0]; errflag=TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; } else if (number<200) { assert((number-100)>=0 && (number-100)<sizearray(fatalmsg)); msg=fatalmsg[number-100]; pre=prefix[1]; errnum++; /* a fatal error also counts as an error */ } else { assert((number-200)>=0 && (number-200)<sizearray(warnmsg)); msg=warnmsg[number-200]; pre=prefix[2]; warnnum++; } /* if */ strexpand(string,(unsigned char *)msg,sizeof string-2,SCPACK_TABLE); if (notice>0) { int len; assert(notice<sizearray(noticemsg)); strcat(string,"; "); len=strlen(string); strexpand(string+len,(unsigned char *)noticemsg[notice],sizeof string-len-1,SCPACK_TABLE); } /* if */ strcat(string,"\n"); if (errline>0) errstart=errline; /* forced error position, set single line destination */ else errline=fline; /* normal error, errstart may (or may not) have been marked, endpoint is current line */ if (errstart>errline) errstart=errline; /* special case: error found at end of included file */ if (errfile>=0) { filename=get_inputfile(errfile);/* forced filename */ } else { filename=inpfname; /* current file */ if (filename==NULL || strlen(filename)==0) filename=get_sourcefile(0); if (filename==NULL || strlen(filename)==0) filename="(none)"; } /* if */ assert(filename!=NULL); va_start(argptr,number); if (strlen(errfname)==0) { int start= (errstart==errline) ? -1 : errstart; if (pc_error((int)number,string,filename,start,errline,argptr)) { if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,3); /* user abort */ } /* if */ } else { FILE *fp=fopen(errfname,"a"); if (fp!=NULL) { if (errstart>=0 && errstart!=errline) fprintf(fp,"%s(%d -- %d) : %s %03d: ",filename,errstart,errline,pre,(int)number); else fprintf(fp,"%s(%d) : %s %03d: ",filename,errline,pre,(int)number); vfprintf(fp,string,argptr); fclose(fp); } /* if */ } /* if */ va_end(argptr); if (number>=100 && number<200 || errnum>25){ if (strlen(errfname)==0) { va_start(argptr,number); pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr); va_end(argptr); } /* if */ if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,2); /* fatal error, quit */ } /* if */ errline=-1; errfile=-1; /* check whether we are seeing many errors on the same line */ if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile) errorcount=0; lastline=fline; lastfile=fcurrent; if (number<200) errorcount++; if (errorcount>=3) error(107); /* too many error/warning messages on one line */ return 0; }
/* error * * Outputs an error message (note: msg is passed optionally). * If an error is found, the variable "errflag" is set and subsequent * errors are ignored until lex() finds a semicolumn or a keyword * (lex() resets "errflag" in that case). * * Global references: inpfname (reffered to only) * fline (reffered to only) * fcurrent (reffered to only) * errflag (altered) */ int error(int number,...) { static const char *prefix[3]={ "error", "fatal error", "warning" }; static int lastline,errorcount; static short lastfile; const char *msg,*pre; va_list argptr; // sErrLine is used to temporarily change the line number of reported errors. // Pawn has an upstream bug where this is not reset on early-return, which // can lead to broken line numbers in error messages. int errline = sErrLine; sErrLine = -1; bool is_warning = (number >= 200 && !sc_warnings_are_errors); /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore * the error reporting is enabled only in the second pass (and only when * actually producing output). Fatal errors may never be ignored. */ int not_fatal = (number < FIRST_FATAL_ERROR || number >= 200); if (errflag && not_fatal) return 0; if (sc_status != statWRITE && not_fatal) { if (!sc_err_status) return 0; } /* also check for disabled warnings */ if (number>=200) { int index=(number-200)/8; int mask=1 << ((number-200)%8); if ((warndisable[index] & mask)!=0) return 0; } /* if */ if (number<FIRST_FATAL_ERROR) { msg=errmsg[number-1]; pre=prefix[0]; errflag=TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; } else if (number<200){ msg=fatalmsg[number-FIRST_FATAL_ERROR]; pre=prefix[1]; errnum++; /* a fatal error also counts as an error */ } else { msg=warnmsg[number-200]; if (sc_warnings_are_errors) { pre=prefix[0]; errnum++; } else { pre=prefix[2]; warnnum++; } } /* if */ assert(errstart<=fline); if (errline>0) errstart=errline; else errline=fline; assert(errstart<=errline); va_start(argptr,number); if (strlen(errfname)==0) { int start= (errstart==errline) ? -1 : errstart; if (pc_error(number,msg,inpfname,start,errline,argptr)) { if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,3); /* user abort */ } /* if */ } else { FILE *fp=fopen(errfname,"a"); if (fp!=NULL) { if (errstart>=0 && errstart!=errline) fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number); else fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number); vfprintf(fp,msg,argptr); fclose(fp); } /* if */ } /* if */ va_end(argptr); if ((number>=FIRST_FATAL_ERROR && number<200) || errnum>25){ if (strlen(errfname)==0) { va_start(argptr,number); pc_error(0,"\nCompilation aborted.",NULL,0,0,argptr); va_end(argptr); } /* if */ if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,2); /* fatal error, quit */ } /* if */ /* check whether we are seeing many errors on the same line */ if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile) errorcount=0; lastline=fline; lastfile=fcurrent; if (!is_warning) errorcount++; if (errorcount>=3) error(FATAL_ERROR_OVERWHELMED_BY_BAD); return 0; }
/* error * * Outputs an error message (note: msg is passed optionally). * If an error is found, the variable "errflag" is set and subsequent * errors are ignored until lex() finds a semicolumn or a keyword * (lex() resets "errflag" in that case). * * Global references: inpfname (reffered to only) * fline (reffered to only) * fcurrent (reffered to only) * errflag (altered) */ SC_FUNC int error(int number,...) { static char *prefix[3]={ "error", "fatal error", "warning" }; static int lastline,errorcount; static short lastfile; char *msg,*pre; va_list argptr; /* errflag is reset on each semicolon. * In a two-pass compiler, an error should not be reported twice. Therefore * the error reporting is enabled only in the second pass (and only when * actually producing output). Fatal errors may never be ignored. */ if ((errflag || sc_status!=statWRITE) && (number<100 || number>=200)) return 0; /* also check for disabled warnings */ if (number>=200) { int index=(number-200)/8; int mask=1 << ((number-200)%8); if ((warnstack.disable[index] & mask)!=0) return 0; } /* if */ if (number<100){ msg=errmsg[number-1]; pre=prefix[0]; errflag=TRUE; /* set errflag (skip rest of erroneous expression) */ errnum++; } else if (number<200){ msg=fatalmsg[number-100]; pre=prefix[1]; errnum++; /* a fatal error also counts as an error */ } else { msg=warnmsg[number-200]; pre=prefix[2]; warnnum++; } /* if */ assert(errstart<=fline); if (errline>0) errstart=errline; else errline=fline; assert(errstart<=errline); va_start(argptr,number); if (strlen(errfname)==0) { int start= (errstart==errline) ? -1 : errstart; if (pc_error(number,msg,inpfname,start,errline,argptr)) { if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,3); /* user abort */ } /* if */ } else { FILE *fp=fopen(errfname,"a"); if (fp!=NULL) { if (errstart>=0 && errstart!=errline) fprintf(fp,"%s(%d -- %d) : %s %03d: ",inpfname,errstart,errline,pre,number); else fprintf(fp,"%s(%d) : %s %03d: ",inpfname,errline,pre,number); vfprintf(fp,msg,argptr); fclose(fp); } /* if */ } /* if */ va_end(argptr); if (number>=100 && number<200 || errnum>25){ if (strlen(errfname)==0) { va_start(argptr,number); pc_error(0,"\nCompilation aborted.\n\n",NULL,0,0,argptr); va_end(argptr); } /* if */ if (outf!=NULL) { pc_closeasm(outf,TRUE); outf=NULL; } /* if */ longjmp(errbuf,2); /* fatal error, quit */ } /* if */ errline=-1; /* check whether we are seeing many errors on the same line */ if ((errstart<0 && lastline!=fline) || lastline<errstart || lastline>fline || fcurrent!=lastfile) errorcount=0; lastline=fline; lastfile=fcurrent; if (number<200) errorcount++; if (errorcount>=3) error(107); /* too many error/warning messages on one line */ return 0; }