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 if (string) 105 for (i = 1; *string; string++, i++) { 106 if (*string == ch) 107 return (i); 108 } 109 return (-1); 110 } 111 /* 112 * clobber the first occurance of ch in string by the new character 113 */ 114 char * 115 substitute(char *string, char chold, char chnew) 116 { 117 char *cp = string; 118 119 if (cp) 120 while (*cp) { 121 if (*cp == chold) { 122 *cp = chnew; 123 break; 124 } 125 cp++; 126 } 127 return (string); 128 } 129 130 char 131 lastchar(char *string) 132 { 133 int length; 134 135 if (string == NULL) 136 return ('\0'); 137 length = strlen(string); 138 if (length >= 1) 139 return (string[length-1]); 140 else 141 return ('\0'); 142 } 143 144 char 145 firstchar(char *string) 146 { 147 if (string) 148 return (string[0]); 149 else 150 return ('\0'); 151 } 152 153 char 154 next_lastchar(char *string) 155 { 156 int length; 157 158 if (string == NULL) 159 return ('\0'); 160 length = strlen(string); 161 if (length >= 2) 162 return (string[length - 2]); 163 else 164 return ('\0'); 165 } 166 167 void 168 clob_last(char *string, char newstuff) 169 { 170 int length = 0; 171 if (string) 172 length = strlen(string); 173 if (length >= 1) 174 string[length - 1] = newstuff; 175 } 176 177 /* 178 * parse a string that is the result of a format %s(%d) 179 * return TRUE if this is of the proper format 180 */ 181 boolean 182 persperdexplode(char *string, char **r_perd, char **r_pers) 183 { 184 char *cp; 185 int length = 0; 186 187 if (string) 188 length = strlen(string); 189 if ((length >= 4) && (string[length - 1] == ')')) { 190 for (cp = &string[length - 2]; 191 (isdigit(*cp)) && (*cp != '('); --cp) 192 continue; 193 if (*cp == '(') { 194 string[length - 1] = '\0'; /* clobber the ) */ 195 *r_perd = strsave(cp+1); 196 string[length - 1] = ')'; 197 *cp = '\0'; /* clobber the ( */ 198 *r_pers = strsave(string); 199 *cp = '('; 200 return (TRUE); 201 } 202 } 203 return (FALSE); 204 } 205 206 static char cincomment[] = CINCOMMENT; 207 static char coutcomment[] = COUTCOMMENT; 208 static char fincomment[] = FINCOMMENT; 209 static char foutcomment[] = FOUTCOMMENT; 210 static char newline[] = NEWLINE; 211 static char piincomment[] = PIINCOMMENT; 212 static char pioutcomment[] = PIOUTCOMMENT; 213 static char lispincomment[] = LISPINCOMMENT; 214 static char riincomment[] = RIINCOMMENT; 215 static char rioutcomment[] = RIOUTCOMMENT; 216 static char troffincomment[] = TROFFINCOMMENT; 217 static char troffoutcomment[] = TROFFOUTCOMMENT; 218 static char mod2incomment[] = MOD2INCOMMENT; 219 static char mod2outcomment[] = MOD2OUTCOMMENT; 220 221 struct lang_desc lang_table[] = { 222 /* INUNKNOWN 0 */ "unknown", cincomment, coutcomment, 223 /* INCPP 1 */ "cpp", cincomment, coutcomment, 224 /* INCC 2 */ "cc", cincomment, coutcomment, 225 /* INAS 3 */ "as", ASINCOMMENT, newline, 226 /* INLD 4 */ "ld", cincomment, coutcomment, 227 /* INLINT 5 */ "lint", cincomment, coutcomment, 228 /* INF77 6 */ "f77", fincomment, foutcomment, 229 /* INPI 7 */ "pi", piincomment, pioutcomment, 230 /* INPC 8 */ "pc", piincomment, pioutcomment, 231 /* INFRANZ 9 */ "franz", lispincomment, newline, 232 /* INLISP 10 */ "lisp", lispincomment, newline, 233 /* INVAXIMA 11 */ "vaxima", lispincomment, newline, 234 /* INRATFOR 12 */ "ratfor", fincomment, foutcomment, 235 /* INLEX 13 */ "lex", cincomment, coutcomment, 236 /* INYACC 14 */ "yacc", cincomment, coutcomment, 237 /* INAPL 15 */ "apl", ".lm", newline, 238 /* INMAKE 16 */ "make", ASINCOMMENT, newline, 239 /* INRI 17 */ "ri", riincomment, rioutcomment, 240 /* INTROFF 18 */ "troff", troffincomment, troffoutcomment, 241 /* INMOD2 19 */ "mod2", mod2incomment, mod2outcomment, 242 /* INSUNF77 20 */ "Sunf77", fincomment, foutcomment, 243 0, 0, 0 244 }; 245 246 void 247 printerrors(boolean look_at_subclass, int errorc, Eptr errorv[]) 248 { 249 int i; 250 Eptr errorp; 251 252 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) { 253 if (errorp->error_e_class == C_IGNORE) 254 continue; 255 if (look_at_subclass && errorp->error_s_class == C_DUPL) 256 continue; 257 (void) printf("Error %d, (%s error) [%s], text = \"", 258 i, 259 class_table[errorp->error_e_class], 260 lang_table[errorp->error_language].lang_name); 261 wordvprint(stdout, errorp->error_lgtext, errorp->error_text); 262 (void) printf("\"\n"); 263 } 264 } 265 266 void 267 wordvprint(FILE *fyle, int wordc, char *wordv[]) 268 { 269 int i; 270 char *sep = ""; 271 272 for (i = 0; i < wordc; i++) 273 if (wordv[i]) { 274 (void) fprintf(fyle, "%s%s", sep, wordv[i]); 275 sep = " "; 276 } 277 } 278 279 /* 280 * Given a string, parse it into a number of words, and build 281 * a wordc wordv combination pointing into it. 282 */ 283 void 284 wordvbuild(char *string, int *r_wordc, char ***r_wordv) 285 { 286 char *cp; 287 char *saltedbuffer; 288 char **wordv; 289 int wordcount; 290 int wordindex; 291 292 saltedbuffer = strsave(string); 293 for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) { 294 while (*cp && isspace(*cp)) 295 cp++; 296 if (*cp == 0) 297 break; 298 while (*cp && !isspace(*cp)) 299 cp++; 300 } 301 wordv = Calloc(wordcount + 1, sizeof (char *)); 302 for (cp = saltedbuffer, wordindex = 0; wordcount; 303 wordindex++, --wordcount) { 304 while (*cp && isspace(*cp)) 305 cp++; 306 if (*cp == 0) 307 break; 308 wordv[wordindex] = cp; 309 while (*cp && !isspace(*cp)) 310 cp++; 311 *cp++ = '\0'; 312 } 313 if (wordcount != 0) 314 error("Initial miscount of the number of words in a line\n"); 315 wordv[wordindex] = NULL; 316 #ifdef FULLDEBUG 317 for (wordcount = 0; wordcount < wordindex; wordcount++) 318 (void) printf("Word %d = \"%s\"\n", wordcount, 319 wordv[wordcount]); 320 (void) printf("\n"); 321 #endif 322 *r_wordc = wordindex; 323 *r_wordv = wordv; 324 } 325 /* 326 * Compare two 0 based wordvectors 327 */ 328 int 329 wordvcmp(char **wordv1, int wordc, char **wordv2) 330 { 331 int i; 332 int back; 333 334 for (i = 0; i < wordc; i++) { 335 if (wordv1[i] == 0 || wordv2[i] == 0) 336 return (-1); 337 if (back = strcmp(wordv1[i], wordv2[i])) { 338 return (back); 339 } 340 } 341 return (0); /* they are equal */ 342 } 343 344 /* 345 * splice a 0 basedword vector onto the tail of a 346 * new wordv, allowing the first emptyhead slots to be empty 347 */ 348 char ** 349 wordvsplice(int emptyhead, int wordc, char **wordv) 350 { 351 char **nwordv; 352 int nwordc = emptyhead + wordc; 353 int i; 354 355 nwordv = Calloc(nwordc, sizeof (char *)); 356 for (i = 0; i < emptyhead; i++) 357 nwordv[i] = 0; 358 for (i = emptyhead; i < nwordc; i++) { 359 nwordv[i] = wordv[i-emptyhead]; 360 } 361 return (nwordv); 362 } 363 364 /* 365 * plural'ize and verb forms 366 */ 367 static char *S = "s"; 368 static char *N = ""; 369 370 char * 371 plural(int n) 372 { 373 return (n > 1 ? S : N); 374 } 375 376 char * 377 verbform(int n) 378 { 379 return (n > 1 ? N : S); 380 } 381