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