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 committed Aug 21, 2018
1 parent 950f7b5 commit f7cae72
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 12 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" CONFIGFLAGS="--enable-debug --enable-Werror --enable-libgap"

script:
- gcov --version
- bash etc/ci-prepare.sh && bash etc/ci.sh
Expand Down
3 changes: 3 additions & 0 deletions GNUmakefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ ADDGUARDS2 = @ADDGUARDS2@
# garbage collector source files
GC_SOURCES = @GC_SOURCES@

# Dynamic library
BUILD_LIBGAP = @BUILD_LIBGAP@

# compatibility mode
COMPAT_MODE = @COMPAT_MODE@
GAPARCH = @GAPARCH@
Expand Down
12 changes: 10 additions & 2 deletions Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
all: gap$(EXEEXT) gac
.PHONY: all

libgap: libgap.la
libgap: libgap.la sysinfo.gap symlinks
.PHONY: libgap

# Backwards compatibility: add "default" target as alias for "all"
Expand Down Expand Up @@ -64,6 +64,7 @@ SOURCES += src/intfuncs.c
SOURCES += src/intrprtr.c
SOURCES += src/io.c
SOURCES += src/iostream.c
SOURCES += src/libgap-api.c
SOURCES += src/listfunc.c
SOURCES += src/listoper.c
SOURCES += src/lists.c
Expand Down Expand Up @@ -121,7 +122,6 @@ ifeq ($(HPCGAP),yes)
SOURCES += src/hpc/traverse.c
endif


########################################################################
# Preprocessor flags
#
Expand Down Expand Up @@ -395,6 +395,8 @@ gap$(EXEEXT): $(OBJS) cnf/GAP-LDFLAGS cnf/GAP-LIBS cnf/GAP-OBJS

endif

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

########################################################################
# The "docomp" target regenerates the various src/c_*.c files, and
Expand Down Expand Up @@ -986,6 +988,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 -l $(top_srcdir) -m 32m -q -T > 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
5 changes: 3 additions & 2 deletions lib/init.g
Original file line number Diff line number Diff line change
Expand Up @@ -1042,11 +1042,12 @@ if IsLIBGAP then
elif IsHPCGAP and THREAD_UI() then
ReadLib("hpc/consoleui.g");
MULTI_SESSION();
else
PROGRAM_CLEAN_UP();
elif not IsLIBGAP then
SESSION();
PROGRAM_CLEAN_UP();
fi;

PROGRAM_CLEAN_UP();


#############################################################################
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
95 changes: 95 additions & 0 deletions src/libgap-api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// 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;
}


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)
{
Obj copy;
UInt len;

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


// 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
//
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;
}
47 changes: 47 additions & 0 deletions src/libgap-api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// LibGAP API - API for using GAP as shared library.
//
// WARNING
//
// This API is work in progress, hence subject to change.
//
// We currently only provide a small amount of functionality
// via a well-defined API that wraps internal GAP functions.
//
// Users of GAP as a library currently call directly into
// GAP kernel functions. In the future we would like to hide
// all GAP internal functions (in the .so/.dll file) and only
// allow access to GAP via functions defined in this file.
//
// If you have a request to expose functionality via the API
// please contact us via the GAP mailing list or github
// issue tracker.
//

#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);

// List operations. These are currently here like this, because they are used in
// testlibgap.
UInt GAP_List_Length(Obj list);
Obj GAP_List_AtPosition(Obj list, Int pos);

UInt GAP_String_Length(Obj string);
Int GAP_String_GetCString(Obj string, Char *buffer, UInt max);

Obj GAP_ValueGlobalVariable(const char * name);

Obj GAP_EvalString(const char * cmd);

#endif
49 changes: 49 additions & 0 deletions tst/testlibgap/basic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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;

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;
}
19 changes: 19 additions & 0 deletions tst/testlibgap/basic.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 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 f7cae72

Please sign in to comment.