@@ -27,13 +27,27 @@ enum States {
27
27
IfBody
28
28
}
29
29
30
+ /// Types of parameters a capability can use
30
31
pub enum Param {
31
32
String ( ~str ) ,
32
33
Char ( char ) ,
33
34
Number ( int )
34
35
}
35
36
36
- pub fn expand ( cap : & [ u8 ] , params : & mut [ Param ] , sta : & mut [ Param ] , dyn : & mut [ Param ] ) -> ~[ u8 ] {
37
+ /**
38
+ Expand a parameterized capability
39
+
40
+ # Arguments
41
+ * `cap` - string to expand
42
+ * `params` - vector of params for %p1 etc
43
+ * `sta` - vector of params corresponding to static variables
44
+ * `dyn` - vector of params corresponding to stativ variables
45
+
46
+ To be compatible with ncurses, `sta` and `dyn` should be the same between calls to `expand` for
47
+ multiple capabilities for the same terminal.
48
+ */
49
+ pub fn expand ( cap : & [ u8 ] , params : & mut [ Param ] , sta : & mut [ Param ] , dyn : & mut [ Param ] )
50
+ -> Result < ~[ u8 ] , ~str > {
37
51
assert ! ( cap. len( ) != 0 , "expanding an empty capability makes no sense" ) ;
38
52
assert ! ( params. len( ) <= 9 , "only 9 parameters are supported by capability strings" ) ;
39
53
@@ -68,15 +82,15 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa
68
82
'%' => { output. push ( cap[ i] ) ; state = Nothing } ,
69
83
'c' => match stack. pop ( ) {
70
84
Char ( c) => output. push ( c as u8 ) ,
71
- _ => fail ! ( "a non-char was used with %c" )
85
+ _ => return Err ( ~ "a non-char was used with %c")
72
86
},
73
87
's' => match stack.pop() {
74
88
String(s) => output.push_all(s.to_bytes()),
75
- _ => fail ! ( "a non-str was used with %s" )
89
+ _ => return Err(~ " a non-str was used with %s")
76
90
} ,
77
91
'd' => match stack. pop ( ) {
78
92
Number ( x) => output. push_all ( x. to_str ( ) . to_bytes ( ) ) ,
79
- _ => fail ! ( "a non-number was used with %d" )
93
+ _ => return Err ( ~ "a non-number was used with %d")
80
94
} ,
81
95
'p' => state = PushParam ,
82
96
'P' => state = SetVar ,
@@ -85,52 +99,52 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa
85
99
'{' => state = IntConstant ,
86
100
'l' => match stack. pop ( ) {
87
101
String ( s) => stack. push ( Number ( s. len ( ) as int ) ) ,
88
- _ => fail ! ( "a non-str was used with %l" )
102
+ _ => return Err ( ~ "a non-str was used with %l")
89
103
} ,
90
104
'+' => match ( stack. pop ( ) , stack. pop ( ) ) {
91
105
( Number ( x) , Number ( y) ) => stack. push ( Number ( x + y) ) ,
92
- ( _, _) => fail ! ( "non-numbers on stack with +" )
106
+ ( _, _) => return Err ( ~ "non-numbers on stack with +")
93
107
},
94
108
'-' => match (stack.pop(), stack.pop()) {
95
109
(Number(x), Number(y)) => stack.push(Number(x - y)),
96
- ( _, _) => fail ! ( "non-numbers on stack with -" )
110
+ (_, _) => return Err(~ " non-numbers on stack with -")
97
111
},
98
112
'*' => match (stack.pop(), stack.pop()) {
99
113
(Number(x), Number(y)) => stack.push(Number(x * y)),
100
- ( _, _) => fail ! ( "non-numbers on stack with *" )
114
+ (_, _) => return Err(~ " non-numbers on stack with * ")
101
115
},
102
116
'/' => match (stack.pop(), stack.pop()) {
103
117
(Number(x), Number(y)) => stack.push(Number(x / y)),
104
- ( _, _) => fail ! ( "non-numbers on stack with /" )
118
+ (_, _) => return Err(~ " non-numbers on stack with /")
105
119
},
106
120
'm' => match (stack.pop(), stack.pop()) {
107
121
(Number(x), Number(y)) => stack.push(Number(x % y)),
108
- ( _, _) => fail ! ( "non-numbers on stack with %" )
122
+ (_, _) => return Err(~ " non-numbers on stack with %")
109
123
},
110
124
'&' => match (stack.pop(), stack.pop()) {
111
125
(Number(x), Number(y)) => stack.push(Number(x & y)),
112
- ( _, _) => fail ! ( "non-numbers on stack with &" )
126
+ (_, _) => return Err(~ " non-numbers on stack with & ")
113
127
},
114
128
'|' => match (stack.pop(), stack.pop()) {
115
129
(Number(x), Number(y)) => stack.push(Number(x | y)),
116
- ( _, _) => fail ! ( "non-numbers on stack with |" )
130
+ (_, _) => return Err(~ " non-numbers on stack with |")
117
131
},
118
- 'A' => fail ! ( "logical operations unimplemented" ) ,
119
- 'O' => fail ! ( "logical operations unimplemented" ) ,
120
- '!' => fail ! ( "logical operations unimplemented" ) ,
132
+ 'A' => return Err(~ " logical operations unimplemented") ,
133
+ 'O' => return Err ( ~ "logical operations unimplemented") ,
134
+ '!' => return Err ( ~ "logical operations unimplemented") ,
121
135
'~' => match stack. pop ( ) {
122
136
Number ( x) => stack. push ( Number ( !x) ) ,
123
- _ => fail ! ( "non-number on stack with %~" )
137
+ _ => return Err ( ~ "non-number on stack with %~")
124
138
} ,
125
139
'i' => match ( copy params[ 0 ] , copy params[ 1 ] ) {
126
140
( Number ( x) , Number ( y) ) => {
127
141
params[ 0 ] = Number ( x + 1 ) ;
128
142
params[ 1 ] = Number ( y + 1 ) ;
129
143
} ,
130
- ( _, _) => fail ! ( "first two params not numbers with %i" )
144
+ ( _, _) => return Err ( ~ "first two params not numbers with %i")
131
145
} ,
132
- '?' => state = fail ! ( "if expressions unimplemented" ) ,
133
- _ => fail ! ( "unrecognized format option %c" , cur)
146
+ '?' => state = return Err ( fmt ! ( "if expressions unimplemented (%?)" , cap ) ) ,
147
+ _ => return Err ( fmt ! ( "unrecognized format option %c" , cur) )
134
148
}
135
149
} ,
136
150
PushParam => {
@@ -145,7 +159,7 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa
145
159
let idx = ( cur as u8 ) - ( 'a' as u8 ) ;
146
160
dyn[ idx] = stack. pop ( ) ;
147
161
} else {
148
- fail ! ( "bad variable name in %P" ) ;
162
+ return Err ( ~ "bad variable name in %P ") ;
149
163
}
150
164
} ,
151
165
GetVar => {
@@ -156,7 +170,7 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa
156
170
let idx = ( cur as u8 ) - ( 'a' as u8 ) ;
157
171
stack. push ( copy dyn[ idx] ) ;
158
172
} else {
159
- fail ! ( "bad variable name in %g" ) ;
173
+ return Err ( ~ "bad variable name in %g") ;
160
174
}
161
175
} ,
162
176
CharConstant => {
@@ -174,14 +188,14 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa
174
188
intstate. push ( cur as u8 ) ;
175
189
old_state = Nothing ;
176
190
}
177
- _ => fail ! ( "unimplemented state" )
191
+ _ => return Err ( ~ "unimplemented state")
178
192
}
179
193
if state == old_state {
180
194
state = Nothing ;
181
195
}
182
196
i += 1 ;
183
197
}
184
- output
198
+ Ok ( output)
185
199
}
186
200
187
201
#[ cfg( test) ]
0 commit comments