1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <stdio.h> 28 #include <ctype.h> 29 #include <stdlib.h> 30 #include <unistd.h> 31 #include <stdarg.h> 32 #include <string.h> 33 #include "error.h" 34 35 /* 36 * Arrayify a list of rules 37 */ 38 void 39 arrayify(int *e_length, Eptr **e_array, Eptr header) 40 { 41 Eptr errorp; 42 Eptr *array; 43 int listlength; 44 int listindex; 45 46 for (errorp = header, listlength = 0; 47 errorp; errorp = errorp->error_next, listlength++) 48 continue; 49 array = Calloc(listlength+1, sizeof (Eptr)); 50 for (listindex = 0, errorp = header; 51 listindex < listlength; 52 listindex++, errorp = errorp->error_next) { 53 array[listindex] = errorp; 54 errorp->error_position = listindex; 55 } 56 array[listindex] = (Eptr)0; 57 *e_length = listlength; 58 *e_array = array; 59 } 60 61 /*PRINTFLIKE1*/ 62 static void 63 error(char *format, ...) 64 { 65 va_list args; 66 67 va_start(args, format); 68 (void) fprintf(stderr, "Error: "); 69 (void) vfprintf(stderr, format, args); 70 (void) fprintf(stderr, "\n"); 71 (void) fflush(stdout); 72 (void) fflush(stderr); 73 va_end(args); 74 exit(6); 75 } 76 77 void * 78 Calloc(int nelements, int size) 79 { 80 void *back; 81 if ((back = calloc(nelements, size)) == NULL) { 82 error("Ran out of memory.\n"); 83 exit(1); 84 } 85 return (back); 86 } 87 88 char * 89 strsave(char *instring) 90 { 91 char *outstring; 92 (void) strcpy(outstring = Calloc(1, strlen(instring) + 1), 93 instring); 94 return (outstring); 95 } 96 /* 97 * find the position of a given character in a string 98 * (one based) 99 */ 100 int 101 position(char *string, char ch) 102 { 103 int i; 104 105 if (string) { 106 for (i = 1; *string; string++, i++) { 107 if (*string == ch) 108 return (i); 109 } 110 } 111 return (-1); 112 } 113 /* 114 * clobber the first occurance of ch in string by the new character 115 */ 116 char * 117 substitute(char *string, char chold, char chnew) 118 { 119 char *cp = string; 120 121 if (cp) { 122 while (*cp) { 123 if (*cp == chold) { 124 *cp = chnew; 125 break; 126 } 127 cp++; 128 } 129 } 130 return (string); 131 } 132 133 char 134 lastchar(char *string) 135 { 136 int length; 137 138 if (string == NULL) 139 return ('\0'); 140 length = strlen(string); 141 if (length >= 1) 142 return (string[length-1]); 143 else 144 return ('\0'); 145 } 146 147 char 148 firstchar(char *string) 149 { 150 if (string) 151 return (string[0]); 152 else 153 return ('\0'); 154 } 155 156 char 157 next_lastchar(char *string) 158 { 159 int length; 160 161 if (string == NULL) 162 return ('\0'); 163 length = strlen(string); 164 if (length >= 2) 165 return (string[length - 2]); 166 else 167 return ('\0'); 168 } 169 170 void 171 clob_last(char *string, char newstuff) 172 { 173 int length = 0; 174 if (string) 175 length = strlen(string); 176 if (length >= 1) 177 string[length - 1] = newstuff; 178 } 179 180 /* 181 * parse a string that is the result of a format %s(%d) 182 * return TRUE if this is of the proper format 183 */ 184 boolean 185 persperdexplode(char *string, char **r_perd, char **r_pers) 186 { 187 char *cp; 188 int length = 0; 189 190 if (string) 191 length = strlen(string); 192 if ((length >= 4) && (string[length - 1] == ')')) { 193 for (cp = &string[length - 2]; 194 (isdigit(*cp)) && (*cp != '('); --cp) 195 continue; 196 if (*cp == '(') { 197 string[length - 1] = '\0'; /* clobber the ) */ 198 *r_perd = strsave(cp+1); 199 string[length - 1] = ')'; 200 *cp = '\0'; /* clobber the ( */ 201 *r_pers = strsave(string); 202 *cp = '('; 203 return (TRUE); 204 } 205 } 206 return (FALSE); 207 } 208 209 static char cincomment[] = CINCOMMENT; 210 static char coutcomment[] = COUTCOMMENT; 211 static char fincomment[] = FINCOMMENT; 212 static char foutcomment[] = FOUTCOMMENT; 213 static char newline[] = NEWLINE; 214 static char piincomment[] = PIINCOMMENT; 215 static char pioutcomment[] = PIOUTCOMMENT; 216 static char lispincomment[] = LISPINCOMMENT; 217 static char riincomment[] = RIINCOMMENT; 218 static char rioutcomment[] = RIOUTCOMMENT; 219 static char troffincomment[] = TROFFINCOMMENT; 220 static char troffoutcomment[] = TROFFOUTCOMMENT; 221 static char mod2incomment[] = MOD2INCOMMENT; 222 static char mod2outcomment[] = MOD2OUTCOMMENT; 223 224 struct lang_desc lang_table[] = { 225 /* INUNKNOWN 0 */ "unknown", cincomment, coutcomment, 226 /* INCPP 1 */ "cpp", cincomment, coutcomment, 227 /* INCC 2 */ "cc", cincomment, coutcomment, 228 /* INAS 3 */ "as", ASINCOMMENT, newline, 229 /* INLD 4 */ "ld", cincomment, coutcomment, 230 /* INLINT 5 */ "lint", cincomment, coutcomment, 231 /* INF77 6 */ "f77", fincomment, foutcomment, 232 /* INPI 7 */ "pi", piincomment, pioutcomment, 233 /* INPC 8 */ "pc", piincomment, pioutcomment, 234 /* INFRANZ 9 */ "franz", lispincomment, newline, 235 /* INLISP 10 */ "lisp", lispincomment, newline, 236 /* INVAXIMA 11 */ "vaxima", lispincomment, newline, 237 /* INRATFOR 12 */ "ratfor", fincomment, foutcomment, 238 /* INLEX 13 */ "lex", cincomment, coutcomment, 239 /* INYACC 14 */ "yacc", cincomment, coutcomment, 240 /* INAPL 15 */ "apl", ".lm", newline, 241 /* INMAKE 16 */ "make", ASINCOMMENT, newline, 242 /* INRI 17 */ "ri", riincomment, rioutcomment, 243 /* INTROFF 18 */ "troff", troffincomment, troffoutcomment, 244 /* INMOD2 19 */ "mod2", mod2incomment, mod2outcomment, 245 /* INSUNF77 20 */ "Sunf77", fincomment, foutcomment, 246 0, 0, 0 247 }; 248 249 void 250 printerrors(boolean look_at_subclass, int errorc, Eptr errorv[]) 251 { 252 int i; 253 Eptr errorp; 254 255 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) { 256 if (errorp->error_e_class == C_IGNORE) 257 continue; 258 if (look_at_subclass && errorp->error_s_class == C_DUPL) 259 continue; 260 (void) printf("Error %d, (%s error) [%s], text = \"", 261 i, 262 class_table[errorp->error_e_class], 263 lang_table[errorp->error_language].lang_name); 264 wordvprint(stdout, errorp->error_lgtext, errorp->error_text); 265 (void) printf("\"\n"); 266 } 267 } 268 269 void 270 wordvprint(FILE *fyle, int wordc, char *wordv[]) 271 { 272 int i; 273 char *sep = ""; 274 275 for (i = 0; i < wordc; i++) 276 if (wordv[i]) { 277 (void) fprintf(fyle, "%s%s", sep, wordv[i]); 278 sep = " "; 279 } 280 } 281 282 /* 283 * Given a string, parse it into a number of words, and build 284 * a wordc wordv combination pointing into it. 285 */ 286 void 287 wordvbuild(char *string, int *r_wordc, char ***r_wordv) 288 { 289 char *cp; 290 char *saltedbuffer; 291 char **wordv; 292 int wordcount; 293 int wordindex; 294 295 saltedbuffer = strsave(string); 296 for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) { 297 while (*cp && isspace(*cp)) 298 cp++; 299 if (*cp == 0) 300 break; 301 while (*cp && !isspace(*cp)) 302 cp++; 303 } 304 wordv = Calloc(wordcount + 1, sizeof (char *)); 305 for (cp = saltedbuffer, wordindex = 0; wordcount; 306 wordindex++, --wordcount) { 307 while (*cp && isspace(*cp)) 308 cp++; 309 if (*cp == 0) 310 break; 311 wordv[wordindex] = cp; 312 while (*cp && !isspace(*cp)) 313 cp++; 314 *cp++ = '\0'; 315 } 316 if (wordcount != 0) 317 error("Initial miscount of the number of words in a line\n"); 318 wordv[wordindex] = NULL; 319 #ifdef FULLDEBUG 320 for (wordcount = 0; wordcount < wordindex; wordcount++) 321 (void) printf("Word %d = \"%s\"\n", wordcount, 322 wordv[wordcount]); 323 (void) printf("\n"); 324 #endif 325 *r_wordc = wordindex; 326 *r_wordv = wordv; 327 } 328 /* 329 * Compare two 0 based wordvectors 330 */ 331 int 332 wordvcmp(char **wordv1, int wordc, char **wordv2) 333 { 334 int i; 335 int back; 336 337 for (i = 0; i < wordc; i++) { 338 if (wordv1[i] == 0 || wordv2[i] == 0) 339 return (-1); 340 if (back = strcmp(wordv1[i], wordv2[i])) { 341 return (back); 342 } 343 } 344 return (0); /* they are equal */ 345 } 346 347 /* 348 * splice a 0 basedword vector onto the tail of a 349 * new wordv, allowing the first emptyhead slots to be empty 350 */ 351 char ** 352 wordvsplice(int emptyhead, int wordc, char **wordv) 353 { 354 char **nwordv; 355 int nwordc = emptyhead + wordc; 356 int i; 357 358 nwordv = Calloc(nwordc, sizeof (char *)); 359 for (i = 0; i < emptyhead; i++) 360 nwordv[i] = 0; 361 for (i = emptyhead; i < nwordc; i++) { 362 nwordv[i] = wordv[i-emptyhead]; 363 } 364 return (nwordv); 365 } 366 367 /* 368 * plural'ize and verb forms 369 */ 370 static char *S = "s"; 371 static char *N = ""; 372 373 char * 374 plural(int n) 375 { 376 return (n > 1 ? S : N); 377 } 378 379 char * 380 verbform(int n) 381 { 382 return (n > 1 ? N : S); 383 } 384