AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte ScriptEngine II (v. 0.6.1)

ScriptEngine II (v. 0.6.1)

Ein Thema von littleDave · begonnen am 21. Sep 2009 · letzter Beitrag vom 4. Aug 2011
Antwort Antwort
Seite 1 von 12  1 2311     Letzte » 
Benutzerbild von littleDave
littleDave
Registriert seit: 27. Apr 2006
Hallo liebe DP'ler

ScriptEngineII


ist der Nachfolger meiner letzten ScriptEngine. Da es sich um ein komplettes Remake handelt, sind die beiden jedoch nicht mehr vergleichbar.

Kurzübersicht
  • Die Script-Engine bnutzt Object-Pascal als Script-Sprache und unterstützt objekt-orientierte Programmierung.
  • Der Quelltext wird in ByteCode übersetzt, der dann von einer optimierten RunTime ausgeführt wird
  • Trotz der Möglichkeiten ist das Interface der Komponente sehr klein und übersichtlich gehalten
  • Für den Einstieg habe ich eine kleine Doku in Form eines PDFs mit in den Download gepackt

Installation
In der ZIP-Datei befindet sich ein Unterordner "src". Diesen extrahiert ihr einfach in einen Ordner eurer Wahl und fügt diesen Ordner dann in den Bibliothekspfad von Delphi hinzu. Im Quelltextorder befindet sich die Datei "ScriptEngine.inc". Diese Datei kann zum konfigurieren der ScriptEngine benutzt werden. Die einzelnen Defines sind (hoffentlich) ausreichend erklärt.

Benötigte Delphi-Version
Bisher hab ich es nur mit Delphi 7 und mit Lazarus getestet. Unter FreePascal hab ich nur ein paar Tests ausgeführt und diese sind auch korrekt gelaufen. Unter Delphi 2009/2010 hab ich die ScriptEngine ebenfalls erfolgreich getestet.

Besonderheiten
  • wenn man innerhalb einer Klassenmethode auf andere Klassenmethoden oder -Variablen zugreifen will, muss man immer "Self" mit angeben
    Update 10.10.2010
    Mit der Version ist 0.5.4.1 ist das nun nicht mehr notwendig!
  • Records sind Referenz-Typen

Bisherige Probleme
Im Moment sind noch folgende Probleme vorhanden:
  • überladene Methoden haben bisher folgende Einschränkung:
    • sie müssen alle vom selben Typ sein (statisch, nicht statisch)
  • der Befehl reintroduce ist noch nicht vorhanden

Lizenz
MPL v1.1 , GPL v3.0 oder LGPL v3.0

Feature-Liste
  • Übersicht
    • Object-Pascal als Dialekt
    • Ganzzahltypen: byte, shortint, word, smallint, cardinal, integer, int64
    • Fließkommatypen: single, double
    • Stringtypen: string, UTF8String, WideString
    • Operatoren: + - * / div mod shr shl and or xor not @
    • Vergleich: = < > <= >= <> is
    • Schleifen: for while repeat for-in-do
    • Datenvergleich: if case
    • Spezielle Blocks: try-finally / try-except
    • Konstanten
    • verschachtelte Unit-Namen (z.B. Unit1.SubUnit.SubUnit)
    • Partielle Units
    • Ablaufkontrolle: continue break exit
    • Exception-Handling und Exception-Throw möglich
    • Multi-Threading-Scripts
  • Methoden
    • Methodentypen: procedure function constructor destructor
    • Methodenparametertypen: const var
    • Methodenoperatoren: virtual abstract override overload forward
    • Import von DLL-Methoden direkt im Script (z.B.: procedure Sleep(milliSec: DWORD); external 'kernel32.dllname 'Sleep'; stdcall; )
    • OOP-Features: inherited
    • Spezielle Operatoren: external export
    • Unterstützte Aufrufkonventionen: register pascal stdcall cdecl
    • Methoden-Pointer
    • Events
  • Records
    • Abschnitte: private protected public
    • Record-Constanten (const-Deklaration in der record-Deklaration)
    • (statische) Record-Methoden
    • (statische) Record-Variablen
    • (statische) Record-Properties
    • Property-Typen: read+write, read-only, write-only
    • Property-Zugriff: direkt, über Methoden, über Methoden mit Parametern
  • Klassen
    • Objekt-Orientierte Programmierung
    • Klassenvererbung
    • Methoden überschreiben
    • Klassen-Sektionen: private protected public
    • Class-Constanten (const-Deklaration in der Class-Deklaration)
    • (statische) Klassenmethoden
    • (statische) Klassenvariablen
    • (statische) Klassenproperties
    • Property-Typen: read+write, read-only, write-only
    • Property-Zugriff: direkt, über Methoden, über Methoden mit Parametern
    • Partielle Klassen (so ähnlich wie bei .NET)
  • Class Helpers
    • Es können zu jedem Datentyp beliebig viele "Helfer-Klassen" erstellt werden
    • gleicher Aufbau wie bei normalen Klassen, nur die Deklaration ist etwas anders:
      • TStringHelper = helper for string
    • Class Helpers erweitern eine Klasse/einen Datentyp ohne die Vererbung zu nutzen
  • Compiler
    • schneller Compiler
    • eingebauter Unit-Cache für schnelleres kompilieren (so wie Delphi-DCUs)
    • partielle Units – mehrere einzelne Units mit gleichem Namen werden zu einer Unit zusammengefasst
    • Linker zum zusammenstellen und zum optimieren des Byte-Codes
    • IntelliSense / Code-Completion und Parameter-Hints-Unterstützung
    • eingebaut als abstrakte Klasse – für SynEdit bereits vorhanden
    • Speichern des kompilierten ByteCodes in einen Stream
  • RunTime
    • schneller ByteCode-Interpreter
    • direkter Aufruf von Delphi-Funktionen
    • Script-Methoden aus dem Programm heraus aufrufbar
    • Script-Methoden als TMethod-Event nativ aufrufbar
    • einfacher Garbage Collector für Script-Klassen (nur falls das Objekt nicht manuell zerstört wurde)
    • eigener Memory-Manager mit Caching für schnelleres Ausführen und für weniger Speicherfragmentierung
    • Exception-Handling
    • Stack-Tracing
  • Quelltext
    • durchgehende Namenskonvention (Units starten mit uSE2 und Klassen mit TSE2)
    • bisher keine Memory-Leaks gefunden

Noch ein paar kurze Hinweise
- Diesmal habe ich leider nicht so viele Beispiele mit in den Download hinein gepackt - es werden aber noch ein paar nachgeliefert

SVN
Ich hab für die Script-Engine ein Source-Forge-Projekt erstellt. Dort sind alle Änderungen auch per SVN abrufbar. Wichtige Releases werd ich natürlich weiterhin hier hochladen

Mitgelieferte IDE
Ich habe die kompilierte Version meiner aktuellen IDE mit in das Download-Paket gepackt. Zusätzlich hab ich den Source in den Unterordner IDEsrc gepackt - zusammen mit den drei kompilierten Packages. Mit der IDE kann man ein paar Testprojekte öffnen, die sich im Unterordner "Projects" befinden.

Ich hoffe, euch gefällt die neue Script-Engine und vielleicht kann der eine oder andere sie ja benutzen.

Download
Auf SourceForge.net (ca. 2,6 MB)

Grüße
Miniaturansicht angehängter Grafiken
screenshot1.png  
Jabber: littleDave@jabber.org
in case of 1 is 0 do external raise while in public class of object array else repeat until 1 is 0

Geändert von littleDave (10. Apr 2011 um 14:59 Uhr)
 
Benutzerbild von igel457
igel457

 
FreePascal / Lazarus
 
#2
  Alt 22. Sep 2009, 13:02
Hallo.

Erstmal ein dickes Lob für diese tolle Bibliothek, ich lese mir gerade deine vorbildhaft gestaltete Anleitung durch und spiele vielleicht mal noch ein wenig damit herum.

Was mir jedoch seltsam erscheint ist, dass du das Ganze unter eine CreativeCommons-Lizenz veröffentlicht hast - eigentlich sind diese ja gerade nicht für Software sondern Kunst (Texte, Musik, Bilder, Videos) geeignet.

Auch das "Keine Bearbeitung: der Quelltext darf nur unverändert weitergegeben werden" finde ich seltsam - wenn ich das Ganze nun in ein Opensource-Spiel integriere und dabei einige Dinge verbessere, warum darf ich dann diese Verbesserungen nicht der Öffentlichkeit (also auch dir) zurückgeben? Wenn ich die Script-Engine jedoch in ein Closed-Source-Spiel einbinde, dann kann ich umschreiben, was ich möchte und darf das dann veröffentlichen. Das ganze widersetzt sich a) dem Sinn von OpenSource und b) glaube ich dem, was du erreichen möchtest.
Zum Beispiel werde ich nicht in der Lage sein, deine Script-Engine in Andorra 2D zu integrieren und muss mir dann leider wohl eine andere Lösung suchen.

Warum veröffentlichst du es nicht unter einer Lizenz wie der GPL/LGPL und verkaufst kommerzielle Lizenzen?

Sonst wiederhole ich nochmal: Klasse Arbeit, weiter so!

Andreas
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

 
Delphi 7 Professional
 
#3
  Alt 22. Sep 2009, 13:23
Zitat von igel457:
Erstmal ein dickes Lob für diese tolle Bibliothek, ich lese mir gerade deine vorbildhaft gestaltete Anleitung durch und spiele vielleicht mal noch ein wenig damit herum.
Danke für das Lob, war auch einiges an Arbeit.

Zitat von igel457:
Was mir jedoch seltsam erscheint ist, dass du das Ganze unter eine CreativeCommons-Lizenz veröffentlicht hast - eigentlich sind diese ja gerade nicht für Software sondern Kunst (Texte, Musik, Bilder, Videos) geeignet.

Auch das "Keine Bearbeitung: der Quelltext darf nur unverändert weitergegeben werden" finde ich seltsam - wenn ich das Ganze nun in ein Opensource-Spiel integriere und dabei einige Dinge verbessere, warum darf ich dann diese Verbesserungen nicht der Öffentlichkeit (also auch dir) zurückgeben? Wenn ich die Script-Engine jedoch in ein Closed-Source-Spiel einbinde, dann kann ich umschreiben, was ich möchte und darf das dann veröffentlichen. Das ganze widersetzt sich a) dem Sinn von OpenSource und b) glaube ich dem, was du erreichen möchtest.
Zum Beispiel werde ich nicht in der Lage sein, deine Script-Engine in Andorra 2D zu integrieren und muss mir dann leider wohl eine andere Lösung suchen.

Warum veröffentlichst du es nicht unter einer Lizenz wie der GPL/LGPL und verkaufst kommerzielle Lizenzen?
Wegen der Lizenz bin ich mir selbst noch nicht so ganz zufrieden. Also GPL/LGPL finde ich persönlich nicht so wirklich gut, da ich auch Freeware-Programme das Framework nutzen können sollen, ohne den Quelltext mit frei geben zu müssen bzw. ohne dass das Framework in eine externe Library ausgelagert werden muss. Unter der BSD-Lizenz will ich das nicht stellen, denn wenn Leute mit dem Framework Geld verdienen, dann will ich auch was von dem Kuchen abhaben .

Aber mit fällt gerade was ein: das Framework wird grundsätzlich erstmal unter LGPL oder GPL freigegeben. Mit kurzer Absprache kann man auch eine andere Lizenz haben - was bei kommerziellen Einsatz einen gewissen Obolus kostet. Ich werd mir das noch überlegen (vielleicht noch ein/zwei Kommentare abwarten) - aber vielleicht heute Abend schon die Lizenz ändern.

Zitat von igel457:
Sonst wiederhole ich nochmal: Klasse Arbeit, weiter so!
Danke für das Lob - das freut mich
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

 
Delphi 12 Athens
 
#4
  Alt 22. Sep 2009, 13:32
Wegen der Lizenz, da hatte ich vor 'ner Weile auch mit zu kämpfen und am Ende ist das hier rausgekommen

MPL v1.1 , GPL v3.0 or LGPL v3.0


Kannst dir ja gern nochmal die Beiträge durchlesen
http://www.delphipraxis.net/internal...t.php?t=109739

Ansonsten gibt es noch massenhaft Themen dazu [dp]Lizenz*[/dp]
(oder einfach z.B. Begriffen=Lizenz und Autor=himitsu, da ich in einigen anderen Themen auch schon drin rumgepostet hab)
und in meinem himXML-Thread versteckt sich auch eine kleine Diskusion dazu (so zwischendurch ab Seite 4 oder so)


Mann oh mann, soviele ScriptEngines hier in der DP, da weiß man bald garnicht mehr, welche man nehmen soll
  Mit Zitat antworten Zitat
kalmi01
 
#5
  Alt 22. Sep 2009, 14:37
Hi,

habe die Demos mal unter D2009 compiliert:
  • uSE2Linker.pas(157): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'AnsiString'
    uSE2Linker.pas(207): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'AnsiString'
    uSE2Linker.pas(274): E2010 Inkompatible Typen: 'AnsiChar' und 'Char'
    uSE2Linker.pas(897): W1057 Implizite String-Umwandlung von 'AnsiString' zu 'string'
    uSE2Linker.pas(898): W1057 Implizite String-Umwandlung von 'AnsiString' zu 'string'
    uSE2Linker.pas(898): W1057 Implizite String-Umwandlung von 'AnsiString' zu 'string'
    uSE2Linker.pas(981): W1057 Implizite String-Umwandlung von 'AnsiString' zu 'string'
    uSE2Linker.pas(982): W1057 Implizite String-Umwandlung von 'AnsiString' zu 'string'
    uSE2Linker.pas(982): W1057 Implizite String-Umwandlung von 'AnsiString' zu 'string'
wobei lediglich in Zeile 274 das Chr(d) in AnsiChar(d) geändert werden musste.

Gruss
Michael
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

 
Delphi 7 Professional
 
#6
  Alt 22. Sep 2009, 14:47
Zitat von kalmi01:
habe die Demos mal unter D2009 compiliert:
  • uSE2Linker.pas(157): W1058 Implizite String-Umwandlung mit potenziellem Datenverlust von 'string' zu 'AnsiString'
    ...
wobei lediglich in Zeile 274 das Chr(d) in AnsiChar(d) geändert werden musste.

Gruss
Michael
Danke fürs Testen

Delphi 2009/2010 wird offiziell nicht unterstützt, da ich keine Möglichkeit habe, es zu testen. Werde die Zeile aber natürlich ersetzen.

Grüße
  Mit Zitat antworten Zitat
kalmi01
 
#7
  Alt 22. Sep 2009, 14:57
Zitat von littleDave:
Delphi 2009/2010 wird offiziell nicht unterstützt, da ich keine Möglichkeit habe, es zu testen. Werde die Zeile aber natürlich ersetzen.
ist schon klar, aber :
Zitat von littleDave:
Mit Delphi 2009/2010 hab ich die Script-Engine nicht ausprobiert, jedoch wurden alle Strings, die auch wirklich Ansi-Strings seien sollen, als solche deklariert.
deshalb wollte ich einfach mal ne Rückmeldung geben.
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

 
Delphi 7 Professional
 
#8
  Alt 22. Sep 2009, 16:11
Zitat von kalmi01:
Zitat von littleDave:
Delphi 2009/2010 wird offiziell nicht unterstützt, da ich keine Möglichkeit habe, es zu testen. Werde die Zeile aber natürlich ersetzen.
ist schon klar, aber :
Zitat von littleDave:
Mit Delphi 2009/2010 hab ich die Script-Engine nicht ausprobiert, jedoch wurden alle Strings, die auch wirklich Ansi-Strings seien sollen, als solche deklariert.
deshalb wollte ich einfach mal ne Rückmeldung geben.
So war das nicht gemeint - es war nur ein Hinweis. Ich finds wunderbar, dass du mir das gesagt hast.

Nochmal eben zum Lizenz-Problemchen
Ich habe nochmal genauer drüber nachgedacht, wie ich das mit der Lizenz jetzt mache. Ich finde den Vorschlag von himitsu mit den Mehrfachlizenzen wirklich gut und ich habe ihn auch im Endeffekt genau so umgesetzt: MPL, LGPL oder GPL. Das mit dem Verkaufen von kommerziellen Lizenzen hab ich mir dabei auch durch den Kopf gehen lassen und fand die Idee für mich nicht mehr so wirklich gut.

Wenn jemand das Framework wirklich gut findet, dann bin ich eigentlich auch schon mit einem Kommentar, Verbesserungsvorschlägen oder einer Spende (z.B. Beerware) total zufrieden.

Ich hab den Anfangspost sowie alle Positionen mit den Lizenzen (die mir gerade eingefallen sind) im Download angepasst.

Grüße
  Mit Zitat antworten Zitat
Vasco da Gama

 
Delphi 2009 Professional
 
#9
  Alt 22. Sep 2009, 18:00
Hi, ich wollte deine Engine mal wie in der .pdf Datei beschrieben ausprobieren.
vor punkt 2.4 scheitere ich, ich zitiere:
Zitat:
Wenn das Programm jetzt ausgeführt wird, werden zwar keine Fehlermeldungen mehr angezeigt, jedoch wird auch keine Zahl angezeigt. Das liegt jetzt aber nicht daran, dass das Script nicht ausgeführt wird – im Gegenteil. Es liegt nur daran, dass die Output-Methode der Script-Engine-Console noch nicht gesetzt ist. Doch das kann man schnell ändern.
Allerdings bekomme ich bei folgendem Code:
Delphi-Quellcode:
unit testunit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,
  uSE2Compiler, // für den Compiler
  uSE2UnitCacheMngr, // für den Unit-Cache-Manager
  uSE2Errors, // für TSE2ErrorType
  uSE2Reader, // wird zum Lesen der Daten benutzt
  uSE2PEData, // die ByteCode-Daten
  uSE2RunTime; // für die RunTime

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure CompilerError(Sender: TObject; ErrorType: TSE2ErrorType; ErrorUnit, ErrorText: string; ErrorPos, ErrorLine: integer; UserData: TObject);
    procedure CompilerNeedUnit(Sender: TObject; const Name: string; const Readers: TList);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  Compiler : TSE2Compiler;
  RunTime : TSE2RunTime;
  PEData : TSE2PE;
begin
  Compiler := TSE2Compiler.Create;// den Compiler erstellen
  try // hier wird der Quelltext des Scripts compiliert
    Compiler.OnGetFile := CompilerNeedUnit;
    Compiler.OnCompilerError := CompilerError;
    PEData := Compiler.Compile(
              'program MyScript;'
              +#13#10+ 'uses MyUnit;'
              +#13#10+ 'var i: integer;'
              +#13#10+ 'begin'+#13#10+ ' i := Add(2, 4);'
              +#13#10+ ' Console.WriteLine(i);'
              +#13#10+ 'end.'+#13#10); // falls das compilieren erfolgreich war, ist PEData ungleich nil
    if PEData <> nil then
    begin
      try // hier wird die RunTime erstellt, die das kompilierte
          // Script ausführt
        RunTime := TSE2RunTime.Create;
        try
          // zuerst muss das kompilierte Script übergeben werden
          RunTime.AppCode := PEData; // nun muss die RunTime initialisiert werden
          RunTime.Initialize; // hier wird das Script ausgeführt
          RunTime.Run; // nun noch die RunTime stoppen
          RunTime.Finalize; // wenn wir folgende Zeile nicht einfügen
          // RunTime.AppCode := nil
          // wird das Objekt PEData automatisch von der RunTime
          // freigegeben.
          // Da wir das aber selbst machen, fügen wir die Zeile ein RunTime.AppCode := nil;
        finally
          // die RunTime freigeben
          RunTime.Free;
        end;
      finally
        // das kompilierte Skript freigeben
        PEData.Free;
      end;
    end;
  finally // den Compiler freigeben
    Compiler.Free;
  end;
end;

procedure TForm1.CompilerError(Sender: TObject; ErrorType: TSE2ErrorType; ErrorUnit, ErrorText: string; ErrorPos, ErrorLine: integer; UserData: TObject);
begin
  // nur Fehler anzeigen
  if ErrorType = petError then // Fehlernachricht anzeigen
    ShowMessage('Compiler error: '+#13#10+ Format('[%s] [Zeile %d]: %s', [ErrorUnit, ErrorLine, ErrorText] ) );
end;

procedure TForm1.CompilerNeedUnit(Sender: TObject; const Name: string; const Readers: TList);
begin
  // falls der Compiler die Unit "MyUnit" haben will
  if SameText(Name, 'MyUnit') then
  begin
    // dann wird er Quelltext der Unit hinzugefügt
    // dazu muss in der Liste "Readers" ein Objekt vom
    // Typ "TSE2Reader" hinzufügen. Jedoch ist "TSE2Reader"
    // eine abstrakte Klasse. Vom Reader sind zwei Versionen
    // bei der Script-Engine mit dabei:
    // - ein StringReader, mit dem man direkt den Quelltext als
    // string übergeben kann
    // - ein StreamReader, mit dem man den Stream mit dem Quelltext
    // auslesen kann
     // da hier direkt ein String benutzt wird, wird der TStringReader
     // benutzt
     Readers.Add( TSE2StringReader.Create(
        // nun übergibt man im Constructor direkt den Quelltext
        // der Unit "MyUnit"
        'unit MyUnit;'+#13#10+
        'interface'+#13#10+
        ' function Add(const i1, i2: integer): integer;'+#13#10+
        'implementation'+#13#10+
        ' function Add(const i1, i2: integer): integer;'+#13#10+
        ' begin result := i1 + i2;end;'+#13#10+
        'end.' ) );
     end;
end;

end.
Bei Programmstart eine Fehlermeldung:
Erste Gelegenheit für Exception bei $7572FBAE. Exception-Klasse EInvalidPointer mit Meldung 'Ungültige Zeigeroperation'. Prozess TestProject.exe (1676)

So sagt mir das zumidest der Debugger

Ich hoffe du kannst mir helfen.

mfG
Flo
  Mit Zitat antworten Zitat
Benutzerbild von littleDave
littleDave

 
Delphi 7 Professional
 
#10
  Alt 22. Sep 2009, 18:16
Zitat von Vasco da Gama:
Hi, ich wollte deine Engine mal wie in der .pdf Datei beschrieben ausprobieren.
vor punkt 2.4 scheitere ich, ich zitiere:
Zitat:
Wenn das Programm jetzt ausgeführt wird, werden zwar keine Fehlermeldungen mehr angezeigt, jedoch wird auch keine Zahl angezeigt. Das liegt jetzt aber nicht daran, dass das Script nicht ausgeführt wird – im Gegenteil. Es liegt nur daran, dass die Output-Methode der Script-Engine-Console noch nicht gesetzt ist. Doch das kann man schnell ändern.
Allerdings bekomme ich bei folgendem Code:
//... Bei Programmstart eine Fehlermeldung:
Erste Gelegenheit für Exception bei $7572FBAE. Exception-Klasse EInvalidPointer mit Meldung 'Ungültige Zeigeroperation'. Prozess TestProject.exe (1676)

So sagt mir das zumidest der Debugger

Ich hoffe du kannst mir helfen.

mfG
Das liegt bei deinem Quellcode bei Zeile 65f - die schaut bei dir so aus:
Delphi-Quellcode:
  // Da wir das aber selbst machen, fügen wir die Zeile ein RunTime.AppCode := nil;
finally
müsste aber so aussehen:
Delphi-Quellcode:
  // Da wir das aber selbst machen, fügen wir die Zeile ein
  RunTime.AppCode := nil; // <---
finally
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:50 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz