Annotation of 43BSD/ucb/error/errorpi.c, revision 1.1.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.