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