\unprotect

\newcount\argument
\newcount\radix

\newcount\scratcha
\newcount\scratchb

% \scratcha => radix multiplier
% \scratchb => scratch for division with rest

\def\converttoradix#1#2{%
%  \message{<- #2 to #1: }%
  \def\radixresult##1{}%
  \radix = #1
  \scratcha = 1
  \argument = #2
  \ifnum \argument > 0
    \doloop{%
      \multiply \scratcha \radix
      \ifnum \scratcha > \argument \exitloop \fi
    }%
    \divide \scratcha \radix
    \ifnum \scratcha = 1
      \edef\radixresult{\the\argument}%
    \else
      \doloop{% need to do division with remainder 
%        \message{((\the\argument)(\the\scratcha))}%
        \scratchb = \argument
        \divide \scratchb \scratcha
        \edef\radixresult{\radixresult,\the\scratchb}%
        \multiply \scratchb \scratcha
        \advance \argument - \scratchb
        \divide \scratcha \radix
        \ifnum \scratcha = 1 
         \edef\radixresult{\radixresult,\the\argument}%
         \exitloop\fi
      }%
    \fi
  \else
    \edef\radixresult{0}%
  \fi
%  \message{\radixresult -> }%
}

\newcount\result

\def\convertfromradix#1#2{%
  \radix = #1
  \expandafter\let\expandafter\chartonum\csname radtonum#1\endcsname
  \buildcommalist #2\end\end
  \edef\radixresult{\the\result}%
}

\def\convertradix#1#2#3{%
  \convertfromradix{#1}{#3}%
  \converttoradix{#2}{\radixresult}%
}

\def\buildcommalist#1#2%
  {\ifx#2\end 
     \advance \result \chartonum{#1}%
     \let\next\gobbletwoarguments
   \else
      \advance \result \chartonum{#1}%
      \multiply \result \radix
      \let\next\buildcommalist
   \fi
   \next#2%
}

\setvalue{radtonum2}#1%
  {\ifcase #1 0\or 1\else \error\fi}

\setvalue{radtonum8}#1%
  {\ifcase #1 0\or 1\or2\or3\or4\or5\or6\or7\else \error\fi}

\setvalue{radtonum10}#1%
  {\ifcase #1 0\or 1\or2\or3\or4\or5\or6\or7\or8\or9\else \error\fi}

\setvalue{radtonum16}#1%
  {\ifcase #1 0\or 1\or2\or3\or4\or5\or6\or7\or8\or9\else 
   \ifx#1a10\else \ifx#1b11\else \ifx#1c12\else
   \ifx#1d13\else \ifx#1e14\else \ifx#1f15\else
   \ifx#1A10\else \ifx#1B11\else \ifx#1C12\else
   \ifx#1D13\else \ifx#1E14\else \ifx#1F15\else
     \error
   \fi\fi\fi\fi\fi\fi
   \fi\fi\fi\fi\fi\fi
  \fi}

% certain radix types don't use zero's. In decimal, there is
% a special thingy for 0, and we use "1" "0" to indicate 10.
% In e.g. alphabetic radices, there is a symbol for "10", and
% no special symbol for 0. (In such radices, there is generally 
% a special way to specify "zero")

\def\radixnozeroes#1#2{%
  \def\oldval{}%
  \edef\newlist##1{}%
  \def\radixnum{#1}%
  \processcommacommand[#2]\dofixzeroes
  \edef\newlist{\newlist,\oldval}%
  \let#2\newlist
}

\def\dofixzeroes#1{%
 \ifnum #1 = 0
   \ifx\oldval\empty
      \edef\newval{#1}%
   \else
     \scratchcounter = \oldval
     \advance\scratchcounter -1
     \edef\oldval{\the\scratchcounter}%
     \ifnum\oldval > 0
       \edef\newlist{\newlist,\oldval}%
     \fi
     \edef\newval{\radixnum}%
   \fi
 \else
   \ifx\oldval\empty\else
   \edef\newlist{\newlist,\oldval}%
   \fi
   \edef\newval{#1}%
 \fi
 \edef\oldval{\newval}%
}

% 1,1 => aa
% 1,2 => bb
% 2,1 => aaa
% 1,2,3 => 26*1+2 x (3)

% toplevel commands:

\newcount\dcharc
\newcount\dcharcount

\def\dodcharacter#1{%
    \advance\scratchcounter 1
    \ifnum\scratchcounter = \commalistsize
      \ifnum\dcharcount = 0 \dcharcount = 1\fi
      \dorecurse{\the\dcharcount}{\character{#1}}% 
    \else
      \dcharc = #1
      \advance \dcharc 1
      \ifnum \dcharcount = 0 \else
          \multiply \dcharcount 26
      \fi
      \advance\dcharcount \dcharc
    \fi
}%

\def\dcharacters#1{%
  \converttoradix{26}{#1}%
  \radixnozeroes{26}\radixresult
  \expandafter\getcommalistsize\expandafter[\radixresult]
  \dcharcount = 0
  \scratchcounter = 0
  \dcharc = 1
  \processcommacommand[\radixresult]\dodcharacter}

\def\characters#1{%
  \converttoradix{26}{#1}%
  \radixnozeroes{26}\radixresult
  \processcommacommand[\radixresult]\character}

\def\Characters#1{%
  \converttoradix{26}{#1}%
  \radixnozeroes{26}\radixresult
  \processcommacommand[\radixresult]\Character}

\def\octal#1{\converttoradix{8}{#1}%
  \expandafter\processcommalist\expandafter[\radixresult]\numbers}

\def\hexal#1{\converttoradix{16}{#1}%
  \expandafter\processcommalist\expandafter[\radixresult]\lchexnumber}

\def\Hexal#1{\converttoradix{16}{#1}%
  \expandafter\processcommalist\expandafter[\radixresult]\uchexnumber}

\def\binary#1{\converttoradix{2}{#1}%
  \expandafter\processcommalist\expandafter[\radixresult]\numbers}

\protect
