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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <ctype.h> 31 #include <stdlib.h> 32 #include <unistd.h> 33 #include <stdarg.h> 34 #include <string.h> 35 #include "error.h" 36 37 /* 38 * Arrayify a list of rules 39 */ 40 void 41 arrayify(int *e_length, Eptr **e_array, Eptr header) 42 { 43 Eptr errorp; 44 Eptr *array; 45 int listlength; 46 int listindex; 47 48 for (errorp = header, listlength = 0; 49 errorp; errorp = errorp->error_next, listlength++) 50 continue; 51 array = Calloc(listlength+1, sizeof (Eptr)); 52 for (listindex = 0, errorp = header; 53 listindex < listlength; 54 listindex++, errorp = errorp->error_next) { 55 array[listindex] = errorp; 56 errorp->error_position = listindex; 57 } 58 array[listindex] = (Eptr)0; 59 *e_length = listlength; 60 *e_array = array; 61 } 62 63 /*PRINTFLIKE1*/ 64 static void 65 error(char *format, ...) 66 { 67 va_list args; 68 69 va_start(args, format); 70 (void) fprintf(stderr, "Error: "); 71 (void) vfprintf(stderr, format, args); 72 (void) fprintf(stderr, "\n"); 73 (void) fflush(stdout); 74 (void) fflush(stderr); 75 va_end(args); 76 exit(6); 77 } 78 79 void * 80 Calloc(int nelements, int size) 81 { 82 void *back; 83 if ((back = calloc(nelements, size)) == NULL) { 84 error("Ran out of memory.\n"); 85 exit(1); 86 } 87 return (back); 88 } 89 90 char * 91 strsave(char *instring) 92 { 93 char *outstring; 94 (void) strcpy(outstring = Calloc(1, strlen(instring) + 1), 95 instring); 96 return (outstring); 97 } 98 /* 99 * find the position of a given character in a string 100 * (one based) 101 */ 102 int 103 position(char *string, char ch) 104 { 105 int i; 106 if (string) 107 for (i = 1; *string; string++, i++) { 108 if (*string == ch) 109 return (i); 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 return (string); 130 } 131 132 char 133 lastchar(char *string) 134 { 135 int length; 136 137 if (string == NULL) 138 return ('\0'); 139 length = strlen(string); 140 if (length >= 1) 141 return (string[length-1]); 142 else 143 return ('\0'); 144 } 145 146 char 147 firstchar(char *string) 148 { 149 if (string) 150 return (string[0]); 151 else 152 return ('\0'); 153 } 154 155 char 156 next_lastchar(char *string) 157 { 158 int length; 159 160 if (string == NULL) 161 return ('\0'); 162 length = strlen(string); 163 if (length >= 2) 164 return (string[length - 2]); 165 else 166 return ('\0'); 167 } 168 169 void 170 clob_last(char *string, char newstuff) 171 { 172 int length = 0; 173 if (string) 174 length = strlen(string); 175 if (length >= 1) 176 string[length - 1] = newstuff; 177 } 178 179 /* 180 * parse a string that is the result of a format %s(%d) 181 * return TRUE if this is of the proper format 182 */ 183 boolean 184 persperdexplode(char *string, char **r_perd, char **r_pers) 185 { 186 char *cp; 187 int length = 0; 188 189 if (string) 190 length = strlen(string); 191 if ((length >= 4) && (string[length - 1] == ')')) { 192 for (cp = &string[length - 2]; 193 (isdigit(*cp)) && (*cp != '('); --cp) 194 continue; 195 if (*cp == '(') { 196 string[length - 1] = '\0'; /* clobber the ) */ 197 *r_perd = strsave(cp+1); 198 string[length - 1] = ')'; 199 *cp = '\0'; /* clobber the ( */ 200 *r_pers = strsave(string); 201 *cp = '('; 202 return (TRUE); 203 } 204 } 205 return (FALSE); 206 } 207 208 static char cincomment[] = CINCOMMENT; 209 static char coutcomment[] = COUTCOMMENT; 210 static char fincomment[] = FINCOMMENT; 211 static char foutcomment[] = FOUTCOMMENT; 212 static char newline[] = NEWLINE; 213 static char piincomment[] = PIINCOMMENT; 214 static char pioutcomment[] = PIOUTCOMMENT; 215 static char lispincomment[] = LISPINCOMMENT; 216 static char riincomment[] = RIINCOMMENT; 217 static char rioutcomment[] = RIOUTCOMMENT; 218 static char troffincomment[] = TROFFINCOMMENT; 219 static char troffoutcomment[] = TROFFOUTCOMMENT; 220 static char mod2incomment[] = MOD2INCOMMENT; 221 static char mod2outcomment[] = MOD2OUTCOMMENT; 222 223 struct lang_desc lang_table[] = { 224 /* INUNKNOWN 0 */ "unknown", cincomment, coutcomment, 225 /* INCPP 1 */ "cpp", cincomment, coutcomment, 226 /* INCC 2 */ "cc", cincomment, coutcomment, 227 /* INAS 3 */ "as", ASINCOMMENT, newline, 228 /* INLD 4 */ "ld", cincomment, coutcomment, 229 /* INLINT 5 */ "lint", cincomment, coutcomment, 230 /* INF77 6 */ "f77", fincomment, foutcomment, 231 /* INPI 7 */ "pi", piincomment, pioutcomment, 232 /* INPC 8 */ "pc", piincomment, pioutcomment, 233 /* INFRANZ 9 */ "franz", lispincomment, newline, 234 /* INLISP 10 */ "lisp", lispincomment, newline, 235 /* INVAXIMA 11 */ "vaxima", lispincomment, newline, 236 /* INRATFOR 12 */ "ratfor", fincomment, foutcomment, 237 /* INLEX 13 */ "lex", cincomment, coutcomment, 238 /* INYACC 14 */ "yacc", cincomment, coutcomment, 239 /* INAPL 15 */ "apl", ".lm", newline, 240 /* INMAKE 16 */ "make", ASINCOMMENT, newline, 241 /* INRI 17 */ "ri", riincomment, rioutcomment, 242 /* INTROFF 18 */ "troff", troffincomment, troffoutcomment, 243 /* INMOD2 19 */ "mod2", mod2incomment, mod2outcomment, 244 /* INSUNF77 20 */ "Sunf77", fincomment, foutcomment, 245 0, 0, 0 246 }; 247 248 void 249 printerrors(boolean look_at_subclass, int errorc, Eptr errorv[]) 250 { 251 int i; 252 Eptr errorp; 253 254 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) { 255 if (errorp->error_e_class == C_IGNORE) 256 continue; 257 if (look_at_subclass && errorp->error_s_class == C_DUPL) 258 continue; 259 (void) printf("Error %d, (%s error) [%s], text = \"", 260 i, 261 class_table[errorp->error_e_class], 262 lang_table[errorp->error_language].lang_name); 263 wordvprint(stdout, errorp->error_lgtext, errorp->error_text); 264 (void) printf("\"\n"); 265 } 266 } 267 268 void 269 wordvprint(FILE *fyle, int wordc, char *wordv[]) 270 { 271 int i; 272 char *sep = ""; 273 274 for (i = 0; i < wordc; i++) 275 if (wordv[i]) { 276 (void) fprintf(fyle, "%s%s", sep, wordv[i]); 277 sep = " "; 278 } 279 } 280 281 /* 282 * Given a string, parse it into a number of words, and build 283 * a wordc wordv combination pointing into it. 284 */ 285 void 286 wordvbuild(char *string, int *r_wordc, char ***r_wordv) 287 { 288 char *cp; 289 char *saltedbuffer; 290 char **wordv; 291 int wordcount; 292 int wordindex; 293 294 saltedbuffer = strsave(string); 295 for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) { 296 while (*cp && isspace(*cp)) 297 cp++; 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