[BACK]Return to pi.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / error

Annotation of src/usr.bin/error/pi.c, Revision 1.2

1.2     ! deraadt     1: /*     $OpenBSD: pi.c,v 1.3 1995/09/02 06:15:44 jtc Exp $      */
1.1       deraadt     2: /*     $NetBSD: pi.c,v 1.3 1995/09/02 06:15:44 jtc Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1980, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  */
                     36:
                     37: #ifndef lint
                     38: #if 0
                     39: static char sccsid[] = "@(#)pi.c       8.1 (Berkeley) 6/6/93";
                     40: #endif
1.2     ! deraadt    41: static char rcsid[] = "$OpenBSD: pi.c,v 1.3 1995/09/02 06:15:44 jtc Exp $";
1.1       deraadt    42: #endif /* not lint */
                     43:
                     44: #include <stdio.h>
                     45: #include <ctype.h>
                     46: #include <string.h>
                     47: #include "error.h"
                     48:
                     49: extern char    *currentfilename;
                     50: static char    *c_linenumber;
                     51: static char    *unk_hdr[] = {"In", "program", "???"};
                     52: static char    **c_header = &unk_hdr[0];
                     53:
                     54: /*
                     55:  *     Attempt to handle error messages produced by pi (and by pc)
                     56:  *
                     57:  *     problem #1:     There is no file name available when a file does not
                     58:  *                     use a #include; this will have to be given to error
                     59:  *                     in the command line.
                     60:  *     problem #2:     pi doesn't always tell you what line number
                     61:  *                     a error refers to; for example during the tree
                     62:  *                     walk phase of code generation and error detection,
                     63:  *                     an error can refer to "variable foo in procedure bletch"
                     64:  *                     without giving a line number
                     65:  *     problem #3:     line numbers, when available, are attached to
                     66:  *                     the source line, along with the source line itself
                     67:  *                     These line numbers must be extracted, and
                     68:  *                     the source line thrown away.
                     69:  *     problem #4:     Some error messages produce more than one line number
                     70:  *                     on the same message.
                     71:  *                     There are only two (I think):
                     72:  *                             %s undefined on line%s
                     73:  *                             %s improperly used on line%s
                     74:  *                     here, the %s makes line plural or singular.
                     75:  *
                     76:  *     Here are the error strings used in pi version 1.2 that can refer
                     77:  *     to a file name or line number:
                     78:  *
                     79:  *             Multiply defined label in case, lines %d and %d
                     80:  *             Goto %s from line %d is into a structured statement
                     81:  *             End matched %s on line %d
                     82:  *             Inserted keyword end matching %s on line %d
                     83:  *
                     84:  *     Here are the general pi patterns recognized:
                     85:  *     define piptr == -.*^-.*
                     86:  *     define msg = .*
                     87:  *     define digit = [0-9]
                     88:  *     definename = .*
                     89:  *     define date_format letter*3 letter*3 (digit | (digit digit))
                     90:  *                     (digit | (digit digit)):digit*2 digit*4
                     91:  *
                     92:  *     {e,E} (piptr) (msg)     Encounter an error during textual scan
                     93:  *     E {digit}* - (msg)      Have an error message that refers to a new line
                     94:  *     E - msg                 Have an error message that refers to current
                     95:  *                                     function, program or procedure
                     96:  *     (date_format) (name):   When switch compilation files
                     97:  *     ... (msg)               When refer to the previous line
                     98:  *     'In' ('procedure'|'function'|'program') (name):
                     99:  *                             pi is now complaining about 2nd pass errors.
                    100:  *
                    101:  *     Here is the output from a compilation
                    102:  *
                    103:  *
                    104:  *          2          var     i:integer;
                    105:  *     e --------------^--- Inserted ';'
                    106:  *     E 2 - All variables must be declared in one var part
                    107:  *     E 5 - Include filename must end in .i
                    108:  *     Mon Apr 21 15:56 1980  test.h:
                    109:  *          2  begin
                    110:  *     e ------^--- Inserted ';'
                    111:  *     Mon Apr 21 16:06 1980  test.p:
                    112:  *     E 2 - Function type must be specified
                    113:  *          6  procedure foo(var x:real);
                    114:  *     e ------^--- Inserted ';'
                    115:  *     In function bletch:
                    116:  *       E - No assignment to the function variable
                    117:  *       w - variable x is never used
                    118:  *     E 6 - foo is already defined in this block
                    119:  *     In procedure foo:
                    120:  *       w - variable x is neither used nor set
                    121:  *          9          z : = 23;
                    122:  *     E --------------^--- Undefined variable
                    123:  *         10          y = [1];
                    124:  *     e ----------------^--- Inserted ':'
                    125:  *         13          z := 345.;
                    126:  *     e -----------------------^--- Digits required after decimal point
                    127:  *     E 10 - Constant set involved in non set context
                    128:  *     E 11 - Type clash: real is incompatible with integer
                    129:  *        ... Type of expression clashed with type of variable in assignment
                    130:  *     E 12 - Parameter type not identical to type of var parameter x of foo
                    131:  *     In program mung:
                    132:  *       w - variable y is never used
                    133:  *       w - type foo is never used
                    134:  *       w - function bletch is never used
                    135:  *       E - z undefined on lines 9 13
                    136:  */
                    137: char *Months[] = {
                    138:        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                    139:        "Jul", "Aug", "Sep", "Oct","Nov", "Dec",
                    140:        0
                    141: };
                    142: char *Days[] = {
                    143:        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0
                    144: };
                    145: char *Piroutines[] = {
                    146:                "program", "function", "procedure", 0
                    147: };
                    148:
                    149:
                    150: static boolean structured, multiple;
                    151:
                    152: char *pi_Endmatched[] = {"End", "matched"};
                    153: char *pi_Inserted[] = {"Inserted", "keyword", "end", "matching"};
                    154:
                    155: char *pi_multiple[] = {"Mutiply", "defined", "label", "in", "case,", "line"};
                    156: char *pi_structured[] = {"is", "into", "a", "structured", "statement"};
                    157:
                    158: char *pi_und1[] = {"undefined", "on", "line"};
                    159: char *pi_und2[] = {"undefined", "on", "lines"};
                    160: char *pi_imp1[] = {"improperly", "used", "on", "line"};
                    161: char *pi_imp2[] = {"improperly", "used", "on", "lines"};
                    162:
                    163: boolean alldigits(string)
                    164:        reg     char    *string;
                    165: {
                    166:        for (; *string && isdigit(*string); string++)
                    167:                continue;
                    168:        return(*string == '\0');
                    169: }
                    170: boolean instringset(member, set)
                    171:                char    *member;
                    172:        reg     char    **set;
                    173: {
                    174:        for(; *set; set++){
                    175:                if (strcmp(*set, member) == 0)
                    176:                        return(TRUE);
                    177:        }
                    178:        return(FALSE);
                    179: }
                    180:
                    181: boolean isdateformat(wordc, wordv)
                    182:        int     wordc;
                    183:        char    **wordv;
                    184: {
                    185:        return(
                    186:                (wordc == 5)
                    187:             && (instringset(wordv[0], Days))
                    188:             && (instringset(wordv[1], Months))
                    189:             && (alldigits(wordv[2]))
                    190:             && (alldigits(wordv[4])) );
                    191: }
                    192:
                    193: boolean piptr(string)
                    194:        reg     char    *string;
                    195: {
                    196:        if (*string != '-')
                    197:                return(FALSE);
                    198:        while (*string && *string == '-')
                    199:                string++;
                    200:        if (*string != '^')
                    201:                return(FALSE);
                    202:        string++;
                    203:        while (*string && *string == '-')
                    204:                string++;
                    205:        return(*string == '\0');
                    206: }
                    207:
                    208: extern int     wordc;
                    209: extern char    **wordv;
                    210:
                    211: Errorclass pi()
                    212: {
                    213:        char    **nwordv;
                    214:
                    215:        if (wordc < 2)
                    216:                return (C_UNKNOWN);
                    217:        if (   ( strlen(wordv[1]) == 1)
                    218:            && ( (wordv[1][0] == 'e') || (wordv[1][0] == 'E') )
                    219:            && ( piptr(wordv[2]) )
                    220:        ) {
                    221:                boolean longpiptr = 0;
                    222:                /*
                    223:                 *      We have recognized a first pass error of the form:
                    224:                 *      letter ------^---- message
                    225:                 *
                    226:                 *      turn into an error message of the form:
                    227:                 *
                    228:                 *      file line 'pascal errortype' letter \n |---- message
                    229:                 *      or of the form:
                    230:                 *      file line letter |---- message
                    231:                 *              when there are strlen("(*[pi]") or more
                    232:                 *              preceding '-' on the error pointer.
                    233:                 *
                    234:                 *      Where the | is intended to be a down arrow, so that
                    235:                 *      the pi error messages can be inserted above the
                    236:                 *      line in error, instead of below.  (All of the other
                    237:                 *      langauges put thier messages before the source line,
                    238:                 *      instead of after it as does pi.)
                    239:                 *
                    240:                 *      where the pointer to the error has been truncated
                    241:                 *      by 6 characters to account for the fact that
                    242:                 *      the pointer points into a tab preceded input line.
                    243:                 */
                    244:                language = INPI;
                    245:                (void)substitute(wordv[2], '^', '|');
                    246:                longpiptr = position(wordv[2],'|') > (6+8);
                    247:                nwordv = wordvsplice(longpiptr ? 2 : 4, wordc, wordv+1);
                    248:                nwordv[0] = strsave(currentfilename);
                    249:                nwordv[1] = strsave(c_linenumber);
                    250:                if (!longpiptr){
                    251:                        nwordv[2] = "pascal errortype";
                    252:                        nwordv[3] = wordv[1];
                    253:                        nwordv[4] = strsave("%%%\n");
                    254:                        if (strlen(nwordv[5]) > (8-2))  /* this is the pointer */
                    255:                                nwordv[5] += (8-2);     /* bump over 6 characters */
                    256:                }
                    257:                wordv = nwordv - 1;             /* convert to 1 based */
                    258:                wordc += longpiptr ? 2 : 4;
                    259:                return(C_TRUE);
                    260:        }
                    261:        if (   (wordc >= 4)
                    262:            && (strlen(wordv[1]) == 1)
                    263:            && ( (*wordv[1] == 'E') || (*wordv[1] == 'w') || (*wordv[1] == 'e') )
                    264:            && (alldigits(wordv[2]))
                    265:            && (strlen(wordv[3]) == 1)
                    266:            && (wordv[3][0] == '-')
                    267:        ){
                    268:                /*
                    269:                 *      Message of the form: letter linenumber - message
                    270:                 *      Turn into form: filename linenumber letter - message
                    271:                 */
                    272:                language = INPI;
                    273:                nwordv = wordvsplice(1, wordc, wordv + 1);
                    274:                nwordv[0] = strsave(currentfilename);
                    275:                nwordv[1] = wordv[2];
                    276:                nwordv[2] = wordv[1];
                    277:                c_linenumber = wordv[2];
                    278:                wordc += 1;
                    279:                wordv = nwordv - 1;
                    280:                return(C_TRUE);
                    281:        }
                    282:        if (   (wordc >= 3)
                    283:            && (strlen(wordv[1]) == 1)
                    284:            && ( (*(wordv[1]) == 'E') || (*(wordv[1]) == 'w') || (*(wordv[1]) == 'e') )
                    285:            && (strlen(wordv[2]) == 1)
                    286:            && (wordv[2][0] == '-')
                    287:        ) {
                    288:                /*
                    289:                 *      Message of the form: letter - message
                    290:                 *      This happens only when we are traversing the tree
                    291:                 *      during the second pass of pi, and discover semantic
                    292:                 *      errors.
                    293:                 *
                    294:                 *      We have already (presumably) saved the header message
                    295:                 *      and can now construct a nulled error message for the
                    296:                 *      current file.
                    297:                 *
                    298:                 *      Turns into a message of the form:
                    299:                 *      filename (header) letter - message
                    300:                 *
                    301:                 *      First, see if it is a message referring to more than
                    302:                 *      one line number.  Only of the form:
                    303:                 *              %s undefined on line%s
                    304:                 *              %s improperly used on line%s
                    305:                 */
                    306:                boolean undefined = 0;
                    307:                int     wordindex;
                    308:
                    309:                language = INPI;
                    310:                if (    (undefined = (wordvcmp(wordv+2, 3, pi_und1) == 0) )
                    311:                     || (undefined = (wordvcmp(wordv+2, 3, pi_und2) == 0) )
                    312:                     || (wordvcmp(wordv+2, 4, pi_imp1) == 0)
                    313:                     || (wordvcmp(wordv+2, 4, pi_imp2) == 0)
                    314:                ){
                    315:                        for (wordindex = undefined ? 5 : 6; wordindex <= wordc;
                    316:                            wordindex++){
                    317:                                nwordv = wordvsplice(2, undefined ? 2 : 3, wordv+1);
                    318:                                nwordv[0] = strsave(currentfilename);
                    319:                                nwordv[1] = wordv[wordindex];
                    320:                                if (wordindex != wordc)
                    321:                                        erroradd(undefined ? 4 : 5, nwordv,
                    322:                                                C_TRUE, C_UNKNOWN);
                    323:                        }
                    324:                        wordc = undefined ? 4 : 5;
                    325:                        wordv = nwordv - 1;
                    326:                        return(C_TRUE);
                    327:                }
                    328:
                    329:                nwordv = wordvsplice(1+3, wordc, wordv+1);
                    330:                nwordv[0] = strsave(currentfilename);
                    331:                nwordv[1] = strsave(c_header[0]);
                    332:                nwordv[2] = strsave(c_header[1]);
                    333:                nwordv[3] = strsave(c_header[2]);
                    334:                wordv = nwordv - 1;
                    335:                wordc += 1 + 3;
                    336:                return(C_THISFILE);
                    337:        }
                    338:        if (strcmp(wordv[1], "...") == 0){
                    339:                /*
                    340:                 *      have a continuation error message
                    341:                 *      of the form: ... message
                    342:                 *      Turn into form : filename linenumber message
                    343:                 */
                    344:                language = INPI;
                    345:                nwordv = wordvsplice(1, wordc, wordv+1);
                    346:                nwordv[0] = strsave(currentfilename);
                    347:                nwordv[1] = strsave(c_linenumber);
                    348:                wordv = nwordv - 1;
                    349:                wordc += 1;
                    350:                return(C_TRUE);
                    351:        }
                    352:        if(   (wordc == 6)
                    353:           && (lastchar(wordv[6]) == ':')
                    354:           && (isdateformat(5, wordv + 1))
                    355:        ){
                    356:                /*
                    357:                 *      Have message that tells us we have changed files
                    358:                 */
                    359:                language = INPI;
                    360:                currentfilename = strsave(wordv[6]);
                    361:                clob_last(currentfilename, '\0');
                    362:                return(C_SYNC);
                    363:        }
                    364:        if(   (wordc == 3)
                    365:           && (strcmp(wordv[1], "In") == 0)
                    366:           && (lastchar(wordv[3]) == ':')
                    367:           && (instringset(wordv[2], Piroutines))
                    368:        ) {
                    369:                language = INPI;
                    370:                c_header = wordvsplice(0, wordc, wordv+1);
                    371:                return(C_SYNC);
                    372:        }
                    373:        /*
                    374:         *      now, check for just the line number followed by the text
                    375:         */
                    376:        if (alldigits(wordv[1])){
                    377:                language = INPI;
                    378:                c_linenumber = wordv[1];
                    379:                return(C_IGNORE);
                    380:        }
                    381:        /*
                    382:         *      Attempt to match messages refering to a line number
                    383:         *
                    384:         *      Multiply defined label in case, lines %d and %d
                    385:         *      Goto %s from line %d is into a structured statement
                    386:         *      End matched %s on line %d
                    387:         *      Inserted keyword end matching %s on line %d
                    388:         */
                    389:        multiple = structured = 0;
                    390:        if (
                    391:               ( (wordc == 6) && (wordvcmp(wordv+1, 2, pi_Endmatched) == 0))
                    392:            || ( (wordc == 8) && (wordvcmp(wordv+1, 4, pi_Inserted) == 0))
                    393:            || ( multiple = ((wordc == 9) && (wordvcmp(wordv+1,6, pi_multiple) == 0) ) )
                    394:            || ( structured = ((wordc == 10) && (wordvcmp(wordv+6,5, pi_structured) == 0 ) ))
                    395:        ){
                    396:                language = INPI;
                    397:                nwordv = wordvsplice(2, wordc, wordv+1);
                    398:                nwordv[0] = strsave(currentfilename);
                    399:                nwordv[1] = structured ? wordv [5] : wordv[wordc];
                    400:                wordc += 2;
                    401:                wordv = nwordv - 1;
                    402:                if (!multiple)
                    403:                        return(C_TRUE);
                    404:                erroradd(wordc, nwordv, C_TRUE, C_UNKNOWN);
                    405:                nwordv = wordvsplice(0, wordc, nwordv);
                    406:                nwordv[1] = wordv[wordc - 2];
                    407:                return(C_TRUE);
                    408:        }
                    409:        return(C_UNKNOWN);
                    410: }