Skip to content

Commit

Permalink
Add GAP kernel API (aka libgap)
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Pfeiffer authored and markuspf committed Aug 28, 2018
1 parent 1fc77f0 commit f8f85a0
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,6 @@ doc/gapmacrodoc.idx
/hpcgap/ward

/builds/

/libgap.la
/.libs
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ matrix:
# test error reporting and compiling (quickest job in this test suite)
- env: TEST_SUITES="testspecial test-compile"

# test libgap
- env: TEST_SUITES="testlibgap"

script:
- gcov --version
- bash etc/ci-prepare.sh && bash etc/ci.sh
Expand Down
19 changes: 14 additions & 5 deletions Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
all: gap$(EXEEXT) gac
.PHONY: all

libgap: libgap.la
.PHONY: libgap

# Backwards compatibility: add "default" target as alias for "all"
default: all
.PHONY: default
Expand Down Expand Up @@ -64,6 +61,9 @@ SOURCES += src/intfuncs.c
SOURCES += src/intrprtr.c
SOURCES += src/io.c
SOURCES += src/iostream.c
ifeq ($(HPCGAP),no) # we don't support a kernel API in HPC-GAP atm
SOURCES += src/libgap-api.c
endif
SOURCES += src/listfunc.c
SOURCES += src/listoper.c
SOURCES += src/lists.c
Expand Down Expand Up @@ -121,7 +121,6 @@ ifeq ($(HPCGAP),yes)
SOURCES += src/hpc/traverse.c
endif


########################################################################
# Preprocessor flags
#
Expand Down Expand Up @@ -389,13 +388,16 @@ gap$(EXEEXT): libgap.la cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS

else

all: libgap.so
libgap.so: symlinks libgap.la
$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) -shared $(OBJS) $(GAP_LIBS) -o $@

# Linking rule and dependencies for the main gap executable
gap$(EXEEXT): $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS
$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) $(OBJS) $(GAP_LIBS) -o $@

endif


########################################################################
# The "docomp" target regenerates the various src/c_*.c files, and
# replaces the old "etc/docomp" script.
Expand Down Expand Up @@ -458,6 +460,7 @@ clean:
rm -rf obj
rm -f gap$(EXEEXT) gac ffgen
rm -f libgap.la
rm -f libgap.so
rm -f gen/gap_version.c
rm -f doc/wsp.g
rm -f cnf/GAP-{CFLAGS,CPPFLAGS,LDFLAGS,LIBS,OBJS}
Expand Down Expand Up @@ -986,6 +989,12 @@ testbugfix: all
ReadGapRoot( "tst/testbugfix.g" );' | $(TESTGAP) | \
tee `date -u +dev/log/testbugfix2_%Y-%m-%d-%H-%M` )

testlibgap: libgap.la obj/tst/testlibgap/basic.lo
$(QUIET_LINK)$(LINK) $(GAP_LDFLAGS) obj/tst/testlibgap/basic.lo libgap.la -o test-libgap
./test-libgap -A -l $(top_srcdir) -m 32m -q -T --nointeract > basic.out
diff $(top_srcdir)/tst/testlibgap/basic.expect basic.out
.PHONY: testlibgap

coverage:
gcov -o . $(SOURCES)

Expand Down
4 changes: 4 additions & 0 deletions etc/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ GAPInput

;;

testlibgap)
make testlibgap
;;

*)
if [[ ! -f $SRCDIR/tst/${TEST_SUITE}.g ]]
then
Expand Down
8 changes: 0 additions & 8 deletions lib/streams.gi
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,6 @@ function( stream )
CloseStream(stream);
end );

BindGlobal("LIBGAP_EvalString",
function(string)
local instream, obj;
instream := InputTextString(string);
obj := READ_ALL_COMMANDS(instream, 0, false);
return obj;
end);


#############################################################################
##
Expand Down
62 changes: 62 additions & 0 deletions src/libgap-api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// LibGAP API - API for using GAP as shared library.

#include "libgap-api.h"

#include "bool.h"
#include "opers.h"
#include "calls.h"
#include "gapstate.h"
#include "gvars.h"
#include "lists.h"
#include "streams.h"
#include "stringobj.h"

//
// Setup and initialisation
//
void GAP_Initialize(int argc,
char ** argv,
char ** env,
CallbackFunc markBagsCallback,
CallbackFunc errorCallback)
{
InitializeGap(&argc, argv, env);
SetExtraMarkFuncBags(markBagsCallback);
STATE(JumpToCatchCallback) = errorCallback;
}


// Combines GVarName and ValGVar. For a given string, it returns the value
// of the gvar with name <name>, or NULL if the global variable is not
// defined.
Obj GAP_ValueGlobalVariable(const char * name)
{
UInt gvar = GVarName(name);
// TODO: GVarName should never return 0?
if (gvar != 0) {
return ValGVar(gvar);
}
else {
return NULL;
}
}

//
// Evaluate a string of GAP commands
//
// To see an example of how to use this function
// see tst/testlibgap/basic.c
//
Obj GAP_EvalString(const char * cmd)
{
Obj instream;
Obj res;
Obj viewObjFunc, streamFunc;

streamFunc = GAP_ValueGlobalVariable("InputTextString");
viewObjFunc = GAP_ValueGlobalVariable("ViewObj");

instream = DoOperation1Args(streamFunc, MakeString(cmd));
res = READ_ALL_COMMANDS(instream, False, True, viewObjFunc);
return res;
}
21 changes: 21 additions & 0 deletions src/libgap-api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// LibGAP API - API for using GAP as shared library.

#ifndef LIBGAP_API_H
#define LIBGAP_API_H

#include "gap.h"

typedef void (*CallbackFunc)(void);

// Initialisation and finalization

void GAP_Initialize(int argc,
char ** argv,
char ** env,
CallbackFunc markBagsCallback,
CallbackFunc errorCallback);

Obj GAP_ValueGlobalVariable(const char * name);
Obj GAP_EvalString(const char * cmd);

#endif
77 changes: 77 additions & 0 deletions tst/testlibgap/basic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Small program to test libgap linkability and basic working
*/
#include <stdio.h>
#include <unistd.h>
#include <compiled.h>
#include <libgap-api.h>
extern char ** environ;

UInt GAP_List_Length(Obj list)
{
return LEN_LIST(list);
}

Obj GAP_List_AtPosition(Obj list, Int pos)
{
return ELM_LIST(list, pos);
}

UInt GAP_String_Length(Obj string)
{
return GET_LEN_STRING(string);
}

Int GAP_String_GetCString(Obj string, Char * buffer, UInt n)
{
UInt len;

if (IS_STRING(string)) {
if (!IS_STRING_REP(string))
string = CopyToStringRep(string);
len = GET_LEN_STRING(string) + 1;
if (len >= n)
len = n - 1;
// Have to use mempcy because GAP strings can contain
// \0.
memcpy(buffer, CSTR_STRING(string), len);
if (len == n - 1)
buffer[n] = '\0';
return 1;
}
return 0;
}

void test_eval(const char * cmd)
{
Obj res, ires;
Int rc, i;
Char buffer[4096];
printf("gap> %s\n", cmd);
res = GAP_EvalString(cmd);
rc = GAP_List_Length(res);
for (i = 1; i <= rc; i++) {
ires = GAP_List_AtPosition(res, i);
if (GAP_List_AtPosition(ires, 1) == True) {
GAP_String_GetCString(GAP_List_AtPosition(ires, 5), buffer,
sizeof(buffer));
printf("%s\n", buffer);
}
}
}
int main(int argc, char ** argv)
{
printf("# Initializing GAP...\n");
GAP_Initialize(argc, argv, environ, 0L, 0L);
CollectBags(0, 1); // full GC
test_eval("1+2+3;");
test_eval("g:=FreeGroup(2);");
test_eval("a:=g.1;");
test_eval("b:=g.2;");
test_eval("lis:=[a^2, a^2, b*a];");
test_eval("h:=g/lis;");
test_eval("c:=h.1;");
test_eval("Set([1..1000000], i->Order(c));");
printf("# done\n");
return 0;
}
18 changes: 18 additions & 0 deletions tst/testlibgap/basic.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Initializing GAP...
gap> 1+2+3;
6
gap> g:=FreeGroup(2);
<free group on the generators [ f1, f2 ]>
gap> a:=g.1;
f1
gap> b:=g.2;
f2
gap> lis:=[a^2, a^2, b*a];
[ f1^2, f1^2, f2*f1 ]
gap> h:=g/lis;
<fp group on the generators [ f1, f2 ]>
gap> c:=h.1;
f1
gap> Set([1..1000000], i->Order(c));
[ 2 ]
# done

0 comments on commit f8f85a0

Please sign in to comment.