1 /* $NetBSD: subr.c,v 1.14 2003/08/07 11:13:38 agc Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93"; 36 #endif 37 __RCSID("$NetBSD: subr.c,v 1.14 2003/08/07 11:13:38 agc Exp $"); 38 #endif /* not lint */ 39 40 #include <ctype.h> 41 #include <err.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include "error.h" 46 /* 47 * Arrayify a list of rules 48 */ 49 void 50 arrayify(int *e_length, Eptr **e_array, Eptr header) 51 { 52 Eptr errorp; 53 Eptr *array; 54 int listlength; 55 int listindex; 56 57 for (errorp = header, listlength = 0; 58 errorp; errorp = errorp->error_next, listlength++) 59 continue; 60 array = (Eptr*)Calloc(listlength+1, sizeof (Eptr)); 61 for(listindex = 0, errorp = header; 62 listindex < listlength; 63 listindex++, errorp = errorp->error_next){ 64 array[listindex] = errorp; 65 errorp->error_position = listindex; 66 } 67 array[listindex] = NULL; 68 *e_length = listlength; 69 *e_array = array; 70 } 71 72 char * 73 Calloc(int nelements, int size) 74 { 75 char *back; 76 if ( (back = (char *)calloc(nelements, size)) == NULL) 77 errx(1, "Ran out of memory."); 78 return(back); 79 } 80 81 /* 82 * find the position of a given character in a string 83 * (one based) 84 */ 85 int 86 position(char *string, char ch) 87 { 88 int i; 89 if (string) 90 for (i=1; *string; string++, i++){ 91 if (*string == ch) 92 return(i); 93 } 94 return(-1); 95 } 96 97 /* 98 * clobber the first occurance of ch in string by the new character 99 */ 100 char * 101 substitute(char *string, char chold, char chnew) 102 { 103 char *cp = string; 104 105 if (cp) 106 while (*cp){ 107 if (*cp == chold){ 108 *cp = chnew; 109 break; 110 } 111 cp++; 112 } 113 return(string); 114 } 115 116 char 117 lastchar(char *string) 118 { 119 int length; 120 if (string == NULL) return('\0'); 121 length = strlen(string); 122 if (length >= 1) 123 return(string[length-1]); 124 else 125 return('\0'); 126 } 127 128 char 129 firstchar(char *string) 130 { 131 if (string) 132 return(string[0]); 133 else 134 return('\0'); 135 } 136 137 char 138 next_lastchar(char *string) 139 { 140 int length; 141 if (string == NULL) return('\0'); 142 length = strlen(string); 143 if (length >= 2) 144 return(string[length - 2]); 145 else 146 return('\0'); 147 } 148 149 void 150 clob_last(char *string, char newstuff) 151 { 152 int length = 0; 153 if (string) 154 length = strlen(string); 155 if (length >= 1) 156 string[length - 1] = newstuff; 157 } 158 159 /* 160 * parse a string that is the result of a format %s(%d) 161 * return TRUE if this is of the proper format 162 */ 163 boolean 164 persperdexplode(char *string, char **r_perd, char **r_pers) 165 { 166 char *cp; 167 int length = 0; 168 169 if (string) 170 length = strlen(string); 171 if ( (length >= 4) 172 && (string[length - 1] == ')' ) ){ 173 for (cp = &string[length - 2]; 174 (isdigit((unsigned char)*cp)) && (*cp != '('); 175 --cp) 176 continue; 177 if (*cp == '('){ 178 string[length - 1] = '\0'; /* clobber the ) */ 179 *r_perd = strdup(cp+1); 180 string[length - 1] = ')'; 181 *cp = '\0'; /* clobber the ( */ 182 *r_pers = strdup(string); 183 *cp = '('; 184 return(TRUE); 185 } 186 } 187 return(FALSE); 188 } 189 190 /* 191 * parse a quoted string that is the result of a format \"%s\"(%d) 192 * return TRUE if this is of the proper format 193 */ 194 boolean 195 qpersperdexplode(char *string, char **r_perd, char **r_pers) 196 { 197 char *cp; 198 int length = 0; 199 200 if (string) 201 length = strlen(string); 202 if ( (length >= 4) 203 && (string[length - 1] == ')' ) ){ 204 for (cp = &string[length - 2]; 205 (isdigit((unsigned char)*cp)) && (*cp != '('); 206 --cp) 207 continue; 208 if (*cp == '(' && *(cp - 1) == '"'){ 209 string[length - 1] = '\0'; 210 *r_perd = strdup(cp+1); 211 string[length - 1] = ')'; 212 *(cp - 1) = '\0'; /* clobber the " */ 213 *r_pers = strdup(string + 1); 214 *(cp - 1) = '"'; 215 return(TRUE); 216 } 217 } 218 return(FALSE); 219 } 220 221 static char cincomment[] = CINCOMMENT; 222 static char coutcomment[] = COUTCOMMENT; 223 static char fincomment[] = FINCOMMENT; 224 static char foutcomment[] = FOUTCOMMENT; 225 static char newline[] = NEWLINE; 226 static char piincomment[] = PIINCOMMENT; 227 static char pioutcomment[] = PIOUTCOMMENT; 228 static char lispincomment[] = LISPINCOMMENT; 229 static char riincomment[] = RIINCOMMENT; 230 static char rioutcomment[] = RIOUTCOMMENT; 231 static char troffincomment[] = TROFFINCOMMENT; 232 static char troffoutcomment[] = TROFFOUTCOMMENT; 233 static char mod2incomment[] = MOD2INCOMMENT; 234 static char mod2outcomment[] = MOD2OUTCOMMENT; 235 236 struct lang_desc lang_table[] = { 237 { /*INUNKNOWN 0*/ "unknown", cincomment, coutcomment }, 238 { /*INCPP 1*/ "cpp", cincomment, coutcomment }, 239 { /*INCC 2*/ "cc", cincomment, coutcomment }, 240 { /*INAS 3*/ "as", ASINCOMMENT, newline }, 241 { /*INLD 4*/ "ld", cincomment, coutcomment }, 242 { /*INLINT 5*/ "lint", cincomment, coutcomment }, 243 { /*INF77 6*/ "f77", fincomment, foutcomment }, 244 { /*INPI 7*/ "pi", piincomment, pioutcomment }, 245 { /*INPC 8*/ "pc", piincomment, pioutcomment }, 246 { /*INFRANZ 9*/ "franz",lispincomment, newline }, 247 { /*INLISP 10*/ "lisp", lispincomment, newline }, 248 { /*INVAXIMA 11*/ "vaxima",lispincomment,newline }, 249 { /*INRATFOR 12*/ "ratfor",fincomment, foutcomment }, 250 { /*INLEX 13*/ "lex", cincomment, coutcomment }, 251 { /*INYACC 14*/ "yacc", cincomment, coutcomment }, 252 { /*INAPL 15*/ "apl", ".lm", newline }, 253 { /*INMAKE 16*/ "make", ASINCOMMENT, newline }, 254 { /*INRI 17*/ "ri", riincomment, rioutcomment }, 255 { /*INTROFF 18*/ "troff",troffincomment,troffoutcomment }, 256 { /*INMOD2 19*/ "mod2", mod2incomment, mod2outcomment }, 257 { 0, 0, 0 } 258 }; 259 260 void 261 printerrors(boolean look_at_subclass, int errorc, Eptr errorv[]) 262 { 263 int i; 264 Eptr errorp; 265 266 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]){ 267 if (errorp->error_e_class == C_IGNORE) 268 continue; 269 if (look_at_subclass && errorp->error_s_class == C_DUPL) 270 continue; 271 printf("Error %d, (%s error) [%s], text = \"", 272 i, 273 class_table[errorp->error_e_class], 274 lang_table[errorp->error_language].lang_name); 275 wordvprint(stdout,errorp->error_lgtext,errorp->error_text); 276 printf("\"\n"); 277 } 278 } 279 280 void 281 wordvprint(FILE *fyle, int wordc, char **wordv) 282 { 283 int i; 284 char *sep = ""; 285 286 for(i = 0; i < wordc; i++) 287 if (wordv[i]) { 288 fprintf(fyle, "%s%s",sep,wordv[i]); 289 sep = " "; 290 } 291 } 292 293 /* 294 * Given a string, parse it into a number of words, and build 295 * a wordc wordv combination pointing into it. 296 */ 297 void 298 wordvbuild(char *string, int *r_wordc, char ***r_wordv) 299 { 300 char *cp; 301 char **wordv; 302 int wordcount; 303 int wordindex; 304 305 for (wordcount = 0, cp = string; *cp; wordcount++){ 306 while (*cp && isspace((unsigned char)*cp)) 307 cp++; 308 if (*cp == '\0') 309 break; 310 while (*cp && !isspace((unsigned char)*cp)) 311 cp++; 312 } 313 wordv = (char **)Calloc(wordcount + 1, sizeof (char *)); 314 for (cp=string,wordindex=0; wordcount; wordindex++,--wordcount){ 315 while (*cp && isspace((unsigned char)*cp)) 316 cp++; 317 if (*cp == '\0') 318 break; 319 wordv[wordindex] = cp; 320 while(*cp && !isspace((unsigned char)*cp)) 321 cp++; 322 *cp++ = '\0'; 323 } 324 if (wordcount != 0) 325 errx(6, "Initial miscount of the number of words in a line"); 326 wordv[wordindex] = NULL; 327 #ifdef FULLDEBUG 328 for (wordcount = 0; wordcount < wordindex; wordcount++) 329 printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]); 330 printf("\n"); 331 #endif 332 *r_wordc = wordindex; 333 *r_wordv = wordv; 334 } 335 336 /* 337 * Compare two 0 based wordvectors 338 */ 339 int 340 wordvcmp(char **wordv1, int wordc, char **wordv2) 341 { 342 int i; 343 int back; 344 345 for (i = 0; i < wordc; i++){ 346 if (wordv1[i] == NULL || wordv2[i] == NULL) 347 return(-1); 348 if ((back = strcmp(wordv1[i], wordv2[i])) != 0) 349 return(back); 350 } 351 return(0); /* they are equal */ 352 } 353 354 /* 355 * splice a 0 basedword vector onto the tail of a 356 * new wordv, allowing the first emptyhead slots to be empty 357 */ 358 char ** 359 wordvsplice(int emptyhead, int wordc, char **wordv) 360 { 361 char **nwordv; 362 int nwordc = emptyhead + wordc; 363 int i; 364 365 nwordv = (char **)Calloc(nwordc, sizeof (char *)); 366 for (i = 0; i < emptyhead; i++) 367 nwordv[i] = NULL; 368 for(i = emptyhead; i < nwordc; i++){ 369 nwordv[i] = wordv[i-emptyhead]; 370 } 371 return(nwordv); 372 } 373 374 /* 375 * plural'ize and verb forms 376 */ 377 static char *S = "s"; 378 static char *N = ""; 379 380 char * 381 plural(int n) 382 { 383 return( n > 1 ? S : N); 384 } 385 386 char * 387 verbform(int n) 388 { 389 return( n > 1 ? N : S); 390 } 391