1 /* $NetBSD: subr.c,v 1.4 1995/09/10 15:55:15 christos 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 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93"; 39 #endif 40 static char rcsid[] = "$NetBSD: subr.c,v 1.4 1995/09/10 15:55:15 christos Exp $"; 41 #endif /* not lint */ 42 43 #include <stdio.h> 44 #include <ctype.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include "error.h" 48 /* 49 * Arrayify a list of rules 50 */ 51 arrayify(e_length, e_array, header) 52 int *e_length; 53 Eptr **e_array; 54 Eptr header; 55 { 56 reg Eptr errorp; 57 reg Eptr *array; 58 reg int listlength; 59 reg int listindex; 60 61 for (errorp = header, listlength = 0; 62 errorp; errorp = errorp->error_next, listlength++) 63 continue; 64 array = (Eptr*)Calloc(listlength+1, sizeof (Eptr)); 65 for(listindex = 0, errorp = header; 66 listindex < listlength; 67 listindex++, errorp = errorp->error_next){ 68 array[listindex] = errorp; 69 errorp->error_position = listindex; 70 } 71 array[listindex] = (Eptr)0; 72 *e_length = listlength; 73 *e_array = array; 74 } 75 76 /*VARARGS1*/ 77 error(msg, a1, a2, a3) 78 char *msg; 79 { 80 fprintf(stderr, "Error: "); 81 fprintf(stderr, msg, a1, a2, a3); 82 fprintf(stderr, "\n"); 83 fflush(stdout); 84 fflush(stderr); 85 exit(6); 86 } 87 /*ARGSUSED*/ 88 char *Calloc(nelements, size) 89 int nelements; 90 int size; 91 { 92 char *back; 93 if ( (back = (char *)calloc(nelements, size)) == (char *)NULL){ 94 error("Ran out of memory.\n"); 95 exit(1); 96 } 97 return(back); 98 } 99 100 char *strsave(instring) 101 char *instring; 102 { 103 char *outstring; 104 (void)strcpy(outstring = (char *)Calloc(1, strlen(instring) + 1), 105 instring); 106 return(outstring); 107 } 108 /* 109 * find the position of a given character in a string 110 * (one based) 111 */ 112 int position(string, ch) 113 reg char *string; 114 reg char ch; 115 { 116 reg int i; 117 if (string) 118 for (i=1; *string; string++, i++){ 119 if (*string == ch) 120 return(i); 121 } 122 return(-1); 123 } 124 /* 125 * clobber the first occurance of ch in string by the new character 126 */ 127 char *substitute(string, chold, chnew) 128 char *string; 129 char chold, chnew; 130 { 131 reg char *cp = string; 132 133 if (cp) 134 while (*cp){ 135 if (*cp == chold){ 136 *cp = chnew; 137 break; 138 } 139 cp++; 140 } 141 return(string); 142 } 143 144 char lastchar(string) 145 char *string; 146 { 147 int length; 148 if (string == 0) return('\0'); 149 length = strlen(string); 150 if (length >= 1) 151 return(string[length-1]); 152 else 153 return('\0'); 154 } 155 156 char firstchar(string) 157 char *string; 158 { 159 if (string) 160 return(string[0]); 161 else 162 return('\0'); 163 } 164 165 char next_lastchar(string) 166 char *string; 167 { 168 int length; 169 if (string == 0) return('\0'); 170 length = strlen(string); 171 if (length >= 2) 172 return(string[length - 2]); 173 else 174 return('\0'); 175 } 176 177 clob_last(string, newstuff) 178 char *string, newstuff; 179 { 180 int length = 0; 181 if (string) 182 length = strlen(string); 183 if (length >= 1) 184 string[length - 1] = newstuff; 185 } 186 187 /* 188 * parse a string that is the result of a format %s(%d) 189 * return TRUE if this is of the proper format 190 */ 191 boolean persperdexplode(string, r_perd, r_pers) 192 char *string; 193 char **r_perd, **r_pers; 194 { 195 reg 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 * parse a quoted string that is the result of a format \"%s\"(%d) 220 * return TRUE if this is of the proper format 221 */ 222 boolean qpersperdexplode(string, r_perd, r_pers) 223 char *string; 224 char **r_perd, **r_pers; 225 { 226 reg char *cp; 227 int length = 0; 228 229 if (string) 230 length = strlen(string); 231 if ( (length >= 4) 232 && (string[length - 1] == ')' ) ){ 233 for (cp = &string[length - 2]; 234 (isdigit(*cp)) && (*cp != '('); 235 --cp) 236 continue; 237 if (*cp == '(' && *(cp - 1) == '"'){ 238 string[length - 1] = '\0'; 239 *r_perd = strsave(cp+1); 240 string[length - 1] = ')'; 241 *(cp - 1) = '\0'; /* clobber the " */ 242 *r_pers = strsave(string + 1); 243 *(cp - 1) = '"'; 244 return(TRUE); 245 } 246 } 247 return(FALSE); 248 } 249 250 static char cincomment[] = CINCOMMENT; 251 static char coutcomment[] = COUTCOMMENT; 252 static char fincomment[] = FINCOMMENT; 253 static char foutcomment[] = FOUTCOMMENT; 254 static char newline[] = NEWLINE; 255 static char piincomment[] = PIINCOMMENT; 256 static char pioutcomment[] = PIOUTCOMMENT; 257 static char lispincomment[] = LISPINCOMMENT; 258 static char riincomment[] = RIINCOMMENT; 259 static char rioutcomment[] = RIOUTCOMMENT; 260 static char troffincomment[] = TROFFINCOMMENT; 261 static char troffoutcomment[] = TROFFOUTCOMMENT; 262 static char mod2incomment[] = MOD2INCOMMENT; 263 static char mod2outcomment[] = MOD2OUTCOMMENT; 264 265 struct lang_desc lang_table[] = { 266 /*INUNKNOWN 0*/ "unknown", cincomment, coutcomment, 267 /*INCPP 1*/ "cpp", cincomment, coutcomment, 268 /*INCC 2*/ "cc", cincomment, coutcomment, 269 /*INAS 3*/ "as", ASINCOMMENT, newline, 270 /*INLD 4*/ "ld", cincomment, coutcomment, 271 /*INLINT 5*/ "lint", cincomment, coutcomment, 272 /*INF77 6*/ "f77", fincomment, foutcomment, 273 /*INPI 7*/ "pi", piincomment, pioutcomment, 274 /*INPC 8*/ "pc", piincomment, pioutcomment, 275 /*INFRANZ 9*/ "franz",lispincomment, newline, 276 /*INLISP 10*/ "lisp", lispincomment, newline, 277 /*INVAXIMA 11*/ "vaxima",lispincomment,newline, 278 /*INRATFOR 12*/ "ratfor",fincomment, foutcomment, 279 /*INLEX 13*/ "lex", cincomment, coutcomment, 280 /*INYACC 14*/ "yacc", cincomment, coutcomment, 281 /*INAPL 15*/ "apl", ".lm", newline, 282 /*INMAKE 16*/ "make", ASINCOMMENT, newline, 283 /*INRI 17*/ "ri", riincomment, rioutcomment, 284 /*INTROFF 18*/ "troff",troffincomment,troffoutcomment, 285 /*INMOD2 19*/ "mod2", mod2incomment, mod2outcomment, 286 0, 0, 0 287 }; 288 289 printerrors(look_at_subclass, errorc, errorv) 290 boolean look_at_subclass; 291 int errorc; 292 Eptr errorv[]; 293 { 294 reg int i; 295 reg Eptr errorp; 296 297 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]){ 298 if (errorp->error_e_class == C_IGNORE) 299 continue; 300 if (look_at_subclass && errorp->error_s_class == C_DUPL) 301 continue; 302 printf("Error %d, (%s error) [%s], text = \"", 303 i, 304 class_table[errorp->error_e_class], 305 lang_table[errorp->error_language].lang_name); 306 wordvprint(stdout,errorp->error_lgtext,errorp->error_text); 307 printf("\"\n"); 308 } 309 } 310 311 wordvprint(fyle, wordc, wordv) 312 FILE *fyle; 313 int wordc; 314 char *wordv[]; 315 { 316 int i; 317 char *sep = ""; 318 319 for(i = 0; i < wordc; i++) 320 if (wordv[i]) { 321 fprintf(fyle, "%s%s",sep,wordv[i]); 322 sep = " "; 323 } 324 } 325 326 /* 327 * Given a string, parse it into a number of words, and build 328 * a wordc wordv combination pointing into it. 329 */ 330 wordvbuild(string, r_wordc, r_wordv) 331 char *string; 332 int *r_wordc; 333 char ***r_wordv; 334 { 335 reg char *cp; 336 char **wordv; 337 int wordcount; 338 int wordindex; 339 340 for (wordcount = 0, cp = string; *cp; wordcount++){ 341 while (*cp && isspace(*cp)) 342 cp++; 343 if (*cp == 0) 344 break; 345 while (!isspace(*cp)) 346 cp++; 347 } 348 wordv = (char **)Calloc(wordcount + 1, sizeof (char *)); 349 for (cp=string,wordindex=0; wordcount; wordindex++,--wordcount){ 350 while (*cp && isspace(*cp)) 351 cp++; 352 if (*cp == 0) 353 break; 354 wordv[wordindex] = cp; 355 while(!isspace(*cp)) 356 cp++; 357 *cp++ = '\0'; 358 } 359 if (wordcount != 0) 360 error("Initial miscount of the number of words in a line\n"); 361 wordv[wordindex] = (char *)0; 362 #ifdef FULLDEBUG 363 for (wordcount = 0; wordcount < wordindex; wordcount++) 364 printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]); 365 printf("\n"); 366 #endif 367 *r_wordc = wordindex; 368 *r_wordv = wordv; 369 } 370 /* 371 * Compare two 0 based wordvectors 372 */ 373 int wordvcmp(wordv1, wordc, wordv2) 374 char **wordv1; 375 int wordc; 376 char **wordv2; 377 { 378 reg int i; 379 int back; 380 for (i = 0; i < wordc; i++){ 381 if (wordv1[i] == 0 || wordv2[i] == 0) 382 return(-1); 383 if (back = strcmp(wordv1[i], wordv2[i])){ 384 return(back); 385 } 386 } 387 return(0); /* they are equal */ 388 } 389 390 /* 391 * splice a 0 basedword vector onto the tail of a 392 * new wordv, allowing the first emptyhead slots to be empty 393 */ 394 char **wordvsplice(emptyhead, wordc, wordv) 395 int emptyhead; 396 int wordc; 397 char **wordv; 398 { 399 reg char **nwordv; 400 int nwordc = emptyhead + wordc; 401 reg int i; 402 403 nwordv = (char **)Calloc(nwordc, sizeof (char *)); 404 for (i = 0; i < emptyhead; i++) 405 nwordv[i] = 0; 406 for(i = emptyhead; i < nwordc; i++){ 407 nwordv[i] = wordv[i-emptyhead]; 408 } 409 return(nwordv); 410 } 411 /* 412 * plural'ize and verb forms 413 */ 414 static char *S = "s"; 415 static char *N = ""; 416 char *plural(n) 417 int n; 418 { 419 return( n > 1 ? S : N); 420 } 421 char *verbform(n) 422 int n; 423 { 424 return( n > 1 ? N : S); 425 } 426 427