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

unix.superglobalmegacorp.com

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