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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <stdio.h> 31 #include <ctype.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <stdarg.h> 35 #include <string.h> 36 #include "error.h" 37 38 /* 39 * Arrayify a list of rules 40 */ 41 void 42 arrayify(int *e_length, Eptr **e_array, Eptr header) 43 { 44 Eptr errorp; 45 Eptr *array; 46 int listlength; 47 int listindex; 48 49 for (errorp = header, listlength = 0; 50 errorp; errorp = errorp->error_next, listlength++) 51 continue; 52 array = Calloc(listlength+1, sizeof (Eptr)); 53 for (listindex = 0, errorp = header; 54 listindex < listlength; 55 listindex++, errorp = errorp->error_next) { 56 array[listindex] = errorp; 57 errorp->error_position = listindex; 58 } 59 array[listindex] = (Eptr)0; 60 *e_length = listlength; 61 *e_array = array; 62 } 63 64 /*PRINTFLIKE1*/ 65 static void 66 error(char *format, ...) 67 { 68 va_list args; 69 70 va_start(args, format); 71 (void) fprintf(stderr, "Error: "); 72 (void) vfprintf(stderr, format, args); 73 (void) fprintf(stderr, "\n"); 74 (void) fflush(stdout); 75 (void) fflush(stderr); 76 va_end(args); 77 exit(6); 78 } 79 80 void * 81 Calloc(int nelements, int size) 82 { 83 void *back; 84 if ((back = calloc(nelements, size)) == NULL) { 85 error("Ran out of memory.\n"); 86 exit(1); 87 } 88 return (back); 89 } 90 91 char * 92 strsave(char *instring) 93 { 94 char *outstring; 95 (void) strcpy(outstring = Calloc(1, strlen(instring) + 1), 96 instring); 97 return (outstring); 98 } 99 /* 100 * find the position of a given character in a string 101 * (one based) 102 */ 103 int 104 position(char *string, char ch) 105 { 106 int i; 107 if (string) 108 for (i = 1; *string; string++, i++) { 109 if (*string == ch) 110 return (i); 111 } 112 return (-1); 113 } 114 /* 115 * clobber the first occurance of ch in string by the new character 116 */ 117 char * 118 substitute(char *string, char chold, char chnew) 119 { 120 char *cp = string; 121 122 if (cp) 123 while (*cp) { 124 if (*cp == chold) { 125 *cp = chnew; 126 break; 127 } 128 cp++; 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 (!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 (!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