VERLIB := "KANT V4 2005-10-10 ; GAP v3r3p0 1993-11-09";
if not IsBound( VERSRC ) then  VERSRC := "unknown";  fi;
if not IsBound( VERSYS ) then  VERSYS := "unknwon";  fi;

if not IsBound(VERBUILD) then 
  VERBUILD := Replace(Pipe("uname -s","")+" unknown","\n",""); 
fi;

VERSION := [];
Append_( VERSION,   "lib: " );   Append_( VERSION, VERLIB );
Append_( VERSION, ", src: " );   Append_( VERSION, VERSRC );
Append_( VERSION, ", sys: " );   Append_( VERSION, VERSYS );
Append_( VERSION, ", build: " ); Append_( VERSION, VERBUILD );
Print("\c");

######################################################################
##Print(_USE_DOC_DUMP_P,"\n");
######################################################################
if not QUIET and BANNER then
PR := function ( str )  Print("     ",str,"\n");  end;
PR("                                                                    ");
PR("                                                           ooooqp   ");
PR("   oooo    oooo       .o.        .oooooo..o ooooo   ooooo    .dP'   ");
PR("   `888   .8P'       .888.      d8P'    `Y8 `888'   `888'   d88b.   ");
PR("    888  d8'        .8'888.     Y88bo.       888     888   o.  )8   ");
PR("    88888K         .8' `888.     `'Y8888o.   888ooooo888   `888P'   ");
PR("    888`88b.      .88ooo8888.        `'Y88b  888     888            ");
PR("    888  `88b.   .8'     `888.  oo     .d8P  888     888            ");
PR("   o888o  o888o o88o     o8888o 8''88888P'  o888o   o888o           ");
PR("                                                                    ");
Print("     Shell of the KANT V4 Software, Version 3, build: ",VERBUILD,"\n");
PR("                                                                    ");
PR("Copyright (c) 1994-2005 Prof. Dr. M. E. Pohst,                      ");
PR("Technische Universitaet Berlin. All rights reserved.                ");
PR("                                                                    ");
PR("For registration and support send an email to kant@math.tu-berlin.de");
PR("--------------------------------------------------------------------");
PR("KANT V4 is based on Magma developed by Prof. J. Cannon,                ");
PR("Copyright (c) 2002 Prof. J. Cannon, University of Sydney.           ");
PR("Shell is based on GAP developed by Lehrstuhl D Mathematik, RWTH Aachen,");
PR("Copyright (c) 1992 Lehrstuhl D Mathematik, RWTH Aachen.             ");
PR("                                                                    ");
PR("Enter \"?\" for help and \"quit;\" to leave KASH                    ");
PR("                                                                    ");
fi;
ReadIndent := "";
######################################################################
######################################################################
# Auxiliary global vars
#

Unbind(Ignore);

_Ignore_Me:=
  function(arg)
    return VOID;
  end;

Ignore := _Ignore_Me;

if not IsBound( InfoRead1 )  then InfoRead1 := _Ignore_Me; fi;
if not IsBound( InfoRead2 )  then InfoRead2 := _Ignore_Me; fi;

__ARGREC:=rec();

__CURRENT_LIB := "init.g";
__PREVIOUS_LIB := "init.g";
_PackageBanner := "";

#############################################################################
##
#F  CheckArgs( <record> )
##
## see init-methods for documentation
CheckArgs:=
  function(argl,bind,defaults)
    local i,lim,argrec;
    argrec:=rec();
    for i in [1..Length(bind)] do
      if IsBound(defaults[i]) then
        __ARGREC.(bind[i]):=defaults[i];
        argrec.(bind[i]):=defaults[i];
      else
        __ARGREC.(bind[i]):=FAILURE;
        argrec.(bind[i]):=FAILURE;
      fi;
    od;
    if Length(bind)<Length(argl) then
      lim := Length(bind);
    else
      lim := Length(argl);
    fi;
    for i in [1..lim] do
      if IsBound(argl[i]) then
        __ARGREC.(bind[i]):=argl[i];
        argrec.(bind[i]):=argl[i];
      fi;
    od;
    return argrec;
  end;

IsSuccess:=i->not(i=FAILURE);
IsFailure:=i->i=FAILURE;


HasOptarg:=
  function(argl)
    if IsList(argl) and Length(argl)>0 and
       Type(argl[Length(argl)])=record then
      return TRUE;
    else
      return FALSE;
    fi;
  end;

ExtractOptarg:=
  function(argl)
    local optarg;
    if HasOptarg(argl) then
      return argl[Length(argl)];
    else
      # return empty record if not optarg was found
      return FAILURE; #rec();
    fi;
  end;

ExtractOptarg_:=
  function(argl)
    local optarg;
    optarg := ExtractOptarg(argl);
    if IsSuccess(optarg) then
      _Remove__list_eor(argl,Length(argl));
    fi;
    return optarg;
  end;

Optarg :=
  function(argl,bind,defaults)
    local i,optarg;
    optarg := ExtractOptarg_(argl);
    if optarg=FAILURE then
      optarg:=rec();
    fi;
    for i in [1..Length(bind)] do
      if not IsBound(optarg.(bind[i])) then
        optarg.(bind[i]):=defaults[i];
      fi;
    od;
   
    return optarg;
  end;


__FAILUREDOC:=[any,"Fail","Determines what to return in case of failure.",rec(Default:=FAILURE)];
__SUCCESSDOC:=[any,"Success","Determines what to return in case of success.",rec(Default:=SUCCESS)];
__FAILUREREC:=rec(Fail:=FAILURE,Failure:=FAILURE);
__SUCCESSREC:=rec(Success:=SUCCESS);
__FAILSUCCREC:=rec(Fail:=FAILURE,Success:=SUCCESS);


### wtf? thought we had this :(
StringSplit := function( string, separator )
  local mpos, result, j, tmpstring, startpos, endpos, length;
  mpos := StringMatchPositions(separator, string);

  if Length(mpos) = 0 then
    return [string];
  fi;

  result := [];
  for j in [1..Length(mpos)] do
    if j>1 then
      startpos := mpos[j-1][2];
    else
      startpos := 1;
    fi;
    endpos := mpos[j][1];
    length := endpos-startpos;
    tmpstring := Substring(string, startpos, length);
    _Add__list_any(result,tmpstring);
  od;
  endpos:=mpos[Length(mpos)][2];
  length:=Length(string)+1-endpos;
  if length>0 then
    _Add__list_any(result,Substring(string,endpos,length));
  elif length=0 then
    _Add__list_any(result,"");
  fi;

  return result;
  end;


ReadPath := function ( paths, name, exts, infomsg )
    local readIndent, pathlist, path, file, found, ext, i;

    ## what's this ReadIndent stupidity?
    readIndent := Copy( ReadIndent );
    Append_( ReadIndent, "  " );
    found := false;

    ## now we expect paths to be a list, if not regard it as string and split
    ## accordingly
    if Type(paths)=string then
      pathlist := StringSplit(paths,";");
    else
      pathlist := paths;
    fi;

    ## now we expect exts to be a list, if not it's a single string atom which
    ## in turn is wrapped into a list
    if Type(exts)=string then
      exts := [exts];
    fi;

    ## now recurse on pathlist and try combinations of any element in path with
    ## any element in ext
    while found=FALSE and Length(pathlist) > 0 do
      path := pathlist[1];
      file := path + name;
      i := 1;
      while found=FALSE and i<=Length(exts) do
        ext := exts[i];
        __PREVIOUS_LIB := __CURRENT_LIB;
        __CURRENT_LIB := name+ext;
        found := READ( file+ext );
        __CURRENT_LIB := __PREVIOUS_LIB;
        i := i+1;
      od;
      Remove_(pathlist,1);
    od;
    ReadIndent := readIndent;
    return found;
end;



FindPath := function ( paths, name, exts )
    local pathlist, path, file, found, ext, i;
    found := false;
    
    ## now we expect paths to be a list, if not regard it as string and split
    ## accordingly
    if Type(paths)=string then
      pathlist := StringSplit(paths,";");
    else
      pathlist := paths;
    fi;

    ## now we expect exts to be a list, if not it's a single string atom which
    ## in turn is wrapped into a list
    if Type(exts)=string then
      exts := [exts];
    fi;

    ## now recurse on pathlist and try combinations of any element in path with
    ## any element in ext
    ## now recurse on pathlist and try combinations of any element in path with
    ## any element in ext
    while found=FALSE  and Length(pathlist) > 0 do
      path := pathlist[1];
      file := path + name;
      i := 1;
      while found=FALSE and i<=Length(exts) do
        ext := exts[i];
        __PREVIOUS_LIB := __CURRENT_LIB;
        __CURRENT_LIB := name+ext;
        found := Open( file+ext, "r");
        __CURRENT_LIB := __PREVIOUS_LIB;
        i := i+1;
      od;
      Remove_(pathlist,1);
    od;
    if found=FALSE then
      return FALSE;
    else
      Close(found);
      return file+ext;
    fi;
end;

#/*TEX**TEX|***TEX***TEX***TEX***TEX**TEX***TEX***TEX***TEX***TEX***TEX***TEX**
#FXN       Read
#CALLING   Read(name);
#SHORTDOC  Read a file containing \KASH\ commands.
#LONGDOC   The file "name" must be both existing and readable.
#          \KASH\ looks first in the given path, then in the current directory
#          and finally in {\tt LIBNAME../src}. 
#ARGUS     name @ string
#EXAMPLE   Assume that we have a file named "in" in our current
#          working directory. First, we take a look at its contents: @ 
#          kash> Exec("cat in");
#          Time(true);
#          x := Poly(Zx, [1,0]);
#          Palg := function(O)
#            local px;
#            px := PolyAlg(O);
#            x := Poly(px, [1,0]);
#            return px;
#          end;
#
#          kash> Read("in");
#          kash> x;
#          x
#          Time: 0 ms
#
#
#**HISTORY*|*HISTORY***HISTORY***HISTORY**HISTORY***HISTORY***HISTORY***HISTORY
#
#**C***C***|***C***C***C***C***C***C**C***C***C***C***C***C***C***C***C***C***/
Read := function ( filename )
  ## Banner handling
  _PackageBanner := "";

  if not ReadPath( ";./;"+ LIBNAME + ";"+ LIBNAME + "../src/", filename,
                   ["",".g",".k"], "Read" ) then
    Error("the file '",filename,"' must exist and be readable");
  fi;

  Print(_PackageBanner);
end;


#/*TEX**TEX|***TEX***TEX***TEX***TEX**TEX***TEX***TEX***TEX***TEX***TEX***TEX**
#FXN       ReadLib
#CALLING   ReadLib(name);
#SHORTDOC  The same as Read, but here the file should be in the
#          \KASH\ lib directory and it must have the extension ``.g''.
#ARGUS     name @ string
#XREF      Read
#EXAMPLE   We will read the neq.g library. This will define a function
#          solving norm equations by suitable principal ideal tests. @ 
#          kash> ReadLib("neq");
#          kash> Neq(o, 7);
#          Prime 7: 1 [ 2 ]
#          No solution
#          false
#          Time: 40 ms
#          kash> Neq(o, 11);
#          Prime 11: 1 [ 1, 1 ]
#          [ [ [ [ <11, [5, 2]>, 1 ], [ <11, [8, 2]>, 1 ] ], [ 0, 1 ], [ 1, 0 ] ] ]
#          at most 2 different solutions! 
#          Ideals : [ [ <11, [5, 2]>, 1 ], [ <11, [8, 2]>, 1 ] ]
#          Ideal Basis of all (possible) solutions: [ [ <11, [8, 2]>, <11, [5, 2]> ] ] 
#          [ [1, 3], [-2, -3] ]
#          Time: 260 ms
#          kash> OrderNormEquation(o, 11, -1);
#          [ [-2, -3], [-1, -3] ]
#          Time: 180 ms
#**HISTORY*|*HISTORY***HISTORY***HISTORY**HISTORY***HISTORY***HISTORY***HISTORY
#
#**C***C***|***C***C***C***C***C***C**C***C***C***C***C***C***C***C***C***C***/
ReadLib:=
  function(arg)
    local name, optarg,
      ## Profiling
      stime,etime;

    ## Banner handling
    _PackageBanner := "";

    ## now check args >8)
    CheckArgs(arg,["name","optarg"],[,rec(IgnoreErrors:=FALSE,Fail:=FAILURE)]);
    name:=__ARGREC.("name");
    optarg:=__ARGREC.("optarg");

    if not(QUIET) and BANNER then
      stime:=UTime();
      Print(name);
    fi;
    if not(ReadPath(LIBNAME+ ";"+ LIBNAME + "../src/", name, [".g", ".k"], "ReadLib"))  then
      Print("(m) ");
      if IsBound(optarg.("IgnoreErrors")) and optarg.("IgnoreErrors") then
        return SUCCESS;
      elif IsBound(optarg.("Fail")) then
        return optarg.("Fail");
      else
        Error("the library file '",name,"' must exist and be readable");
      fi;
    fi;
    if not(QUIET) and BANNER then
      Print(" ");
      etime:=UTime();
      Print("[",etime-stime,"] ");
      Print(_PackageBanner);
    fi;

    return SUCCESS;
  end;


##############################################################################

## Type Atom definitions must occur early.  Put all of them here.
## The Type Atoms must be defined before __DOC is read.

## Read list utils very first lest circular dependencies occur -SF
ReadLib("list",rec(IgnoreErrors:=TRUE));
ReadLib("alist",rec(IgnoreErrors:=TRUE));
ReadLib("term",rec(IgnoreErrors:=TRUE));

## Read documentation utils first lest circular dependencies occur -SF
ReadLib("__DOC",rec(IgnoreErrors:=TRUE));

ReadLib("doc",rec(IgnoreErrors:=TRUE));
ReadLib("docui",rec(IgnoreErrors:=TRUE));
## stupid but necessary due to double linked forward declarations
ReadLib("docui",rec(IgnoreErrors:=TRUE));  

ReadLib("method",rec(IgnoreErrors:=TRUE));
## here follows documentation and definition of overloaded functions
ReadLib("init-methods",rec(IgnoreErrors:=TRUE));

ReadLib("constants",rec(IgnoreErrors:=TRUE));
ReadLib("kash",rec(IgnoreErrors:=TRUE));
ReadLib("matrix",rec(IgnoreErrors:=TRUE));
ReadLib("map",rec(IgnoreErrors:=TRUE));

_QaosBannerShown:=TRUE;
ReadLib("qaos",rec(IgnoreErrors:=TRUE));

#ReadLib("powerSer",rec(IgnoreErrors:=TRUE));
ReadLib("locFact",rec(IgnoreErrors:=TRUE));

#####################################################################
# some default settings
#####################################################################

Colors(true);
Colors("prompt",  "green");
Colors("normal",  "magenta");
Colors("error",   "red");
#Colors("command", "black");
if "Windows" in VERBUILD then 
# the background of the DOS window is black by default
  Colors("result",  "cyan");
else
Colors("result",  "blue");
fi;
Time(true);
Print("\n");

######################################################################
# global variable indicating that the doc dump should not be used
######################################################################

_USE_DOC_DUMP_P := FALSE;

######################################################################

## have to be AFTER definitions of GetVerbose and SetVerbose --
## they are defined in kash.g

AUTO(ReadLib("elliptic"),EllipticCurve);
#AUTO(ReadLib("zetaMod"),ZetaMod);

##########################################################################

__CURRENT_LIB := "<interactive environment>";

