
program BASECONV
  { TP7/BP7; can be shortened with Result in Delphi.
  Numbers are unsigned. Bases 2..36.
  Compact; not optimised for speed.
  Faster conversions between a character and a value are possible.
  Without parameters, manual testing, Base to Decimal to Base.
  With two parameters, InBase & OutBase, is a Filter; with three,
  the third is converted. } ;

(****  UNDERTESTED ****)

const C36 : string [36] = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;

procedure StrToLI
  (const B : byte ; const S : string ; var OK : boolean ; var Ans : longint) ;
var J, P : byte ;
begin OK := false ; Ans := 0 ;
  for J := 1 to Length(S) do begin
    P := Pred(Pos(UpCase(S[J]), C36)) ;
    if P>=B then EXIT ;
    Ans := Ans*B + P ;
    end ;
  OK := true end {StrToLI} ;

function LItoStr(const B : byte ; L : longint) : string ;
var S : string ;
begin S := '' ;
  repeat S := C36[Succ(L mod B)]+S ; L := L div B until L=0 ;
  (* see http://www.merlyn.demon.co.uk/remaindr.txt for combined Div, Mod *)
  LItoStr := S end {LItoStr} ;

procedure UseAsFilter ;
var L : longint ; J : integer ; Bi, Bo : byte ; S : string ; K : boolean ;
begin
  if not (ParamCount in [2, 3]) then HALT(2) ;
  Val(ParamStr(1), Bi, J) ;
  Val(ParamStr(2), Bo, J) ;
  if ParamCount=2 then Readln(S) else S := ParamStr(3) ;
  StrToLI(Bi, S, K, L) ; if not K then HALT(1) ;
  Writeln(LItoStr(Bo, L)) ;
  end {UseAsFilter} ;

procedure UseManually ;
var SS : string ; LI : longint ; Base : byte ; OK : boolean ;
begin
  Writeln('BASECONV   www.merlyn.demon.co.uk  >= 2002-01-22') ;
  repeat Write(' Base ? ') ; Readln(Base) until Base in [2..36] ;
  repeat Write(' Number in Base (. to end) ? ') ;
    Readln(SS) ; if SS='.' then BREAK ;
    StrToLI(Base, SS, OK, LI) ;
    if not OK then begin Writeln(' Bad digit!') ; CONTINUE end ;
    SS := LItoStr(Base, LI) ;
    Writeln(' Decimal : ', LI:12, '   Base ', Base, ' : ', SS) ;
    until false ;
  end {UseManually} ;



BEGIN ;

if ParamCount>0 then UseAsFilter else UseManually ;

END.