@@ -194,6 +194,24 @@ func Format(cfg *Config, format string, args []string) (string, int, error) {
194194 initialArgs := len (args )
195195
196196 for i := 0 ; i < len (format ); i ++ {
197+ // readDigits reads from 0 to max digits, either octal or
198+ // hexadecimal.
199+ readDigits := func (max int , hex bool ) string {
200+ j := 0
201+ for ; j < max ; j ++ {
202+ c := format [i + j ]
203+ if (c >= '0' && c <= '9' ) ||
204+ (hex && c >= 'a' && c <= 'f' ) ||
205+ (hex && c >= 'A' && c <= 'F' ) {
206+ // valid octal or hex char
207+ } else {
208+ break
209+ }
210+ }
211+ digits := format [i : i + j ]
212+ i += j - 1 // -1 since the outer loop does i++
213+ return digits
214+ }
197215 c := format [i ]
198216 switch {
199217 case c == '\\' : // escaped
@@ -217,6 +235,32 @@ func Format(cfg *Config, format string, args []string) (string, int, error) {
217235 buf .WriteByte ('\v' )
218236 case '\\' , '\'' , '"' , '?' : // just the character
219237 buf .WriteByte (c )
238+ case '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' :
239+ digits := readDigits (3 , false )
240+ // if digits don't fit in 8 bits, 0xff via strconv
241+ n , _ := strconv .ParseUint (digits , 8 , 8 )
242+ buf .WriteByte (byte (n ))
243+ case 'x' , 'u' , 'U' :
244+ i ++
245+ max := 2
246+ if c == 'u' {
247+ max = 4
248+ } else if c == 'U' {
249+ max = 8
250+ }
251+ digits := readDigits (max , true )
252+ if len (digits ) > 0 {
253+ // can't error
254+ n , _ := strconv .ParseUint (digits , 16 , 32 )
255+ if c == 'x' {
256+ // always as a single byte
257+ buf .WriteByte (byte (n ))
258+ } else {
259+ buf .WriteRune (rune (n ))
260+ }
261+ break
262+ }
263+ fallthrough
220264 default : // no escape sequence
221265 buf .WriteByte ('\\' )
222266 buf .WriteByte (c )
0 commit comments