-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. -- All rights reserved. -- Copyright (C) 2007-2011, Gabriel Dos Reis. -- All rights reserved. -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions are -- met: -- -- - Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- -- - Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in -- the documentation and/or other materials provided with the -- distribution. -- -- - Neither the name of The Numerical ALgorithms Group Ltd. nor the -- names of its contributors may be used to endorse or promote products -- derived from this software without specific prior written permission. -- -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER -- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import sys_-macros import astr namespace BOOT $erLocMsgDatabaseName := pathname '(co_-eng msgs a) $erGlbMsgDatabaseName := pathname '(co_-eng msgs i) $newcompErrorCount := 0 $imPrTagGuys == ['unimple, 'bug, 'debug, 'say, 'warn] $toWhereGuys == ['fileOnly, 'screenOnly ] $imPrGuys == ['imPr] $repGuys == ['noRep, 'rep] $attrCats == ['$imPrGuys, '$toWhereGuys, '$repGuys] $LINELENGTH := 80 $preLength := 11 $LOGLENGTH := $LINELENGTH - 6 $specificMsgTags := [] $showKeyNum := nil $compErrorPrefix := '"Error" $compBugPrefix := '"Bug!" $ncMsgList := [] --% --% Messages for the USERS of the compiler. -- The program being compiled has a minor error. -- Give a message and continue processing. ncSoftError(pos, erMsgKey, erArgL,:optAttr) == $newcompErrorCount := $newcompErrorCount + 1 desiredMsg erMsgKey => processKeyedError msgCreate ('error, pos, erMsgKey, erArgL, $compErrorPrefix,optAttr) -- The program being compiled is seriously incorrect. -- Give message and throw to a recovery point. ncHardError(pos, erMsgKey, erArgL,:optAttr) == $newcompErrorCount := $newcompErrorCount + 1 desiredMsg erMsgKey => processKeyedError msgCreate('error,pos,erMsgKey, erArgL, $compErrorPrefix,optAttr) ncError() -- Bug in the compiler: something which shouldn't have happened did. ncBug (erMsgKey, erArgL,:optAttr) == $newcompErrorCount := $newcompErrorCount + 1 processKeyedError msgCreate('bug,$nopos, erMsgKey, erArgL,$compBugPrefix,optAttr) enterBreak() ncAbort() --% Lower level functions --msgObject tag -- catagory of msg -- -- attributes as a-list -- 'imPr => dont save for list processing -- toWhere, screen or file -- 'norep => only display once in list -- pos -- position with possible FROM/TO tag -- key -- key for message database -- argL -- arguments to be placed in the msg test -- prefix -- things like "Error: " -- text -- the actual text msgCreate(tag,posWTag,key,argL,optPre,:optAttr) == if cons? key then tag := 'old msg := [tag,posWTag,key,argL,optPre,nil] if first optAttr then setMsgForcedAttrList(msg,first optAttr) putDatabaseStuff msg initImPr msg initToWhere msg msg processKeyedError msg == getMsgTag? msg = 'old => --temp erMsg := getMsgKey msg --temp if pre := getMsgPrefix? msg then --temp erMsg := ['"%b", pre, '"%d", :erMsg] --temp sayBrightly ['"old msg from ",_ CallerName 4,:erMsg] --temp msgImPr? msg => msgOutputter msg $ncMsgList := [msg,:$ncMsgList] --------------------------------- --%getting info from db. putDatabaseStuff msg == [text,attributes] := getMsgInfoFromKey msg if attributes then setMsgUnforcedAttrList(msg,attributes) setMsgText(msg,text) getMsgInfoFromKey msg == $msgDatabaseName : local := [] msgText := msgKey := getMsgKey? msg => --temp oldmsgs use key tostoretext dbL := [$erLocMsgDatabaseName,$erGlbMsgDatabaseName] getErFromDbL (msgKey,dbL) getMsgKey msg --temp oldmsgs msgText := segmentKeyedMsg msgText [msgText,attributes] := removeAttributes msgText msgText := substituteSegmentedMsg(msgText, getMsgArgL msg) [msgText,attributes] getErFromDbL (erMsgKey,dbL) == erMsg := nil while null erMsg repeat dbName := first dbL dbL := rest dbL $msgDatabaseName := dbName lastName := null dbL -- fileFound := '"co_-eng.msgs" fileFound := '"s2_-us.msgs" if fileFound or lastName then erMsg := fetchKeyedMsg(erMsgKey,not lastName) erMsg ----------------------- --%character position marking processChPosesForOneLine msgList == chPosList := posPointers msgList for msg in msgList repeat if getMsgFTTag? msg then putFTText (msg,chPosList) posLetter := rest assoc(poCharPosn getMsgPos msg,chPosList) oldPre := getMsgPrefix msg setMsgPrefix (msg,strconc(oldPre,_ makeString($preLength - 4 - # oldPre),posLetter) ) leaderMsg := makeLeaderMsg chPosList append!(msgList,[leaderMsg]) --a back cons posPointers msgList == --gets all the char posns for msgs on one line --associates them with a uppercase letter pointers := '"ABCDEFGHIJKLMONPQRS" increment := 0 posList:= [] ftPosList := [] for msg in msgList repeat pos := poCharPosn getMsgPos msg if pos ~= IFCAR posList then posList := [pos,:posList] if getMsgFTTag? msg = 'FROMTO then ftPosList := [poCharPosn getMsgPos2 msg,:ftPosList] for toPos in ftPosList repeat posList := insertPos(toPos,posList) for pos in posList repeat posLetterList := [[pos,:pointers.increment],:posLetterList] increment := increment + 1 posLetterList insertPos(newPos,posList) == --insersts a position in the proper place of a positon list --used for the 2nd pos of a fromto done := false bot := [0,:posList] top := [] while not done repeat top := [first bot,:top] bot := rest bot pos := first bot done := pos < newPos => false pos = newPos => true pos > newPos => top := [newPos,:top] true [rest reverse top,:bot] putFTText (msg,chPosList) == tag := getMsgFTTag? msg pos := poCharPosn getMsgPos msg charMarker := rest assoc(pos,chPosList) tag = 'FROM => markingText := ['"(from ",charMarker,'" and on) "] setMsgText(msg,[:markingText,:getMsgText msg]) tag = 'TO => markingText := ['"(up to ",charMarker,'") "] setMsgText(msg,[:markingText,:getMsgText msg]) tag = 'FROMTO => pos2 := poCharPosn getMsgPos2 msg charMarker2 := rest assoc(pos2,chPosList) markingText := ['"(from ",charMarker,'" up to ",_ charMarker2,'") "] setMsgText(msg,[:markingText,:getMsgText msg]) rep (c,n) == n > 0 => makeString(n, c) '"" --called from parameter list of nc message functions From pos == ['FROM, pos] To pos == ['TO, pos] FromTo (pos1,pos2) == ['FROMTO, pos1, pos2] ------------------------ --%processing error lists processMsgList (erMsgList,lineList) == $outputList :local := []--grows in queueUp errors $noRepList :local := []--grows in queueUp errors erMsgList := erMsgSort erMsgList for line in lineList repeat msgLine := makeMsgFromLine line $outputList := [msgLine,:$outputList] globalNumOfLine := poGlobalLinePosn getMsgPos msgLine erMsgList := queueUpErrors(globalNumOfLine,erMsgList) $outputList := append(erMsgList,$outputList) --the nopos's st := '"---------SOURCE-TEXT-&-ERRORS------------------------" listOutputter reverse $outputList erMsgSort erMsgList == [msgWPos,msgWOPos] := erMsgSep erMsgList msgWPos := listSort(function erMsgCompare, msgWPos) msgWOPos := reverse msgWOPos [:msgWPos,:msgWOPos] erMsgCompare(ob1,ob2)== pos1 := getMsgPos ob1 pos2 := getMsgPos ob2 compareposns(pos2,pos1) erMsgSep erMsgList == msgWPos := [] msgWOPos := [] for msg in erMsgList repeat if poNopos? getMsgPos msg then msgWOPos := [msg,:msgWOPos] else msgWPos := [msg,:msgWPos] [msgWPos,msgWOPos] getLinePos line == first line getLineText line == rest line queueUpErrors(globalNumOfLine,msgList)== thisPosMsgs := [] notThisLineMsgs := [] for msg in msgList _ while thisPosIsLess(getMsgPos msg,globalNumOfLine) repeat --these are msgs that refer to positions from earlier compilations if not redundant (msg,notThisPosMsgs) then notThisPosMsgs := [msg,:notThisPosMsgs] msgList := rest msgList for msg in msgList _ while thisPosIsEqual(getMsgPos msg,globalNumOfLine) repeat if not redundant (msg,thisPosMsgs) then thisPosMsgs := [msg,:thisPosMsgs] msgList := rest msgList if thisPosMsgs then thisPosMsgs := processChPosesForOneLine thisPosMsgs $outputList := append!(thisPosMsgs,$outputList) if notThisPosMsgs then $outputList := append!(notThisPosMsgs,$outputList) msgList redundant(msg,thisPosMsgs) == found := nil if msgNoRep? msg then for item in $noRepList repeat sameMsg?(msg,item) => return (found := true) $noRepList := [msg,$noRepList] found or listMember?(msg,thisPosMsgs) sameMsg? (msg1,msg2) == (getMsgKey msg1 = getMsgKey msg2) and _ (getMsgArgL msg1 = getMsgArgL msg2) thisPosIsLess(pos,num) == poNopos? pos => nil poGlobalLinePosn pos < num thisPosIsEqual(pos,num) == poNopos? pos => nil poGlobalLinePosn pos = num --%outputting stuff listOutputter outputList == for msg in outputList repeat msgOutputter msg msgOutputter msg == st := getStFromMsg msg shouldFlow := not (leader? msg or line? msg) if toScreen? msg then if shouldFlow then st := flowSegmentedMsg(st,$LINELENGTH,0) sayBrightly st if toFile? msg then if shouldFlow then st := flowSegmentedMsg(st,$LOGLENGTH,0) alreadyOpened := alreadyOpened? msg toScreen? msg == getMsgToWhere msg ~= 'fileOnly toFile? msg == getMsgToWhere msg ~= 'screenOnly alreadyOpened? msg == not msgImPr? msg getStFromMsg msg == $optKeyBlanks : local := '"" --set in setOptKeyBlanks() setOptKeyBlanks() preStL := getPreStL getMsgPrefix? msg getMsgTag msg = 'line => [$optKeyBlanks, :preStL, getMsgText msg] posStL := getPosStL msg optKey := $showKeyNum => msgKey := getMsgKey? msg => PNAME msgKey '"no key " '"" st :=[posStL,getMsgLitSym msg,_ optKey,:preStL,_ tabbing msg,:getMsgText msg] tabbing msg == chPos := 2 if getMsgPrefix? msg then chPos := chPos + $preLength - 1 if $showKeyNum then chPos := chPos + 8 ["%t",:chPos] setOptKeyBlanks() == $optKeyBlanks := $showKeyNum => '"%x8" '"" getPosStL msg == not showMsgPos? msg => '"" msgPos := getMsgPos msg howMuch := msgImPr? msg => decideHowMuch (msgPos,$lastPos) listDecideHowMuch (msgPos,$lastPos) $lastPos := msgPos fullPrintedPos := ppos msgPos printedFileName := ['"%x2",'"[",:remLine fullPrintedPos,'"]" ] printedLineNum := ['"%x2",'"[",:remFile fullPrintedPos,'"]" ] printedOrigin := ['"%x2",'"[",:fullPrintedPos,'"]" ] howMuch = 'ORG => [$optKeyBlanks,:printedOrigin, '"%l"] howMuch = 'LINE => [$optKeyBlanks,:printedLineNum, '"%l"] howMuch = 'FILE => [$optKeyBlanks,:printedFileName, '"%l"] howMuch = 'ALL => [$optKeyBlanks,:printedFileName, '"%l",_ $optKeyBlanks,:printedLineNum, '"%l"] '"" showMsgPos? msg == not msgImPr? msg and not msgLeader? msg remFile positionList == IFCDR IFCDR positionList remLine positionList == [IFCAR positionList] decideHowMuch(pos,oldPos) == --when printing a msg, we wish not to show pos infor that was --shown for a previous msg with identical pos info. --org prints out the word noposition or console ((poNopos? pos) and (poNopos? oldPos)) or _ ((poPosImmediate? pos) and (poPosImmediate? oldPos)) => 'NONE (poNopos? pos) or (poPosImmediate? pos) => 'ORG (poNopos? oldPos) or (poPosImmediate? oldPos) => 'ALL poFileName oldPos ~= poFileName pos => 'ALL poLinePosn oldPos ~= poLinePosn pos => 'LINE 'NONE listDecideHowMuch(pos,oldPos) == ((poNopos? pos) and (poNopos? oldPos)) or _ ((poPosImmediate? pos) and (poPosImmediate? oldPos)) => 'NONE (poNopos? pos) => 'ORG (poNopos? oldPos) => 'NONE poGlobalLinePosn pos < poGlobalLinePosn oldPos => poPosImmediate? pos => 'ORG 'LINE --(poNopos? pos) or (poPosImmediate? pos) => 'ORG 'NONE getPreStL optPre == null optPre => [makeString 2] spses := (extraPlaces := ($preLength - (# optPre) - 3)) > 0 => makeString extraPlaces '"" ['"%b", optPre,spses,'":", '"%d"] ------------------- --% a-list stuff desiredMsg (erMsgKey,:optCatFlag) == isKeyQualityP(erMsgKey,'show) => true isKeyQualityP(erMsgKey,'stifle) => false not null optCatFlag => first optCatFlag true isKeyQualityP (key,qual) == --returns pair if found, else nil found := false while not found and (qualPair := assoc(key,$specificMsgTags)) repeat if rest qualPair = qual then found := true qualPair ----------------------------- --% these functions handle the attributes initImPr msg == symbolMember?(getMsgTag msg,$imPrTagGuys) => setMsgUnforcedAttr (msg,'$imPrGuys,'imPr) initToWhere msg == member ('trace,getMsgCatAttr (msg,'catless)) => setMsgUnforcedAttr (msg,'$toWhereGuys,'screenOnly) msgImPr? msg == (getMsgCatAttr (msg,'$imPrGuys) = 'imPr) msgNoRep? msg == (getMsgCatAttr (msg,'$repGuys) = 'noRep) msgLeader? msg == getMsgTag msg = 'leader getMsgToWhere msg == getMsgCatAttr (msg,'$toWhereGuys) getMsgCatAttr (msg,cat) == IFCDR objectAssoc(cat, ncAlist msg) setMsgForcedAttrList (msg,aL) == for attr in aL repeat setMsgForcedAttr(msg,whichCat attr,attr) setMsgUnforcedAttrList (msg,aL) == for attr in aL repeat setMsgUnforcedAttr(msg,whichCat attr,attr) setMsgForcedAttr(msg,cat,attr) == cat = 'catless => setMsgCatlessAttr(msg,attr) ncPutQ(msg,cat,attr) setMsgUnforcedAttr(msg,cat,attr) == cat = 'catless => setMsgCatlessAttr(msg,attr) objectAssoc(cat, ncAlist msg) = nil => ncPutQ(msg,cat,attr) setMsgCatlessAttr(msg,attr) == ncPutQ(msg,'catless,CONS (attr, IFCDR objectAssoc("catless", ncAlist msg))) whichCat attr == found := 'catless for cat in $attrCats repeat -- ??? a cat is a vector. if listMember?(attr,eval cat) then found := cat return found found -------------------------------------- --% these functions directly interact with the message object makeLeaderMsg chPosList == st := makeString($preLength- 3) oldPos := -1 for [posNum,:posLetter] in reverse chPosList repeat st := strconc(st, _ rep(char ".", (posNum - oldPos - 1)),posLetter) oldPos := posNum ['leader,$nopos,'nokey,nil,nil,[st]] makeMsgFromLine line == posOfLine := getLinePos line textOfLine := getLineText line globalNumOfLine := poGlobalLinePosn posOfLine localNumOfLine := i := poLinePosn posOfLine stNum := toString i strconc(rep(char " ", ($preLength - 7 - # stNum)),_ stNum) ['line,posOfLine,nil,nil, strconc('"Line", localNumOfLine),_ textOfLine] getMsgTag msg == ncTag msg getMsgTag? msg == IFCAR member (getMsgTag msg,_ ['line,'old,'error,'warn,'bug,'unimple,'remark,'stat,'say,'debug]) leader? msg == getMsgTag msg = 'leader line? msg == getMsgTag msg = 'line getMsgPosTagOb msg == msg.1 getMsgPos msg == getMsgFTTag? msg => second getMsgPosTagOb msg getMsgPosTagOb msg getMsgPos2 msg == getMsgFTTag? msg => third getMsgPosTagOb msg ncBug('"not a from to",[]) getMsgFTTag? msg == IFCAR member (IFCAR getMsgPosTagOb msg,_ ['FROM,'TO,'FROMTO]) getMsgKey msg == msg.2 getMsgKey? msg == ident? (val := getMsgKey msg) => val getMsgArgL msg == msg.3 getMsgPrefix? msg == (pre := msg.4) = 'noPre => nil pre getMsgPrefix msg == msg.4 getMsgLitSym msg == getMsgKey? msg => '" " '"*" getMsgText msg == msg.5 setMsgPrefix (msg,val) == msg.4 := val setMsgText (msg,val) == msg.5 := val