home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / error / pi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  12.5 KB  |  405 lines

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