[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.1.1.1

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