Custom mask

@Sayantan2048 now it's me asking you for review! I consider you the boss of mask mode, at least for now. And I don't want to commit stuff if it disturbs your work or clashes with some plans of yours.

This commit moves the placeholder-to-range logic into a separate function. It also adds some separate expansion phases for the custom masks ?1..?4 so they can in turn contain static placeholders (but you can't include ?1 within ?2 and so on).

A debug print is left in there for now and a couple others are there but commented. Some examples:
```
# output two-digit hex codes prefixed with 0x
../run/john -4=[?da-f] -mask=0x?4?4 -stdout

# output five-letter words, first letter capitalized or not, last character is a special or digit
../run/john -1=?u?l -2=?d?s -mask=?1?l?l?l?2 -stdout

# output words of length 8, using Hashcat's default mask
../run/john -mask=?1?2?2?2?2?2?2?3 -stdout

# test case, watch escaped characters
../run/john -stdout -enc:ascii -1=a-z -2=[A-Z] -3=?u?l -4=[?d?s] -mask=?1?2?3?4
```
The brackets in `-4=[?da-f]` are optional, they will be filled-in unless already there.