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