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