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