00001 /* pomdp_err.c 00002 00003 ***** 00004 Copyright 1994-1997, Brown University 00005 Copyright 1998, 1999, Anthony R. Cassandra 00006 00007 All Rights Reserved 00008 00009 Permission to use, copy, modify, and distribute this software and its 00010 documentation for any purpose other than its incorporation into a 00011 commercial product is hereby granted without fee, provided that the 00012 above copyright notice appear in all copies and that both that 00013 copyright notice and this permission notice appear in supporting 00014 documentation. 00015 00016 ANTHONY CASSANDRA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 00017 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ANY 00018 PARTICULAR PURPOSE. IN NO EVENT SHALL ANTHONY CASSANDRA BE LIABLE FOR 00019 ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00020 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00021 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00022 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00023 ***** 00024 00025 This module contains the functions necessary for the creation, 00026 maintainence and output of the data structure that holds the error 00027 information generated by the scanner/parser. 00028 00029 */ 00030 00031 #include <stdio.h> 00032 #include <stdlib.h> 00033 #include <string.h> 00034 #include "parse_err.h" /* constant and type defs. */ 00035 00036 /*********************** GLOBAL VARIABLES ***************************/ 00037 /* GLOBAL Array of error messages */ 00038 static char *Err_Strings[NBR_ERRORS] = { 00039 ERROR_MSSG_0, 00040 ERROR_MSSG_1, 00041 ERROR_MSSG_2, 00042 ERROR_MSSG_3, 00043 ERROR_MSSG_4, 00044 ERROR_MSSG_5, 00045 ERROR_MSSG_6, 00046 ERROR_MSSG_7, 00047 ERROR_MSSG_8, 00048 ERROR_MSSG_9, 00049 ERROR_MSSG_10, 00050 ERROR_MSSG_11, 00051 ERROR_MSSG_12, 00052 ERROR_MSSG_13, 00053 ERROR_MSSG_14, 00054 ERROR_MSSG_15, 00055 ERROR_MSSG_16, 00056 ERROR_MSSG_17, 00057 ERROR_MSSG_18, 00058 ERROR_MSSG_19, 00059 ERROR_MSSG_20, 00060 ERROR_MSSG_21, 00061 ERROR_MSSG_22, 00062 ERROR_MSSG_23, 00063 ERROR_MSSG_24, 00064 ERROR_MSSG_25, 00065 ERROR_MSSG_26, 00066 ERROR_MSSG_27, 00067 ERROR_MSSG_28 00068 }; 00069 00070 /* pointer to the linked list of errors */ 00071 Err_node *Err_list; /* GLOBAL error list */ 00072 00073 00074 /********************** ERR_initialize ******************************/ 00075 void ERR_initialize() 00076 /* 00077 Initializes the linked list of errors by creating the first 00078 node in that list as empty. The list will actually start with the 00079 second node of the list. The 'unused first node' scheme is used so that 00080 functions that might alter the front of the list need not return 00081 a pointer to the list (as would be required, since the front of the 00082 list might change). 00083 */ 00084 { 00085 /* Initialize the error list */ 00086 Err_list = (Err_node *) malloc(sizeof(Err_node)); 00087 checkAllocatedPointer((void *) Err_list ); 00088 00089 Err_list->nextError = NULL; 00090 Err_list->source = NULL; 00091 Err_list->modString = NULL; 00092 00093 } /* ERR_initialize */ 00094 /********************** ERR_enter ***********************************/ 00095 void ERR_enter(source, lineno, errorid, modificationString) 00096 /* 00097 The routine will create a new node for the linked list of errors and fill 00098 it with the proper data. It will then insert this node into the existing linked 00099 list of errors in line number order. If there already exists one or more errors 00100 for that line number the new node will be placed at the end of all of those so 00101 that for a line, first generated is the first displayed. Error messages with no 00102 associated line number will always precede all the other messages with a line 00103 number and, similiarly, on a first generated-first displayed basis. 00104 00105 Parameter Descriptions: 00106 00107 "source" is a pointer to a string that will indicate the 00108 part of the compiler generating the message as well 00109 as the function (routine) that is giving the message. 00110 This will onl be displayed to output during the 00111 debugging of the compiler. 00112 00113 "lineno" is the line number that the error occured on. If a line 00114 number is inappropriate, pass the constant NO_LINE. 00115 00116 "errorid" is the type of error that occured. If this number is 00117 larger than the maximum id, an error message will be output 00118 and no error will be recorded. 00119 00120 "modificationString" is a pointer to a string of characters that will 00121 be used to replace the character ERR_META when the error 00122 message is printed out. (if ERR_META is in error message) 00123 00124 */ 00125 char *source; 00126 int lineno,errorid; 00127 char *modificationString; 00128 { 00129 Err_node *newNode; /* node for new error */ 00130 00131 Err_node *tempPtr, /* for insertion in sorted list */ 00132 *trailPtr; 00133 00134 /* Is the error number valid? */ 00135 if (errorid >= NBR_ERRORS) 00136 { 00137 printf(OUT_OF_RANGE_MSSG, errorid); 00138 return; 00139 } 00140 00141 /* Create a new error node */ 00142 newNode = (Err_node *) malloc(sizeof(Err_node)); 00143 checkAllocatedPointer((void *) newNode ); 00144 00145 /* Put the information in */ 00146 newNode->lineNumber = lineno; 00147 newNode->errorNumber = errorid; 00148 if( modificationString != NULL ) { 00149 newNode->modString = (char *) calloc(strlen(modificationString)+1, 00150 sizeof(char)); 00151 strcpy(newNode->modString, modificationString); 00152 } 00153 else 00154 newNode->modString = NULL; 00155 00156 00157 if( source != NULL ) { 00158 newNode->source = (char *) calloc(strlen(source)+1, sizeof(char)); 00159 strcpy(newNode->source, source); 00160 } 00161 else 00162 newNode->source = NULL; 00163 00164 newNode->nextError = NULL; 00165 00166 /* Insert it in the linked list in sorted order (by line number) */ 00167 trailPtr = Err_list; 00168 tempPtr = Err_list->nextError; 00169 00170 while(tempPtr != NULL) 00171 { 00172 if (tempPtr->lineNumber <= newNode->lineNumber) 00173 { 00174 trailPtr = tempPtr; 00175 tempPtr = tempPtr->nextError; 00176 } /* end if */ 00177 00178 else /* list line number > new line number */ 00179 break; /* this is the place to insert */ 00180 00181 } /* end of while loop */ 00182 /* node will be inserted after "trailPtr" and before "tempPtr" */ 00183 00184 newNode->nextError = tempPtr; 00185 trailPtr->nextError = newNode; 00186 00187 } /* ERR_enter */ 00188 /***************************** ERR_dump ***********************************/ 00189 int ERR_dump() 00190 /* 00191 This function prints out the error messages found in the list 00192 Err_list. Each error 00193 is printed on a separate line. If the error string has the 00194 character ERR_META in it, the string that was passed to ERR_enter 00195 when the node was created will be passed instead. ("modString") 00196 If there were no errors in the list, the message "No Errors found." 00197 will be printed. 00198 The "source" string of where the error occurred is only printed out 00199 when the Global constant DEBUG is not zero. 00200 */ 00201 { 00202 char *currChar; /* used for outputting string */ 00203 Err_node *currErr; /* used for traversing node list */ 00204 int numErrors = 0; 00205 int numWarnings = 0; 00206 00207 if (Err_list->nextError == NULL) 00208 /* then there are no errors in the list */ 00209 { 00210 /* printf(NO_ERRORS); */ 00211 return 0; 00212 } /* end if no errors in list */ 00213 00214 00215 /* Write out error list */ 00216 currErr = Err_list->nextError; 00217 00218 while (currErr != NULL) { 00219 if ((DEBUG) && (currErr->source != NULL)) 00220 /* then printout where error was generated */ 00221 printf("(%s) ", currErr->source); 00222 00223 /* check whether it is a warning or an error */ 00224 switch(currErr->errorNumber) { 00225 /* WARINGS */ 00226 case -1: /* Currently no warnings are defined */ 00227 numWarnings++; 00228 if (currErr->lineNumber == NO_LINE) 00229 /* then the warning didn't have a line number associated 00230 with it */ 00231 printf(NO_LINE_WARNING); 00232 00233 else /* there was a line number */ 00234 printf(LINE_WARNING, currErr->lineNumber); 00235 break; 00236 00237 /* ERRORS */ 00238 default: 00239 numErrors++; 00240 00241 if (currErr->lineNumber == NO_LINE) 00242 /* then the error didn't have a line number associated 00243 with it 00244 */ 00245 printf(NO_LINE_ERROR); 00246 00247 else /* there was a line number */ 00248 printf(LINE_ERROR, currErr->lineNumber); 00249 break; 00250 } /* end of switch */ 00251 00252 /* Dump the string */ 00253 currChar = Err_Strings[currErr->errorNumber]; 00254 00255 while (*currChar != '\0') { 00256 /* Meta-symbol? */ 00257 if ((*currChar == ERR_META) && (currErr->modString != NULL )) 00258 printf("%s",currErr->modString); /* dump str */ 00259 else /* just write character */ 00260 printf("%c",*currChar); 00261 00262 /* Next character */ 00263 currChar = currChar + 1; 00264 } 00265 00266 printf("\n"); /* next line */ 00267 00268 /* Next error node */ 00269 currErr = currErr->nextError; 00270 } 00271 00272 printf("%d errors and %d warnings found.\n", numErrors, numWarnings); 00273 return 1; 00274 00275 } /* ERR_dump */ 00276 /***************************************************************************/ 00277 void ERR_cleanUp() { 00278 Err_node *temp; 00279 00280 while( Err_list != NULL ) { 00281 temp = Err_list; 00282 Err_list = Err_list->nextError; 00283 if( temp->source != NULL ) 00284 free( temp->source ); 00285 if( temp->modString != NULL ) 00286 free( temp->modString ); 00287 free( temp ); 00288 } /* while */ 00289 00290 } 00291 /***************************************************************************/