To me, extension pattern match is simple and more flexible.
[code][general]
NANP = NXXNXXXXXX; "10-digit phone number starting with area code"
NA_LOCAL = NXXXXXX; a North American local #
MY_AREA = 555; local area code
[macro-valid-nanp]
; NANP validation
; USAGE: Macro(valid-nanp,[number],[prompt])
; can be called with or without ${ARG2}
; “Please enter the number you wish to call, then pound.“
exten => s,1,Set(PROMPT=vm-enter-num-to-call&vm-then-pound)
exten => s,n,GotoIf(${ARG2}?:match)
exten => s,n,Set(PROMPT=${ARG2})
; can be called with or without ${ARG1}; use ${MACRO_EXTEN} without
exten => s,n(match),GotoIf(${ARG1}?${ARG1},1:${MACRO_EXTEN},1)
exten => _${NA_LOCAL},1,Goto(1${MY_AREA}${EXTEN},1)
exten => _${NANP},1,Goto(1${EXTEN},1)
exten => _1${NANP},1,Goto(${MACRO_CONTEXT},${EXTEN},$[${MACRO_PRIORITY} + 1])
; handle invalid #
; workaround for not having =~ in 1.2
exten => _Z.,1,Set(NUMBER=$[”${EXTEN}” : “([0-9]+)”])
; exten => _Z.,n,NoOp(${Trail})
exten => _Z.,n,GotoIf(${NUMBER}=${EXTEN}?:${NUMBER},1)
exten => _Z.,n,Set(NUMBER=); reset
exten => _Z.,n,SayDigits(${EXTEN})
; use Background() and matching to allow input either as extension
; or in Read()
; loop back
exten => _Z.,n(input),Playback(privacy-incorrect)
exten => _Z.,n,Read(NUMBER,${PROMPT},15,10)
; calling context needs to handle nil input
exten => _Z.,n,GotoIf(${NUMBER}?${NUMBER},1:${MACRO_CONTEXT},#,1);
[/code]
An example to use this would be like:
exten => s,1,Read(NUMBER,,15,,,10)
exten => s,n,Goto(${NUMBER},1)
exten => _X.,1,Macro(valid-${ARG3},,${PROMPT})
exten => _X.,n,Dial(Zap/${EXTEN})
Although the macro looks long, the basic idea is captured in 3 lines
exten => _${NA_LOCAL},1,Goto(1${MY_AREA}${EXTEN},1)
exten => _${NANP},1,Goto(1${EXTEN},1)
exten => _1${NANP},1,Goto(${MACRO_CONTEXT},${EXTEN},$[${MACRO_PRIORITY} + 1])
Much of the macro code is used to deal with invalid input and 1.2 expression queerness.