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