4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
35 extern char *currentfilename
;
36 static char *c_linenumber
;
37 static char *unk_hdr
[] = {"In", "program", "???"};
38 static char **c_header
= &unk_hdr
[0];
41 * Attempt to handle error messages produced by pi (and by pc)
43 * problem #1: There is no file name available when a file does not
44 * use a #include; this will have to be given to error
45 * in the command line.
46 * problem #2: pi doesn't always tell you what line number
47 * a error refers to; for example during the tree
48 * walk phase of code generation and error detection,
49 * an error can refer to "variable foo in procedure bletch"
50 * without giving a line number
51 * problem #3: line numbers, when available, are attached to
52 * the source line, along with the source line itself
53 * These line numbers must be extracted, and
54 * the source line thrown away.
55 * problem #4: Some error messages produce more than one line number
56 * on the same message.
57 * There are only two (I think):
58 * %s undefined on line%s
59 * %s improperly used on line%s
60 * here, the %s makes line plural or singular.
62 * Here are the error strings used in pi version 1.2 that can refer
63 * to a file name or line number:
65 * Multiply defined label in case, lines %d and %d
66 * Goto %s from line %d is into a structured statement
67 * End matched %s on line %d
68 * Inserted keyword end matching %s on line %d
70 * Here are the general pi patterns recognized:
71 * define piptr == -.*^-.*
73 * define digit = [0-9]
75 * define date_format letter*3 letter*3 (digit | (digit digit))
76 * (digit | (digit digit)):digit*2 digit*4
78 * {e,E} (piptr) (msg) Encounter an error during textual scan
79 * E {digit}* - (msg) Have an error message that refers to a new line
80 * E - msg Have an error message that refers to current
81 * function, program or procedure
82 * (date_format) (name): When switch compilation files
83 * ... (msg) When refer to the previous line
84 * 'In' ('procedure'|'function'|'program') (name):
85 * pi is now complaining about 2nd pass errors.
87 * Here is the output from a compilation
91 * e --------------^--- Inserted ';'
92 * E 2 - All variables must be declared in one var part
93 * E 5 - Include filename must end in .i
94 * Mon Apr 21 15:56 1980 test.h:
96 * e ------^--- Inserted ';'
97 * Mon Apr 21 16:06 1980 test.p:
98 * E 2 - Function type must be specified
99 * 6 procedure foo(var x:real);
100 * e ------^--- Inserted ';'
101 * In function bletch:
102 * E - No assignment to the function variable
103 * w - variable x is never used
104 * E 6 - foo is already defined in this block
106 * w - variable x is neither used nor set
108 * E --------------^--- Undefined variable
110 * e ----------------^--- Inserted ':'
112 * e -----------------------^--- Digits required after decimal point
113 * E 10 - Constant set involved in non set context
114 * E 11 - Type clash: real is incompatible with integer
115 * ... Type of expression clashed with type of variable in assignment
116 * E 12 - Parameter type not identical to type of var parameter x of foo
118 * w - variable y is never used
119 * w - type foo is never used
120 * w - function bletch is never used
121 * E - z undefined on lines 9 13
124 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
125 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
129 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0
131 char *Piroutines
[] = {
132 "program", "function", "procedure", 0
136 static boolean structured
, multiple
;
138 char *pi_Endmatched
[] = {"End", "matched"};
139 char *pi_Inserted
[] = {"Inserted", "keyword", "end", "matching"};
141 char *pi_multiple
[] = {"Mutiply", "defined", "label", "in", "case,", "line"};
142 char *pi_structured
[] = {"is", "into", "a", "structured", "statement"};
144 char *pi_und1
[] = {"undefined", "on", "line"};
145 char *pi_und2
[] = {"undefined", "on", "lines"};
146 char *pi_imp1
[] = {"improperly", "used", "on", "line"};
147 char *pi_imp2
[] = {"improperly", "used", "on", "lines"};
150 alldigits(char *string
)
152 for (; *string
&& isdigit(*string
); string
++)
154 return (*string
== '\0');
158 instringset(char *member
, char **set
)
160 for (; *set
; set
++) {
161 if (strcmp(*set
, member
) == 0)
168 isdateformat(int wordc
, char **wordv
)
170 return ((wordc
== 5) &&
171 (instringset(wordv
[0], Days
)) &&
172 (instringset(wordv
[1], Months
)) &&
173 (alldigits(wordv
[2])) && (alldigits(wordv
[4])));
181 while (*string
&& *string
== '-')
186 while (*string
&& *string
== '-')
188 return (*string
== '\0');
201 if ((strlen(wordv
[1]) == 1) &&
202 ((wordv
[1][0] == 'e') || (wordv
[1][0] == 'E')) &&
204 boolean longpiptr
= 0;
206 * We have recognized a first pass error of the form:
207 * letter ------^---- message
209 * turn into an error message of the form:
211 * file line 'pascal errortype' letter \n |---- message
213 * file line letter |---- message
214 * when there are strlen("(*[pi]") or more
215 * preceding '-' on the error pointer.
217 * Where the | is intended to be a down arrow, so that
218 * the pi error messages can be inserted above the
219 * line in error, instead of below. (All of the other
220 * langauges put thier messages before the source line,
221 * instead of after it as does pi.)
223 * where the pointer to the error has been truncated
224 * by 6 characters to account for the fact that
225 * the pointer points into a tab preceded input line.
228 (void) substitute(wordv
[2], '^', '|');
229 longpiptr
= position(wordv
[2], '|') > (6+8);
230 nwordv
= wordvsplice(longpiptr
? 2 : 4, wordc
, wordv
+1);
231 nwordv
[0] = strsave(currentfilename
);
232 nwordv
[1] = strsave(c_linenumber
);
234 nwordv
[2] = "pascal errortype";
235 nwordv
[3] = wordv
[1];
236 nwordv
[4] = strsave("%%%\n");
237 if (strlen(nwordv
[5]) > (8-2)) {
238 /* this is the pointer */
239 /* bump over 6 characters */
243 wordv
= nwordv
- 1; /* convert to 1 based */
244 wordc
+= longpiptr
? 2 : 4;
248 (strlen(wordv
[1]) == 1) &&
249 ((*wordv
[1] == 'E') || (*wordv
[1] == 'w') ||
250 (*wordv
[1] == 'e')) &&
251 (alldigits(wordv
[2])) &&
252 (strlen(wordv
[3]) == 1) &&
253 (wordv
[3][0] == '-')) {
255 * Message of the form: letter linenumber - message
256 * Turn into form: filename linenumber letter - message
259 nwordv
= wordvsplice(1, wordc
, wordv
+ 1);
260 nwordv
[0] = strsave(currentfilename
);
261 nwordv
[1] = wordv
[2];
262 nwordv
[2] = wordv
[1];
263 c_linenumber
= wordv
[2];
269 (strlen(wordv
[1]) == 1) &&
270 ((*(wordv
[1]) == 'E') || (*(wordv
[1]) == 'w') ||
271 (*(wordv
[1]) == 'e')) &&
272 (strlen(wordv
[2]) == 1) &&
273 (wordv
[2][0] == '-')) {
275 * Message of the form: letter - message
276 * This happens only when we are traversing the tree
277 * during the second pass of pi, and discover semantic
280 * We have already (presumably) saved the header message
281 * and can now construct a nulled error message for the
284 * Turns into a message of the form:
285 * filename (header) letter - message
287 * First, see if it is a message referring to more than
288 * one line number. Only of the form:
289 * %s undefined on line%s
290 * %s improperly used on line%s
292 boolean undefined
= 0;
296 if (((undefined
= (wordvcmp(wordv
+2, 3, pi_und1
) == 0)) != 0) ||
298 (wordvcmp(wordv
+2, 3, pi_und2
) == 0)) != 0) ||
299 (wordvcmp(wordv
+2, 4, pi_imp1
) == 0) ||
300 (wordvcmp(wordv
+2, 4, pi_imp2
) == 0)) {
301 for (wordindex
= undefined
? 5 : 6; wordindex
<= wordc
;
303 nwordv
= wordvsplice(2, undefined
? 2 : 3,
305 nwordv
[0] = strsave(currentfilename
);
306 nwordv
[1] = wordv
[wordindex
];
307 if (wordindex
!= wordc
)
308 erroradd(undefined
? 4 : 5, nwordv
,
311 wordc
= undefined
? 4 : 5;
316 nwordv
= wordvsplice(1+3, wordc
, wordv
+1);
317 nwordv
[0] = strsave(currentfilename
);
318 nwordv
[1] = strsave(c_header
[0]);
319 nwordv
[2] = strsave(c_header
[1]);
320 nwordv
[3] = strsave(c_header
[2]);
325 if (strcmp(wordv
[1], "...") == 0) {
327 * have a continuation error message
328 * of the form: ... message
329 * Turn into form : filename linenumber message
332 nwordv
= wordvsplice(1, wordc
, wordv
+1);
333 nwordv
[0] = strsave(currentfilename
);
334 nwordv
[1] = strsave(c_linenumber
);
340 (lastchar(wordv
[6]) == ':') &&
341 (isdateformat(5, wordv
+ 1))) {
343 * Have message that tells us we have changed files
346 currentfilename
= strsave(wordv
[6]);
347 clob_last(currentfilename
, '\0');
351 (strcmp(wordv
[1], "In") == 0) &&
352 (lastchar(wordv
[3]) == ':') &&
353 (instringset(wordv
[2], Piroutines
))) {
355 c_header
= wordvsplice(0, wordc
, wordv
+1);
359 * now, check for just the line number followed by the text
361 if (alldigits(wordv
[1])) {
363 c_linenumber
= wordv
[1];
367 * Attempt to match messages refering to a line number
369 * Multiply defined label in case, lines %d and %d
370 * Goto %s from line %d is into a structured statement
371 * End matched %s on line %d
372 * Inserted keyword end matching %s on line %d
374 multiple
= structured
= 0;
375 if (((wordc
== 6) && (wordvcmp(wordv
+1, 2, pi_Endmatched
) == 0)) ||
376 ((wordc
== 8) && (wordvcmp(wordv
+1, 4, pi_Inserted
) == 0)) ||
377 (multiple
= ((wordc
== 9) &&
378 (wordvcmp(wordv
+1, 6, pi_multiple
) == 0))) ||
379 (structured
= ((wordc
== 10) &&
380 (wordvcmp(wordv
+6, 5, pi_structured
) == 0)))) {
382 nwordv
= wordvsplice(2, wordc
, wordv
+1);
383 nwordv
[0] = strsave(currentfilename
);
384 nwordv
[1] = structured
? wordv
[5] : wordv
[wordc
];
389 erroradd(wordc
, nwordv
, C_TRUE
, C_UNKNOWN
);
390 nwordv
= wordvsplice(0, wordc
, nwordv
);
391 nwordv
[1] = wordv
[wordc
- 2];