This file is indexed.

/usr/lib/hugs/packages/hugsbase/Hugs/GenericPrint.hs is in hugs 98.200609.21-5.3ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
----------------------------------------------------------------
-- A "generic" (or "polymorphic") print function in Haskell
-- This is very heavily based on the code in printer.c
-- (Together with the decompiler and error catching primitives,
-- this might make a good base on which to build a debugger?)
--
-- NB This library is an _experimental_ feature which may be
--    removed in future versions of Hugs.
--    It can only be used if Hugs was configured with the
--    "--enable-internal--prims" flag.
----------------------------------------------------------------

module Hugs.GenericPrint(
        printError, 
        outputString, 
        print
        ) where

import Prelude hiding (print)

import Hugs.Internals(
        Name, nameInfo, nameString,
        Cell, getCell,
        CellKind(..), classifyCell,
        )

import Hugs.IOExts( unsafePerformIO )
import Hugs.Array
import Data.Char( showLitChar, isAlpha )
import Data.List( intersperse )

----------------------------------------------------------------
-- The top-level print routine 
----------------------------------------------------------------

printError   :: Cell -> IO ()
outputString :: String -> IO ()
print        :: a -> IO ()

printError err = do
  putStr "\nProgram error: " 
  printDBadRedex err 
  putStr "\n"

outputString s = outputStr (getCell s)

print x        = print' True (getCell x)

----------------------------------------------------------------

printBadRedex err = do
  putChar '{' 
  print' False err 
  putChar '}'

printDBadRedex err = do
  kind <- classifyCell False err
  case kind of
    Apply fun args -> do
      funkind <- classifyCell False fun
      case (funkind, args) of
        (Fun nm, [msg]) | nm == nameError ->
          outputStr msg
        _ -> printBadRedex err
    _ -> printBadRedex err

outputStr :: Cell -> IO ()
outputStr xs = do
  kind <- hugsClassifyCell True xs
  case kind of
    Apply fun args ->
      hugsClassifyCell True fun >>= \ funkind ->
      case (funkind, args) of
      (Con nm, [y,ys]) | nm == nameCons ->
        hugsClassifyCell True y >>= \ ykind ->
        case ykind of
        Char c ->
          putChar c >>
          outputStr ys
        Error err ->
          printBadRedex err >>
          outputStr ys
        _ ->
          printBadRedex y >>
          outputStr ys
      (Error err, _) ->
        printBadRedex err
      _ ->
        printBadRedex xs
    Con nm | nm == nameNil ->
        return ()
    Error err ->
        printBadRedex err
    _ ->
        printBadRedex xs

print' :: Bool -> Cell -> IO ()
print' strict x = printCell strict min_prec x

--ToDo: combine with sprint (if possible)
lprint :: Bool -> Cell -> Cell -> IO ()
lprint strict x xs =
  printCell strict min_prec x >>
  hugsClassifyCell strict xs >>= \ kind ->
  case kind of
  Apply fun args ->
      hugsClassifyCell strict fun >>= \ funkind ->
        case (funkind, args) of
        (Con nm, [y,ys]) | nm == nameCons ->
          putStr ", " >>
          lprint strict y ys
        (Error err, _) ->
          printBadRedex err
        _ ->
          putStr "] ++ " >>
          printBadRedex xs
  Con nm | nm == nameNil ->
          putChar ']'
  Error err ->
          printBadRedex err
  _ ->
          putStr "] ++ " >>
          printBadRedex xs

sprint :: Bool -> Char -> Cell -> IO ()
sprint strict c xs =
  putStr (showLitChar c "") >>
  hugsClassifyCell strict xs >>= \ kind ->
  case kind of
  Apply fun args ->
      hugsClassifyCell strict fun >>= \ funkind ->
        case (funkind, args) of
        (Con nm, [y,ys]) | nm == nameCons ->
          hugsClassifyCell strict y >>= \ ykind ->
          case ykind of
          Char c -> sprint strict c ys
          _      -> lprint False y ys
        _ ->
          putStr "\" ++ " >>
          printBadRedex xs
  Con nm | nm == nameNil ->
          putChar '"'
  _ ->
          putStr "\" ++ " >>
          printBadRedex xs

printCell :: Bool -> Int -> Cell -> IO ()
printCell strict d x =
  hugsClassifyCell strict x >>= \ kind ->
  case kind of
  Apply fun args ->
      hugsClassifyCell strict fun >>= \ funkind ->
      case funkind of
      Con nm ->
        case args of
          [x,xs] | nm == nameCons
            -> hugsClassifyCell strict x >>= \ xkind ->
               case xkind of
               Char c -> putChar '"' >> sprint strict c xs
               _      -> putChar '[' >> lprint strict x xs

          [x] | assoc /= 'A'
            -> printParen True (
                 printCell strict (fun_prec-1) x >>
                 putChar ' ' >>
                 putStr (asOp nameStr)
               )

          (x1:x2:xs) | assoc /= 'A'
            -> printParen (not (null xs) && d >= fun_prec) (
                 printParen (d <= p) (do
                   printCell strict lp x1
                   putChar ' '           
                   putStr (asOp nameStr) 
                   putChar ' '           
                   printCell strict rp x2
                   ) >>
                 mapM_ (\ arg ->
                   putChar ' ' >>
                   printCell strict p arg
                 ) xs
                 )

          xs
            -> printParen (not (null xs) && d >= fun_prec) (
                 -- test that xs is nonNull should be redundant but
                 -- no harm being robust
                 putStr (asVar nameStr)       >>
                 mapM_ (\arg ->
                   putChar ' ' >>
                   printCell strict fun_prec arg
                 ) xs
                 )
         where
          (arity, p, assoc) = nameInfo nm
          nameStr = nameString nm

          -- from Appendix E2 of Haskell 1.2 report
          lp = if assoc == 'L' then p else p+1
          rp = if assoc == 'R' then p else p+1
        
      Fun nm ->
        printParen (d >= fun_prec) (
          putStr (asVar nameStr)       >>
          mapM_ (\arg ->
            putChar ' ' >>
            -- switch to lazy printing!
            printCell False fun_prec arg
          ) args
          )
       where
        nameStr = nameString nm
      
      Tuple arity ->
        printParen (not (null extra) && d >= fun_prec) (
          printParen True (
            for__ fields (\ field ->
              printCell strict min_prec field
            ) (putChar ',') >>
            -- Haskell's syntax makes it impossible to construct an
            -- incomplete tuple - but let's play safe!
            mapM_ (\_ ->
              putChar ','
            ) [numArgs+1..arity]
          ) >>
          -- Haskell's type system makes extra arguments impossible
          -- - but let's play safe!
          mapM_ (\ arg ->
            putChar ' ' >>
            printCell strict fun_prec arg
          ) extra
        )
       where
        (fields, extra) = splitAt arity args

      Error err ->
          printBadRedex err

      _
        -> printParen (not (null args) && d >= fun_prec) (
             printCell strict fun_prec fun   >>
             mapM_ (\arg ->
               putChar ' ' >>
               printCell strict fun_prec arg
             ) args
             )
     where
        numArgs = length args

  Fun nm ->
    putStr (asVar (nameString nm))

  Con nm ->
    putStr (asVar (nameString nm))

  Tuple arity ->
    putStr ('(' : replicate arity ',' ++ ")")

  Int x ->
    putStr (show x)

  Integer x ->
    putStr (show x)

  Float x ->
    putStr (show x)

  Char x ->
    putStr ('\'' : showLitChar x "\'")

  Prim prim ->
    putStr prim

  Error err ->
    printBadRedex err

----------------------------------------------------------------
-- Cell/Name utilities
----------------------------------------------------------------

nameCons    =  cellName (:)
nameNil     =  cellName []
nameError   =  cellName error

-- Here's something VERY subtle.
-- We use classifyCell instead of hugsClassifyCell because
-- otherwise, this gets put in the same dependency class as everything
-- else and the lack of polymorphic recursion bites us.
-- (Using classifyCell is equally good here because it wont fail.)
cellName :: a -> Name
cellName x = unsafePerformIO (
  classifyCell True (getCell x) >>= \ kind ->
  case kind of
  Fun nm -> return nm
  Con nm -> return nm
  )

-- This implements the error-handling policy:
hugsClassifyCell :: Bool -> Cell -> IO CellKind
hugsClassifyCell strict obj =
  classifyCell strict obj >>= \ kind ->
  case kind of
  Error err ->
    if failOnError then
      exitWith (printError err)
    else
      return kind
  _ ->
    return kind

----------------------------------------------------------------
-- Utilities
----------------------------------------------------------------

for__ :: Monad m => [a] -> (a -> m ()) -> m () -> m ()
for__ xs f inc = sequence_ $ intersperse inc $ map f xs

min_prec, max_prec, fun_prec :: Int
min_prec = 0
max_prec = 9
fun_prec = max_prec+2

asOp str
 | isOp str  = str
 | otherwise = '`' : str ++ "`"

asVar str
 | isOp str  = '(' : str ++ ")"
 | otherwise = str

isOp (c:_) = not (isAlpha c || c == '[')
isOp _     = False

printParen :: Bool -> IO () -> IO ()
printParen True m  = putChar '(' >> m >> putChar ')'
printParen False m = m

----------------------------------------------------------------
-- Missing primitives
----------------------------------------------------------------

-- In Hugs0, this accessed the value of the :set -f" flag
failOnError :: Bool
failOnError = True

-- In Hugs0, this executed the action and terminated the current evaluation
exitWith :: IO () -> IO a
exitWith m = m >> error "{exitWith}"

----------------------------------------------------------------