diff options
author | buisson | 2003-03-14 16:37:29 +0000 |
---|---|---|
committer | buisson | 2003-03-14 16:37:29 +0000 |
commit | 4f5b107bbeca639a0a507ece0ac589ab3fe6a34c (patch) | |
tree | 99337ca802b0f9c82047e2ee96f154862049d08d | |
parent | 23abb4b87c7e40ed259dd02f653516f60e55ade4 (diff) | |
download | ivy-ada-4f5b107bbeca639a0a507ece0ac589ab3fe6a34c.zip ivy-ada-4f5b107bbeca639a0a507ece0ac589ab3fe6a34c.tar.gz ivy-ada-4f5b107bbeca639a0a507ece0ac589ab3fe6a34c.tar.bz2 ivy-ada-4f5b107bbeca639a0a507ece0ac589ab3fe6a34c.tar.xz |
Initial revision
-rw-r--r-- | README | 29 | ||||
-rw-r--r-- | copyright | 7 | ||||
-rw-r--r-- | src/Makefile | 31 | ||||
-rw-r--r-- | src/ivy.adb | 243 | ||||
-rw-r--r-- | src/ivy.ads | 178 | ||||
-rw-r--r-- | src/send.adb | 71 | ||||
-rw-r--r-- | src/spy.adb | 86 | ||||
-rw-r--r-- | src/spy_cb.adb | 22 | ||||
-rw-r--r-- | src/spy_cb.ads | 10 |
9 files changed, 677 insertions, 0 deletions
@@ -0,0 +1,29 @@ +-------------------------------------------------------------------- +Read Me first ! +-------------------------------------------------------------------- +To use this ivy-c ada wrapper, you must have ivy-c installed on your system. +(requires /usr/lib/libivy.so(.....) ) + +To compile "my_prog" (only if ivy.ads and ivy.adb are in current directory): + +%:gnatmake my_prog -largs -livy + +For instance, you will find in the src directory, to little examples +of how to use ivy in your programs : spy and send. + +just compile them by ready-to-use makefile : + +%:make or make spy or make send +%:make clean + +-------------------------------------------------------------------- +A lire avant de compiler ! +-------------------------------------------------------------------- +Pour utiliser Ivy en Ada, Ivy-c doit etre installe +(presence de /usr/lib/libivy.so(.....) obligatoire) + +Pour compiler "my_prog": +(si ivy.ads et ivy.adb sont dans le repertoire courant) + +gnatmake my_prog -largs -livy + diff --git a/copyright b/copyright new file mode 100644 index 0000000..4c688a7 --- /dev/null +++ b/copyright @@ -0,0 +1,7 @@ +This is open source software distributed under the terms of the GNU +Lesser General Public License. See the +/usr/share/common-licenses/LGPL-2.1 file for details. Some included +utilities are distributed under the terms of the GNU General Public +License, a copy of which is included in the file +/usr/share/common-licenses/GPL. + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..d63f55c --- /dev/null +++ b/src/Makefile @@ -0,0 +1,31 @@ +# +# Ivy, C interface +# +# Copyright (C) 1997-2002 +# Centre d'Études de la Navigation Aérienne +# +# Makefile +# +# Authors: François-Régis Colin <fcolin@cena.fr> +# Stéphane Chatty <chatty@cena.fr> +# +# $Id$ +# +# Please refer to file version.h for the +# copyright notice regarding this software +# + +TARGETS = spy send + +all: commands + +commands: $(TARGETS) + +spy: + gnatmake spy.adb -largs -livy + +send: + gnatmake send.adb -largs -livy + +clean: + -rm -f $(TARGETS) *.o *.ali *~ diff --git a/src/ivy.adb b/src/ivy.adb new file mode 100644 index 0000000..ae3dec9 --- /dev/null +++ b/src/ivy.adb @@ -0,0 +1,243 @@ +package body Ivy is + + +Type Dummy is null record; +Type Proc_Ptr is access procedure; + +--------------------------- routines de Ivy-c ------------------------------ +procedure C_IvyInit (Appname : C.Strings.chars_ptr; + Ready : C.Strings.chars_ptr; + AppCallback : AppCallback_T; + AppData : UserData_T; + DieCallback : DieCallback_T; + DieData : UserData_T); +pragma Import (C, C_IvyInit, "IvyInit"); + +procedure C_IvyStart ( Bus : C.Strings.chars_ptr ); +pragma Import (C, C_IvyStart, "IvyStart"); + +function C_IvyBindMsg (MsgCallback : MsgCallback_T; + Data : UserData_T; + Mess : C.char_array) + return Subscription_Id_T; +pragma Import (C, C_IvyBindMsg, "IvyBindMsg"); + +procedure C_IvyBindMsg (MsgCallback : MsgCallback_T; + Data : UserData_T; + Mess : C.char_array) is + +Dummy : Subscription_Id_T; +begin + Dummy:= C_IvyBindMsg (MsgCallback, Data, Mess); +end C_IvyBindMsg; +-- pragma Import (C, C_IvyBindMsg, "IvyBindMsg"); Non autorise en version 3.12 +-- de gnat (import multiple avec profils differents !?) + +-- Il faudrait traiter va_list .... +-- ou utiliser _BindMsg + +function C_IvySendMsg (Format : C.char_array := C.To_C("%s"); + Mess : C.char_array) return C.int; +pragma Import (C, C_IvySendMsg, "IvySendMsg"); + +procedure C_IvySendMsg (Format : C.char_array := C.To_C("%s"); + Mess : C.char_array) is +Dummy : C.int; +begin + Dummy:=C_IvySendMsg (Format, Mess); +end C_IvySendMsg; +-- pragma Import (C, C_IvySendMsg, "IvySendMsg"); Non autorise en version 3.12 +-- de gnat (import multiple avec profils differents !?) + +procedure C_IvySendDieMsg ( app : AppClientPtr_T); +pragma Import (C, C_IvySendDieMsg,"IvySendDieMsg"); + +procedure C_IvyUnbindMsg( Id : Subscription_Id_T); +pragma import (C, C_IvyUnbindMsg,"IvyUnbindMsg"); + +procedure C_IvyMainLoop ( Hook : Proc_Ptr := null); -- Hook inutile en Ada +pragma Import (C, C_IvyMainLoop, "IvyMainLoop"); + +------------------------------------------------------------------------- + +-- Objet protege pour garantir l'exclusion sur l'utilisation des +-- routines C (non re-entrantes) fournies par la lib Ivy. +-- Autorise aussi les appels en fonction du contexte: +-- Configure une seule fois, et les autres quand le bus est en +-- regime de croisiere.... + +Protected API is + entry Configure ( + AppName : String; -- nom de l'application + Ready : String; -- ready Message peut etre NULL + Bus : String := Default_Bus; + -- valeur par defaut de la lib Ivy C + AppCallback : AppCallback_T := null; + AppData : UserData_T := Null_Data; + DieCallback : DieCallback_T := null; + DieData : UserData_T:= Null_Data); + + entry SendMsg (Mess : String; Nb : out Nombre_T); + entry SendMsg (Mess : String); + entry SendDieMsg ( app : AppClientPtr_T); + entry Wait_BusReady; + entry BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + regexp : String; + Id : out Subscription_Id_T); + entry BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + regexp : String); + entry UnbindMsg ( Id : Subscription_Id_T); +private + BusReady : Boolean :=False; +end API; + +protected body API is + +entry Configure( + AppName : String; -- nom de l'application + Ready : String; -- ready Message peut etre NULL + Bus : String := Default_Bus; + -- valeur par defaut de la lib Ivy C + AppCallback : AppCallback_T :=null; + AppData : UserData_T := Null_Data; + DieCallback: DieCallback_T := null; + DieData : UserData_T:= Null_Data) + when not(BusReady) is +begin + C_IvyInit (Appname => C.Strings.New_String(AppName), + Ready => C.Strings.New_String(Ready), + AppCallback => AppCallback, + AppData => AppData, + DieCallback => DieCallback, + DieData => DieData); + C_IvyStart(C.Strings.New_String(Bus)); + BusReady:= True; +end configure; + +entry SendMsg (Mess : String; Nb : out Nombre_T) when BusReady is +begin + Nb:=Nombre_T(C_IvySendMsg( Mess => C.To_C(Mess))); +end SendMsg; + +entry SendMsg (Mess : String) when BusReady is +begin + C_IvySendMsg( Mess => C.To_C(Mess)); +end SendMsg; + +entry SendDieMsg ( app : AppClientPtr_T) when BusReady is +begin + C_IvySendDieMsg(app); +end SendDieMsg; + +entry BindMsg ( MsgCallback : MsgCallback_T; + User_data : UserData_T; + Regexp : String; + Id : out Subscription_Id_T) when BusReady is +begin + Id:=C_IvyBindMsg( MsgCallback, user_data, C.To_C(regexp)); +end BindMsg; + +entry BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + Regexp : String) when BusReady is +begin + C_IvyBindMsg( MsgCallback, user_data, C.To_C(regexp)); +end BindMsg; + +entry UnbindMsg ( Id : Subscription_Id_T) when BusReady is +begin + C_IvyUnbindMsg(Id); +end UnbindMsg; + +entry Wait_BusReady when BusReady is +begin + null; +end Wait_BusReady; + +end API; + +----------------------------------------------------------- +-- Tache qui encapsule la mainloop C (qui ne retourne jamais) + +Task Ivy_Run; +Task body Ivy_Run is +begin + API.Wait_BusReady; + C_IvyMainloop; +end Ivy_Run; + +------------------- Configure ------------------------ + +procedure Configure ( + AppName : String; -- nom de l'application + Ready : String; -- ready Message peut etre NULL + Bus : String := Default_Bus; + AppCallback : AppCallback_T := null; + AppData : UserData_T := Null_Data; + DieCallback : DieCallback_T := null; + DieData : UserData_T:= Null_Data) is +begin + API.Configure(AppName, Ready, Bus, AppCallback, AppData, + DieCallback, DieData); +end Configure; + +------------------- SendMsg -------------------------- + +function SendMsg (Mess : String) return Nombre_T is + +Nb : Nombre_T; +begin + API.SendMsg(Mess,Nb); + return Nb; +end SendMsg; + +procedure SendMsg (Mess : String) is +Dummy : Nombre_T; +begin + API.SendMsg(Mess,Dummy); +end SendMsg; + + +------------------ SendDieMsg ------------------------- + +procedure SendDieMsg ( app : AppClientPtr_T) is +begin + API.SendDieMsg( App); +end SendDieMsg; + +------------------ BindMsg ---------------------------- + +function BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + regexp : String) return Subscription_Id_T is +Id : Subscription_Id_T; +begin + API.BindMsg(MsgCallback, user_data, regexp, Id); + return Id; +end BindMsg; + +procedure BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + regexp : String) is +Dummy : Subscription_Id_T; +begin + API.BindMsg(MsgCallback, user_data, regexp, Dummy); +end BindMsg; + +------------------- UnbindMsg ---------------------------- + +procedure UnbindMsg ( Id : Subscription_Id_T) is +begin + API. UnbindMsg ( Id); +end UnbindMsg; + +-------------------- Kill ----------------------------------- + +procedure Kill is +begin + -- Massacre sauvage de la main loop! + abort Ivy_Run; +end Kill; +end ivy; diff --git a/src/ivy.ads b/src/ivy.ads new file mode 100644 index 0000000..e77b7b0 --- /dev/null +++ b/src/ivy.ads @@ -0,0 +1,178 @@ + +-- Ajouter commentaires sur le binding +-- pas d'exeptions a cause du C + +-- +-- Portage rapide pour utiliser Ivy en mode minimal en Ada +-- (Interfaces avec les routines C) +-- + +with Interfaces.C; +with Interfaces.C.Strings; +with Interfaces.C.Pointers; + + +package Ivy is + + +Default_Bus : constant String := ":2010"; + +------------------------------------------------------------------- +-- Interface avec C +------------------------------------------------------------------- +package C renames Interfaces.C; + +type chars_ptr_array is array(C.size_t range <>) + of aliased C.Strings.chars_ptr; + +-- Package pour les char ** de C +Package chars_ptr_pointers is new Interfaces.C.Pointers( + Index => C.size_t, + Element => C.Strings.chars_ptr, + Element_array => chars_ptr_array, + Default_Terminator => C.Strings.Null_Ptr); + +-- les types char * et char ** de C +Type C_Char_Etoile_T is new C.Strings.chars_ptr; + +--Type C_Char_Etoile_Etoile_T is new chars_ptr_pointers.Pointer; +subType C_Char_Etoile_Etoile_T is chars_ptr_pointers.Pointer; + +-- Transformation Chaine de caracteres C -> String Ada +Function Value ( V : C.Strings.chars_ptr) return String + renames C.Strings.Value; + +------------------------------------------------------------------- +-- +-- Les Types necessaires pour interfacer avec les routines Ivy C +-- +------------------------------------------------------------------- + +subtype C_Int_T is C.int; +Subtype Nombre_T is C.int; +Type UserData_T is new Integer; +Null_Data : constant UserData_T := 0; +Type Id_T is new C.int; + +Type AppEvent_T is (AppConnected, AppDisconnected); +for AppEvent_T use (AppConnected => C.int(0), + AppDisconnected => C.int(1)); + +Type AppClientPtr_T is private; +Type Subscription_Id_T is private; -- identificateur quand on s'abonne + +-- Type de callback appele sur connexion deconnexion d'une appli +Type AppCallback_T is access procedure ( + app : AppClientPtr_T; + user_data : UserData_T; + event : AppEvent_T); + +-- Type de callback appele sur reception de die +Type DieCallback_T is access procedure( + app : AppClientPtr_T; + user_data : UserData_T; + id : Id_T); + +-- Type de callback appele sur reception de messages normaux +Type MsgCallback_T is access procedure( + app : AppClientPtr_T; + user_data : UserData_T; + argc : C_Int_T; + argv : C_Char_Etoile_Etoile_T); + +-- Type de callback appele sur reception de messages directs +Type MsgDirectCallback_T is access procedure( + app : AppClientPtr_T; + user_data : UserData_T; + id : Id_T; + msg : C_Char_Etoile_T); + +-- filtrage des regexps +-- procedure Classes( ) a implementer avec operateur + +-- pour pouvoir ecrire: Classes("avion"+"....."+"...."); + +-------------------------------------------------------------------------- +-- +-- Les Procedure et fonctions principales d'Ivy +-- +-------------------------------------------------------------------------- + +-- Procedure de configuration qui appelle IvyInit, IvyStart, +-- (IvyBindMsg si neccessaire) et IvyMainloop + +procedure Configure ( + AppName : String; -- nom de l'application + Ready : String; -- ready Message peut etre NULL + Bus : String := Default_Bus; + -- valeur par defaut de la lib Ivy C + AppCallback : AppCallback_T := null; + AppData : UserData_T := Null_Data; + DieCallback : DieCallback_T := null; + DieData : UserData_T:= Null_Data); + +function SendMsg (Mess : String) return Nombre_T ; +-- emission d'un message +-- rend le nombre de messages effectivement envoyes + +procedure SendMsg (Mess : String); +-- emission d'un message sans compte-rendu + +procedure SendDieMsg ( app : AppClientPtr_T); +-- emission d'un message die pour terminer l'application + +-- Abonnement avec une regexp +-- La fonction rend un identificateur utile pour se desabonner +function BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + regexp : String) return Subscription_Id_T; + +procedure BindMsg ( MsgCallback : MsgCallback_T; + user_data : UserData_T; + regexp : String); + +-- Annulation abonnement +procedure UnbindMsg ( Id : Subscription_Id_T); + +-- Tue la main loop Ivy (definitif avant un exit ....) +Procedure Kill; + +--------------------------------------------------------------------------- +private + +Type Dummy; +Type AppClientPtr_T is access Dummy; +Type Subscription_Id_T is access Dummy; -- identificateur quand on s'abonne + +-- Les procedures ou fonctions de la lib ivy en C utilisent ces types +-- pointeurs sur des structures ad hoc. +-- En Ada, pour ce binding, on a juste besoin de recuperer des variables +-- de ces types pour les fournir a d'autres procedures sans intervenir +-- directement sur les donnees sur lesquelles elles pointent, d'ou le +-- typage utilise. + + +-- Autres infos pour poursuivre le portage + +--typedef struct _clnt_lst *IvyClientPtr; +--/* identifiant d'une expression reguliere ( Bind/Unbind ) */ +--typedef struct _msg_rcv *MsgRcvPtr; + + +--/* query sur les applications connectees */ +--char *IvyGetApplicationName( IvyClientPtr app ); +--char *IvyGetApplicationHost( IvyClientPtr app ); +--IvyClientPtr IvyGetApplication( char *name ); +--char *IvyGetApplicationList(); +--char **IvyGetApplicationMessages( IvyClientPtr app); /* demande de reception d'un message */ + + +--/* emission d'un message d'erreur */ +--void IvySendError( IvyClientPtr app, int id, const char *fmt, ... ); + + +--/* Message Direct Inter-application */ + +--void IvyBindDirectMsg( MsgDirectCallback callback, void *user_data); +--void IvySendDirectMsg( IvyClientPtr app, int id, char *msg ); + +end Ivy; diff --git a/src/send.adb b/src/send.adb new file mode 100644 index 0000000..6e65025 --- /dev/null +++ b/src/send.adb @@ -0,0 +1,71 @@ +with Ivy; use Ivy; +with Ada.Text_Io; use Ada.Text_Io; + +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with GNAT.Command_Line; use GNAT.Command_Line; +with GNAT.OS_Lib; + +Procedure Send is + +--| Envoi sur le bus des lignes tapees au clavier +--| (l'envoi d'une ligne a lieu sur le "Return") + +Buffer: String(1..128); +Last: Natural; + +Bus : Unbounded_String := To_Unbounded_String(Ivy.Default_Bus); +IvyBus : GNAT.OS_Lib.String_Access; +--| Pour recuperer la variable d'environnement IVYBUS + + +-- Mode d'emploi +Procedure Print_Usage is +begin + Put_Line("send accepte:"); + Put_Line(" -b arg : Port Ivy"); + Put_Line(" -h : help"); +end Print_Usage; + +begin -- send + +--| +--| Variables d'environnement +--| + +IvyBus:= GNAT.OS_Lib.Getenv("IVYBUS"); +if IvyBus.all'length /= 0 then --| La variable existe + Bus:= To_Unbounded_string(IvyBus.all); +end if; + +--| +--| Recuperation ligne de commande +--| + +loop + case Getopt ("b: h ") is + when Ascii.NUL => exit; + when 'b' => + Bus := To_Unbounded_String(Parameter); + Ada.Text_Io.Put_Line ("Bus : " & To_String(Bus)); + when 'h' => + Print_Usage; + return; + when others => + null; -- cannot occur! + end case; +end loop; + +-- Initialisation Bus + +Ivy.Configure( AppName => "Send", + Ready => "Hello", + Bus => To_String(Bus)); + +-- envoi de messages saisis au clavier + +loop + Get_Line(Buffer,last); + Ivy.SendMsg(Buffer(1..Last)); +end loop; + +end Send; diff --git a/src/spy.adb b/src/spy.adb new file mode 100644 index 0000000..1b7f785 --- /dev/null +++ b/src/spy.adb @@ -0,0 +1,86 @@ +with Ivy; +with Spy_Cb; + +with Ada.Text_Io; use Ada.Text_Io; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with GNAT.Command_Line; use GNAT.Command_Line; +with GNAT.OS_Lib; + +-- Exemple message rejeu 2.00: +-- TrackMovedEvent Flight=8182 CallSign=AF261DO Ssr=0464 Sector=TW +-- Layers=M,I X=52.70 Y=55.88 Vx=133 Vy=436 Afl=175 Rate=-2760 Heading=17 +-- GroundSpeed=456 Tendency=-1 Time=10:00:00 + +procedure spy is + +--| Equivalent de Ivyprobe en Ada en reception + +Bus : Unbounded_String := To_Unbounded_String(Ivy.Default_Bus); +IvyBus : GNAT.OS_Lib.String_Access; +--| Pour recuperer la variable d'environnement IVYBUS + +Regexp: Unbounded_String; +Default_Regexp: Unbounded_String :=To_Unbounded_String("(.*)"); +--| tous les messages + + +-- Mode d'emploi +Procedure Print_Usage is +begin + Put_Line("spy accepte:"); + Put_Line(" -b arg : Port Ivy"); + Put_Line(" -h : help"); + Put_Line(" regexp : Regexp pour abonnement - '(.*)' par defaut"); +end Print_Usage; + +begin -- Spy + +--| +--| Variables d'environnement +--| + +IvyBus:= GNAT.OS_Lib.Getenv("IVYBUS"); +if IvyBus.all'length /= 0 then --| La variable existe + Bus:= To_Unbounded_string(IvyBus.all); +end if; + +--| +--| Recuperation ligne de commande +--| + +loop + case Getopt ("b: h") is + when Ascii.NUL => exit; + when 'b' => + Bus := To_Unbounded_String(Parameter); + Ada.Text_Io.Put_Line ("Bus : " & To_String(Bus)); + when 'h' => + Print_Usage; + return; + when others => + null; -- cannot occur! + end case; +end loop; + +Regexp:= To_Unbounded_String(Get_Argument); +if Regexp=Null_Unbounded_String then + Regexp:=Default_Regexp; +end if; + +--| +--| Initialisation Bus +--| + + + Ivy.Configure( AppName => "Spy", + Ready => "Hello", + Bus => To_String(Bus)); + + Ivy.BindMsg( MsgCallback => Spy_Cb.Print'access, + User_Data => 0, + Regexp => To_String(Regexp) ); +-- exemples: +-- Regexp => "^AIRCRAFT:(.*) heading=([0-9]*) (.*)"); +-- Regexp => "^AIRCRAFT:([A-Z]*[0-9]*)" ); +-- Regexp => "^AIRCRAFT:(.*)"); +end Spy; diff --git a/src/spy_cb.adb b/src/spy_cb.adb new file mode 100644 index 0000000..9335876 --- /dev/null +++ b/src/spy_cb.adb @@ -0,0 +1,22 @@ +with Ada.Text_Io; +use Ada.Text_Io; + +package body Spy_Cb is + +procedure Print(app : AppClientPtr_T; + user_data : UserData_T; + argc : C_Int_T; + argv : C_Char_Etoile_Etoile_T) is + +Tab_arg : C_Char_Etoile_Etoile_T := argv; + +begin + for I in 1..argc loop + Put( " |- " & C_Int_T'Image(I) & " -| "& + Value(Tab_arg.all)); + Chars_ptr_pointers.Increment(Tab_arg); + end loop; + New_Line; +end Print; + +end Spy_Cb; diff --git a/src/spy_cb.ads b/src/spy_cb.ads new file mode 100644 index 0000000..8600287 --- /dev/null +++ b/src/spy_cb.ads @@ -0,0 +1,10 @@ +with Ivy; use Ivy; + +package Spy_Cb is + +procedure Print(app : AppClientPtr_T; + user_data : UserData_T; + argc : C_Int_T; + argv : C_Char_Etoile_Etoile_T); + +end Spy_Cb; |