Skip to content
Snippets Groups Projects
Commit b4deb5c6 authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

pp

parent b6ebd595
No related branches found
No related tags found
No related merge requests found
// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
// Jonathan Lambrechts
//
#include <stdarg.h> #include <stdarg.h>
#include "Bindings.h"
#include <stdio.h> #include <stdio.h>
void methodBinding::setArgNames(const char *arg1, ...) { #include "Bindings.h"
void methodBinding::setArgNames(const char *arg1, ...)
{
va_list ap; va_list ap;
va_start(ap, arg1); va_start(ap, arg1);
const char *name=arg1; const char *name=arg1;
......
// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#ifndef _BINDINGS_H_ #ifndef _BINDINGS_H_
#define _BINDINGS_H_ #define _BINDINGS_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include <typeinfo> #include <typeinfo>
...@@ -8,21 +14,16 @@ class methodBinding{ ...@@ -8,21 +14,16 @@ class methodBinding{
std::string _description; std::string _description;
std::vector<std::string> _argNames; std::vector<std::string> _argNames;
public: public:
inline const std::vector<std::string> &getArgNames()const{ inline const std::vector<std::string> &getArgNames() const { return _argNames; }
return _argNames;
}
void setArgNames(const char * arg1, ...); void setArgNames(const char * arg1, ...);
void setDescription(std::string description){ _description = description; } void setDescription(std::string description){ _description = description; }
inline const std::string getDescription() const { return _description; } inline const std::string getDescription() const { return _description; }
}; };
#if defined(HAVE_LUA) #if defined(HAVE_LUA)
#include "LuaBindings.h" #include "LuaBindings.h"
#else // no bindings #else // no bindings
#include "DummyBindings.h" #include "DummyBindings.h"
#endif #endif
#endif #endif
// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
#ifndef _DUMMY_BINDINGS_H_ #ifndef _DUMMY_BINDINGS_H_
#define _DUMMY_BINDINGS_H_ #define _DUMMY_BINDINGS_H_
...@@ -8,7 +13,8 @@ class classBinding { ...@@ -8,7 +13,8 @@ class classBinding {
void setParentClass(){} void setParentClass(){}
template <typename cb> template <typename cb>
methodBinding *addMethod(std::string n, cb f){ return new methodBinding(); } methodBinding *addMethod(std::string n, cb f){ return new methodBinding(); }
template <typename tObj, typename t0, typename t1, typename t2, typename t3, typename t4> template <typename tObj, typename t0, typename t1, typename t2, typename t3,
typename t4>
methodBinding *setConstructor(){ return 0; } methodBinding *setConstructor(){ return 0; }
template <typename tObj, typename t0, typename t1, typename t2, typename t3> template <typename tObj, typename t0, typename t1, typename t2, typename t3>
methodBinding *setConstructor(){ return 0; } methodBinding *setConstructor(){ return 0; }
......
// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle
//
// See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
// Jonathan Lambrechts
//
#include "GmshConfig.h" #include "GmshConfig.h"
#if defined(HAVE_LUA) #if defined(HAVE_LUA)
...@@ -16,6 +25,7 @@ ...@@ -16,6 +25,7 @@
#include "Bindings.h" #include "Bindings.h"
#include "drawContext.h" #include "drawContext.h"
#include "GmshMessage.h" #include "GmshMessage.h"
#if defined(HAVE_SOLVER) #if defined(HAVE_SOLVER)
#include "linearSystemCSR.h" #include "linearSystemCSR.h"
#endif #endif
...@@ -35,28 +45,34 @@ extern "C" { ...@@ -35,28 +45,34 @@ extern "C" {
class gmshOptions { class gmshOptions {
public: public:
gmshOptions(){}; gmshOptions(){};
void colorSet(std::string category, int index, std::string name, int value) { void colorSet(std::string category, int index, std::string name, int value)
{
GmshSetOption(category,name,(unsigned int)(value), index); GmshSetOption(category,name,(unsigned int)(value), index);
} }
int colorGet(std::string category, int index, std::string name) { int colorGet(std::string category, int index, std::string name)
{
unsigned int value; unsigned int value;
GmshGetOption(category, name, value, index); GmshGetOption(category, name, value, index);
return value; return value;
} }
double numberGet(std::string category, int index, std::string name) { double numberGet(std::string category, int index, std::string name)
{
double value; double value;
GmshGetOption(category, name, value, index); GmshGetOption(category, name, value, index);
return value; return value;
} }
void numberSet(std::string category, int index, std::string name, double value) { void numberSet(std::string category, int index, std::string name, double value)
{
GmshSetOption(category, name, value, index); GmshSetOption(category, name, value, index);
} }
std::string stringGet(std::string category, int index, std::string name) { std::string stringGet(std::string category, int index, std::string name)
{
std::string value; std::string value;
GmshGetOption(category, name, value, index); GmshGetOption(category, name, value, index);
return value; return value;
} }
void stringSet(std::string category, int index, std::string name, double value) { void stringSet(std::string category, int index, std::string name, double value)
{
GmshSetOption(category, name, value, index); GmshSetOption(category, name, value, index);
} }
static void registerBindings(binding *b) { static void registerBindings(binding *b) {
...@@ -64,22 +80,28 @@ class gmshOptions { ...@@ -64,22 +80,28 @@ class gmshOptions {
cb->setDescription("access the gmsh option database"); cb->setDescription("access the gmsh option database");
methodBinding *mb; methodBinding *mb;
mb = cb->addMethod("colorSet", &gmshOptions::colorSet); mb = cb->addMethod("colorSet", &gmshOptions::colorSet);
mb->setDescription("set the value of a color (unsigned int) option. This is equivalent to category[index].name = value"); mb->setDescription("set the value of a color (unsigned int) option. This is "
"equivalent to category[index].name = value");
mb->setArgNames("category", "index", "name", "value", NULL); mb->setArgNames("category", "index", "name", "value", NULL);
mb = cb->addMethod("colorGet", &gmshOptions::colorGet); mb = cb->addMethod("colorGet", &gmshOptions::colorGet);
mb->setDescription("return the value of a color (unsigned int) option. This is equivalent to category[index].name"); mb->setDescription("return the value of a color (unsigned int) option. This "
"is equivalent to category[index].name");
mb->setArgNames("category", "index", "name", NULL); mb->setArgNames("category", "index", "name", NULL);
mb = cb->addMethod("numberSet", &gmshOptions::numberSet); mb = cb->addMethod("numberSet", &gmshOptions::numberSet);
mb->setDescription("set the value of a number option. This is equivalent to category[index].name = value"); mb->setDescription("set the value of a number option. This is equivalent "
"to category[index].name = value");
mb->setArgNames("category", "index", "name", "value", NULL); mb->setArgNames("category", "index", "name", "value", NULL);
mb = cb->addMethod("numberGet", &gmshOptions::numberGet); mb = cb->addMethod("numberGet", &gmshOptions::numberGet);
mb->setDescription("return the value of a number option. This is equivalent to category[index].name"); mb->setDescription("return the value of a number option. This is equivalent "
"to category[index].name");
mb->setArgNames("category", "index", "name", NULL); mb->setArgNames("category", "index", "name", NULL);
mb = cb->addMethod("srtingSet", &gmshOptions::stringSet); mb = cb->addMethod("srtingSet", &gmshOptions::stringSet);
mb->setDescription("set the value of a string option. This is equivalent to category[index].name = \"value\""); mb->setDescription("set the value of a string option. This is equivalent "
"to category[index].name = \"value\"");
mb->setArgNames("category", "index", "name", "value", NULL); mb->setArgNames("category", "index", "name", "value", NULL);
mb = cb->addMethod("srtingGet", &gmshOptions::stringGet); mb = cb->addMethod("srtingGet", &gmshOptions::stringGet);
mb->setDescription("return the value of a string option. This is equivalent to category[index].name"); mb->setDescription("return the value of a string option. This is equivalent "
"to category[index].name");
mb->setArgNames("category", "index", "name", NULL); mb->setArgNames("category", "index", "name", NULL);
mb = cb->setConstructor<gmshOptions>(); mb = cb->setConstructor<gmshOptions>();
mb->setDescription("an instance of gmshOptions is needed to access the database"); mb->setDescription("an instance of gmshOptions is needed to access the database");
...@@ -102,7 +124,8 @@ const char *colorBlue = "\033[1;34m"; ...@@ -102,7 +124,8 @@ const char *colorBlue = "\033[1;34m";
const char *colorDefault = "\033[0m"; const char *colorDefault = "\033[0m";
const char *colorBold = "\033[1m"; const char *colorBold = "\033[1m";
static void printMethod(std::string name, luaMethodBinding *mb, bool isConstructor=false) { static void printMethod(std::string name, luaMethodBinding *mb, bool isConstructor=false)
{
std::vector<std::string> argTypeNames; std::vector<std::string> argTypeNames;
mb->getArgTypeNames(argTypeNames); mb->getArgTypeNames(argTypeNames);
std::cout << " "; std::cout << " ";
...@@ -123,34 +146,41 @@ static void printMethod(std::string name, luaMethodBinding *mb, bool isConstruct ...@@ -123,34 +146,41 @@ static void printMethod(std::string name, luaMethodBinding *mb, bool isConstruct
std::cout << colorBold << ")\n" << colorDefault; std::cout << colorBold << ")\n" << colorDefault;
const std::string description = mb->getDescription(); const std::string description = mb->getDescription();
std::cout << (description.empty() ? "no help available" : description) << "\n"; std::cout << (description.empty() ? "no help available" : description) << "\n";
} }
static void listMethods(classBinding *cb){
static void listMethods(classBinding *cb)
{
if(cb->methods.size()) if(cb->methods.size())
std::cout<<colorGreen<<"Methods from "<<cb->getClassName()<<colorDefault<<"\n"; std::cout << colorGreen << "Methods from " << cb->getClassName()
for(std::map<std::string,luaMethodBinding *>::iterator it = cb->methods.begin(); it!=cb->methods.end(); it++){ << colorDefault<< "\n";
for(std::map<std::string, luaMethodBinding *>::iterator it = cb->methods.begin();
it != cb->methods.end(); it++){
printMethod(it->first, it->second); printMethod(it->first, it->second);
} }
if(cb->getParent()) if(cb->getParent())
listMethods(cb->getParent()); listMethods(cb->getParent());
} }
static int luaHelp (lua_State *L){ static int luaHelp (lua_State *L)
{
int argc = lua_gettop(L); int argc = lua_gettop(L);
binding *b = binding::instance(); binding *b = binding::instance();
if (argc == 0){ if (argc == 0){
std::cout << "this is the gmsh help\n"; std::cout << "this is the gmsh help\n";
for(std::map<std::string,classBinding *>::iterator it = b->classes.begin(); it!=b->classes.end(); it++){ for(std::map<std::string,classBinding *>::iterator it = b->classes.begin();
it != b->classes.end(); it++){
if(it->second->getParent()) if(it->second->getParent())
continue; continue;
std::cout << colorBlue << " " << it->first<<colorDefault << " : "; std::cout << colorBlue << " " << it->first<<colorDefault << " : ";
const std::string description = it->second->getDescription(); const std::string description = it->second->getDescription();
std::cout << (description.empty() ? "no help available" : description) << "\n"; std::cout << (description.empty() ? "no help available" : description) << "\n";
} }
}else{ }
else{
const char *className = luaL_checkstring(L, 1); const char *className = luaL_checkstring(L, 1);
if(b->classes.find(className) == b->classes.end()){ if(b->classes.find(className) == b->classes.end()){
std::cout<<"Class "<<colorBold<<className<<colorDefault<<" does not exist.\n"; std::cout << "Class " << colorBold << className << colorDefault
<< " does not exist.\n";
return 0; return 0;
} }
classBinding *cb = b->classes[className]; classBinding *cb = b->classes[className];
...@@ -166,8 +196,10 @@ static int luaHelp (lua_State *L){ ...@@ -166,8 +196,10 @@ static int luaHelp (lua_State *L){
listMethods(cb); listMethods(cb);
std::cout << "\n"; std::cout << "\n";
if(cb->children.size()){ if(cb->children.size()){
std::cout<<colorGreen<<"Children of "<<cb->getClassName()<<colorDefault<<"\n"; std::cout << colorGreen << "Children of " << cb->getClassName()
for(std::set<classBinding *>::iterator it = cb->children.begin(); it!=cb->children.end(); it++){ << colorDefault << "\n";
for(std::set<classBinding *>::iterator it = cb->children.begin();
it != cb->children.end(); it++){
std::cout << " " << colorBlue << (*it)->getClassName() << colorDefault << " : "; std::cout << " " << colorBlue << (*it)->getClassName() << colorDefault << " : ";
const std::string description = (*it)->getDescription(); const std::string description = (*it)->getDescription();
std::cout << (description.empty() ? "no help available" : description) << "\n"; std::cout << (description.empty() ? "no help available" : description) << "\n";
...@@ -178,19 +210,23 @@ static int luaHelp (lua_State *L){ ...@@ -178,19 +210,23 @@ static int luaHelp (lua_State *L){
return 0; return 0;
} }
#if defined(HAVE_READLINE)
#ifdef HAVE_READLINE static int luaSave (lua_State *L)
static int luaSave (lua_State *L){ {
const char *filename = luaL_checkstring(L, 1); const char *filename = luaL_checkstring(L, 1);
write_history(filename); write_history(filename);
return 0; return 0;
} }
static int luaClear (lua_State *L){
static int luaClear(lua_State *L)
{
clear_history(); clear_history();
return 0; return 0;
} }
#endif #endif
static int luaRefresh (lua_State *L){
static int luaRefresh (lua_State *L)
{
drawContext::global()->draw(); drawContext::global()->draw();
return 0; return 0;
} }
...@@ -211,16 +247,19 @@ int binding::readFile(const char *filename) ...@@ -211,16 +247,19 @@ int binding::readFile(const char *filename)
return (s == 0); return (s == 0);
} }
static int countInArguments(const std::vector<std::string> &types){ static int countInArguments(const std::vector<std::string> &types)
{
int c = 0; int c = 0;
for(int i = 1; i < types.size(); i++) for(int i = 1; i < types.size(); i++)
c+=(types[i] != "-1"); c+=(types[i] != "-1");
return c; return c;
} }
void binding::checkDocCompleteness(){ void binding::checkDocCompleteness()
{
int nBad = 0; int nBad = 0;
for(std::map<std::string,classBinding *>::iterator cb = classes.begin(); cb!=classes.end();cb++) { for(std::map<std::string, classBinding *>::iterator cb = classes.begin();
cb!=classes.end();cb++) {
if(cb->second->getDescription().empty()){ if(cb->second->getDescription().empty()){
Msg::Error("binded class %s has no description.", cb->first.c_str()); Msg::Error("binded class %s has no description.", cb->first.c_str());
nBad++; nBad++;
...@@ -228,7 +267,8 @@ void binding::checkDocCompleteness(){ ...@@ -228,7 +267,8 @@ void binding::checkDocCompleteness(){
luaMethodBinding *constructor = cb->second->getConstructor(); luaMethodBinding *constructor = cb->second->getConstructor();
if(constructor){ if(constructor){
if(constructor->getDescription().empty()){ if(constructor->getDescription().empty()){
Msg::Error("binded constructor of class %s has no description.", cb->first.c_str()); Msg::Error("binded constructor of class %s has no description.",
cb->first.c_str());
nBad++; nBad++;
} }
std::vector<std::string> argTypeNames; std::vector<std::string> argTypeNames;
...@@ -236,14 +276,16 @@ void binding::checkDocCompleteness(){ ...@@ -236,14 +276,16 @@ void binding::checkDocCompleteness(){
int nTypeArg = countInArguments(argTypeNames); int nTypeArg = countInArguments(argTypeNames);
int nDocArg = constructor->getArgNames().size(); int nDocArg = constructor->getArgNames().size();
if(nTypeArg != nDocArg){ if(nTypeArg != nDocArg){
Msg::Error("binded constructor of class %s takes %i arguments but %i are documented.", Msg::Error("binded constructor of class %s takes %i arguments but %i "
cb->first.c_str(), nTypeArg, nDocArg); "are documented.", cb->first.c_str(), nTypeArg, nDocArg);
nBad++; nBad++;
} }
} }
for(std::map<std::string,luaMethodBinding*>::iterator mb = cb->second->methods.begin(); mb != cb->second->methods.end(); mb++){ for(std::map<std::string,luaMethodBinding*>::iterator mb = cb->second->methods.begin();
mb != cb->second->methods.end(); mb++){
if(mb->second->getDescription().empty()){ if(mb->second->getDescription().empty()){
Msg::Error("binded method %s.%s has no description.", cb->first.c_str(),mb->first.c_str()); Msg::Error("binded method %s.%s has no description.", cb->first.c_str(),
mb->first.c_str());
nBad++; nBad++;
} }
std::vector<std::string> argTypeNames; std::vector<std::string> argTypeNames;
...@@ -258,10 +300,11 @@ void binding::checkDocCompleteness(){ ...@@ -258,10 +300,11 @@ void binding::checkDocCompleteness(){
} }
} }
if(nBad != 0){ if(nBad != 0){
Msg::Error("Bindings documentation is not complete (%i error(s) ). To enforce documentation completeness, I will exit now. Please complete the documentation and run gmsh again ;-) .\n",nBad); Msg::Error("Bindings documentation is not complete (%i error(s)). To enforce "
exit(1); "documentation completeness, I will exit now. Please complete the "
"documentation and run Gmsh again ;-)", nBad);
Msg::Exit(1);
} }
} }
void binding::interactiveSession() void binding::interactiveSession()
...@@ -271,7 +314,7 @@ void binding::interactiveSession() ...@@ -271,7 +314,7 @@ void binding::interactiveSession()
checkDocCompleteness(); checkDocCompleteness();
Msg::Info("Starting interactive lua session, press Ctrl-D to exit"); Msg::Info("Starting interactive lua session, press Ctrl-D to exit");
#ifdef HAVE_READLINE #if defined(HAVE_READLINE)
using_history(); using_history();
while (const char *line=readline("lua> ")){ while (const char *line=readline("lua> ")){
char *expansion = NULL; char *expansion = NULL;
...@@ -288,8 +331,7 @@ void binding::interactiveSession() ...@@ -288,8 +331,7 @@ void binding::interactiveSession()
clear_history(); clear_history();
#else #else
std::string line; std::string line;
while(std::cout<<"lua> ", while(std::cout << "lua> ", getline(std::cin, line)){
getline(std::cin,line) ){
reportErrors(L, luaL_dostring(L, line.c_str())); reportErrors(L, luaL_dostring(L, line.c_str()));
} }
#endif #endif
...@@ -307,7 +349,7 @@ binding::binding() ...@@ -307,7 +349,7 @@ binding::binding()
luaopen_base(L); luaopen_base(L);
luaopen_table(L); luaopen_table(L);
luaopen_os(L); luaopen_os(L);
//luaopen_io(L); luaopen_io(L);
luaopen_string(L); luaopen_string(L);
luaopen_math(L); luaopen_math(L);
luaopen_debug(L); luaopen_debug(L);
...@@ -315,7 +357,7 @@ binding::binding() ...@@ -315,7 +357,7 @@ binding::binding()
luaL_openlibs(L); luaL_openlibs(L);
lua_register(L, "help",luaHelp); lua_register(L, "help",luaHelp);
#ifdef HAVE_READLINE #if defined(HAVE_READLINE)
lua_register(L, "saveHistory", luaSave); lua_register(L, "saveHistory", luaSave);
lua_register(L, "clearHistory", luaClear); lua_register(L, "clearHistory", luaClear);
lua_register(L, "refreshGraphics", luaRefresh); lua_register(L, "refreshGraphics", luaRefresh);
......
This diff is collapsed.
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
// //
// See the LICENSE.txt file for license information. Please report all // See the LICENSE.txt file for license information. Please report all
// bugs and problems to <gmsh@geuz.org>. // bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
// Emilie Marchandise
//
#include "GmshConfig.h" #include "GmshConfig.h"
......
...@@ -11,17 +11,17 @@ ...@@ -11,17 +11,17 @@
Code contributions to Gmsh have been provided by David Colignon Code contributions to Gmsh have been provided by David Colignon
(colormaps), Emilie Marchandise (compound geometrical entities), (colormaps), Emilie Marchandise (compound geometrical entities),
Gaetan Bricteux (Gauss integration and levelsets), Jacques Lechelle Gaetan Bricteux (Gauss integration and levelsets), Jacques Lechelle
(DIFFPACK mesh format), Jonathan Lambrechts (fields), Jozef Vesely (DIFFPACK mesh format), Jonathan Lambrechts (fields, solver), Jozef
(Tetgen), Koen Hillewaert (high order elements), Laurent Stainier Vesely (Tetgen), Koen Hillewaert (high order elements), Laurent
(eigenvalue solvers, tensor display and MacOS bits), Marc Ume Stainier (eigenvalue solvers, tensor display and MacOS bits), Marc Ume
(original list code), Mark van Doesburg (Open CASCADE face (original list code), Mark van Doesburg (Open CASCADE face
connection), Matt Gundry (Plot3d mesh format), Matti Pellikka connection), Matt Gundry (Plot3d mesh format), Matti Pellikka
(Homology), Nicolas Tardieu (Netgen), Pascale Noyret (MED mesh (Homology), Nicolas Tardieu (Netgen), Pascale Noyret (MED mesh
format), Pierre Badel (root finding and minimization), Ruth Sabariego format), Pierre Badel (root finding and minimization), Ruth Sabariego
(pyramids), Stephen Guzik (CGNS and partitioners), Bastien Gorissen (pyramids), Stephen Guzik (CGNS and partitioners), Bastien Gorissen
(parallel remote). See comments in the sources for more (parallel remote), Eric Bechet (solver). See comments in the sources
information. If we forgot to list your contributions please send us an for more information. If we forgot to list your contributions please
email! send us an email!
The AVL tree code (Common/avl.*) and the YUV image code The AVL tree code (Common/avl.*) and the YUV image code
(Graphics/gl2yuv.*) are copyright (C) 1988-1993, 1995 The Regents of (Graphics/gl2yuv.*) are copyright (C) 1988-1993, 1995 The Regents of
...@@ -111,9 +111,9 @@ Thanks to the following folks who have contributed by providing fresh ...@@ -111,9 +111,9 @@ Thanks to the following folks who have contributed by providing fresh
ideas on theoretical or programming topics, who have sent patches, ideas on theoretical or programming topics, who have sent patches,
requests for changes or improvements, or who gave us access to exotic requests for changes or improvements, or who gave us access to exotic
machines for testing Gmsh: Juan Abanto, Olivier Adam, Guillaume machines for testing Gmsh: Juan Abanto, Olivier Adam, Guillaume
Alleon, Eric Bechet, Laurent Champaney, Pascal Dupuis, Patrick Dular, Alleon, Laurent Champaney, Pascal Dupuis, Patrick Dular, Philippe
Philippe Geuzaine, Johan Gyselinck, Francois Henrotte, Benoit Meys, Geuzaine, Johan Gyselinck, Francois Henrotte, Benoit Meys, Nicolas
Nicolas Moes, Osamu Nakamura, Chad Schmutzer, Jean-Luc Fl'ejou, Xavier Moes, Osamu Nakamura, Chad Schmutzer, Jean-Luc Fl'ejou, Xavier
Dardenne, Christophe Prud'homme, Sebastien Clerc, Jose Miguel Pasini, Dardenne, Christophe Prud'homme, Sebastien Clerc, Jose Miguel Pasini,
Philippe Lussou, Jacques Kools, Bayram Yenikaya, Peter Hornby, Krishna Philippe Lussou, Jacques Kools, Bayram Yenikaya, Peter Hornby, Krishna
Mohan Gundu, Christopher Stott, Timmy Schumacher, Carl Osterwisch, Mohan Gundu, Christopher Stott, Timmy Schumacher, Carl Osterwisch,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment