Schnittstellen werden heute meist als C-, C++ oder BASIC-Programme codiert. Der Programmieraufwand für die Erstellung einer Schnittstelle ist vor allem im Bereich der GIS-Systeme gross, da neben Sachdaten auch Geometriedaten übertragen werden müssen. Dies führt dazu, dass nur relativ wenige Schnittstellen (hauptsächlich DXF) mit begrenztem Funktionsumfang von den Systemherstellern angeboten werden.
Mit der Entwicklung von ICS wurde ein anderer Weg beschritten. Bei ICS handelt es sich um ein flexibles Schnittstellensystem für die schnelle Entwicklung von Schnittstellenprogammen. Folgende Ideen lagen der Entwicklung von ICS zugrunde:
Jedes Schnittstellenprogramm kann in einen Input- und in einen Outputmodul zerlegt werden. Dabei liest der Inputmodul Objekte aus der Inputdatei und wandelt sie in ein neutrales internes Objektformat um. Der Outputmodul nimmt Objekte vom Inputmodul entgegen und schreibt sie in die Outputdatei. Damit wird eine Entkoppelung des Schnittstellenprogramms in zwei unabhängige, wiederverwendbare Module erreicht
Im Kern werden die Funktionen zusammengefasst, welche von allen Modulen benötigt werden (z.B. String- und Geometriefunktionen). Dadurch müssen diese Funktionen nur einmal programmiert werden
Der Datenfluss der Objekte vom Inputmodul zum Outputmodul wird nicht durch ein compiliertes Programm gesteuert, sondern über die Skriptsprache iG/Script
Nachfolgend ist die Architektur einer ICS-Schnittstelle dargestellt:
| ![[Anmerkung]](images/note.png) | |
| Der Kern und die Input- bzw. Outputmodule werden von der infoGrips GmbH entwickelt. iG/Script-Programme können auch vom Benutzer geschrieben werden. | 
Der ICS-Kern enthält, neben den allgemeinen Funktionen für die Behandlung von Datenstrukturen (Strings, Geometrie, Maps etc.), einen Interpreter für die iG/Script-Sprache. iG/Script ist eine allgemeine Programmiersprache mit einem vordefinierten Satz von Standardfunktionen. Die Sprache enthält neben arithmetischen-, logischen- und Zuweisungsoperationen, auch Kontrollstrukturen wie IF und WHILE. Daneben bietet sie die Möglichkeit den Sprachumfang durch Prozeduren zu erweitern. Als Basistypen kennt die iG/Script-Sprache die Typen Integer, Real, String, Boolean und Geometrie. Strukturierte Datentypen können über den Datentyp Map erzeugt werden. Input- bzw. Outputmodule können, falls nötig, zusätzliche Datentypen implementieren.
Zu bestehenden Programmiersprachen ist iG/Script am ehesten mit der Programmiersprache FORTH verwandt. Mit FORTH verbindet sie, dass sie ebenfalls alle Operationen über einen Stack abwickelt und eine klammerfreie Darstellung von Ausdrücken verwendet. Der wesentliche Unterschied zwischen FORTH und iG/Script liegt darin, dass FORTH für die hardwarenahe Programmierung entwickelt wurde, iG/Script hingegen ist eine hardwareunabhängige Sprache die sich besonders für die Entwicklung von Schnittstellenapplikationen eignet.
Objekte sind die Basisdatenstruktur von iG/Script. Objekte können mit iG/Script über die Input- bzw. Outputmodule gelesen, geschrieben und über Methoden des Kerns manipuliert werden. Bei den Objekten wird zwischen einfachen und stukturierten bzw. zwischen benannten und unbenannten Objekten unterschieden.
Unter einfachen Objekten versteht man in iG/Script Konstanten der Basistypen. In iG/Script sind folgende Basistypen fest eingebaut:
String, z.B.
               'hello, World'
Integer, z.B.
               1234
Real, z.B.
               123.456
Boolean, d.h.
               TRUE oder FALSE
Geometrie, d.h. Punkt, Linie oder Fläche
Blob, d.h. beliebiger binärer Wert
Strukturierte Objekte bestehen aus einer oder mehreren Komponenten. Komponenten haben einen Namen und einen Wert. Der Wert einer Komponente kann ein Basystyp oder auch ein Objekt sein, d.h. strukturierte Objekte sind im allgemeinen Fall hierarchisch aufgebaut.
Beispiel 1. IN-Objekt
Ein Objekt, dass vom INTERLIS-Inputmodul ILIN aus der
            Tabelle LFP gelesen wurde, hat u.a. folgende Komponenten
            (Entstehung, Nummer,
            Numpos, etc.):
| Komponente | Wert | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| 
 | 
 | 
| ![[Anmerkung]](images/note.png) | |
| Strukturierte Objekte werden in iG/Script als sog. Map's implementiert. Mehr dazu in ???. | 
Listen sind beliebige, einfach verknüpfte Ketten von ICS Objekten. Jeder Basistyp oder jedes sturkturierte Objekt (Map) oder auch jede Liste kann wieder Element einer Liste sein. Für die Bearbeitung von Listen stellt der ICS Kern eine Reihe von eingebauten Methoden zur Vefügung. Listen können z.B. dynamisch wachsen oder schrumpfen, Listen können durchsucht werden, etc.
Arrays sind Gruppen von ICS Objekten. Die einelnen Objekte eines Arrays können über einen ganzahligen Index angesprochen (indiziert) werden. Array haben im Gegensatz zu den Listen immer eine fixe Länge.
Die meisten Objekte von iG/Script sind Komponenten des
         vordefinierten Systemobjekts ROOT. Komponenten von
         ROOT haben einen Namen über den sie in der
         Scriptsprache direkt adressiert werden können. z.B. hat das IN-Objekt
         aus dem ILIN Beispiel im System den Namen ROOT.IN
         und die Nummer Komponente den Namen
         ROOT.IN.Nummer.
Der Name des Objekts entspricht also dem Pfad von der Wurzel (ROOT) bis zum Objekt (analog zu Dateinamen in einem Dateibaum). Allgemein kann ein Objekt in iG/Script über folgenden Namen angesprochen werden:
<Objektname> := ROOT.<Komponentename>
<Komponentenname> := <Name> | <Komponentenname> . <Name>
<Name> := <Zeichenkette>
Um die Schreibweise zu vereinfachen, ist es erlaubt
         ROOT am Anfang des Objektnamens wegzulassen. Die
         Nummer Komponente des IN-Objekts kann daher in
         iG/Script auch als IN.Nummer angesprochen
         werden.
iG/Script arbeitet ähnlich wie ein HP-Taschenrechner, d.h. iG/Script kommt vollständig ohne Klammerung von Ausdrücken aus. Alle Zwischenergebnisse werden auf dem sog. Stack abgelegt. Will man z.B. 1 + 2 berechnen so schreibt man in iG/Script:
1 2 +
weitere Beispiele:
| Ausdruck | iG/Script-Lösung | 
| 2 * (1 + 7) |  | 
| 
 |  | 
Konstanten der Basistypen werden sofort auf den Stack geschoben. Sehen wir uns also den Stack während der Berechnung des Ausdrucks 2 * 3 genauer an:
| Eingabe | Stack | 
| 2 | [2] | 
| 3  |  | 
| *  |  | 
In der obigen Darstellung wird der Stack durch [ ...
      ] repräsentiert (diese Darstellung wurde aus Platzgründen
      gewählt, normalerweise wird ein Stack oft als senkrechte Kolonne
      dargestellt). Das am weitesten rechts stehende Objekt wird aktuelles,
      erstes oder auch oberstes Objekt des
      Stacks genannt. Alle iG/Script-Methoden nehmen die N obersten Objekte
      des Stacks als Argumente und liefern M Objekte auf dem Stack als
      Resultate zurück. Z.B. konsumiert die Multiplikationsmethode 2 Argumente
      auf dem Stack und liefert nach ihrer Beendigung das Resultat als
      oberstes Objekt des Stacks zurück.
Neben arithmetischen Methoden kennt iG/Script-Skript weitere Standardmethoden für die Bearbeitung von Strings oder die Ausgabe auf den Bildschirm etc.. Gleichartige Methoden werden zu einer Klasse zusammengefasst (eine Klasse wird durch ein Modul implementiert). Die iG/Script-Standardmethoden gehören z.B. zu der Klasse ICS. Will man eine Methode aus einer bestimmten Klasse aufrufen so schreibt man in iG/Script
<Klasse>.<Methode>
also z.B. ILIN.READ_OBJECT (Aufruf der Methode
      READ_OBJECT aus der Klasse ILIN).
      Die Standardmethoden sind in der Klasse ICS implementiert. Methoden der
      Klasse ICS müssen jedoch nicht mit dem Klassennamen qualifiziert werden
      (ICS.<Methode). Es genügt den Methodennamen anzugeben, die Angabe des
      Klassennamens ICS ist jedoch erlaubt.
Beispiel 2. Abgekürzter Methodenaufruf
- und ICS.- sind beides
         erlaubte Schreibweisen für die Subtraktionsmethode
| ![[Anmerkung]](images/note.png) | |
| Man sieht, dass Methoden gleich adressiert werden wie Objekte. Tatsächlich sind Methoden in ICS nichts anderes als Komponenten eines Klassenobjekts. | 
Damit das nachfolgende Beispiel besser verstanden werden kann, sollen hier kurz einige wichtige Standardmethoden eingeführt werden (eine vollständige Liste der Standardklassen und Standardmethoden ist im Referenzhandbuch enthalten):
| Methode | Beschreibung | 
| 
 | zeigt das oberste Objekt des Stacks auf dem Bildschirm an | 
| 
 | dupliziert das oberste Objekt auf dem Stack | 
| 
 | hängt die obersten beiden Objekte des Stacks als String zusammen | 
| 
 | berechnet die Länge des obersten Stringobjekts | 
Damit sind wir nun in der Lage, ein einfaches iG/Script-Beispiel
      anzugeben. In dem Beispiel soll die Länge des Strings 'hello,
      World' berechnet werden und zusammen mit dem String auf den
      Bildschirm ausgegeben werden. Wir benutzen dazu die Standardmethoden
      DUP, LEN, APP und DISP.
Beispiel 3. iG/Script Code
'hello, World'! Stack: ['hello, World']DUP! Stack: ['hello, World', 'hello, World']LEN! Stack: ['hello, World', 12]APP! Stack: ['hello, World12']DISP! Stack: [] Ausgabe auf Bildschirm: hello, World12
Man sieht an diesem Beispiel wie die Methoden ihre Argumente vom Stack entgegennehmen und ihre Resultate wieder auf dem Stack ablegen. Dieses Verhalten ist für iG/Script typisch.
Oft ist es notwendig, Zwischenresultate einer Berechnung permanent abzulegen. Der Stack ist dazu ungeeignet, da seine Werte durch die Methoden ständig neu überschrieben werden. Für die permanente Speicherung von Objekten verfügt die iG/Script-Sprache deshalb über den Objekttyp Map. Maps müssen durch den Benutzer deklariert werden und zwar vor der ersten ausführbaren Anweisung im Skript. Mapdeklarationen haben folgende Syntax:
MAP <Mapname> 
   {<Name1> => <Wert1>}+ 
END_MAP
In obigem Beispiel enthält das Map-Objekt TEST die Komponenten VAR1 und VAR2. Der Wert von VAR1 ist 'hello, World' und der Wert von VAR2 ist 'dies ist ein Test'. Der Wert einer Komponente kann im Skript mit:
<Mapname>.<Komponentenname>
angesprochen werden (s.a. 2.2). Analog zu den Basistypen wird der Wert einer Komponente sofort nachdem sie im Skript angetroffen wurde auf den Stack geschoben.
Beispiel 5. Arbeiten mit dem Stack
TEST.VAR1! Stack: ['hello, World']TEST.VAR2! Stack: ['hello, World','dies ist ein Test']APP! Stack: ['hello, Worlddies ist ein Test']DISP! Stack: [] Bildschirm: hello, Worlddies ist ein Test
Komponenten kann wie folgt ein neuer Wert zugewiesen werden:
=> <Komponente> 
oder
-> <Komponente>
Mit => wird jeweils das oberste Objekt des
      Stacks der Komponente zugewiesen. Mit -> wird nur
      der Teilstring des obersten Stackelements bis zum ersten Komma
      zugeordnet (nur bei Stringobjekten möglich). Der Rest des Strings bleibt
      auf dem Stack erhalten.
Beispiel 6. Benutzung von => und
         ->
'hallo' => TEST.VAR1 ! TEST.VAR1 enthält nun 'hallo'!Stack: [] 'hello, World' -> TEST.VAR1 ! TEST.VAR1 enthält nun 'hello'! Stack: [' World'] => TEST.VAR2 ! TEST.VAR2 enthält nun ' World' ! Stack: []
Es ist auch erlaubt nicht existierenden Komponenten einen Wert zu
      zuweisen (die Map muss allerdings bereits existieren). Will man also
      z.B. den Wert von TEST.VAR1 und
      TEST.VAR2 vertauschen so kann man wie folgt
      vorgehen:
Beispiel 7. Zuweisung von Variablen
TEST.VAR1 => TEST.TMP! die Zwischenvariable TEST.TMP wird erzeugtTEST.VAR2 => TEST.VAR1TEST.TMP => TEST.VAR2
| ![[Anmerkung]](images/note.png) | |
| Komponenten werden häufig als Variablen in einem iG/Script
         Programm gebraucht. Für die Speicherung von Variablen stellt ICS
         daher die vordefinierte Map  | 
Jeglicher Text nach einem ! bis zum Ende der aktuellen Zeile wird in iG/Script als Kommentar aufgefasst.
Neben der DISP Methode, gibt es noch eine spezielle eingebaute Methode DISPLAY welche sich besonders für die Ausgabe von Objekten eignet:
DISPLAY <Objekt>
Gibt den Wert des Objekts auf den Bildschirm aus
DISPLAY $
Gibt das oberste Objekt des Stacks aus (analog DISP)
DISPLAY <String>,<Objekt>
Gibt den Inhalt des Strings und des Objekts aus (z.B.
      DISPLAY 'TEST.VAR1=',TEST.VAR1). Dabei wird der Wert
      des Objekts in einen String umgewandelt und am Ende von <String>
      angehängt. Es dürfen auch mehrere Strings und Objekte in der Liste
      aufgeführt werden. Die einzelnen Werte müssen jeweils durch ein Komma
      getrennt werden.
| ![[Anmerkung]](images/note.png) | |
| Neben  | 
Map-Objekte werden in der iG/Script-Sprache in drei verschiedenen Zusammenhängen gebraucht. Die erste Bedeutung als Variablenspeicher haben wir bereits kennengelernt (s.a. 2.6). Maps können aber auch als Abbildungstabellen oder als Objektspeicher benutzt werden. Betrachten wir z.B. folgende Map:
MAP Jahreszeiten Januar => Winter Mai => Frühling Juni => Sommer September => Herbst END_MAP
Dieses Map-Objekt kann als Abbildungstabelle von Monaten auf
      Jahreszeiten aufgefasst werden. Schreibt man in iG/Script z.B.
      'Januar' Jahreszeiten so wird auf dem Stack
      'Winter' abgelegt.
Beispiel 9. Abbildungen mit Maps
'Januar' Jahreszeiten DISP! Bildschirm: 'Winter''Mai' Jahreszeiten DISP! Bildschirm: 'Frühling'
Abbildungstabellen können auch kombiniert werden. Es ist z.B. folgende zusätzliche Map definiert
MAP Temperatur Winter=> kalt Sommer=> warm DEFAULT=> mittel END_MAP
Dann führen die Ausdücke zu folgenden Resultaten:
'Januar' Jahreszeiten Temperatur DISP! Bildschirm: kalt'September' Jahreszeiten Temperatur DISP! Bildschirm: mittel
Im letzten Beispiel führte die erste Abbildung
      'September' Jahreszeiten zu
      'Herbst'. 'Herbst' wurde dann
      durch Temperatur abbgebildet. Da aber keine Komponente Herbst in der Map
      Temperatur definiert wurde, wurde der Wert der Komponente
      DEFAULT zurückgeliefert. Falls in einer Map keine
      DEFAULT-Komponente existiert und auf eine unbekannte
      Komponente zugegriffen wird, bricht der iG/Script-Interpreter mit einer
      entsprechenden Fehlermeldung ab.
Die letzte Bedeutung von Maps sind Maps als Objektspeicher. Wie bereits erklärt, liefern die Inputmodule Objekte in einem neutralen Datenformat und geben diese an die Outputmodule weiter. In ICS wurde als Konvention festgelegt, dass Inputmodule ihre Objekte in der Map IN liefern müssen. Ebenfalls als Konvention wurde festgelegt, dass alle Outputmodule ihre Objekte in der Map OUT entgegennehmen müssen.
Beispiel 10. IN-Objekt als Map
Es wird mit der Methode MSIN.READ_OBJECT ein
         Text aus einem DGN-File gelesen, dann enthält die IN Map folgende
         Komponenten:
MAP IN TXT => 'Test' ! Textinhalt GEOM => 740380.150/270810.950 ! Textposition ROT => 270.0 ! Textwinkel FONT => 27 ! Font etc. END_MAP
Die IN und die OUT Map
      können in iG/Script wie jede andere Map bearbeitet werden. Es ist daher
      möglich die Komponenten als Variablen ('Test2' =>
      IN.TXT), oder die Map als Abbildungstabelle zu interpretieren
      ('TXT' IN DISP, Bildschirm: Test).
Wie bereits angetönt, kann man mit Listen oder Arrays mehrere Objekte zu einem neuen Objekt zusammenfassen. Für Listen stehen u.A. folgende Methoden zur Verfügung (s.a. Anhang):
| Methode | Beschreibung | 
| CREATE_LIST ! [][l list] | Erzeugt eine leere Liste auf dem Stack. | 
| APPEND_TO_LIST ! [l list,o object][l
                  list] | Hängt eine Objekt an die Liste <l>
                  an. | 
Beispiel 11. Erzeugen einer Liste
Folgendes Beispiel zeigt den Einsatz von Listen.
CREATE_LIST 'abc' APPEND_TO_LIST 'uvw' APPEND_TO_LIST => VAR.L VAR.L DISP
Obwohl Listen keine Arrays sind, kann man trotzdem auf die einzelnen Elemente einer Liste indiziert zugreifen. Es stehen folgende Indexfunktionen zur Verfügung:
| Methode | Beschreibung | 
| list.<i> | Liefert das <i>. Elemente
                  einer Liste auf dem Stack. Das 1. Element hat den Index
                  1. | 
| list.FIRST | Liefert das 1. Element der Liste uns ist daher
                  equivalent zu list.1. | 
| list.LAST | Liefert das letzte Element der Liste. | 
| list.SIZE | Liefert die Anzahl Elemente der Liste. | 
Arrays sind spezielle Liste, welche eine fixe, unveränderliche Länge aufweisen. Auf die Elemente eines Arrays kann über einen numerischen Index zugegriffen werden. Der Zugriff auf einzelne Elemente des Arrays ist effizienter möglich als bei Listen. Dafür können Arrays in der Grösse nicht verändert werden.
Für Arrays stehen u.A. folgende Methoden zur Verfügung (s.a. Anhang):
| Methode | Beschreibung | 
| CREATE_ARRAY ! [i size][a
                  array] | Erzeugt einen leeren Array der Grösse size. | 
| INSERT_ARRAY ! [a array,i index, o
                  object][] | Schreibt das Objekt an der Position indexin den Array. | 
Wie die meisten Programmiersprachen verfügt auch iG/Script über
      Kontrollstrukturen um den Ablauf eines Programms zu steuern. In
      iG/Script sind die Kontrollstrukturen IF und
      WHILE enthalten.
Syntax der IF Kontrollstruktur:
IF <Bedingung1> THEN
   <Ausdruck1>
ELSIF <Bedingung2> THEN
   <Ausdruck2>
ELSE 
   <Ausdruck3>
END_IF
Die IF-Kontrollstruktur hat die übliche Bedeutung, d.h. ist die Bedingung1 erfüllt (TRUE) dann wird Ausdruck1 ausgeführt, falls Bedingung2 erfüllt ist dann wird Ausdruck2 ausgeführt etc. Der ELSE und der ELSIF Zweig in einer IF-Kontrollstruktur sind optional. Der ELSIF-Zweig kann beliebig oft wiederholt werden. Eine IF-Kontrollstruktur ist selber wieder ein Ausdruck, d.h. IF-Kontrollstrukturen können geschachtelt werden.
Syntax von Bedingungen:
<Wert1> =  <Wert2> ! Gleichheit 
<Wert1> <> <Wert2> ! Ungleichheit 
<Wert1> <  <Wert2> ! <Wert1> kleiner als <Wert2>
<Wert1> <= <Wert2> ! <Wert1> kleiner oder gleich <Wert2>
<Wert1> >  <Wert2> ! <Wert1> grösser als <Wert2>
<Wert1> >= <Wert2> ! <Wert1> grösser oder gleich <Wert2> 
Bsp: IF TEST.VAR1 = 'hello' THEN
      'hello, World' DISP ELSE
      'tschüss'
      DISP END_IF
Syntax der WHILE-Kontrollstruktur
WHILE <Bedingung> DO 
   <Ausdruck> 
END_WHILE
Die WHILE-Kontrollstruktur hat die übliche Bedeutung, d.h. solange die Bedingung erfüllt (TRUE) ist, wird der Ausdruck ausgeführt. Die WHILE-Kontrollstruktur ist selbst wieder ein Ausdruck, d.h. WHILE-Kontrollstrukturen können geschachtelt werden.
Beispiel 14. WHILE Schlaufe
! dieses Beispiel zeigt 'hello, World' 10 mal auf
! dem Bildschirm an
0 => VAR.I
WHILE VAR.I < 10 DO 
   'hello, World' DISP 
   VAR.I INC => VAR.I
END_WHILEDie Ausführung der WHILE-Kontrollstruktur kann an einer beliebigen
      Stelle mit BREAK oder CONTINUE
      unterbrochen werden. BREAK verzweigt dabei zur ersten
      Anweisung nach der WHILE-Kontrollstruktur. CONTINUE
      verzweigt an den Anfang der WHILE-Kontrollstruktur (d.h. unmittelbar vor
      die <Bedingung>). Die Anweisungen BREAK und
      CONTINUE sind nur innerhalb von
      WHILE-Kontrollstrukturen erlaubt.
Beispiel 15. Beenden der WHILE Schlaufe mit BREAK
! dieses Beispiel zeigt 'hello, World' 10 mal auf! dem Bildschirm an (Variante mit BREAK)0 => VAR.IWHILE TRUE DOIF VAR.I = 10 THENBREAKEND_IF'hello, World'DISPVAR.I INC => VAR.IEND_WHILE
| ![[Anmerkung]](images/note.png) | |
| Bei mehrfach geschachtelten WHILE-Kontrollstrukturen,
         unterbrechen  | 
Das letzte Sprachelement von iG/Script, das noch nicht beschrieben wurde, sind die Prozeduren. Mit Prozeduren kann der Benutzer eigene Befehle aus Standardmethoden erzeugen. Prozeduren müssen wie Maps deklariert werden, bevor sie verwendet werden können. Nachfolgend ist die Syntax einer Prozedurdeklaration angegeben:
PROCEDURE <Prozedurname> 
   <Ausdruck> 
END_PROCEDURE
Wir wollen nun eine neue Prozedur QUADRAT definieren mit der das Quadrat des obersten Elements des Stacks berechnet wird. Das Resultat soll das oberste Element auf dem Stack ersetzen.
PROCEDURE QUADRAT ! [n input][n output]
   DUP *
END_PROCEDURE| ![[Anmerkung]](images/note.png) | |
| Der Kommentar  | 
Die neue Prozedur können wir nun wie folgt benutzen:
2 ! Stack: [2]
QUADRAT ! Stack: [4] hier wurde DUP * durchgeführt
DISP ! Stack:[] Bilschirmausgabe: 4Prozeduren sind also nichts anderes als benannte Teile eines Skripts. Ihre Argumente beziehen Prozeduren meistens über den Stack. Es können allerdings auch Maps für die Parameterübergabe benutzt werden. Folgendes Beispiel benutzt die vordefinierte Map VAR für die Parameterübergabe:
PROCEDURE QUADRAT2
   VAR.VAL 
   DUP * => VAR.VAL
END_PROCEDURE
5 => VAR.VAL
QUADRAT2
VAR.VAL DISP ! liefert als Resultat 25 auf dem Bildschirm| ![[Anmerkung]](images/note.png) | |
| Prozeduren können an einer beliebigen Stelle mit
          | 
Für die Speicherung von Zwischenresultaten innerhalb der Prozedur
      steht ausserdem noch die vordefinierte Map LOCAL zur
      Verfügung. Jede Prozedur hat ihre eigene LOCAL Map
      welche nicht mit anderen Prozeduren geteilt wird. Der Inhalt der
      LOCAL Map ist ausserdem nur während der Ausführung
      der Prozedur definiert. Die LOCAL Map kann also nicht
      für die Parameterübergabe zwischen Prozeduren benutzt werden (die
      VAR Map hingegen schon).
Konstanten und Objekte werden zur Laufzeit sofort auf den Stack
         geschoben. Es wird dabei eine vollständige Kopie des Objekts auf dem
         Stack abgelegt. Bei Maps und anderen strukturierten Objekten (z.B.
         Geometrie) kann das Kopieren aus Effizienzgründen unerwünscht sein,
         man möchte eigentlich nur eine Referenz und keine Kopie des Objekts auf dem
         Stack ablegen. In iG/Script kann dies erreicht werden indem man dem
         Objektnamen ein & voranstellt (z.B.
         &IN,
         &IN.Nummer).
| ![[Anmerkung]](images/note.png) | |
| Map's können nur über eine Referenz auf den Stack geschoben werden. In ICS wird nicht zwischen dem Orginalobjekt und der Referenz unterschieden. Beide sind aus der Sicht von ICS vollständig identisch. Intern sind Referenz und Objekt als Zeiger auf den gleichen Speicherplatz implementiert. Ein Referenzzähler hält fest wie oft ein Objekt in ICS referenziert wird. Falls ein Objekt nicht mehr referenziert wird, wird es automatisch von ICS gelöscht. | 
Beispiel 17. Beispiel mit Referenzen
MAP TEST
END_MAP
&TEST => IN.A ! TEST und IN.A zeigen nun auf das gleiche Objekt 
              ! Der interne Referenzzähler des Objekts hat den Wert 2
'hello' => TEST.B
DISPLAY IN.A.B ! Resultat: 'hello' 
DISPLAY TEST.B ! Resultat: 'hello'
'World' => IN.A.B
DISPLAY IN.A.B ! Resultat: 'World'
DISPLAY TEST.B ! Resultat: 'World'Objekte haben nicht immer einen definierten Wert. Z.B. kann der
         INTERLIS Inputmodul (ILIN) Komponenten ohne Wert
         liefern (falls Attribute in INTERLIS als OPTIONAL
         deklariert sind). Diese Komponenten haben den speziellen Wert
         NULL. Mit dem NULL-Wert kann per
         Definition weder gerechnet, noch kann der NULL-Wert mit anderen
         Werten verglichen werden. Nur das Zuweisen von NULL-Werten auf
         Komponenten ist erlaubt. Für die Bearbeitung von NULL-Werten steht
         ein spezieller Satz von Standardmethoden zur Verfügung:
SET_NULL setzt das oberste Objekt des Stacks auf NULL
1234 SET_NULL Resultat [NULL]
IS_NULL
         liefert TRUE falls das Objekt
         NULL ist
IF IN.A IS_NULL THEN DISPLAY 'IN.A ist NULL' END_IF
IS_NOT_NULL
         liefert TRUE falls das Objekt ungleich
         NULL ist
IF IN.A IS_NOT_NULL THEN DISPLAY 'IN.A ist nicht NULL' END_IF
NVL liefert das 2. Argument
         falls das 1. Argument NULL ist sonst das 1.
         Argument
IN.A 70 NVL
ist daher identisch mit
IF IN.A IS_NULL THEN 70 ELSE IN.A END_IF
Die NVL Methode ist besonders praktisch, wenn sichergestellt
         werden soll, dass nach einer Zuweisung der Inhalt einer Komponente
         nicht NULL ist.
IN.A 70 NVL => OUT.B ! stellt sicher, dass OUT.B nach der
                     ! Zuweisung nie NULL istNormalerweise dürfen Methoden erst aufgerufen werden, wenn alle ihre Argumente bereits auf dem Stack sind (postfix Notation). Eine Ausnahme dieser Regel bilden die sog. Operatoren die zwischen ihren Argumente geschrieben werden dürfen (Infixnotation). In iG/Script sind z.Zt. folgende Operatoren verfügbar:
| 
 | Beschreibung | 
| 
 | Hängt beide Argumente durch ein Komma getrennt als String zusammen. | 
| 
 | Hängt die beide Argumente als String zusammen (ohne Komma). | 
Beispiel 18. Beispiel mit Infix Operatoren
'abc' , 1 , 2 ! Resultat: ['abc,1,2']
'abc' . 1 . 2 ! Resultat: ['abc12']| ![[Anmerkung]](images/note.png) | |
| Die beiden Beispiele können natürlich auch mit der
            eingebauten Methode  | 
Mit iG/Script können Geometrien verarbeitet werden. In der Regel werden Geometrien mit Input-Modulen von Systemen/Formaten gelesen und mit Output-Modulen nach Systeme/Formate geschrieben. Mit Geometrien werden oft Winkel verarbeitet. Die Systeme/Formate können unterschiedliche Winkelsystems aufweisen.
DIe Methoden von iG/Script verwenden immer das mathematische Winkelsystem:
| 
 | Osten | 
| 
 | 0.0 .. 360.0 | 
| 
 | Gegenuhrzeigersinn zunehmend | 
| 
 | Mit Uhrzeigersinn abnehmend | 
Winkel aus einem System/Format mit einem zu iG/Script unterschiedlichen Winkelsystem werden von den Input/Output Modulen von/nach dem iG/Script-Winkelsystem umgerechnet.
Beispiel:
INTERLIS Modell:
INTERLIS Modell: Winkel definiert als GRADS 0.0 .. 399.9
Vermessungstechnisch: 0 Grad = Norden, Bereich = 0.0 .. 399.9, Positiv: Uhrzeigersinn, Negativ: Gegenuhrzeigersinn
INTERLIS lesen:
Das Input Modul ILIN liest den Winkel als INTERLIS GRADS und rechnet diesen in einen iG/Script Winkel um.
INTERLIS GRADS Winkel 350 Grad (Nord-Westen) wird zu iG/Script Winkel 135 Grad (Nord-Westen)
INTERLIS Schreiben:
Das Output Modul ILOUT erhält einen iG/Script Winkel und rechnet diesen in INTERLIS GRADS um.
iG/Script Winkelt 135 Grad (Nord-Westen) wird zu INTERLIS GRADS Winkel 350 Grad (Nord-Westen).
Für das Debugging von iG/Script Programmen stehen folgende Methoden / Operatoren zur Verfügung:
DISPLAY oder DISPDISPLAY oder
                  DISP können an beliebigen Stellen im
                  Skript dazu verwendet werden, ein bestimmtes Objekt in der
                  .log Datei auszugeben:
DISPLAY IN ! zeigt das aktuelle IN-Objekt an (Praefixnotation)
&IN DISP ! das Gleiche wie oben in Postfixnotation
DISPLAY 'Der ist Wert ist ',IN.VALUE ! Formatierte Ausgabe 
                                     ! mit DISPLAYICSCPU.DISPLAY_STACKMit ICSCPU.DISPLAY_STACK kann an
                  einer beliebigen Stelle in einem iG/Script Programm der
                  Inhalt des Stack ausgegeben werden:
1 2 ICSCPU.DISPLAY_STACK + ICSCPU.DISPLAY_STACK
HALTMit HALT kann man ein iG/Script
                  Programm mit einem DOS-Fehlerstatus <> 0
                  abbrechen:
IF 'IN.Name' EXISTS NOT THEN ERROR 'Die Komponenente IN.Name exisitiert nicht' HALT END_IF
Mit iG/Script Direktiven können gewisse Eigenschaften eines iG/Script Programms beinflusst werden. Im Gegensatz zu Methoden oder Prozeduren werden Direktiven nur zu Kompilationszeit durch den iG/Script Compiler ausgeführt.
Für die bessere Übersichtlichkeit ist es erlaubt, iG/Script-Programme auf mehrere Textdateien zu verteilen. Mit der |INCL Direktive kann an einer beliebigen Stelle eines Skripts ein weiteres Skriptfile eingebunden werden. Die |INCL Direktive muss am Anfang einer neuen Zeile stehen.
| ![[Anmerkung]](images/note.png) | |
| In der eingebundenen Datei dürfen ebenfalls
             | 
Trotz der Unterteilung der Verzeichnisstruktur in ein System- und ein User-Verzeichnis können Dateireferenzen relativ definiert werden.
Die INTERLIS Tools suchen Dateien immer
         zuerst als absoluter Pfad, dann relativ zum User-Verzeichnis, dann
         relativ zum System-Verzeichnis, dann relativ zum Verzeichnis
         ILTOOLS_DIR, dann im gleichen Verzeichnis wie die
         Konfiguration und zuletzt im gleichen Verzeichnis wie die
         Konfiguration aber im analogen System-Verzeichnis.
Das nachfolgende Skriptbeispiel einer |INCL
         Direktive soll dies nochmals verdeutlichen:
! Beispiel ICS Konfiguration: ILTOOLS_DIR\user\script\test\test.cfg ! Diese ICS Konfiguration bindet eine Datei ! relativ zu ILTOOLS_DIR\user und/oder ILTOOLS_DIR\system ein |INCL \script\util.lib
Zuerst wird die Datei util.lib unter dem absoluten Pfad
               \script\util.lib gesucht.
Wird util.lib unter diesem Pfad gefunden so wird sie verarbeitet und nicht weiter gesucht.
Wird util.lib unter diesem Pfad nicht gefunden, so wird der nächste Schritt durchgeführt.
Danach wird die Datei util.lib unter dem Pfad
               ILTOOLS_DIR\user\script\util.lib
               gesucht.
Wird util.lib unter diesem Pfad gefunden so wird diese Version verarbeitet und nicht mehr weiter gesucht.
Wird util.lib unter diesem Pfad nicht gefunden, so wird der nächste Schritt durchgeführt.
Danach wird die Datei util.lib unter dem Pfad
               ILTOOLS_DIR\system\script\util.lib
               gesucht.
Wird util.lib unter diesem Pfad gefunden so wird diese Version verarbeitet und nicht weiter gesucht.
Wird util.lib unter diesem Pfad nicht gefunden, so wird der nächste Schritt durchgeführt.
Danach wird die Datei util.lib unter dem Pfad
               ILTOOLS_DIR\script\util.lib gesucht.
Wird util.lib unter diesem Pfad gefunden so wird diese Version verarbeitet und nicht weiter gesucht.
Wird die util.lib unter diesem Pfad nicht gefunden, so wird der nächste Schritt durchgeführt.
Danach wird util.lib unter dem gleichen Pfad wie die ICS
               Konfiguration unter
               ILTOOLS_DIR\user\script\test\util.lib
               gesucht.
Wird util.lib unter diesem Pfad gefunden so wird sie verarbeitet und nicht weiter gesucht.
Wird util.lib unter diesem Pfad nicht gefunden, so wird der nächste Schritt durchgeführt.
Danach wird util.lib unter dem gleichen Pfad wie die ICS
               Konfiguration aber unter dem System-Ast
               ILTOOLS_DIR\system\script\test\util.lib
               gesucht.
Wird util.lib unter diesem Pfad gefunden so wird sie verarbeitet und nicht weiter gesucht.
Wird util.lib unter diesem Pfad nicht gefunden, so wird der nächste Schritt durchgeführt.
Es erfolgt eine Fehlermeldung, dass util.lib nicht gefunden werden konnte.
Falls man bewusst eine Datei aus dem System-Verzeichnis
         verwenden möchte, muss man die Datei relativ zu
         ILTOOLS_DIR definieren:
! Diese ICS Konfiguration bindet eine Datei ! aus ILTOOLS_DIR\system ein |INCL \system\script\util.lib
Falls man eine Datei aus dem gleichen Verzeichnis wie die Hauptkonfiguration verwenden möchte, muss man keinen Pfad definieren.
! Diese ICS Konfiguration bindet eine Datei ! aus dem Verzeichnis der Hauptkonfiguration ein |INCL util.lib
Schliesslich kann man eine Datei auch über einen absoluten Pfad ansprechen.
! Diese ICS Konfiguration bindet eine ! Datei über ihren absoluten Pfad ein |INCL c:\iltools15\user\script\util.lib
| ![[Anmerkung]](images/note.png) | |
| Es wird jedoch dringend davon abgeraten absolute Pfadnamen in Konfigurationen zu benutzen, weil dadurch die Konfigurationen nicht mehr einfach in andere Verzeichnisse kopierbar sind. | 
Unter Windows können Input- und Outputmodule als DLL's (Dynamic
         Link Libraries) implementiert werden. Um die Methoden eines solchen
         Moduls in der Skriptsprache benutzen zu können, muss der Modul zuerst
         mit der |LOAD Direktive geladen werden.
| ![[Anmerkung]](images/note.png) | |
| Die  | 
Die meisten iG/Script Programme benötigen für die Ausführung
         eine gültige Lizenzdatei. Mit der Lizenzdatei wird angegeben, welche
         Module innerhalb eines Skripts benutzt werden können und ob mit der
         Lizenz nur versiegelte Scripts ausführbar sind. Die
         |LICENSE Direktive muss am Anfang einer neuen
         Zeile stehen.
Beispiel 21. Die |LICENSE Direktive
|LICENSE\license\igimp.lic! Angabe der Lizenzdatei relativ ! zu IG_IMPORT_DIR
| ![[Anmerkung]](images/note.png) | |
| Die Lizenzdatei kann entweder durch einen absoluten Pfad oder relativ zum Installationsverzeichnis von ICS angegeben werden. | 
iG/Script Programme können versiegelt werden. Die Versiegelung dient dazu, keine oder nur teilweise Veränderungen in der Codierung von iG/Script Programmen zuzulassen.
Die Versiegelung kann genutzt werden, um iG/Script Programme
         vor ungewollter Veränderung zu schützen. Durch einen Teil des
         Lizenzschlüssels und den Direktiven |SEALHARD und
         |SEALSOFT wird die Art der Versiegelung
         bestimmt.
Es gibt zwei Arten von Versiegelungen, welche in der Lizenz bestimmt werden:
SEAL,HARD"harte" Versiegelung. Mit der Lizenz können nur "hart" versiegelte iG/Script-Programme ausgeführt werden. In "hart" versiegelteniG/Script-Programmen inklusive den Include-Files können keine Veränderungen vorgenommen werden.
SEAL,SOFT"weiche" Versiegelung. Mit der Lizenz können "weich" und "hart" versiegelte iG/Script-Programme ausgeführt werden. In "weich" versiegelten iG/Script-Programmen inklusive den Include-Files können nur innerhalb der MAP-Definitionen Veränderungen vorgenommen werden.
Die Versiegelung SEAL,HARD wird wie folgt
         definiert:
In der Lizenzdatei
In der Lizenzdatei muss folgender Teil enthalten sein:
...,SEAL,HARD,...
Damit können mit dieser Lizenz nur "hart" versiegelte iG/Script Programme ausgeführt werden.
Im iG/Script Programm
In iG/Script Programmen muss folgende Direktive enthalten sein:
|SEALHARD <Checksum>
Wobei <Cecksum> einer
               Check-Summe des iG/Script Programmes entspricht. Die
               |SEALHARD Direktive muss am Anfang einer
               neuen Zeile stehen.
Die Versiegelung SEAL,SOFT wird wie folgt
         definiert:
In der Lizenzdatei
In der Lizenzdatei muss folgender Teil enthalten sein:
...,SEAL,SOFT,...
Damit können mit dieser Lizenz "weich" versiegelte iG/Script Programme ausgeführt werden. Ebenfalls können mit dieser Lizenz "hart" versiegelte iG/Script Programme ausgeführt werden.
Im iG/Script Programm
In iG/Script Programmen muss folgende Direktive enthalten sein:
|SEALSOFT <Cecksum>
Wobei <Cecksum> einer Check-Summe des iG/Script
               Programmes entspricht. Die |SEALSOFT
               Direktive muss am Anfang einer neuen Zeile stehen.
Die Generierung des Lizenzschlüssels mit den Anteilen
         SEAL,HARD oder SEAL,SOFT wird
         durch die infoGrips durchgeführt.
Der Eintrag |SEALHARD <Cecksum> oder
         |SEALSOFT <Checksum> in ein iG/Script
         Programm wird durch die infoGrips durchgeführt.