8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sgs / error / common / errorpi.c
blobe7841c885677316f14c6db07fc12cb6743dbc777
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <string.h>
33 #include "error.h"
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 == -.*^-.*
72 * define msg = .*
73 * define digit = [0-9]
74 * definename = .*
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
90 * 2 var i:integer;
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:
95 * 2 begin
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
105 * In procedure foo:
106 * w - variable x is neither used nor set
107 * 9 z : = 23;
108 * E --------------^--- Undefined variable
109 * 10 y = [1];
110 * e ----------------^--- Inserted ':'
111 * 13 z := 345.;
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
117 * In program mung:
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
123 char *Months[] = {
124 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
125 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
128 char *Days[] = {
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"};
149 boolean
150 alldigits(char *string)
152 for (; *string && isdigit(*string); string++)
153 continue;
154 return (*string == '\0');
157 boolean
158 instringset(char *member, char **set)
160 for (; *set; set++) {
161 if (strcmp(*set, member) == 0)
162 return (TRUE);
164 return (FALSE);
167 boolean
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])));
176 boolean
177 piptr(char *string)
179 if (*string != '-')
180 return (FALSE);
181 while (*string && *string == '-')
182 string++;
183 if (*string != '^')
184 return (FALSE);
185 string++;
186 while (*string && *string == '-')
187 string++;
188 return (*string == '\0');
191 extern int wordc;
192 extern char **wordv;
194 Errorclass
195 pi(void)
197 char **nwordv;
199 if (wordc < 2)
200 return (C_UNKNOWN);
201 if ((strlen(wordv[1]) == 1) &&
202 ((wordv[1][0] == 'e') || (wordv[1][0] == 'E')) &&
203 (piptr(wordv[2]))) {
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
212 * or of the form:
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.
227 language = INPI;
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);
233 if (!longpiptr) {
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 */
240 nwordv[5] += (8-2);
243 wordv = nwordv - 1; /* convert to 1 based */
244 wordc += longpiptr ? 2 : 4;
245 return (C_TRUE);
247 if ((wordc >= 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
258 language = INPI;
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];
264 wordc += 1;
265 wordv = nwordv - 1;
266 return (C_TRUE);
268 if ((wordc >= 3) &&
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
278 * errors.
280 * We have already (presumably) saved the header message
281 * and can now construct a nulled error message for the
282 * current file.
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;
293 int wordindex;
295 language = INPI;
296 if (((undefined = (wordvcmp(wordv+2, 3, pi_und1) == 0)) != 0) ||
297 ((undefined =
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;
302 wordindex++) {
303 nwordv = wordvsplice(2, undefined ? 2 : 3,
304 wordv+1);
305 nwordv[0] = strsave(currentfilename);
306 nwordv[1] = wordv[wordindex];
307 if (wordindex != wordc)
308 erroradd(undefined ? 4 : 5, nwordv,
309 C_TRUE, C_UNKNOWN);
311 wordc = undefined ? 4 : 5;
312 wordv = nwordv - 1;
313 return (C_TRUE);
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]);
321 wordv = nwordv - 1;
322 wordc += 1 + 3;
323 return (C_THISFILE);
325 if (strcmp(wordv[1], "...") == 0) {
327 * have a continuation error message
328 * of the form: ... message
329 * Turn into form : filename linenumber message
331 language = INPI;
332 nwordv = wordvsplice(1, wordc, wordv+1);
333 nwordv[0] = strsave(currentfilename);
334 nwordv[1] = strsave(c_linenumber);
335 wordv = nwordv - 1;
336 wordc += 1;
337 return (C_TRUE);
339 if ((wordc == 6) &&
340 (lastchar(wordv[6]) == ':') &&
341 (isdateformat(5, wordv + 1))) {
343 * Have message that tells us we have changed files
345 language = INPI;
346 currentfilename = strsave(wordv[6]);
347 clob_last(currentfilename, '\0');
348 return (C_SYNC);
350 if ((wordc == 3) &&
351 (strcmp(wordv[1], "In") == 0) &&
352 (lastchar(wordv[3]) == ':') &&
353 (instringset(wordv[2], Piroutines))) {
354 language = INPI;
355 c_header = wordvsplice(0, wordc, wordv+1);
356 return (C_SYNC);
359 * now, check for just the line number followed by the text
361 if (alldigits(wordv[1])) {
362 language = INPI;
363 c_linenumber = wordv[1];
364 return (C_IGNORE);
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)))) {
381 language = INPI;
382 nwordv = wordvsplice(2, wordc, wordv+1);
383 nwordv[0] = strsave(currentfilename);
384 nwordv[1] = structured ? wordv [5] : wordv[wordc];
385 wordc += 2;
386 wordv = nwordv - 1;
387 if (!multiple)
388 return (C_TRUE);
389 erroradd(wordc, nwordv, C_TRUE, C_UNKNOWN);
390 nwordv = wordvsplice(0, wordc, nwordv);
391 nwordv[1] = wordv[wordc - 2];
392 return (C_TRUE);
394 return (C_UNKNOWN);