xref: /onnv-gate/usr/src/cmd/sgs/error/common/errorpi.c (revision 291:0ac955735323)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
22*291Smike_s 
23*291Smike_s /*
24*291Smike_s  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25*291Smike_s  * Use is subject to license terms.
26*291Smike_s  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <ctype.h>
32*291Smike_s #include <string.h>
330Sstevel@tonic-gate #include "error.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate extern	char	*currentfilename;
360Sstevel@tonic-gate static	char	*c_linenumber;
370Sstevel@tonic-gate static	char	*unk_hdr[] = {"In", "program", "???"};
380Sstevel@tonic-gate static	char	**c_header = &unk_hdr[0];
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  *	Attempt to handle error messages produced by pi (and by pc)
420Sstevel@tonic-gate  *
430Sstevel@tonic-gate  *	problem #1:	There is no file name available when a file does not
440Sstevel@tonic-gate  *			use a #include; this will have to be given to error
450Sstevel@tonic-gate  *			in the command line.
460Sstevel@tonic-gate  *	problem #2:	pi doesn't always tell you what line number
470Sstevel@tonic-gate  *			a error refers to; for example during the tree
480Sstevel@tonic-gate  *			walk phase of code generation and error detection,
490Sstevel@tonic-gate  *			an error can refer to "variable foo in procedure bletch"
500Sstevel@tonic-gate  *			without giving a line number
510Sstevel@tonic-gate  *	problem #3:	line numbers, when available, are attached to
520Sstevel@tonic-gate  *			the source line, along with the source line itself
530Sstevel@tonic-gate  *			These line numbers must be extracted, and
540Sstevel@tonic-gate  *			the source line thrown away.
550Sstevel@tonic-gate  *	problem #4:	Some error messages produce more than one line number
560Sstevel@tonic-gate  *			on the same message.
570Sstevel@tonic-gate  *			There are only two (I think):
580Sstevel@tonic-gate  *				%s undefined on line%s
590Sstevel@tonic-gate  *				%s improperly used on line%s
600Sstevel@tonic-gate  *			here, the %s makes line plural or singular.
610Sstevel@tonic-gate  *
620Sstevel@tonic-gate  *	Here are the error strings used in pi version 1.2 that can refer
630Sstevel@tonic-gate  *	to a file name or line number:
640Sstevel@tonic-gate  *
650Sstevel@tonic-gate  *		Multiply defined label in case, lines %d and %d
660Sstevel@tonic-gate  *		Goto %s from line %d is into a structured statement
670Sstevel@tonic-gate  *		End matched %s on line %d
680Sstevel@tonic-gate  *		Inserted keyword end matching %s on line %d
690Sstevel@tonic-gate  *
700Sstevel@tonic-gate  *	Here are the general pi patterns recognized:
710Sstevel@tonic-gate  *	define piptr == -.*^-.*
720Sstevel@tonic-gate  *	define msg = .*
730Sstevel@tonic-gate  *	define digit = [0-9]
740Sstevel@tonic-gate  *	definename = .*
75*291Smike_s  *	define date_format letter*3 letter*3 (digit | (digit digit))
760Sstevel@tonic-gate  *			(digit | (digit digit)):digit*2 digit*4
770Sstevel@tonic-gate  *
780Sstevel@tonic-gate  *	{e,E} (piptr) (msg)	Encounter an error during textual scan
790Sstevel@tonic-gate  *	E {digit}* - (msg)	Have an error message that refers to a new line
800Sstevel@tonic-gate  *	E - msg			Have an error message that refers to current
810Sstevel@tonic-gate  *					function, program or procedure
820Sstevel@tonic-gate  *	(date_format) (name):	When switch compilation files
830Sstevel@tonic-gate  *	... (msg)		When refer to the previous line
840Sstevel@tonic-gate  *	'In' ('procedure'|'function'|'program') (name):
850Sstevel@tonic-gate  *				pi is now complaining about 2nd pass errors.
86*291Smike_s  *
870Sstevel@tonic-gate  *	Here is the output from a compilation
880Sstevel@tonic-gate  *
890Sstevel@tonic-gate  *
900Sstevel@tonic-gate  *	     2  	var	i:integer;
910Sstevel@tonic-gate  *	e --------------^--- Inserted ';'
920Sstevel@tonic-gate  *	E 2 - All variables must be declared in one var part
930Sstevel@tonic-gate  *	E 5 - Include filename must end in .i
940Sstevel@tonic-gate  *	Mon Apr 21 15:56 1980  test.h:
950Sstevel@tonic-gate  *	     2  begin
960Sstevel@tonic-gate  *	e ------^--- Inserted ';'
970Sstevel@tonic-gate  *	Mon Apr 21 16:06 1980  test.p:
980Sstevel@tonic-gate  *	E 2 - Function type must be specified
990Sstevel@tonic-gate  *	     6  procedure foo(var x:real);
1000Sstevel@tonic-gate  *	e ------^--- Inserted ';'
1010Sstevel@tonic-gate  *	In function bletch:
1020Sstevel@tonic-gate  *	  E - No assignment to the function variable
1030Sstevel@tonic-gate  *	  w - variable x is never used
1040Sstevel@tonic-gate  *	E 6 - foo is already defined in this block
1050Sstevel@tonic-gate  *	In procedure foo:
1060Sstevel@tonic-gate  *	  w - variable x is neither used nor set
1070Sstevel@tonic-gate  *	     9  	z : = 23;
1080Sstevel@tonic-gate  *	E --------------^--- Undefined variable
1090Sstevel@tonic-gate  *	    10  	y = [1];
1100Sstevel@tonic-gate  *	e ----------------^--- Inserted ':'
1110Sstevel@tonic-gate  *	    13  	z := 345.;
1120Sstevel@tonic-gate  *	e -----------------------^--- Digits required after decimal point
1130Sstevel@tonic-gate  *	E 10 - Constant set involved in non set context
1140Sstevel@tonic-gate  *	E 11 - Type clash: real is incompatible with integer
1150Sstevel@tonic-gate  *	   ... Type of expression clashed with type of variable in assignment
1160Sstevel@tonic-gate  *	E 12 - Parameter type not identical to type of var parameter x of foo
1170Sstevel@tonic-gate  *	In program mung:
1180Sstevel@tonic-gate  *	  w - variable y is never used
1190Sstevel@tonic-gate  *	  w - type foo is never used
1200Sstevel@tonic-gate  *	  w - function bletch is never used
1210Sstevel@tonic-gate  *	  E - z undefined on lines 9 13
1220Sstevel@tonic-gate  */
1230Sstevel@tonic-gate char *Months[] = {
1240Sstevel@tonic-gate 	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
125*291Smike_s 	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
1260Sstevel@tonic-gate 	0
1270Sstevel@tonic-gate };
1280Sstevel@tonic-gate char *Days[] = {
1290Sstevel@tonic-gate 	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0
1300Sstevel@tonic-gate };
1310Sstevel@tonic-gate char *Piroutines[] = {
1320Sstevel@tonic-gate 		"program", "function", "procedure", 0
1330Sstevel@tonic-gate };
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate static boolean	structured, multiple;
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate char *pi_Endmatched[] = {"End", "matched"};
1390Sstevel@tonic-gate char *pi_Inserted[] = {"Inserted", "keyword", "end", "matching"};
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate char *pi_multiple[] = {"Mutiply", "defined", "label", "in", "case,", "line"};
1420Sstevel@tonic-gate char *pi_structured[] = {"is", "into", "a", "structured", "statement"};
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate char *pi_und1[] = {"undefined", "on", "line"};
1450Sstevel@tonic-gate char *pi_und2[] = {"undefined", "on", "lines"};
1460Sstevel@tonic-gate char *pi_imp1[] = {"improperly", "used", "on", "line"};
1470Sstevel@tonic-gate char *pi_imp2[] = {"improperly", "used", "on", "lines"};
1480Sstevel@tonic-gate 
149*291Smike_s boolean
alldigits(char * string)150*291Smike_s alldigits(char *string)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	for (; *string && isdigit(*string); string++)
1530Sstevel@tonic-gate 		continue;
154*291Smike_s 	return (*string == '\0');
1550Sstevel@tonic-gate }
156*291Smike_s 
157*291Smike_s boolean
instringset(char * member,char ** set)158*291Smike_s instringset(char *member, char **set)
1590Sstevel@tonic-gate {
160*291Smike_s 	for (; *set; set++) {
1610Sstevel@tonic-gate 		if (strcmp(*set, member) == 0)
162*291Smike_s 			return (TRUE);
1630Sstevel@tonic-gate 	}
164*291Smike_s 	return (FALSE);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate 
167*291Smike_s boolean
isdateformat(int wordc,char ** wordv)168*291Smike_s isdateformat(int wordc, char **wordv)
1690Sstevel@tonic-gate {
170*291Smike_s 	return ((wordc == 5) &&
171*291Smike_s 	    (instringset(wordv[0], Days)) &&
172*291Smike_s 	    (instringset(wordv[1], Months)) &&
173*291Smike_s 	    (alldigits(wordv[2])) && (alldigits(wordv[4])));
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
176*291Smike_s boolean
piptr(char * string)177*291Smike_s piptr(char *string)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	if (*string != '-')
180*291Smike_s 		return (FALSE);
1810Sstevel@tonic-gate 	while (*string && *string == '-')
1820Sstevel@tonic-gate 		string++;
1830Sstevel@tonic-gate 	if (*string != '^')
184*291Smike_s 		return (FALSE);
1850Sstevel@tonic-gate 	string++;
1860Sstevel@tonic-gate 	while (*string && *string == '-')
1870Sstevel@tonic-gate 		string++;
188*291Smike_s 	return (*string == '\0');
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate extern	int	wordc;
1920Sstevel@tonic-gate extern	char	**wordv;
1930Sstevel@tonic-gate 
194*291Smike_s Errorclass
pi(void)195*291Smike_s pi(void)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate 	char	**nwordv;
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (wordc < 2)
2000Sstevel@tonic-gate 		return (C_UNKNOWN);
201*291Smike_s 	if ((strlen(wordv[1]) == 1) &&
202*291Smike_s 	    ((wordv[1][0] == 'e') || (wordv[1][0] == 'E')) &&
203*291Smike_s 	    (piptr(wordv[2]))) {
2040Sstevel@tonic-gate 		boolean	longpiptr = 0;
2050Sstevel@tonic-gate 		/*
2060Sstevel@tonic-gate 		 *	We have recognized a first pass error of the form:
2070Sstevel@tonic-gate 		 *	letter ------^---- message
2080Sstevel@tonic-gate 		 *
2090Sstevel@tonic-gate 		 *	turn into an error message of the form:
2100Sstevel@tonic-gate 		 *
2110Sstevel@tonic-gate 		 *	file line 'pascal errortype' letter \n |---- message
2120Sstevel@tonic-gate 		 *	or of the form:
2130Sstevel@tonic-gate 		 *	file line letter |---- message
2140Sstevel@tonic-gate 		 *		when there are strlen("(*[pi]") or more
2150Sstevel@tonic-gate 		 *		preceding '-' on the error pointer.
2160Sstevel@tonic-gate 		 *
2170Sstevel@tonic-gate 		 *	Where the | is intended to be a down arrow, so that
2180Sstevel@tonic-gate 		 *	the pi error messages can be inserted above the
2190Sstevel@tonic-gate 		 *	line in error, instead of below.  (All of the other
2200Sstevel@tonic-gate 		 *	langauges put thier messages before the source line,
2210Sstevel@tonic-gate 		 *	instead of after it as does pi.)
2220Sstevel@tonic-gate 		 *
2230Sstevel@tonic-gate 		 *	where the pointer to the error has been truncated
2240Sstevel@tonic-gate 		 *	by 6 characters to account for the fact that
2250Sstevel@tonic-gate 		 *	the pointer points into a tab preceded input line.
2260Sstevel@tonic-gate 		 */
2270Sstevel@tonic-gate 		language = INPI;
228*291Smike_s 		(void) substitute(wordv[2], '^', '|');
229*291Smike_s 		longpiptr = position(wordv[2], '|') > (6+8);
2300Sstevel@tonic-gate 		nwordv = wordvsplice(longpiptr ? 2 : 4, wordc, wordv+1);
2310Sstevel@tonic-gate 		nwordv[0] = strsave(currentfilename);
2320Sstevel@tonic-gate 		nwordv[1] = strsave(c_linenumber);
233*291Smike_s 		if (!longpiptr) {
2340Sstevel@tonic-gate 			nwordv[2] = "pascal errortype";
2350Sstevel@tonic-gate 			nwordv[3] = wordv[1];
2360Sstevel@tonic-gate 			nwordv[4] = strsave("%%%\n");
237*291Smike_s 			if (strlen(nwordv[5]) > (8-2)) {
238*291Smike_s 				/* this is the pointer */
239*291Smike_s 				/* bump over 6 characters */
240*291Smike_s 				nwordv[5] += (8-2);
241*291Smike_s 			}
2420Sstevel@tonic-gate 		}
2430Sstevel@tonic-gate 		wordv = nwordv - 1;		/* convert to 1 based */
2440Sstevel@tonic-gate 		wordc += longpiptr ? 2 : 4;
245*291Smike_s 		return (C_TRUE);
2460Sstevel@tonic-gate 	}
247*291Smike_s 	if ((wordc >= 4) &&
248*291Smike_s 	    (strlen(wordv[1]) == 1) &&
249*291Smike_s 	    ((*wordv[1] == 'E') || (*wordv[1] == 'w') ||
250*291Smike_s 		(*wordv[1] == 'e')) &&
251*291Smike_s 	    (alldigits(wordv[2])) &&
252*291Smike_s 	    (strlen(wordv[3]) == 1) &&
253*291Smike_s 	    (wordv[3][0] == '-')) {
2540Sstevel@tonic-gate 		/*
2550Sstevel@tonic-gate 		 *	Message of the form: letter linenumber - message
2560Sstevel@tonic-gate 		 *	Turn into form: filename linenumber letter - message
2570Sstevel@tonic-gate 		 */
2580Sstevel@tonic-gate 		language = INPI;
2590Sstevel@tonic-gate 		nwordv = wordvsplice(1, wordc, wordv + 1);
2600Sstevel@tonic-gate 		nwordv[0] = strsave(currentfilename);
2610Sstevel@tonic-gate 		nwordv[1] = wordv[2];
2620Sstevel@tonic-gate 		nwordv[2] = wordv[1];
2630Sstevel@tonic-gate 		c_linenumber = wordv[2];
2640Sstevel@tonic-gate 		wordc += 1;
2650Sstevel@tonic-gate 		wordv = nwordv - 1;
266*291Smike_s 		return (C_TRUE);
2670Sstevel@tonic-gate 	}
268*291Smike_s 	if ((wordc >= 3) &&
269*291Smike_s 	    (strlen(wordv[1]) == 1) &&
270*291Smike_s 	    ((*(wordv[1]) == 'E') || (*(wordv[1]) == 'w') ||
271*291Smike_s 		(*(wordv[1]) == 'e')) &&
272*291Smike_s 	    (strlen(wordv[2]) == 1) &&
273*291Smike_s 	    (wordv[2][0] == '-')) {
2740Sstevel@tonic-gate 		/*
2750Sstevel@tonic-gate 		 *	Message of the form: letter - message
2760Sstevel@tonic-gate 		 *	This happens only when we are traversing the tree
2770Sstevel@tonic-gate 		 *	during the second pass of pi, and discover semantic
2780Sstevel@tonic-gate 		 *	errors.
2790Sstevel@tonic-gate 		 *
2800Sstevel@tonic-gate 		 *	We have already (presumably) saved the header message
2810Sstevel@tonic-gate 		 *	and can now construct a nulled error message for the
2820Sstevel@tonic-gate 		 *	current file.
2830Sstevel@tonic-gate 		 *
2840Sstevel@tonic-gate 		 *	Turns into a message of the form:
2850Sstevel@tonic-gate 		 *	filename (header) letter - message
286*291Smike_s 		 *
2870Sstevel@tonic-gate 		 *	First, see if it is a message referring to more than
2880Sstevel@tonic-gate 		 *	one line number.  Only of the form:
289*291Smike_s 		 *		%s undefined on line%s
290*291Smike_s 		 *		%s improperly used on line%s
2910Sstevel@tonic-gate 		 */
2920Sstevel@tonic-gate 		boolean undefined = 0;
2930Sstevel@tonic-gate 		int	wordindex;
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 		language = INPI;
296*291Smike_s 		if (((undefined = (wordvcmp(wordv+2, 3, pi_und1) == 0)) != 0) ||
297*291Smike_s 			((undefined =
298*291Smike_s 			    (wordvcmp(wordv+2, 3, pi_und2) == 0)) != 0) ||
299*291Smike_s 		    (wordvcmp(wordv+2, 4, pi_imp1) == 0) ||
300*291Smike_s 		    (wordvcmp(wordv+2, 4, pi_imp2) == 0)) {
3010Sstevel@tonic-gate 			for (wordindex = undefined ? 5 : 6; wordindex <= wordc;
302*291Smike_s 			    wordindex++) {
303*291Smike_s 				nwordv = wordvsplice(2, undefined ? 2 : 3,
304*291Smike_s 				    wordv+1);
3050Sstevel@tonic-gate 				nwordv[0] = strsave(currentfilename);
3060Sstevel@tonic-gate 				nwordv[1] = wordv[wordindex];
3070Sstevel@tonic-gate 				if (wordindex != wordc)
3080Sstevel@tonic-gate 					erroradd(undefined ? 4 : 5, nwordv,
3090Sstevel@tonic-gate 						C_TRUE, C_UNKNOWN);
3100Sstevel@tonic-gate 			}
3110Sstevel@tonic-gate 			wordc = undefined ? 4 : 5;
3120Sstevel@tonic-gate 			wordv = nwordv - 1;
313*291Smike_s 			return (C_TRUE);
3140Sstevel@tonic-gate 		}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 		nwordv = wordvsplice(1+3, wordc, wordv+1);
3170Sstevel@tonic-gate 		nwordv[0] = strsave(currentfilename);
3180Sstevel@tonic-gate 		nwordv[1] = strsave(c_header[0]);
3190Sstevel@tonic-gate 		nwordv[2] = strsave(c_header[1]);
3200Sstevel@tonic-gate 		nwordv[3] = strsave(c_header[2]);
3210Sstevel@tonic-gate 		wordv = nwordv - 1;
3220Sstevel@tonic-gate 		wordc += 1 + 3;
323*291Smike_s 		return (C_THISFILE);
3240Sstevel@tonic-gate 	}
325*291Smike_s 	if (strcmp(wordv[1], "...") == 0) {
3260Sstevel@tonic-gate 		/*
3270Sstevel@tonic-gate 		 *	have a continuation error message
3280Sstevel@tonic-gate 		 *	of the form: ... message
3290Sstevel@tonic-gate 		 *	Turn into form : filename linenumber message
3300Sstevel@tonic-gate 		 */
3310Sstevel@tonic-gate 		language = INPI;
3320Sstevel@tonic-gate 		nwordv = wordvsplice(1, wordc, wordv+1);
3330Sstevel@tonic-gate 		nwordv[0] = strsave(currentfilename);
3340Sstevel@tonic-gate 		nwordv[1] = strsave(c_linenumber);
3350Sstevel@tonic-gate 		wordv = nwordv - 1;
3360Sstevel@tonic-gate 		wordc += 1;
337*291Smike_s 		return (C_TRUE);
3380Sstevel@tonic-gate 	}
339*291Smike_s 	if ((wordc == 6) &&
340*291Smike_s 	    (lastchar(wordv[6]) == ':') &&
341*291Smike_s 	    (isdateformat(5, wordv + 1))) {
3420Sstevel@tonic-gate 		/*
3430Sstevel@tonic-gate 		 *	Have message that tells us we have changed files
3440Sstevel@tonic-gate 		 */
3450Sstevel@tonic-gate 		language = INPI;
3460Sstevel@tonic-gate 		currentfilename = strsave(wordv[6]);
3470Sstevel@tonic-gate 		clob_last(currentfilename, '\0');
348*291Smike_s 		return (C_SYNC);
3490Sstevel@tonic-gate 	}
350*291Smike_s 	if ((wordc == 3) &&
351*291Smike_s 	    (strcmp(wordv[1], "In") == 0) &&
352*291Smike_s 	    (lastchar(wordv[3]) == ':') &&
353*291Smike_s 	    (instringset(wordv[2], Piroutines))) {
3540Sstevel@tonic-gate 		language = INPI;
3550Sstevel@tonic-gate 		c_header = wordvsplice(0, wordc, wordv+1);
356*291Smike_s 		return (C_SYNC);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate 	/*
3590Sstevel@tonic-gate 	 *	now, check for just the line number followed by the text
3600Sstevel@tonic-gate 	 */
361*291Smike_s 	if (alldigits(wordv[1])) {
3620Sstevel@tonic-gate 		language = INPI;
3630Sstevel@tonic-gate 		c_linenumber = wordv[1];
364*291Smike_s 		return (C_IGNORE);
3650Sstevel@tonic-gate 	}
3660Sstevel@tonic-gate 	/*
3670Sstevel@tonic-gate 	 *	Attempt to match messages refering to a line number
3680Sstevel@tonic-gate 	 *
3690Sstevel@tonic-gate 	 *	Multiply defined label in case, lines %d and %d
3700Sstevel@tonic-gate 	 *	Goto %s from line %d is into a structured statement
3710Sstevel@tonic-gate 	 *	End matched %s on line %d
3720Sstevel@tonic-gate 	 *	Inserted keyword end matching %s on line %d
3730Sstevel@tonic-gate 	 */
3740Sstevel@tonic-gate 	multiple = structured = 0;
375*291Smike_s 	if (((wordc == 6) && (wordvcmp(wordv+1, 2, pi_Endmatched) == 0)) ||
376*291Smike_s 	    ((wordc == 8) && (wordvcmp(wordv+1, 4, pi_Inserted) == 0)) ||
377*291Smike_s 	    (multiple = ((wordc == 9) &&
378*291Smike_s 		(wordvcmp(wordv+1, 6, pi_multiple) == 0))) ||
379*291Smike_s 	    (structured = ((wordc == 10) &&
380*291Smike_s 		(wordvcmp(wordv+6, 5, pi_structured) == 0)))) {
3810Sstevel@tonic-gate 		language = INPI;
3820Sstevel@tonic-gate 		nwordv = wordvsplice(2, wordc, wordv+1);
3830Sstevel@tonic-gate 		nwordv[0] = strsave(currentfilename);
3840Sstevel@tonic-gate 		nwordv[1] = structured ? wordv [5] : wordv[wordc];
3850Sstevel@tonic-gate 		wordc += 2;
3860Sstevel@tonic-gate 		wordv = nwordv - 1;
3870Sstevel@tonic-gate 		if (!multiple)
388*291Smike_s 			return (C_TRUE);
3890Sstevel@tonic-gate 		erroradd(wordc, nwordv, C_TRUE, C_UNKNOWN);
3900Sstevel@tonic-gate 		nwordv = wordvsplice(0, wordc, nwordv);
3910Sstevel@tonic-gate 		nwordv[1] = wordv[wordc - 2];
392*291Smike_s 		return (C_TRUE);
3930Sstevel@tonic-gate 	}
394*291Smike_s 	return (C_UNKNOWN);
3950Sstevel@tonic-gate }
396