aboutsummaryrefslogtreecommitdiff
path: root/src/interp/msg.boot
blob: 8670f5ae9fb62f4ee19a35eb667985f4901b480a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
-- 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