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