Annotation of 43BSD/ucb/error/errorpi.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.