$SPELL#.REX

This is the   $SPELL#.REX   (REXX) program.

It is invoked (called) from other REXX programs to spell numbers with various options, including spelling the number as an ordinal number.


The help for the   $SPELL#.REX   REXX program is included here   ──►   $SPELL#.HEL.


The   $SPELL#.REX   REXX program makes use of   $ERR.REX   REXX program which is used to display error messages (via   $T.REX);   error messages are displayed in red if the terminal supports color.
The   $ERR.REX   REXX program is included here   ──►   $ERR.REX.


The   $SPELL#.REX   REXX program makes use of   $T.REX   REXX program which is used to display text messages.
The   $T.REX   REXX program is included here   ──►   $T.REX.

/*REXX program converts a numeric string into English words, with support for ordinals, */
/*─────────────── some national currency symbols, decimal fractions, and other options. */

trace off                                        /*suppress superfluous return codes.   */

parse arg !                                      /*save the original arguments in ! var.*/

if !all( arg() )  then exit                      /*exit pgm if user wanted documentation*/
if !cms           then address ''

signal on halt                                   /*establish a method to handle  HALTs. */
signal on noValue                                /*handle uninitialized REXX variables. */
signal on syntax                                 /*   "   REXX syntax errors in this pgm*/
                                                 /* [↓]  set some REXX variables & such.*/
@abc     = 'abcdefghijklmnopqrstuvwxyz'
@abcU    = @abc
                   upper @abcU
american = 0                                     /*express numbers in American notation.*/
english  = 0                                     /*   "       "     " English      "    */
asayear  = 0                                     /*   "       "    as a year.           */
ordinal  = 0                                     /*   "       "    as an ordinal.      */
leadingz =                                       /*   "    leading zeros in numbers.    */

asis     = 0
blanks   =
british  = 0
clear    = 0
colors   = !cms  |  !pcrexx  |  !r4  |  !roo     /*this terminal supports colors.       */
dot      =
exponents=
fractions=
leading  =
logs     = 0
n        =
ops      = space(!!)
quiet    = 0
sep      = 'none'                                /*a decimal number period separator.   */
single   = 0
tfid     =                                       /*a temporary file id  (if needed).    */
tops     =                                       /*options used for the   $T  REXX pgm. */
xcurr    =

andcent  = 'and'                                 /*English phrase for:  "and xxx cents" */

minus    = 'minus '                              /*   "    word for a  minus sign.      */
nothing  = 'zero'                                /*   "      "   "  "  zero digit.      */
plus     = 'plus '                               /*   "      "   "  "  plus sign.       */
point    = 'point'                               /*   "      "   "  "  decimal point.   */
zero     = 'oh'                                  /*   "      "   "  "  zero.            */

power    = 'power'                               /*phrase when #'s are raised to a power*/
raised   = 'times ten raised to the'             /*   "     "   "   "     "    " "   "  */

cent     = 'cent'                                /*English word for a  ¢ currency symbol*/
dollar   = 'dollar'                              /*   "      "   "  "  $     "       "  */
euro     = 'euro'                                /*   "      "   "  "  ε     "       "  */
franc    = 'franc'                               /*   "      "   "  "  ƒ     "       "  */
piseta   = 'piseta'                              /*   "      "   "  "  ₧     "       "  */
pound    = 'pound'                               /*   "      "   "  "  £     "       "  */
yen      = 'yen'                                 /*   "      "   "  "  ¥     "       "  */

  do  while  ops\==''                            /*process user arguments and options.  */
  parse var  ops     _1  2  1  _  .  1  _o  ops  /*pull assunder some parts of an option*/
  upper _                                        /*uppercase the   _    variable.       */

    select
    when isnum(_)                  then n= n || _ /*if numeric,  then append this digit.*/
    when _==',' | _=="(" | _==')'  then nop       /*ignore any commas  and  parentheses.*/
    when _1==.  &  pos("=",_)\==0  then tops= tops _o
    when abbn('AMERican')          then american= no()
    when abbn('ASAYEAR')       |,
         abbn('ASYEAR')        |,
         abbn('YEAR')              then asayear=  no()
    when  abb('BEINGRAISed')   |,
          abb('RAISEd')            then raised=   na()
    when  abb('BLANKs')            then blanks=   na()
    when abbn('BRITish')           then british=  no()
    when  abb('CENTs')             then cent=     na()
    when abbn('CLearscreen')       then clear=    no()
    when abbn('COLORs')            then colors=   no()
    when  abb('DECIMALpoints') |,
          abb('DOLLARs')           then dollar=   na()
    when abbn('ENGlish')           then english=  no()
    when  abb('EUROs')             then euro=     na()
    when  abb('FRANCs')            then franc=    na()
    when  abb('LEADINGzeroes') |,
          abb('LEADINGzeros')      then leading=  na()
    when abbn('LOGs')              then logs=     no()
    when  abb('MINUSsigns')    |,
          abb('MINUSes')           then minus=    na()" "
    when  abb('NOTHINGs')          then nothing=  na()
    when abbn('ORDinal')           then ordinal=  no()
    when  abb('PISETAs')           then piseta=   na()
    when  abb('POWer')             then power=    na()
    when  abb('PLUSsigns')     |,
          abb('PLUSes')            then plus=     na()" "
    when  abb('POINTs')            then point=    na()
    when  abb('POUNDs')            then pound=    na()
    when abbn('Quiet')             then quiet=    no()
    when  abb('SEPerators')        then sep=      na()
    when abbn('SINGley')           then single=   no()
    when  abb('YENs')              then yen=      na()
    when  abb('ZEROs')         |,
          abb('ZEROes')            then zero=     na()
    otherwise                           n= n  ||  _o
    end   /*select*/

  end     /*while  ops···*/

if sep=='none'  then if pos(",", n)\==0  then sep= ','
if sep=='none'  then sep=
ogn= n                                          /*the original number that was entered. */
_= blanks                                       /*validate the    BLANKS=   option.     */


L= length(_)

if L >3  then call er 55,_

if L==3  then do                                /*it's a decimal value for  BLANKS.     */
              if \isint(_)    then call er 92, _ "BLANK="
              if _<0 | _>255  then call er 81, 0 255 _ "BLANKS="
              blanks= d2c(_)
              end

if L==2  then do                                /*it's a hexadecimal value for  BLANKS. */
              if \ishex(_)    then call er 40,_
              blanks= x2c(_)
              end


if colors  then tops= '.P=1 .A=1 .C=green'  tops    /*colors  used by the  $T  program. */
if logs    then tops= '.F='gettfid(,"ANS")  tops    /*logfile   "   "  "   $T     "     */
tops=space(tops)                                    /*options   "   "  "   $T     "     */

if n==''  then call er 54                           /*oops─ay,  no arguments entered.   */

if asayear   & ordinal              then call er 61, 'ASAYEAR ORDINAL'
if single    & ordinal              then call er 61, 'SINGLEY ORDINAL'
if american  & english              then call er 61, 'AMERICAN ENGLISH'
if american  & british              then call er 61, 'AMERICAN BRITISH'
if \american & \english & \british  then american= 1
if english                          then british = 1

if clear  then !cls                                 /*the terminal screen to be cleared?*/

dig.  =
dig.0 =  zero
dig.1 = 'one'
dig.2 = 'two'
dig.3 = 'three'
dig.4 = 'four'
dig.5 = 'five'
dig.6 = 'six'
dig.7 = 'seven'
dig.8 = 'eight'
dig.9 = 'nine'


_='0 thousand m b tr quadr quint sext sept oct non dec undec duodec tredec quattuordec quinquadec sedec septendec octodec novendec vigin unvigin duovigin tresvigin quattuorvigin quinquavigin sesvigin septemvigin octovigin novemvigin trigin'
_=_ 'untrigin duotrigin trestrigin quattuortrigin quinquatrigin sestrigin septentrigin octotrigin noventrigin quadragin unquadragin duoquadragin tresquadragin quattuorquadragin quinquaquadragin sesquadragin septenquadragin octoquadragin'
_=_ 'novenquadragin quinquagin unquinquagin duoquinquagin tresquinquagin quattuorquinquagin quinquaquinquagin sesquinquagin septenquinquagin octoquinquagin novenquinquagin sexagin unsexagin duosexagin tresexagin quattuorsexagin quinquasexagin'
_=_ 'sesexagin septensexagin octosexagin novensexagin septuagin unseptuagin duoseptuagin treseptuagin quattuorseptuagin quinquaseptuagin seseptuagin septenseptuagin octoseptuagin novenseptuagin octogin unoctogin duooctogin tresoctogin'
_=_ 'quattuoroctogin quinquaoctogin sexoctogin septemoctogin octooctogin novemoctogin nonagin unnonagin duononagin trenonagin quattuornonagin quinquanonagin senonagin septenonagin octononagin novenonagin cen uncen duocen trescen quattuorcen'
_=_ 'quinquacen sexcen septencen octocen novencen decicen undecicen duodecicen tredecicen quattuordecicen quinquadecicen sedecicen septendecicen octodecicen novendecicen viginticen unviginticen duoviginticen tresviginticen quattuorviginticen'
_=_ 'quinquaviginticen sesviginticen septemviginticen octoviginticen novemviginticen trigintacen untrigintacen duotrigintacen trestrigintacen quattuortrigintacen quinquatrigintacen sestrigintacen septentrigintacen octotrigintacen'
_=_ 'noventrigintacen quadragintacen unquadragintacen duoquadragintacen tresquadragintacen quattuorquadragintacen quinquaquadragintacen sesquadragintacen septenquadragintacen octoquadragintacen novenquadragintacen quinquagintacen'
_=_ 'unquinquagintacen duoquinquagintacen tresquinquagintacen quattuorquinquagintacen quinquaquinquagintacen sesquinquagintacen septenquinquagintacen octoquinquagintacen novenquinquagintacen sexagintacen unsexagintacen duosexagintacen'
_=_ 'tresexagintacen quattuorsexagintacen quinquasexagintacen sesexagintacen septensexagintacen octosexagintacen novensexagintacen septuagintacen unseptuagintacen duoseptuagintacen treseptuagintacen quattuorseptuagintacen quinquaseptuagintacen'
_=_ 'seseptuagintacen septenseptuagintacen octoseptuagintacen novenseptuagintacen octogintacen unoctogintacen duooctogintacen tresoctogintacen quattuoroctogintacen quinquaoctogintacen sexoctogintacen septemoctogintacen octooctogintacen'
_=_ 'novemoctogintacen nonagintacen unnonagintacen duononagintacen trenonagintacen quattuornonagintacen quinquanonagintacen senonagintacen septenonagintacen octononagintacen novenonagintacen ducen unducen duoducen treducen quattuorducen'
_=_ 'quinquaducen seducen septenducen octoducen novenducen deciducen undeciducen duodeciducen tredeciducen quattuordeciducen quinquadeciducen sedeciducen septendeciducen octodeciducen novendeciducen vigintiducen unvigintiducen duovigintiducen'
_=_ 'tresvigintiducen quattuorvigintiducen quinquavigintiducen sesvigintiducen septemvigintiducen octovigintiducen novemvigintiducen trigintaducen untrigintaducen duotrigintaducen trestrigintaducen quattuortrigintaducen quinquatrigintaducen'
_=_ 'sestrigintaducen septentrigintaducen octotrigintaducen noventrigintaducen quadragintaducen unquadragintaducen duoquadragintaducen tresquadragintaducen quattuorquadragintaducen quinquaquadragintaducen sesquadragintaducen'
_=_ 'septenquadragintaducen octoquadragintaducen novenquadragintaducen quinquagintaducen unquinquagintaducen duoquinquagintaducen tresquinquagintaducen quattuorquinquagintaducen quinquaquinquagintaducen sesquinquagintaducen'
_=_ 'septenquinquagintaducen octoquinquagintaducen novenquinquagintaducen sexagintaducen unsexagintaducen duosexagintaducen tresexagintaducen quattuorsexagintaducen quinquasexagintaducen sesexagintaducen septensexagintaducen octosexagintaducen'
_=_ 'novensexagintaducen septuagintaducen unseptuagintaducen duoseptuagintaducen treseptuagintaducen quattuorseptuagintaducen quinquaseptuagintaducen seseptuagintaducen septenseptuagintaducen octoseptuagintaducen novenseptuagintaducen'
_=_ 'octogintaducen unoctogintaducen duooctogintaducen tresoctogintaducen quattuoroctogintaducen quinquaoctogintaducen sexoctogintaducen septemoctogintaducen octooctogintaducen novemoctogintaducen nonagintaducen unnonagintaducen'
_=_ 'duononagintaducen trenonagintaducen quattuornonagintaducen quinquanonagintaducen senonagintaducen septenonagintaducen octononagintaducen novenonagintaducen trecen untrecen duotrecen trestrecen quattuortrecen quinquatrecen sestrecen'
_=_ 'septentrecen octotrecen noventrecen decitrecen undecitrecen duodecitrecen tredecitrecen quattuordecitrecen quinquadecitrecen sedecitrecen septendecitrecen octodecitrecen novendecitrecen vigintitrecen unvigintitrecen duovigintitrecen'
_=_ 'tresvigintitrecen quattuorvigintitrecen quinquavigintitrecen sesvigintitrecen septemvigintitrecen octovigintitrecen novemvigintitrecen trigintatrecen untrigintatrecen duotrigintatrecen trestrigintatrecen quattuortrigintatrecen'
_=_ 'quinquatrigintatrecen sestrigintatrecen septentrigintatrecen octotrigintatrecen noventrigintatrecen quadragintatrecen unquadragintatrecen duoquadragintatrecen tresquadragintatrecen quattuorquadragintatrecen quinquaquadragintatrecen'
_=_ 'sesquadragintatrecen septenquadragintatrecen octoquadragintatrecen novenquadragintatrecen quinquagintatrecen unquinquagintatrecen duoquinquagintatrecen tresquinquagintatrecen quattuorquinquagintatrecen quinquaquinquagintatrecen'
_=_ 'sesquinquagintatrecen septenquinquagintatrecen octoquinquagintatrecen novenquinquagintatrecen sexagintatrecen unsexagintatrecen duosexagintatrecen tresexagintatrecen quattuorsexagintatrecen quinquasexagintatrecen sesexagintatrecen'
_=_ 'septensexagintatrecen octosexagintatrecen novensexagintatrecen septuagintatrecen unseptuagintatrecen duoseptuagintatrecen treseptuagintatrecen quattuorseptuagintatrecen quinquaseptuagintatrecen seseptuagintatrecen septenseptuagintatrecen'
_=_ 'octoseptuagintatrecen novenseptuagintatrecen octogintatrecen unoctogintatrecen duooctogintatrecen tresoctogintatrecen quattuoroctogintatrecen quinquaoctogintatrecen sexoctogintatrecen septemoctogintatrecen octooctogintatrecen'
_=_ 'novemoctogintatrecen nonagintatrecen unnonagintatrecen duononagintatrecen trenonagintatrecen quattuornonagintatrecen quinquanonagintatrecen senonagintatrecen septenonagintatrecen octononagintatrecen novenonagintatrecen quadringen'
_=_ 'unquadringen duoquadringen tresquadringen quattuorquadringen quinquaquadringen sesquadringen septenquadringen octoquadringen novenquadringen deciquadringen undeciquadringen duodeciquadringen tredeciquadringen quattuordeciquadringen'
_=_ 'quinquadeciquadringen sedeciquadringen septendeciquadringen octodeciquadringen novendeciquadringen vigintiquadringen unvigintiquadringen duovigintiquadringen tresvigintiquadringen quattuorvigintiquadringen quinquavigintiquadringen'
_=_ 'sesvigintiquadringen septemvigintiquadringen octovigintiquadringen novemvigintiquadringen trigintaquadringen untrigintaquadringen duotrigintaquadringen trestrigintaquadringen quattuortrigintaquadringen quinquatrigintaquadringen'
_=_ 'sestrigintaquadringen septentrigintaquadringen octotrigintaquadringen noventrigintaquadringen quadragintaquadringen unquadragintaquadringen duoquadragintaquadringen tresquadragintaquadringen quattuorquadragintaquadringen'
_=_ 'quinquaquadragintaquadringen sesquadragintaquadringen septenquadragintaquadringen octoquadragintaquadringen novenquadragintaquadringen quinquagintaquadringen unquinquagintaquadringen duoquinquagintaquadringen tresquinquagintaquadringen'
_=_ 'quattuorquinquagintaquadringen quinquaquinquagintaquadringen sesquinquagintaquadringen septenquinquagintaquadringen octoquinquagintaquadringen novenquinquagintaquadringen sexagintaquadringen unsexagintaquadringen duosexagintaquadringen'
_=_ 'tresexagintaquadringen quattuorsexagintaquadringen quinquasexagintaquadringen sesexagintaquadringen septensexagintaquadringen octosexagintaquadringen novensexagintaquadringen septuagintaquadringen unseptuagintaquadringen'
_=_ 'duoseptuagintaquadringen treseptuagintaquadringen quattuorseptuagintaquadringen quinquaseptuagintaquadringen seseptuagintaquadringen septenseptuagintaquadringen octoseptuagintaquadringen novenseptuagintaquadringen octogintaquadringen'
_=_ 'unoctogintaquadringen duooctogintaquadringen tresoctogintaquadringen quattuoroctogintaquadringen quinquaoctogintaquadringen sexoctogintaquadringen septemoctogintaquadringen octooctogintaquadringen novemoctogintaquadringen'
_=_ 'nonagintaquadringen unnonagintaquadringen duononagintaquadringen trenonagintaquadringen quattuornonagintaquadringen quinquanonagintaquadringen senonagintaquadringen septenonagintaquadringen octononagintaquadringen novenonagintaquadringen'
_=_ 'quingen unquingen duoquingen tresquingen quattuorquingen quinquaquingen sesquingen septenquingen octoquingen novenquingen deciquingen undeciquingen duodeciquingen tredeciquingen quattuordeciquingen quinquadeciquingen sedeciquingen'
_=_ 'septendeciquingen octodeciquingen novendeciquingen vigintiquingen unvigintiquingen duovigintiquingen tresvigintiquingen quattuorvigintiquingen quinquavigintiquingen sesvigintiquingen septemvigintiquingen octovigintiquingen'
_=_ 'novemvigintiquingen trigintaquingen untrigintaquingen duotrigintaquingen trestrigintaquingen quattuortrigintaquingen quinquatrigintaquingen sestrigintaquingen septentrigintaquingen octotrigintaquingen noventrigintaquingen quadragintaquinge'
_=_ 'unquadragintaquingen duoquadragintaquingen tresquadragintaquingen quattuorquadragintaquingen quinquaquadragintaquingen sesquadragintaquingen septenquadragintaquingen octoquadragintaquingen novenquadragintaquingen quinquagintaquingen'
_=_ 'unquinquagintaquingen duoquinquagintaquingen tresquinquagintaquingen quattuorquinquagintaquingen quinquaquinquagintaquingen sesquinquagintaquingen septenquinquagintaquingen octoquinquagintaquingen novenquinquagintaquingen sexagintaquingen'
_=_ 'unsexagintaquingen duosexagintaquingen tresexagintaquingen quattuorsexagintaquingen quinquasexagintaquingen sesexagintaquingen septensexagintaquingen octosexagintaquingen novensexagintaquingen septuagintaquingen unseptuagintaquingen'
_=_ 'duoseptuagintaquingen treseptuagintaquingen quattuorseptuagintaquingen quinquaseptuagintaquingen seseptuagintaquingen septenseptuagintaquingen octoseptuagintaquingen novenseptuagintaquingen octogintaquingen unoctogintaquingen'
_=_ 'duooctogintaquingen tresoctogintaquingen quattuoroctogintaquingen quinquaoctogintaquingen sexoctogintaquingen septemoctogintaquingen octooctogintaquingen novemoctogintaquingen nonagintaquingen unnonagintaquingen duononagintaquingen'
_=_ 'trenonagintaquingen quattuornonagintaquingen quinquanonagintaquingen senonagintaquingen septenonagintaquingen octononagintaquingen novenonagintaquingen sescen unsescen duosescen tresescen quattuorsescen quinquasescen sesescen septensescen'
_=_ 'octosescen novensescen decisescen undecisescen duodecisescen tredecisescen quattuordecisescen quinquadecisescen sedecisescen septendecisescen octodecisescen novendecisescen vigintisescen unvigintisescen duovigintisescen tresvigintisescen'
_=_ 'quattuorvigintisescen quinquavigintisescen sesvigintisescen septemvigintisescen octovigintisescen novemvigintisescen trigintasescen untrigintasescen duotrigintasescen trestrigintasescen quattuortrigintasescen quinquatrigintasescen'
_=_ 'sestrigintasescen septentrigintasescen octotrigintasescen noventrigintasescen quadragintasescen unquadragintasescen duoquadragintasescen tresquadragintasescen quattuorquadragintasescen quinquaquadragintasescen sesquadragintasescen'
_=_ 'septenquadragintasescen octoquadragintasescen novenquadragintasescen quinquagintasescen unquinquagintasescen duoquinquagintasescen tresquinquagintasescen quattuorquinquagintasescen quinquaquinquagintasescen sesquinquagintasescen'
_=_ 'septenquinquagintasescen octoquinquagintasescen novenquinquagintasescen sexagintasescen unsexagintasescen duosexagintasescen tresexagintasescen quattuorsexagintasescen quinquasexagintasescen sesexagintasescen septensexagintasescen'
_=_ 'octosexagintasescen novensexagintasescen septuagintasescen unseptuagintasescen duoseptuagintasescen treseptuagintasescen quattuorseptuagintasescen quinquaseptuagintasescen seseptuagintasescen septenseptuagintasescen octoseptuagintasescen'
_=_ 'novenseptuagintasescen octogintasescen unoctogintasescen duooctogintasescen tresoctogintasescen quattuoroctogintasescen quinquaoctogintasescen sexoctogintasescen septemoctogintasescen octooctogintasescen novemoctogintasescen nonagintasesce'
_=_ 'unnonagintasescen duononagintasescen trenonagintasescen quattuornonagintasescen quinquanonagintasescen senonagintasescen septenonagintasescen octononagintasescen novenonagintasescen septingen unseptingen duoseptingen treseptingen'
_=_ 'quattuorseptingen quinquaseptingen seseptingen septenseptingen octoseptingen novenseptingen deciseptingen undeciseptingen duodeciseptingen tredeciseptingen quattuordeciseptingen quinquadeciseptingen sedeciseptingen septendeciseptingen'
_=_ 'octodeciseptingen novendeciseptingen vigintiseptingen unvigintiseptingen duovigintiseptingen tresvigintiseptingen quattuorvigintiseptingen quinquavigintiseptingen sesvigintiseptingen septemvigintiseptingen octovigintiseptingen'
_=_ 'novemvigintiseptingen trigintaseptingen untrigintaseptingen duotrigintaseptingen trestrigintaseptingen quattuortrigintaseptingen quinquatrigintaseptingen sestrigintaseptingen septentrigintaseptingen octotrigintaseptingen'
_=_ 'noventrigintaseptingen quadragintaseptingen unquadragintaseptingen duoquadragintaseptingen tresquadragintaseptingen quattuorquadragintaseptingen quinquaquadragintaseptingen sesquadragintaseptingen septenquadragintaseptingen'
_=_ 'octoquadragintaseptingen novenquadragintaseptingen quinquagintaseptingen unquinquagintaseptingen duoquinquagintaseptingen tresquinquagintaseptingen quattuorquinquagintaseptingen quinquaquinquagintaseptingen sesquinquagintaseptingen'
_=_ 'septenquinquagintaseptingen octoquinquagintaseptingen novenquinquagintaseptingen sexagintaseptingen unsexagintaseptingen duosexagintaseptingen tresexagintaseptingen quattuorsexagintaseptingen quinquasexagintaseptingen sesexagintaseptingen'
_=_ 'septensexagintaseptingen octosexagintaseptingen novensexagintaseptingen septuagintaseptingen unseptuagintaseptingen duoseptuagintaseptingen treseptuagintaseptingen quattuorseptuagintaseptingen quinquaseptuagintaseptingen'
_=_ 'seseptuagintaseptingen septenseptuagintaseptingen octoseptuagintaseptingen novenseptuagintaseptingen octogintaseptingen unoctogintaseptingen duooctogintaseptingen tresoctogintaseptingen quattuoroctogintaseptingen quinquaoctogintaseptingen'
_=_ 'sexoctogintaseptingen septemoctogintaseptingen octooctogintaseptingen novemoctogintaseptingen nonagintaseptingen unnonagintaseptingen duononagintaseptingen trenonagintaseptingen quattuornonagintaseptingen quinquanonagintaseptingen'
_=_ 'senonagintaseptingen septenonagintaseptingen octononagintaseptingen novenonagintaseptingen octingen unoctingen duooctingen tresoctingen quattuoroctingen quinquaoctingen sexoctingen septemoctingen octooctingen novemoctingen decioctingen'
_=_ 'undecioctingen duodecioctingen tredecioctingen quattuordecioctingen quinquadecioctingen sedecioctingen septendecioctingen octodecioctingen novendecioctingen vigintioctingen unvigintioctingen duovigintioctingen tresvigintioctingen'
_=_ 'quattuorvigintioctingen quinquavigintioctingen sesvigintioctingen septemvigintioctingen octovigintioctingen novemvigintioctingen trigintaoctingen untrigintaoctingen duotrigintaoctingen trestrigintaoctingen quattuortrigintaoctingen'
_=_ 'quinquatrigintaoctingen sestrigintaoctingen septentrigintaoctingen octotrigintaoctingen noventrigintaoctingen quadragintaoctingen unquadragintaoctingen duoquadragintaoctingen tresquadragintaoctingen quattuorquadragintaoctingen'
_=_ 'quinquaquadragintaoctingen sesquadragintaoctingen septenquadragintaoctingen octoquadragintaoctingen novenquadragintaoctingen quinquagintaoctingen unquinquagintaoctingen duoquinquagintaoctingen tresquinquagintaoctingen'
_=_ 'quattuorquinquagintaoctingen quinquaquinquagintaoctingen sesquinquagintaoctingen septenquinquagintaoctingen octoquinquagintaoctingen novenquinquagintaoctingen sexagintaoctingen unsexagintaoctingen duosexagintaoctingen tresexagintaoctingen'
_=_ 'quattuorsexagintaoctingen quinquasexagintaoctingen sesexagintaoctingen septensexagintaoctingen octosexagintaoctingen novensexagintaoctingen septuagintaoctingen unseptuagintaoctingen duoseptuagintaoctingen treseptuagintaoctingen'
_=_ 'quattuorseptuagintaoctingen quinquaseptuagintaoctingen seseptuagintaoctingen septenseptuagintaoctingen octoseptuagintaoctingen novenseptuagintaoctingen octogintaoctingen unoctogintaoctingen duooctogintaoctingen tresoctogintaoctingen'
_=_ 'quattuoroctogintaoctingen quinquaoctogintaoctingen sexoctogintaoctingen septemoctogintaoctingen octooctogintaoctingen novemoctogintaoctingen nonagintaoctingen unnonagintaoctingen duononagintaoctingen trenonagintaoctingen'
_=_ 'quattuornonagintaoctingen quinquanonagintaoctingen senonagintaoctingen septenonagintaoctingen octononagintaoctingen novenonagintaoctingen nongen unnongen duonongen trenongen quattuornongen quinquanongen senongen septenongen octonongen'
_=_ 'novenongen decinongen undecinongen duodecinongen tredecinongen quattuordecinongen quinquadecinongen sedecinongen septendecinongen octodecinongen novendecinongen vigintinongen unvigintinongen duovigintinongen tresvigintinongen'
_=_ 'quattuorvigintinongen quinquavigintinongen sesvigintinongen septemvigintinongen octovigintinongen novemvigintinongen trigintanongen untrigintanongen duotrigintanongen trestrigintanongen quattuortrigintanongen quinquatrigintanongen'
_=_ 'sestrigintanongen septentrigintanongen octotrigintanongen noventrigintanongen quadragintanongen unquadragintanongen duoquadragintanongen tresquadragintanongen quattuorquadragintanongen quinquaquadragintanongen sesquadragintanongen'
_=_ 'septenquadragintanongen octoquadragintanongen novenquadragintanongen quinquagintanongen unquinquagintanongen duoquinquagintanongen tresquinquagintanongen quattuorquinquagintanongen quinquaquinquagintanongen sesquinquagintanongen'
_=_ 'septenquinquagintanongen octoquinquagintanongen novenquinquagintanongen sexagintanongen unsexagintanongen duosexagintanongen tresexagintanongen quattuorsexagintanongen quinquasexagintanongen sesexagintanongen septensexagintanongen'
_=_ 'octosexagintanongen novensexagintanongen septuagintanongen unseptuagintanongen duoseptuagintanongen treseptuagintanongen quattuorseptuagintanongen quinquaseptuagintanongen seseptuagintanongen septenseptuagintanongen octoseptuagintanongen'
_=_ 'novenseptuagintanongen octogintanongen unoctogintanongen duooctogintanongen tresoctogintanongen quattuoroctogintanongen quinquaoctogintanongen sexoctogintanongen septemoctogintanongen octooctogintanongen novemoctogintanongen nonagintanonge'
_=_ 'unnonagintanongen duononagintanongen trenonagintanongen quattuornonagintanongen quinquanonagintanongen senonagintanongen septenonagintanongen novenonagintanongen octononagintanongen'


amers= words(_)
                         do j=1  for amers
                         a.j= word(_, j)
                         end   /*j*/
maxzlen= amers * 3

if british  then do
                 engs   = amers * 2   -   2
                 maxzlen= engs  * 3
                                            do k=1  for 2
                                            b.k= a.k
                                            end   /*k*/
                         do j=3  to amers
                         _= j * 2   -   3
                         b._= a.j
                         _n= _ + 1
                         b._n= a.j
                         end   /*j*/
                 drop a.
                 end

n= space(n)
_= left(n, 1)
sig=

if _=='-'  |  _=="+"  then do                             /*handle leading sign (+ -).  */
                           if _=='+'  then sig=  plus
                                      else sig= minus
                           n= substr(n, 2)                /*remove the leading sign.    */
                           end

numeric digits 80 + maxzlen

zpoints = countstr( . , n);      zpoint = zpoints \==0
                                       if zpoints >1  then call er 59, 'decimal-points(.)'
zdollars= countstr('$', n);      zdollar= zdollars\==0
                                       if zdollars>1  then call er 59, 'dollar-signs($)'
zeuros  = countstr('ε', n);      zeuro  = zeuros  \==0
                                       if zeuros  >1  then call er 59, 'euro-signs(ε)'
zfrancs = countstr('ƒ', n);      zfranc = zfrancs \==0
                                       if zfrancs >1  then call er 59, 'franc-signs(ƒ)'
zpounds = countstr('£', n);      zpound = zpounds \==0
                                       if zpounds >1  then call er 59, 'pound-signs(£)'
zyens   = countstr('¥', n);      zyen   = zyens   \==0
                                       if zyens   >1  then call er 59, 'yen-signs(¥)'
zpisetas= countstr('₧', n);      zpiseta= zpisetas\==0
                                       if zpisetas>1  then call er 59, 'piseta-signs(₧)'
zcents  = countstr('¢', n);      zcent  = zcents  \==0
                                       if zcents  >1  then call er 59, 'cent-signs(¢)'

zcurrs  = zdollars + zeuros + zpounds + zyens + zpisetas + zfrancs + zcents
zcurr   = zcurrs \== 0

if zcurrs>2  then call er 59, 'currency symbols'

if zdollar   then do;     xcurr= dollar;     n= changestr("$", n, '');     end
if zeuro     then do;     xcurr= euro;       n= changestr("ε", n, '');     end
if zpound    then do;     xcurr= pound;      n= changestr("£", n, '');     end
if zyen      then do;     xcurr= yen;        n= changestr("¥", n, '');     end
if zpiseta   then do;     xcurr= piseta;     n= changestr("₧", n, '');     end
if zfranc    then do;     xcurr= franc;      n= changestr("ƒ", n, '');     end
if zcent     then do;     xcurr= cent;       n= changestr("¢", n, '');     end

if zpoint    then dot= point                     /*the number has a decimal point.      */

_= right(n, 1)                                   /*pick off right─most character of num.*/
if ismix(_)  |  _=='!'  then n= num(n)           /*if number has a suffix,  convert it. */

parse upper var  n    n  'E'  exponent           /*parse the exponent, if present.      */
parse       var  n    n  '.'  fraction

leadzs= compare(n, copies(0, digits()) ) - 1     /*count the leading zeroes in number.  */
n= changestr(',', n, "")                         /*change commas to nulls  (delete 'em).*/

if isnum(n)  then do                             /*this DO structure must be presered···*/
                  if \asis  then n= n / 1
                  end                            /*elsewise the THEN/ELSEs aren't paired.*/

             else do 1
                  if n==''  then leave           /*this LEAVE is why there is a  DO  1  */
                  expression= n
                  interpret  'number='expression
                  n= number % 1                  /*reduce  NUMBER  to an integer.       */
                  end   /*1*/                    /* [↑]   same as  TRUNC(number)        */

if xcurr\==''  &  xcurr\==zyen  &  n\==1  then xcurr= xcurr's'     /*need to ba plural? */

max#= 10**maxzlen  *  1000   -   1
if \asis  & isnum(n)   then n= n / 1                               /*normalize integer. */

if n\=='' &  isnum(n)  then if n>max#  then call er 81, -max#  max#  ogn   /*in range ? */
if n\=='' & \isint(n)  then call er 53, n                                  /*numeric ?  */
if abs(n)>max#         then call er 81, -max# max# ogn                     /*in range ? */

if leading\==''        then leadingz= copies(leading' ',leadzs)

if asayear  &  right(n, 3)\==000  then do
                                       #= spnte( left(n, max(0, length(n) - 2) ) )
                                       if #==zero       then #=
                                       _2= right(n, 2)
                                       _= spnte(_2)
                                       if _==zero       then _= "hundred"
                                       if _2<10 & _2>0  then _= zero _
                                       #= sig  ||  # _
                                       end

                                else #= sig  ||  leadingz  ||  spnte(n)

if ordinal  then do
                 sx=
                 w= words(#)
                 p= word(#, w)
                 oldp= p
                 pp=
                 if pos('-', p)\==0  then parse var  p     pp  "-"  p
                 if pp\==''          then pp= pp"-"

                      select                                  /* [↓]  adjust some words.*/
                      when p=='one'          then p= "first"
                      when p=='two'          then p= "second"
                      when p=='three'        then p= "third"
                      when p=='five'         then p= "fifth"
                      when p=='eight'        then p= "eighth"
                      when p=='nine'         then p= "ninth"
                      when p=='twelve'       then p= "twelfth"
                      when right(p, 1)=='y'  then p= left(p, length(p) - 1)"ieth"
                      otherwise                  sx= 'th'
                      end   /*select*/

                 if p\==oldp  then if w==1  then #= pp  ||  p
                                            else #= subword(#, 1, w-1)  pp  ||  p
                 #= #  ||  sx
                 end

Lf= length(fraction)
if zdollar  &  (Lf==1  |  Lf==2)  then do
                                       if fraction\=1  then cent= cent's'
                                       fractions= sp(fraction)  cent
                                       dot= xcurr  andcent
                                       xcurr=
                                       end

                                  else do j=1  for Lf
                                       _= substr(fraction, j, 1)
                                       fractions= fractions  dig._
                                       end   /*j*/

if exponent\==''  then do
                       if \isint(exponent)  then call er 53, exponent 'exponent'
                       _= sp(exponent  "ORDINAL")
                       if _\==''            then exponents= raised _ power
                       end

after= space(dot fractions exponents xcurr)
   if after\==''       then after= " "after
#= translate(#  ||  after, , "_")
   if blanks\==''      then #= translate(#, blanks, " ")
   if \quiet           then call $t tops #
return #

/*──────────────────────────────────────────────────────────────────────────────────────*/
spnte: parse arg zz
       if zz==0  |  zz=' '  then return nothing
       en=
       bzz= reverse(zz)
                        has_t= 22
       if british  then has_t= 41

       if single   then do j=1  for length(zz)
                        _= substr(zz, j, 1)
                        en= en dig._
                        end   /*j*/

                   else do j=1  to maxzlen  by 3
                        _= (j+2) % 3
                        if american    then zillion= a._
                                       else zillion= b._
                        if zillion==0  then zillion=
                        if _>=has_t    then zillion= zillion't'

                        if _>2  then if american  then zillion= zillion'illion'
                                                  else if _//2  then zillion= zillion'illion'
                                                                else zillion= zillion'illiard'

                           ttt= reverse( substr(bzz, j, 3) )
                        if ttt=='   '  then leave
                           ttt= right( strip(ttt), 3, 0)
                        if ttt== 000   then iterate
                        x= sphtu(ttt)  zillion
                        if en\==''     then en= sep  ||  en
                           en=x en
                        end   /*j*/

       en= strip( translate(en, , "_") )

       if en==''  then if zcurr  then do           /*this  DO  structure must be intact.*/
                                      if \zcent  then en= " no"
                                      end          /*don't simplify this DO~IF~END group*/

                                 else en=zero
       return en

/*──────────────────────────────────────────────────────────────────────────────────────*/
sphtu: procedure;  parse arg z                      /*SPell Hundred Tens Units.          */
       @987= 'nine eight seven six five four three two one'

       zm= substr(z, 2, 1)
       zr= right(z, 1)
       zh= word(@987, 10 - left(z, 1))

       if zh\==''  then zh= zh  "hundred"

       zt= word('ninety eighty seventy sixty fifty forty thirty twenty',  10 - zm)
       zu= word(@987, 10 - zr)

       @teens= 'ten eleven twelve thir four fif six seven eigh nine'

       if zm==1  then  do
                       zu=
                       zt= word(@teens, zr + 1)
                       if zr>2  then zt= zt'teen'
                       end

       if zt\==''  &  zu\==""   then do
                                     zt= zt'-'zu
                                     zu=
                                     end
       return space(zh zt zu)

/*═════════════════════════════general 1─line subs══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════*/
!all:  !!=!;!=space(!);upper !;call !fid;!nt=right(!var('OS'),2)=='NT';!cls=word('CLS VMFCLEAR CLRSCREEN',1+!cms+!tso*2);if arg(1)\==1 then return 0;if wordpos(!,'? ?SAMPLES ?AUTHOR ?FLOW')==0 then return 0;!call=']$H';call '$H' !fn !;!call=;return 1
!cal:      if symbol('!CALL')\=="VAR" then !call=;  return !call
!env:      !env='ENVIRONMENT';  if !sys=="MSDOS" | !brexx | !r4 | !roo  then !env='SYSTEM';   if !os2  then !env="OS"!env;   !ebcdic=6=='f6'x;   if !crx  then !env="DOS";                                return
!fid:      parse upper source !sys !fun !fid . 1 . . !fn !ft !fm .;  call !sys; if !dos then do; _=lastpos('\', !fn);  !fm=left(!fn, _); !fn=substr(!fn, _+1);  parse var !fn !fn "." !ft;  end;          return word(0  !fn  !ft  !fm, 1 + ("0"arg(1) ) )
!rex:      parse upper version !ver !vernum !verdate .; !brexx='BY'==!vernum; !kexx="KEXX"==!ver; !pcrexx='REXX/PERSONAL'==!ver | "REXX/PC"==!ver; !r4='REXX-R4'==!ver; !regina="REXX-REGINA"==left(!ver, 11);  !roo='REXX-ROO'==!ver;  call !env;  return
!sys:      !cms=!sys=='CMS';  !os2=!sys=="OS2";  !tso=!sys=='TSO' | !sys=="MVS";  !vse=!sys=='VSE';  !dos=pos("DOS", !sys)\==0 | pos('WIN', !sys)\==0 | !sys=="CMD";  !crx=left(!sys, 6)=='DOSCRX';   call !rex;                          return
!var:      call !fid;  if !kexx then return space(dosenv(arg(1)));  return space(value(arg(1),,!env))
$fact!:    procedure; parse arg x _ .;   L=length(x);   n=L - length( strip(x, 'T', "!"));   if n<=-n | _\=='' | arg()\==1  then return x;   z=left(x, L-n);   if z<0 | \isint(z)  then return x;   return $fact(z, n)
$fact:     procedure; parse arg x _ .; arg ,n ! .; n=p(n 1); if \isint(n) then n=0; if x<-n | \isint(x) | n<1 | _ || !\=='' | arg()>2  then return x || copies("!", max(1, n)); !=1; s=x//n; if s==0  then s=n; do j=s  to x  by n; !=!*j; end;   return !
$sfxa:     parse arg ,s,m;  arg u,c;  if pos( left(s, 2), u)\==0  then do j=length(s)  to compare(s,c) -1  by -1;  if right(u, j)\==left(c, j)  then iterate;  _=left(u, length(u) - j);  if isnum(_)  then return m*_;  leave;  end;        return arg(1)
$sfxf:     parse arg y;  if right(y, 1)=='!' then y=$fact!(y);  if \isnum(y)  then y=$sfxz();  if isnum(y)  then return y;                    return $sfxm(y)
$sfxm:     parse arg z;  arg w;  b=1000;  if right(w,1)=='I' then do; z=shorten(z); w=z; upper w; b=1024; end;  p=pos(right(w,1),'KMGTPEZYXWVU');  if p==0 then return arg(1); n=shorten(z); r=num(n,f,1);  if isnum(r) then return r*b**p;  return arg(1)
$sfxz:     return $sfxa($sfxa($sfxa($sfxa($sfxa($sfxa(y,'PAIRs',2),'DOZens',12),'SCore',20),'GREATGRoss',1728),'GRoss',144),'GOOGOLs',1e100)
$t:        !call=']$T';  call "$T" arg(1);  !call=;      return
abb:       arg abbu;  parse arg abb;                     return abbrev(abbu, _, abbl(abb) )
abbl:      return verify(arg(1)'a',@abc,'M')-1
abbn:      parse arg abbn;                               return abb(abbn) | abb('NO'abbn)
countstr:  procedure;  parse arg n,h,s;  if s==''  then s= 1;  w= length(n);  do r=0  until _==0;  _=pos(n, h, s);  s= _ + w;  end;               return r
er:        parse arg _1,_2;  call '$ERR' "14"p(_1) p(word(_1,2) !fid(1)) _2;  if _1<0  then return _1;         exit result
err:       call er "-"arg(1), arg(2);                    return ''
erx:       call er "-"arg(1), arg(2);                    exit ''
getdtfid:  tfid= p( !var("TMP") !var('TEMP') homeDrive()"\");      if substr(tfid, 2, 1)==':'  &  substr(tfid, 3, 1)\=="\"  then tfid= insert('\', t, 2);      return strip( tfid, "T", '\')"\"arg(1)'.'arg(2)
getTFID:   if symbol('TFID')=='LIT' then tfid=; if tfid\=='' then return tfid; gfn=word(arg(1) !fn,1); gft=word(arg(2) 'ANS',1);tfid='TEMP'; if !tso then tfid=gfn'.'gft; if !cms then tfid=gfn','gft",A4";if !dos then tfid=getdTFID(gfn,gft);return tfid
halt:      call er .1
homeDrive: if symbol('HOMEDRIVE')\=="VAR"  then homeDrive=p( !var('HOMEDRIVE') 'C:');                          return homedrive
int:       int=num( arg(1), arg(2) );  if \isint(int)  then call er 92, arg(1)  arg(2);                        return int/1
ishex:     return datatype( arg(1), 'X')
isint:     return datatype( arg(1), 'W')
ismix:     return datatype( arg(1), 'M')
isnum:     return datatype( arg(1), 'N')
na:        if arg(1)\==''  then call er 01, arg(2);  parse var ops  na ops;  if na==''  then call er 35, _o;   return na
nai:       return int(na(), _o)
nan:       return num(na(), _o)
no:        if arg(1)\==''  then call er 01,arg(2);        return left(_, 2)\=='NO'
noValue:   !sigl=sigl;  call er 17, !fid(2)  !fid(3)  !sigl  condition('D')  sourceline(!sigl)
num:       procedure; parse arg x .,f,q; if x=='' then return x; if isnum(x) then return x/1; x=space( translate(x,,','),0); if \isnum(x) then x=$sfxf(x); if isnum(x) then return x/1;if q==1 then return x; if q=='' then call er 53,x f;call erx 53,x f
p:         return word( arg(1), 1)
shorten:   procedure;  parse arg a,n;                  return left(a, max(0, length(a) - p(n 1)))
sp:        !call= ']'!fn;  sp="$SPELL#"(arg(1)  'Q');      !call=;                return sp
syntax:    !sigl= sigl;  call er 13, !fid(2) !fid(3) !sigl !cal() condition('D') sourceline(!sigl)

Note:   The subroutines and functions in the     ══general 1-line subs══     section were kept to one line, elsewise, the program would be exceedingly long.   These functions and subroutines were meant to be brief and not clutter up the main program.