summaryrefslogtreecommitdiff
path: root/tests/general/endetab.icn
blob: b84ef085a81ff180610644c807b7caf7cfd40d95 (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
# test type conversion and error handling in entab/detab

procedure main ()
   s := "rutabaga"
   if entab('1987') ~== "1789" then write ("oops 1")
   if detab('1492') ~== "1249" then write ("oops 2")
   if entab("    ","3") ~== "\t\t" then write ("oops 3")
   if detab("\t\t","3") ~== "    " then write ("oops 4")
   ferr (103, entab, [])
   ferr (103, detab, [])
   ferr (103, entab, [[]])
   ferr (103, detab, [[]])
   ferr (101, entab, [s,2,3,&lcase])
   ferr (101, detab, [s,4,5,&ucase])
   ferr (210, entab, [s,7,4])
   ferr (210, entab, [s,6,6])
   ferr (210, detab, [s,8,5])
   ferr (210, detab, [s,3,3])

   endetab1()

   end


# ferr(err,func,arglst) -- call func(args), verify that error "err" is produced

procedure ferr (err, func, args)
   local val

   val := ""
   every val ||:= image(!args) || ","
   val := val[1:-1]
   msg := "oops -- " || image(func) || "(" || val || ") "
   &error := 1
   if func!args
      then write (msg, "succeeded")
   else if &error ~= 0
      then write (msg, "failed but no error")
   else if &errornumber ~= err
      then write (msg, "got error ",&errornumber," instead of ",err)
   &error := 0
   return
   end

## Test driver for entab and detab
#
#  Input is read from standard input.  Commentary and error reports go to
#  standard output.
#
#  Input lines are first preprocessed by interpreting escape sequences \a, \b,
#  \n, \r, and \t and trimming a trailing '$' character.
#  
#  Input lines beginning with "=" establish tab stop settings.  Each numeric
#  field specifies a tab stop, according to the entab/detab specs.
#  
#  All other lines are passed through entab and then detab, and the results are
#  checked.  The characters "!" and "." are replaced by spaces before calling
#  entab; "!" positions are expected to be replaced by tabs, with "." positions
#  disappearing.  For example, "abcd!...ijk" tests that entab("abcd    ijk")
#  returns "abcd\tijk".
#  
#  The result of each entab call is then passed to detab, with results expected
#  to match the original entab argument (or its detab, if it had any tabs).

procedure endetab1 ()
   params := setup ("=")		# start with default tabs (no args)
   while line := escape (read ()) do {	# read and preprocess line
      if line[1] == "=" then
         params := setup (line)		# '=' line sets tab stops (arg list)
      else {
         s := map (line, "!.", "  ")	# turn "!." characters into spaces
         params[1] := s
         t := invoke (entab, params)	# run entab
         if t ~== interp (line) then {	# check results
            write ("entab failed for: ", map(line,"\t\r\n\b\007","!RNBA"))
            write ("  returned value: ", map(t,   "\t\r\n\b\007","!RNBA"))
         } else {
            if upto ('\t', s) then	# detab input if it had a tab
               s := invoke (detab, params)
            params[1] := t
            t := invoke (detab, params)	# detab the result of the entab
            if t ~== s then {		# compare results
               write ("detab failed for: ", map(line,"\t\r\n\b\007","!RNBA"))
               write ("  returned value: ", map(t,   "\t\r\n\b\007","!RNBA"))
               }
            }
         }
   }
   end

procedure escape (line)		# interpret escape sequences and trim one '$'
   if line[-1] == "$" then
      line := line[1:-1]
   s := ""
   line ? 
      while not pos (0) do {
         s ||:= tab (upto ('\\') | 0)
         s ||:= (="\\" & case (c := move(1)) of {
	    "a": "\007"
            "b": "\b"
            "n": "\n"
            "r": "\r"
            "t": "\t"
            default: "\\" || c
         })
      }
   return s
   end

procedure interp (pattern)	# interpret metacharacters '!.'
   s := ""
   pattern ? 
      while not pos (0) do {
         tab (many ('.'))
         s ||:= tab (upto ('.') | 0)
      }
   return map (s, "!", "\t")
   end

procedure setup (line)		# interpret and report a column spec line
   p := [&null]
   line ? while tab (upto (&digits)) do
      put (p, integer (tab (many (&digits))))
   writes ("testing entab/detab(s")
   every writes (",", \!p)
   write (")")
   return p
   end

procedure invoke (func, a)	# invoke a function with a list of up to 10 args
   return case *a of {
      0:  func ()
      1:  func (a[1])
      2:  func (a[1], a[2])
      3:  func (a[1], a[2], a[3])
      4:  func (a[1], a[2], a[3], a[4])
      5:  func (a[1], a[2], a[3], a[4], a[5])
      6:  func (a[1], a[2], a[3], a[4], a[5], a[6])
      7:  func (a[1], a[2], a[3], a[4], a[5], a[6], a[7])
      8:  func (a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8])
      9:  func (a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9])
      10: func (a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10])
      default: stop ("too many args for invoke")
   }
   end