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