Anforderungen an ABAP-Programme in Unicode-Systemen Version: 3. Mai 2007 Inhalt Seite 1. Codes 3 2. ABAP-Entwicklung unter Unicode 4 3. Bezeichnungen und Vereinbarungen 5 3.1 3.2 3.3 3.4 Datentypen Datenlayout von Strukturen Unicode-Fragmentsicht Zulässige Zeichen 5 6 7 7 4. Einschränkungen in Unicode-Programmen 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 Zeichenartige und numerische Operanden Zugriffe mit Offset- und Längenangaben Zuweisungen Vergleiche Verarbeitung von Zeichenketten Typprüfung und Typkompatibilität Änderungen bei Datenbank-Operationen Längen- und Abstandsermittlung Sonstige Änderungen 5. Neue ABAP-Anweisungen für Unicode 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 8 8 9 11 14 15 16 17 18 19 21 Stringverarbeitung für Bytefolgen Längen- und Abstandsermittlung Zuweisungen an Feldsymbole Includes mit Gruppennamen Dynamische Erzeugung von Datenobjekten Dynamische Feldzuweisungen Ablage von Daten als Cluster Dateischnittstelle Up- und Download von Dateien Generische Typen für Feldsymbole und Parameter Aufbereitung von Listen 6. Neue Klassen für Unicode 21 22 23 26 27 28 29 30 32 32 32 35 6.1 Ermittlung von Feldeigenschaften 6.2 Konvertierung von Daten 35 37 7. RFC und Unicode 38 8. Abrundungsmaßnahmen 38 9. Weitere Beispielprogramme zur Unicode-Umstellung 40 10. Glossar 59 11. Index der Schlüsselworte 60 2 1. Codes Bisher werden bei SAP verschiedene Codes für die Verschlüsselung von Zeichen verschiedener Schriften verwendet, zum Beispiel ASCII, EBCDI oder Double Byte Codepages. · ASCII (American Standard Code for Information Interchange) verschlüsselt jedes Zeichen durch 1 Byte = 8 Bit. Damit lassen sich höchstens 28 = 256 Zeichen darstellen, denen die Kombinationen [00000000, 11111111] zugeordnet werden. Gebräuchliche Codepages sind zum Beispiel ISO88591 für westeuropäische oder ISO88595 für kyrillische Schriften. · EBCDIC (Extended Binary Coded Decimal Interchange) verschlüsselt ebenfalls jedes Zeichen durch 1 Byte, womit sich wiederum 256 Zeichen abbilden lassen. EBCDIC 0697/0500 ist ein altes IBM Format, das zum Beispiel auf AS400 für westeuropäische Schriften verwendet wird. · Double Byte Codepages benötigen 1 bis 2 Byte je Zeichen. Damit können 216 = 65536 Kombinationen gebildet werden, wobei in der Regel nur 10000 - 15000 Zeichen belegt sind. Als Codepages werden zum Beispiel SJIS für japanische und BIG5 für traditionelle chinesische Schrift verwendet. Mit diesen Zeichensätzen kann jede für SAP interessante Sprache einzeln abgedeckt werden. Schwierigkeiten ergeben sich allerdings, wenn man in einem zentralen System Texte aus verschiedenen inkompatiblen Zeichensätzen mischen möchte. Auch der Austausch von Daten zwischen Systemen mit inkompatiblen Zeichensätzen kann zu völlig undefinierten Situationen führen. Die Lösung des Problems ist die Verwendung eines Codes, der alle Zeichen dieser Erde umfaßt. Dieser Code heißt Unicode (ISO/IEC 10646) und besteht mindestens aus 16 Bit = 2 Byte, alternativ aus 32 Bit = 4 Byte je Zeichen. Obwohl der Umstellungsaufwand für SAP-Kernel und Anwendungen enorm ist, ergeben sich langfristig durch die Einführung von Unicode große Vorteile: · · · · · Das gesamte Internet (www) und damit auch mySAP.com basieren auf Unicode, der damit Grundvoraussetzung für internationale Wettbewerbsfähigkeit ist. Mit Unicode können alle SAP-Anwender ein zentrales System installieren, das die Geschäftsprozesse der gesamten Welt abdeckt. Auch Firmen mit verschiedenen verteilten Systemen wollen meist weltweite Konzerndaten verdichtet aufbereiten. Dies ist ohne Unicode nur bedingt möglich. Unter Unicode können gleichzeitig mehrere Sprachen auf einem Frontend verwendet werden. Unicode wird benötigt für einen anwendungsübergreifenden Datenaustausch ohne Datenverlust durch inkompatible Zeichensätze. Als mögliche Form der Darstellung von Dokumenten im World Wide Web (www) kann dabei zum Beispiel XML verwendet werden. ABAP-Programme müssen überall dort geändert werden, wo eine explizite oder implizite Annahme über die interne Länge eines Zeichens gemacht wird. Dadurch 3 wird eine neue Abstraktionsebene erreicht, die es erlaubt, dieselben Porgramme sowohl in einem herkömmlichen als auch in einem Unicode System ablaufen zu lassen. Außerdem hält man sich damit die Möglichkeit offen, bei einer weiteren Vergrößerung des Unicode-Zeichenvorrates eine interne Darstellung der UnicodeZeichen mit 2 oder 4 Byte zu wählen. Die Beispiele in den nachfolgenden Kapiteln unterstellen einen Unicode mit einer Verschlüsselung von 2 Byte je Zeichen. 2. ABAP-Entwicklung unter Unicode Ein Unicode-fähiges ABAP-Programm (UP) ist ein Programm, bei dem alle UnicodePrüfungen wirksam sind. Ein solches Programm liefert in einem Nicht-UnicodeSystem (NUS) dieselben Ergebnisse wie in einem Unicode-System (US). Um die entsprechenden Syntaxprüfungen durchzuführen, muß das Unicodeflag in den Dynpros der Programm- und Klasseneigenschaften aktiviert werden. In einem US können nur Programme ausgeführt werden, die das Unicodeflag gesetzt haben. Für alle SAP-Programme muß zukünftig das Unicodeflag gesetzt sein, damit sie auf Unicode-Systemen laufen können. Ist das Unicodeflag für ein Programm gesetzt, erfolgt die syntaktische Prüfungen und die Programmausführung gemäß den Regeln, die in diesem Dokument beschriebenen sind. Dies ist unabhängig davon, ob es sich um ein US oder ein NUS handelt. Das Unicodeflag wird zukünftig für alle Programme und Klassen gesetzt, die neu angelegt werden. Ist das Unicodeflag nicht gesetzt, kann das Programm nur in einem NUS ausgeführt werden. Für solche Programme sind die nachfolgend beschriebenen Syntax- und Semantikänderungen nicht wirksam. Es können jedoch alle Spracherweiterungen benutzt werden, die im Zusammenhang mit der Unicode-Umstellung eingeführt wurden. Die mit dem Unicodeflag verbundenen Änderungen und Einschränkungen bewirken, daß Programme in US und NUS weitestgehend mit gleicher Semantik ausgeführt werden, wobei in wenigen Fällen dennoch Unterschiede auftreten können. Programme, die in beiden Systemen laufen sollen, müssen daher auch auf beiden Plattformen getestet werden. Zusätzlich wurden im Rahmen der Unicode-Einführung folgende Umstellungen in der Syntaxprüfung an das Unicode-Flag gebunden: 1. Nicht erreichbare Anweisungen führen in UP zu einem Syntaxfehler. In NUP gab dies bisher nur eine Syntaxwarnung. 2. Der Aufruf eines Funktionsbausteins, dessen Parameternamen statisch als Literal oder als Konstante angegeben werden, führt in UP zu einer behandelbaren Ausnahme, wenn ein falscher Parametername angegeben wird. Dies gilt nur für Funktionsbausteine, die nicht via Remote Function Call aufgerufen werden. In NUP wurde ein falscher Name bisher ignoriert. 4 Für die Umstellung von Programmen auf US wird folgendes Vorgehen empfohlen: · Zuerst sollte die Transaktion uccheck im NUS gestartet werden, welche die Unicode-relevanten Syntaxfehler für eine kleine Programmenge ermittelt. Sind Syntaxfehler für eine größere Programmenge zu ermitteln, dann kann ein entsprechender SAMT-Scan mit dem Hauptprogramm RSUNISCAN_FINAL und der Unterroutine SAMT_SEARCH eingeplant werden. · Bevor im NUS das Unicodeflag in den Eigenschaften des betreffenden Programmes angekreuzt wird, müssen sämtliche Syntaxfehler beseitigt werden. · Nach Aktivierung des Unicodeflags im NUS wird immer die UnicodeSyntaxprüfung für dieses Programm durchgeführt. Dazu besteht im Editor unter Hilfsmittel -> Einstellungen -> Editor die Möglichkeit, maximal 50 Syntaxfehler gleichzeitig durch Ankreuzen des entsprechenden Feldes aufzulisten. Wenn alle syntaktischen Anforderungen im NUS erfüllt sind, muß dasselbe Programm anschließend im NUS und im US getestet werden. Testziele sind die Erkennung von Laufzeitfehlern und die Korrektheit der Ergebnisse in beiden Systemen. Um Laufzeitfehler im Vorfeld auszuschließen, sollten Feldsymbole und Parameter immer typisiert werden, damit problematische Stellen bereits von der Syntaxprüfung erkannt werden. · X ABAP: Programmeigenschaften VER00778 ändern Titel Doku-Check Origibalsprache DE Deutsch Erstellt 09.06.1999 Schröder Letzte Änderung 15.01.2000 Schröder Status aktiv Attribute Typ Ausführbares Programm Status Produktives SAP-Standardprogramm Anwendung Basis (System) Berechtigungsgruppe Paket SABP Logische Datenbank Selektionsbildversion Editorsperre Festpunktarithmetik Unicodeprüfungen aktiv Start über Variante Sichern 3. Bezeichnungen und Vereinbarungen 3.1 Datentypen Zu den Datentypen, die in UP als zeichenartig interpretiert werden, gehören: 5 · · · · · · C N D T STRING Zeichenartige Strukturen Character (Buchstaben, Ziffern, Sonderzeichen) Numerisch Character (Ziffern) Datum Zeit Zeichenkette Strukturen, die direkt oder in Unterstrukturen nur Felder der Typen C, N, D oder T enthalten Ein Zeichen dieses Typs ist im NUS 1 Byte und im US so lang, wie es der Länge eines Zeichens auf der jeweiligen Plattform entspricht. Nicht mehr unterstützt wird der Datentyp W. Als byteartig werden Variable der Typen X und XSTRING bezeichnet. Strukturen werden nach folgenden Merkmalen unterschieden: · · · · Flache Struktur enthalten nur Felder der Elementartypen C, N, D, T, F, I, P und X oder wiederum Strukturen mit diesen Typen. Tiefe Strukturen enthalten zusätzlich zu den Elementartypen Strings, interne Tabellen und Feld- oder Objektreferenzen. Geschachtelte Strukturen sind Strukturen, die wiederum Unterstrukturen als Komponenten enthalten. Nicht geschachtelte Strukturen bezeichnen Strukturen, die keine weiteren Strukturen enthalten. 3.2 Datenlayout von Strukturen Für einige Datentypen wie I, F oder Objektreferenzen gibt es bestimmte Ausrichtungsanforderungen, die von der jeweiligen Plattform abhängen. Felder mit einem solchen Typ müssen im Speicher auf Adressen beginnen, die durch 4 oder 8 teilbar sind. Zeichenartigen Typen stehen an Speicheradressen, die je nach Unicode-Darstellung durch 2 oder 4 teilbar sind. Innerhalb einer Struktur werden vor Komponenten mit Ausrichtungsanforderungen gegebenenfalls Bytes eingefügt, um die notwendige Ausrichtung zu erreichen. Diese Bytes werden als Alignment (A) bezeichnet. Grundsätzlich wird eine Unterstruktur gemäß der größten Alignmentanforderung eines der enthaltenen Felder ausgerichtet. Dabei gilt eine enthaltene Unterstruktur als Feld. Includes in Strukturen gelten in diesem Sinne als Unterstruktur. Bei dem folgenden Beispiel einer Struktur mit drei Feldern werden weder in NUS noch in US Alignments gebildet: BEGIN OF struc1, a(1) TYPE X, b(1) TYPE X, c(6) TYPE C, END OF struc1. Dagegen werden im nächsten Beispiel in US Alignments gebildet, in NUS jedoch nicht. Die erste Alignment-Lücke wird wegen der Ausrichtung der Struktur struc3, 6 die zweite wegen der Ausrichtung des C-Feldes c und die dritte wegen der Adressierung der Intergerzahl d gebildet. BEGIN OF struc2, a(1) TYPE X, BEGIN OF struc3, b(1) TYPE X, c(6) TYPE C, END OF struc3, d TYPE I, END OF struc2. NUS a b c US a A b A d c | A struc3 d | 3.3 Unicode-Fragmentsicht Für Prüfungen in UP, zum Beispiel für die Zulässigkeit von Zuweisungen und Vergleichen, ist das Datenlayout von Strukturen relevant, das sich in der UnicodeFragmentsicht niederschlägt. Diese Sicht zerlegt die Struktur in Alignmentlücken, in byte- und zeichenartige Bereiche und alle übrigen Typen wie P, I, F, Strings, Referenzen oder interne Tabellen. Nebeneinander liegende zeichenartige Komponenten einer Struktur mit Ausnahme von Strings werden intern genau dann zu einer Gruppe zusammengefaßt, wenn zwischen diesen Komponenten keine Alignment-Lücken liegen. Dabei werden alle möglichen Ausrichtungsanforderungen für Zeichen berücksichtigt. In gleicher Weise werden auch nebeneinander liegende byteartige Komponenten zusammengefaßt. BEGIN OF struc, a(2) TYPE C, b(4) TYPE N, c TYPE D, d TYPE T, e TYPE F, f(2) TYPE X, g(4) TYPE X, h(8) TYPE C, i(8) TYPE C, END OF struc. Im folgenden Beispiel zeigen F1 - F6 die einzelnen Fragmente der Struktur struc: a | b c d F1 A e f | F2 | F3 | F4 7 g A h | F5 | F6 i | 3.4 Zulässige Zeichen In einem Unicode-System werden auch alle ABAP-Programmquellen als Unicode abgelegt. Wie in ABAP Objects sind in Programmen mit Unicode-Flag nur folgende Zeichen für Bezeichner erlaubt: 1. Die Buchstaben a - z und A - Z ohne Umlaute 2. Die Ziffern 0 - 9 3. Der Unterstrich _ Aus Kompatibilitätsgründen sind auch noch die Zeichen %, $, ?, -, #, * und / erlaubt, die aber nur in begründeten Ausnahmefällen verwendet werden sollten. Der Schrägstrich ist allerdings nur zum Abtrennen von Namensräumen in der Form /name/ möglich, wobei zwischen zwei Schrägstrichen mindestens drei Zeichen stehen müssen. Damit Programme ohne Konvertierungsverluste von einem US in ein NUS transportiert werden können, sollten auch in einem US für Kommentare und Literale keine Zeichen verwendet werden, die in einem NUS nicht darstellbar sind. 4. Einschränkungen in Unicode-Programmen Die für Unicode erforderlichen Anpassungen und Restriktionen wurden seitens der ABAP-Entwicklung auf das Wesentliche beschränkt, um den Aufwand für die Umstellungen der ABAP-Anwender möglichst gering zu halten. Dies hat in einigen Fällen jedoch zu komplexeren Regeln geführt, beispielsweise bei Zuweisungen und Vergleichen zwischen inkompatiblen Strukturen. 4.1 Zeichenartige und numerische Operanden Bisher galt in ABAP die Regel, daß flache Strukturen als Argumente von ABAPAnweisungen auch überall dort verwendet werden können, wo Einzelfelder vom Typ C erwartet wurden. In UP ist dies nicht mehr generell erlaubt. In UP kann bei einer beliebigen Anweisung, die nur ein Einzelfeld erwartet, genau dann ein strukturiertes Feld verwendet werden, wenn dieses aus zeichenartigen Elementartypen oder aus rein zeichenartigen Unterstrukturen besteht. Die Struktur wird wie ein Einzelfeld vom Typ C behandelt. Einschränkungen im Vergleich zu NUS ergeben sich hauptsächlich dadurch, daß flache Strukturen nur noch eingeschränkt und Felder vom Typ X oder XSTRING niemals als zeichenartig betrachtet werden. Flache Strukturen werden auch nur noch dann als numerisch aufgefaßt, wenn sie rein zeichenartig sind. Numerische Argumente sind zum Beispiel Offset- oder Indexangaben wie bei READ TABLE ... INDEX i. Die Zeichenartigkeit von Strukturen zeigen die beiden folgenden Beispiele: 8 BEGIN OF struc1, a(2) TYPE C, b(2) TYPE C, x(1) TYPE X, i TYPE I, END OF struc. BEGIN OF struc2, a(2) TYPE C, n(6) TYPE N, d TYPE D, t TYPE T, END OF struc. Nicht zeichenartig Zeichenartig Ein weiteres Beispiel ist der Gruppenwechsel bei internen Tabellen, veranlaßt durch das Schlüsselwort AT. In NUS werden Felder vom Typ X, die sich rechts vom Gruppenschlüssel befinden, als zeichenartig behandelt und daher mit einem Stern aufgefüllt. Dagegen erhält derselbe Typ in US seinen Initialwert. 4.2 Zugriffe mit Offset- und Längenangaben Allgemein sind Offset/Längenangaben kritisch, weil die Länge der einzelnen Zeichen plattformabhängig ist und damit zunächst nicht geklärt ist, ob gerade bei gemischten Strukturen die Einheit Byte oder Zeichen gemeint ist. Zum Teil wurden daher erhebliche Einschränkungen erforderlich, jedoch ist ein Offset/Längenzugriff auch weiterhin in dem Umfang möglich, wie er nachfolgend dargestellt wird. Von dieser Regelung betroffen sind Zugriffe auf Einzelfelder und Strukturen, die Übergabe von Parametern an Unterprogramme und schließlich das Arbeiten mit Feldsymbolen. · Zugriffe auf Einzelfelder Zugriffe mit Offset/Länge sind auf zeichenartige Einzelfelder, auf Strings und auf Einzelfelder der Typen X und XSTRING zulässig. Offset und Länge werden bei zeichenartigen Feldern und Feldern vom Typ STRING zeichenweise interpretiert. Nur bei den Typen X und XSTRING werden die Werte für Offset und Länge in Byte angenommen. · Zugriffe auf Strukturen Der Zugriff mit Offset und Länge auf strukturierte Felder wird als unerwünschte Programmiertechnik angesehen. Ein solcher Zugriff führt zu Fehlern, wenn in dem mit Offset und Länge überstrichenen Bereich sowohl zeichen- als auch nicht zeichenartige Komponenten liegen. Offset/Längenzugriffe auf Strukturen sind in UP nur zulässig, wenn sie flach sind und die Offset- und Längenangabe nur zeichenartige Felder ab dem Strukturbeginn einschließt. Das nachfolgende Beispiel zeigt eine Struktur mit zeichen- und nicht zeichenartigen Feldern. Ihre Definition im ABAP-Programm und die daraus resultierende Belegung im Hauptspeicher gestaltet sich so: 9 BEGIN OF STRUC, a(3) TYPE C, b(4) TYPE N, c TYPE D, d TYPE T, e TYPE F, f(26) TYPE C, g(4) TYPE X, END OF STRUC. a | b c F1 "Länge 3 Zeichen "Länge 4 Zeichen "Länge 8 Zeichen "Länge 6 Zeichen "Länge 8 Byte "Länge 28 Zeichen "Länge 2 Byte d A e | F2 | F3 | f g F4 |F5| Intern weist die Fragmentsicht fünf Bereiche [F1, F5] auf, wobei hier ein OffsetLängenzugriff nur im Anfangsstück F1 möglich ist. Anweisungen wie struc(21) oder struc+7(14) werden seitens ABAP-Interpreter akzeptiert und wie ein Einzelfeld vom Typ C behandelt. Dagegen ist ein Zugriff struc+57(2) nur noch in NUP zulässig. Ist ein Offset/Längenzugriff auf eine Struktur erlaubt, dann werden in UP sowohl Offset- als auch Längenangaben stets als Zeichen interpretiert. · Parameterübergabe an Formroutinen Die Parameterübergabe bei PERFORM erlaubte bisher, feldübergreifende Offsetund Längenangaben zu verwenden. Das wird zukünftig in UP verboten. Vielmehr führen hier Offset- und Längenzugriffe über Feldgrenzen hinaus zu einem Syntax- oder Laufzeitfehler. Zum Beispiel würden für ein zehnstelliges C-Feld c Zugriffe der Art c+15 oder c+5(10) einen solchen Fehler auslösen. Wird bei einem Parameter nur ein Offset, aber keine Länge angegeben, so wurde bisher die gesamte Länge des Feldes und nicht die Restlänge als Länge für den Zugriff verwendet. Damit sind Parameterangaben nur mit Offset feldübergreifend und lösen daher in UP einen Syntaxfehler aus. Ein PERFORM test USING c+5 ist daher verboten. Auch in UP kann weiterhin bei Parametern in der Form feld+off(*) die Restlänge ab Offset off spezifiziert werden. · Ranges für Offset- und Längenzugriffe bei Feldsymbolen In UP wird sichergestellt, daß Offset/Längenzugriffe bei ASSIGN nur innerhalb eines vorgegebenen Bereichs (Range) zulässig sind. Im Normalfall stimmt der Range bei elementaren Feldern mit den Feldgrenzen und bei flachen Strukturen mit dem rein zeichenartigen Anfangsstück überein. Durch einen speziellen RANGE-Zusatz bei ASSIGN kann der Range auch über diese Grenzen hinaus erweitert werden. Feldsymbolen wird ein für Offset/Längenangaben zulässiger Range zugeordnet. Wird die Quellangabe einer ASSIGN-Anweisung mit einem Feldsymbol angegeben, so übernimmt das Ziel-Feldsymbol den Range der Quelle. Sofern nicht explizit angegeben wird, bestimmt sich der RANGE wie folgt: 10 ASSIGN feld TO <f>. In UP erhält <f> die Feldgrenzen von feld als Range, wobei feld kein Feldsymbol ist. ASSIGN <g> TO <f>. <f> übernimmt den Range von <g>. ASSIGN elfeld+off(len) TO <f>. In UP erhält <f> die Feldgrenzen des Elementarfeldes elfeld als Range. ASSIGN <elfld>+off(len) TO <f>. <f> übernimmt den Range des elemtaren Feldes elfeld. ASSIGN struc+off(len) TO <f>. ASSIGN <struc>+off(len) TO <f>. In UP bestimmt das rein zeichenartige Anfangsstück der flachen Strukturen struc oder <struc> die Range-Grenzen. Kann die Zuweisung an das Feldsymbol nicht erfolgen, weil die Offset- oder Längenangabe den zulässigen Range überschreitet, wird das Feldsymbol in UP auf UNASSIGNED gesetzt. Andere Prüfungen wie zum Beispiel Typ- oder Alignmentprüfungen führen in UP zu einem Laufzeitfehler. Generell werden Offset- und Längenangaben bei den Datentypen C, N, D und T sowie bei flachen Strukturen in Zeichen und sonst in Bytes gezählt. · Offset ohne Längenangabe bei Feldsymbolen Bisher hatte ASSIGN feld+off TO <f> das Sonderverhalten, daß die Feldlänge und nicht die Restlänge von feld genommen wurde, wenn nur ein Offset, aber keine Länge angegeben wurde. Somit ist ein ASSIGN mit feldübergreifendem Offset unter Unicode problematisch und es gelten daher für diese Konstellation folgende Regeln: 1. Mit ASSIGN feld+off(*)... kann weiterhin explizit die Restlänge spezifiziert werden. 2. ASSIGN <f>+off TO <g> ist nur noch dann erlaubt, wenn der LaufzeitTyp von <f> flach und elementar ist, also C, N, D, T (Offset in Zeichen) oder X (Offset in Bytes). 3. ASSIGN feld+off TO <g> wird generell syntaktisch verboten, weil hier jeder Offset <> 0 eine Range-Überschreitung bewirken würde. Davon ausgenommen sind Fälle, bei denen ein RANGE-Zusatz angegeben ist. Mit diesen Regeln ist normalerweise das Weiterschalten eines Feldsymbols mittels ASSIGN <f>+n TO <f> über ein elementares Feld, wie es zum Beispiel in einer Schleife vorkommt, auch in Zukunft möglich. 11 4.3 Zuweisungen Dieser Abschnitt behandelt impizite und explizite Typkonvertierungen mit dem Gleichheitszeichen (=) oder der Anweisung MOVE. Zwei Felder sind konvertibel, wenn der Inhalt des einen Feldes dem zweiten zugewiesen werden kann, ohne einen Laufzeitfehler auszulösen. Bei der Konvertierung zwischen strukturierten Feldern beziehungsweise zwischen einem strukturierten Feld und einem Einzelfeld wurden flache Strukturen bisher wie C-Felder behandelt. Dies ist mit der Einführung von Unicode zu fehleranfällig geworden, da unsicher ist, ob Programme mit plattformunabhängiger Semantik ablauffähig sind. Zwei Felder sind kompatibel, wenn sie in Typ und Länge gleich sind. Bei der Zuweisung von tiefen Strukturen müssen deshalb die Fragmentsichten übereinstimmen. Bei Zuweisung und Vergleich von tiefen Strukturen wurde bisher schon gefordert, daß Typkompatibilität zwischen den Operanden besteht, womit beide Operanden strukturell gleich aufgebaut sein müssen. Diese Forderung wird auch für Unicode-Systeme beibehalten. · Konvertierung zwischen flachen Strukturen Zur Überprüfung, ob die Konvertierung überhaupt erlaubt ist, wird zunächst die Unicode-Fragmentsicht der Strukturen gebildet, indem zeichen- und byteartige Gruppen sowie Alignment-Lücken und sonstige Komponenten zusammengefaßt werden. Wenn die Fragmente von Quell- und Zielstruktur mit Typ und Länge in der Länge der kürzeren Struktur übereinstimmen, ist die Konvertierung erlaubt. Die Zuweisung ist ebenfalls unter folgenden Annahmen zulässig: 1. Beide Strukturen stimmen in allen Fragmenten bis zum vorletzten der kürzeren Struktur überein. 2. Das letzte Fragment der kürzeren Struktur ist eine zeichen- oder byteartige Gruppe. 3. Das korrespondierende Fragment der längeren Struktur ist eine zeichen- oder byteartige Gruppe größerer Länge. Wenn die Zielstruktur länger als die Quellstruktur ist, werden die zeichenartigen Komponenten des Rests mit Leerzeichen gefüllt. Alle anderen Komponenten des Rests werden mit dem typgerechten Initialwert, Alignment-Lücken mit NullBytes gefüllt. Da längere Strukturen bisher generell mit Leerzeichen aufgefüllt wurden, ist die Verwendung von Initialwerten bei nicht zeichenartigen Komponententypen inkompatibel. Diese inkompatible Änderung hat allerdings eher den Charakter einer Fehlerkorrektur. Bei zeichenartigen Komponenten wurde aus Gründen der Kompatibilität darauf verzichtet, mit Initialwerten aufzufüllen. BEGIN OF struc1, a(1) TYPE C, x(1) TYPE X, END OF struc1. BEGIN OF struc2, a(1) TYPE C, b(1) TYPE C, END OF struc2. 12 Die Zuweisung struc1 = struc2 ist unter Unicode nicht erlaubt, weil struc1-x im Gegensatz zu struc2-b nur ein Byte belegt. BEGIN OF struc3, a(2) TYPE C, n(6) TYPE N, i TYPE I, END OF struc3. BEGIN OF struc4, a(8) TYPE C, i TYPE I, f TYPE F, END OF struc4. Diese Zuweisung struc3 = struc4 ist zulässig, weil die Fragmentsichten der zeichenartigen Felder und der Integerzahl übereinstimmen. BEGIN OF struc5, a(1) TYPE X, b(1) TYPE X, c(1) TYPE C, END OF struc5. BEGIN OF struc6, a(1) TYPE X, BEGIN OF struc0, b(1) TYPE X, c(1) TYPE C, END OF struc0, END OF struc6. struc5 = struc6 ist wiederum verboten, weil die Fragmentsichten der beiden Strukturen durch die Alignment-Lücken vor struc0 und vor struc0-c abweichen. BEGIN OF struc7, p(8) TYPE P, c(1) TYPE C, END OF struc7. BEGIN OF struc8, p(8) TYPE P, c(5) TYPE C, o(8) TYPE P, END OF struc8. Die Zuweisung struc7 = struc8 funktioniert, weil die Fragmentsichten in der Länge der Struktur struc7 übereinstimmen. Bei tiefen Strukturen wird wie bisher die Typkompatibilität der Operanden gefordert. Als Abrundungsmaßnahme wurde die Konvertibilität bei ObjektReferenzen und Tabellenkomponenten leicht verallgemeinert. · Konvertierung zwischen Strukturen und Einzelfeldern Für die Konvertierung einer Struktur in ein Einzelfeld und umgekehrt gelten folgende Regeln: 1. Ist eine Struktur rein zeichenartig, dann wird sie bei der Konvertierung wie ein C-Feld behandelt. 2. Ist das Einzelfeld vom Typ C, die Struktur aber nur zum Teil zeichenartig, dann ist die Konvertierung nur erlaubt, wenn die Struktur mit einer zeichenartigen Gruppe beginnt und diese Gruppe mindestens so lang wie das Einzelfeld ist. Die Konvertierung erfolgt nun zwischen der ersten zeichenartigen Gruppe der Struktur und dem Einzelfeld. Wenn die Struktur das Zielfeld ist, werden die zeichenartigen Anteile des Rests mit Leerzeichen und alle anderen Komponenten mit dem typgerechten Initialwert aufgefüllt. 3. Die Konvertierung ist verboten, wenn die Struktur nicht rein zeichenartig und das Einzelfeld nicht vom Typ C ist. Analog zur Zuweisung zwischen Strukturen ist das Auffüllen nicht zeichenartiger Komponenten mit dem Initialwert inkompatibel. 13 · Konvertierung zwischen internen Tabellen Tabellen sind dann konvertierbar, wenn ihre Zeilentypen konvertierbar sind. Die oben beschriebenen Restriktionen wirken sich somit auch auf die Konvertierung von Tabellen aus. · Implizite Konvertierungen Für alle ABAP-Anweisungen, die implizite Konvertierungen entsprechend der MOVE-Semantik verwenden, gelten ebenfalls die obigen Regeln. Dies ist zum Beispiel bei folgenden Anweisungen für interne Tabellen der Fall: APPEND wa TO itab. APPEND LINES OF itab1 TO itab2. INSERT wa INTO itab. INSERT LINES OF itab1 INTO [TABLE] itab2. MODIFY itab FROM wa. MODIFY itab ... TRANSPORTING ... WHERE ... ki = vi ... READ TABLE itab ...INTO wa. READ TABLE itab ...WITH KEY ...ki = vi ... LOOP AT itab INTO wa. LOOP AT itab .... WITH KEY ... ki = vi ... Die selben Einschränkungen wie bei der expliziten Konvertierung gelten auch für die implizite Umwandlung von VALUE-Angaben. 4.4 Vergleiche Prinzipiell gilt die Regel, daß Operanden, die einander mit der MOVE-Anweisung zugewiesen werden können, auch miteinander vergleichbar sind. Abweichend davon sind Objektreferenzen zwar vergleichbar, jedoch nicht immer zuweisbar. · Vergleiche zwischen flachen Strukturen Ein Vergleich ist auch dann möglich, wenn die Strukturen nicht kompatibel sind. Es muß aber analog zu MOVE gelten, daß die Fragmentsichten in der Länge der kürzeren Struktur übereinstimmen. Sind die Strukturen verschieden lang, dann wird die kürzere Struktur bis zur Länge der anderen Struktur aufgefüllt. Analog wie bei der Zuweisung werden beim Auffüllen alle zeichenartigen Komponenten mit Leerzeichen und alle anderen Komponenten mit typgerechtem Initialwert gefüllt. Der Vergleich erfolgt fragmentweise entsprechend der Fragmentsicht. · Vergleiche zwischen Einzelfeldern und Strukturen Bei Vergleichen zwischen Einzelfeldern und Strukturen gelten folgende Regeln: 1. Wenn eine Struktur rein zeichenartig ist, wird sie beim Vergleich wie ein CFeld behandelt. 2. Ist das Einzelfeld vom Typ C, die Struktur aber nur zum Teil zeichenartig, dann ist der Vergleich nur erlaubt, wenn die erste zeichenartige Gruppe der Struktur länger als das Einzelfeld ist. Für den Vergleich wird das Einzelfeld zur Laufzeit auf die Länge der Struktur erweitert und mit Initialwerten 14 aufgefüllt. Der Vergleich erfolgt dann wie bei strukturierten Feldern, wobei das Auffüllen selbst analog der MOVE-Anweisung vorgenommen wird. c0(10) TYPE C. c0 BEGIN OF struc, c1(15) TYPE C, i TYPE I, c2(5) TYPE C, n(7) TYPE N, END OF struc. c1 0 i c2 n In diesem Beispiel wird c0 im Speicher auf die Länge von struc erweitert. Alle Bereiche > 10 werden bei nicht zeichenartigen Komponenten mit typgerechten Initialwerten belegt, ansonsten mit Leerzeichen. · Vergleich zwischen tiefen Strukturen Wie bisher wird bei tiefen Strukturen für den Vergleich im wesentlichen die Typkompatibilität der Operanden gefordert. Der Kompatibilitätstest für die Vergleichbarkeit wurde zur Abrundung dahingehend verallgemeinert, daß analog zu Einzelfeldern Strukturkomponenten mit Referenzen auf Klassen oder Interfaces unabhängig von Klassenhierarchie und Implementierungsrelation miteinander vergleichbar sind. Bei Tabellenkomponenten wird nur die Vergleichbarkeit der Tabellentypen gefordert. · Vergleich zwischen internen Tabellen Tabellen sind dann vergleichbar, wenn ihre Zeilentypen vergleichbar sind. Die oben beschriebenen Restriktionen wirken sich somit auch auf den Vergleich von Tabellen aus. 4.5 Verarbeitung von Zeichenketten Die Zeichenkettenverarbeitung, bei der bisher alle Argumente implizit als Feld vom Typ C interpretiert wurden, wird aufgeteilt in Stringverarbeitung für zeichenartige und byteartige Argumente. · Anweisungen zur Zeichenkettenverarbeitung CLEAR ... WITH CONCATENATE CONDENSE CONVERT TEXT ... INTO SORTABLE CODE OVERLAY REPLACE SEARCH SHIFT SPLIT TRANSLATE ... TO UPPER/LOWER CASE TRANSLATE ... USING Bei diesen Anweisungen müssen die Argumente Einzelfelder der Typen C, N, D, T oder STRING sein, zudem sind rein zeichenartige Strukturen erlaubt. Werden 15 Argumente eines anderen Typs übergeben, so wird ein Syntax- oder Laufzeitfehler ausgelöst. Für die Verarbeitung von Bytefolgen, also Operanden des Typs X oder X-STRING, wird eine Teilmenge dieser Funktionalität durch den Zusatz IN BYTE MODE bereitgestellt. Eine Anweisung CONCATENATE a x b INTO c ist genau dann nicht mehr möglich, wenn a, b, c zeichenartig sind, x jedoch vom Typ X. TRANSLATE ... CODEPAGE ... TRANSLATE ... NUMBER FORMAT ... Diese Anweisungen sind in UP verboten. Als Ersatz werden die neuen Konvertierungsklassen angeboten, die auf Seite 37 näher beschrieben sind. · Vergleichsoperatoren für die Zeichenkettenverarbeitung CO CN CA NA CS NS CP NP Wie bei den Anweisungen zur Stringverarbeitung erfordern diese Operatoren Einzelfelder der Typen C, N, D, T oder STRING als Argumente, außerdem sind wiederum rein zeichenartige Strukturen zugelassen. Für Bytefolgen werden eigene Vergleichsoperatoren angeboten, die durch das Präfix BYTE- definiert werden. · Funktionen zur Stringverarbeitung Die Funktion STRLEN arbeitet nur mit zeichenartigen Feldern und liefert die Länge in Zeichen zurück. Für die Länge von Bytefolgen steht die neue Funktion XSTRLEN zur Verfügung. Die Funktion CHARLEN lieferte unter NUS bisher den Wert 1 für ein Textfeld, das mit einem Single-Byte-Zeichen beginnt. Für ein Textfeld, das mit einem Double-Byte-Zeichen beginnt, wird der Wert 2 zurückgeliefert. Unter US wird CHARLEN den Wert 1 liefern, falls text mit einem einfachen Unicode-Zeichen beginnt. Falls text mit einem Unicode-Doppelzeichen aus der Surrogate Area beginnt, wird 2 zurückgeliefert. Die Funktion NUMOFCHAR liefert die Anzahl der Zeichen eines Strings oder eines zeichenartigen Feldes. In Single-Byte Codepages verhält sich diese Funktion wie STRLEN. In Multi-Byte Codepages werden Zeichen, die mehr als 1 Byte belegen, trotzdem mit der Länge 1 gezählt. · Ausgaben in Felder und Listen Bei WRITE ... TO waren beliebige flache Datentypen als Ziel erlaubt, die wie CFelder behandelt wurden. In UP gilt nun für WRITE ... TO ... die Einschränkung, daß das Zielfeld zeichenartig sein muß. Bei der Tabellenvariante WRITE ... TO 16 itab INDEX idx muß der Zeilentyp der Tabelle zeichenartig sein. Offset und Längenangaben werden dabei zeichenweise gezählt. Mit WRITE konnten bisher beliebige flache Strukturen ausgegeben werden. Wenn das Quellfeld bei WRITE eine flache Struktur Ist, dann muß diese in UP rein zeichenartig sein. Folgende Anweisungen sind davon betroffen: WRITE WRITE WRITE WRITE WRITE f. f TO g[+off][(len)]. (name) TO g. f TO itab[+off][(len)] INDEX idx. (name) TO itab[+off][(len)] INDEX idx. 4.6 Typprüfung und Typkompatibilität Aus historischen Gründen können Feldsymbole und Parameter von Unterprogrammen oder Funktionsbausteinen mit dem Zusatz STRUCTURE typisiert werden. · Wenn Feldsymbole mit FIELD-SYMBOLS <f> STRUCTURE s DEFAULT wa typisiert sind und ihnen später mit ASSIGN wa TO <f> ... ein Datenobjekt wa zugewiesen wird, dann wird in NUP in beiden Anweisungen nur geprüft, ob wa mindestens so lang wie s ist und wa die Ausrichtungsanforderungen von s zur Laufzeit erfüllt. Wenn Parameter in Funktionsbausteinen oder Unterprogrammen mit FORM form1 USING/CHANGING arg STRUCTURE s ... oder FORM form2 TABLES itab_a STRUCTURE s ... typisiert sind und ihnen mit PERFORM form1 USING/CHANGING wa oder PERFORM form2 USING/CHANGING itab_b Aktualparameter übergeben werden, wird in NUP ebenfalls nur geprüft, ob wa oder der Zeilentyp von itab_b mindestens so lang wie s ist und wa beziehungsweise der Zeilentyp von itab_b die Ausrichtungsanforderungen von s erfüllt. Das Gleiche gilt für Parameter von Funktionsbausteinen, die mit STRUCTURE typisiert sind. In UP werden nach einer Typisierung mit STRUCTURE bei einer Zuweisung von Datenobjekten, also beim DEFAULT-Zusatz der Anweisung FIELD-SYMBOLS, beim ASSIGN und bei der Übergabe von Aktualparametern folgende zusätzliche Regeln überprüft: 1. Ist wa beziehungsweise der Zeilentyp von itab_b eine flache oder tiefe Struktur, dann müssen die Unicode-Fragmentsichten von wa beziehungsweise von itab_b und s in der Länge von s übereinstimmen. 2. Ist wa ein Einzelfeld, dann sind nur die zeichenartigen Typen C, N, D oder T erlaubt und die Struktur s muß rein zeichenartig sein. Die Überprüfung dieser beiden Regeln erfordert zusätzliche Laufzeit. Deshalb wird empfohlen, die Parameter nach Möglichkeit mit TYPE zu typisieren, weil der Test auf echte Kompatibilität ungleich schneller ist. 17 · Wurde bei einem Funktionsbaustein ein Argument mit ... LIKE struc typisiert, wobei struc eine flache Struktur ist, so wird in NUP bei der Parameterübergabe nur geprüft, ob das Argument eine flache Struktur gleicher Länge ist. In UP wird zusätzlich geprüft, daß die Fragmentsichten des aktuellen und formalen Parameters übereinstimmen. Aus Performancegründen wird wie im Abschnitt zuvor die Typisierung mit TYPE empfohlen. · Außerdem sind zwei Strukturen, von denen eine oder beide Includes enthalten, nur noch dann kompatibel, wenn die durch Include verursachten AlignmentLücken auf allen Plattformen übereinstimmen. Im folgenden Beispiel sind struc1 und struc2 nicht zueinander kompatibel, weil vor dem INCLUDE im US eine zusätzliche Alignment-Lücke auftritt: BEGIN OF struc1, a(1) TYPE X, b(1) TYPE X, c(1) TYPE C, END OF struc1. BEGIN OF struc2, a(1) TYPE X. INCUDE struc3. END OF struc2. BEGIN OF struc3, b(1) TYPE X, c(1) TYPE C, END OF struc3. Da sich die Typkompatibilität in UP und NUP unterscheiden kann, gelten in NUS für die Prüfung der Parameter stets die Typkompatibilitätsregeln des Aufrufers. Ruft also ein NUP ein UP auf, dann wird die Typkompatibilität wie im NUP bestimmt. Umgekehrt wird die Unicode-Prüfung eingeschaltet, wenn ein UP ein NUP aufruft. 4.7 Änderungen bei Datenbank-Operationen Bei den nachfolgenden Anweisungen werden bisher in NUP die Daten entsprechend der Struktur des Tabellenarbeitsbereichs dbtab in das Feld wa beziehungsweise in die Tabellenzeile itab übertragen, ohne die Struktur derselben zu berücksichtigen. Allein die Länge und die Ausrichtung werden geprüft. SELECT * FROM dbtab ... INTO wa ... SELECT * FROM dbtab ... INTO TABLE itab ... SELECT * FROM dbtab ... APPENDING TABLE itab ... FETCH NEXT CURSOR c ... INTO wa. FETCH NEXT CURSOR c ... INTO TABLE itab. FETCH NEXT CURSOR c ... APPENDING TABLE itab. INSERT INTO dbtab ... FROM wa. INSERT dbtab ... FROM wa. INSERT dbtab ... FROM TABLE itab. UPDATE dbtab ... FROM wa. UPDATE dbtab ... FROM TABLE itab. MODIFY dbtab ... FROM wa. MODIFY dbtab ... FROM TABLE itab. DELETE dbtab FROM wa. DELETE dbtab FROM TABLE itab. In UP gelten nun folgende Regelungen: Ist der Arbeitsbereich beziehungsweise die Zeile der internen Tabelle eine Struktur, dann wird zusätzlich geprüft, ob die Fragmentsichten von Arbeitsbereich und 18 Datenbanktabelle in der Länge der Datenbanktabelle übereinstimmen. Ist der Arbeitsbereich ein Einzelfeld, so muß das Feld zeichenartig und die Datenbanktabelle rein zeichenartig sein. Diese Anforderungen gelten für alle oben aufgeführten Anweisungen. Bei allen Anweisungen zum Bearbeiten von Datenbanktabellen (READ, MODIFY, DELETE, LOOP), die den Zusatz VERSION verwenden, sind für das Versionsfeld nur noch die Typen C, N, D, T und flache Strukturen derselben Typen zulässig. In NUS wird eine Warnung, in US ein Syntaxfehler ausgelöst. 4.8 Längen- und Abstandsermittlung Bei der Längen und Abstandsermittlung von Feldern darf die Anweisung DESCRIBE DISTANCE nicht mehr verwendet werden und muß durch eine der neuen Anweisungen DESCRIBE DISTANCE ... IN BYTE MODE oder DESCRIBE DISTANCE ... IN CHARACTERMODE ersetzt werden. Auch die Anweisung DESCRIBE FIELD ... LENGTH ist obsolet und muß durch eine der neuen Anweisungen DESCRIBE FIELD ... LENGTH ... IN BYTE MODE oder DESCRIBE FIELD ... LENGTH ... IN CHARACTER MODE ersetzt werden. Die Anweisung DESCRIBE FIELD ... TYPE feld lieferte bisher für flache Strukturen den Typ C zurück. In Unicode-Programmen wird für flache Strukturen jetzt der Typ u zurückgegeben, der im ABAP-Quellcode abgefragt werden kann. Für die Anweisung DESCRIBE FIELD ... TYPE ... COMPONENTS ... ergeben sich unter Unicode-Systemen keine Änderungen. Ebenfalls unverändert liefert die Anweisung DESCRIBE ... OUTPUT LENGTH ... weiterhin die Ausgabelänge in Zeichen zurück. 4.9 Sonstige Änderungen Die folgenden Ausführungen betreffen die Dateischnittstelle, Schlüsselangaben bei Tabellen sowie Bit- und Bitmaskenoperationen. Im einzelnen ergeben sich durch die Einführung von Unicode folgende Änderungen: · In der Dateischnittstelle wurde der Befehl OPEN DATASET völlig überarbeitet. In UP muß mindestens einer der Zusätze IN TEXT MODE ENCODING, IN BINARY MODE, IN LEGACY MODE oder IN LEGACY BINARY MODE angegeben werden. Das Lesen und Schreiben von Dateien mittels READ DATASET und TRANSFER kann in US nur noch vorgenommen werden, wenn die zu bearbeitende Datei zuvor explizit geöffnet wurde. Ohne OPEN-Anweisung wird bei diesen Anweisungen ein Laufzeitfehler ausgelöst. Wurde die Datei im TEXT MODE geöffnet, sind bei READ DATASET dsn INTO f für f nur zeichenartige Felder, Strings und rein zeichenartige Strukturen erlaubt, wobei die Typprüfung erst zur Laufzeit erfolgt. Der Zusatz LENGTH bestimmt im TEXT MODE die Länge des Datensatzes in Zeichen, in allen anderen Fällen in Bytes. 19 · Bei den obsoleten Anweisungen LOOP AT dbtab, READ TABLE dbtab und READ TABLE itab wird in UP ein Syntaxfehler ausgelöst, wenn der Schlüssel nicht rein zeichenartig ist. Bei der Anweisung READ TABLE itab wird ein Syntax- oder Laufzeitfehler ausgelöst, wenn der Standardschlüssel der internen Tabelle die Typen X oder XSTRING enthält. Bei dieser READ-Variante wird der tatsächlich zu verwendende Schlüssel durch Ausblenden aller mit Leerzeichen gefüllten Komponenten ermittelt. Dazu muß in UP sichergestellt sein, daß der Vergleich mit SPACE erlaubt ist. Ein Syntax- oder Laufzeitfehler wird auch bei Datenbankzugriffen mit generischem Schlüssel ausgelöst, wenn der Schlüssel nicht rein zeichenartig ist. Davon betroffen sind folgende Befehle: READ TABLE dbtab ...SEARCH GKEQ ... READ TABLE dbtab ...SEARCH GKGE ... LOOP AT dbtab ... REFRESH itab FROM TABLE dbtab. Bei diesen Anweisungen wird der tatsächliche Tabellenschlüssel dadurch ermittelt, daß schließende Leerzeichen des Datenbankschlüssel abgeschnitten werden. Dazu muß in UP sichergestellt sein, daß alle Bestandteile des Schlüssels mit SPACE verglichen werden können. · Bisher wurde bei den Bitanweisungen SET BIT i OF f [TO g] und GET BIT i OF f [INTO g] geprüft, ob das Feld f zeichenartig ist, wobei üblicherweise auch X-Felder, X-Strings und flache Strukturen als zeichenartig betrachtet wurden. Für UP ist dies nicht mehr sinnvoll, da einerseits die Typen X und XSTRING nicht mehr als zeichenartig gelten, anderseits der bitweise Zugriff auf zeichenartige Felder oder Strukturen nicht mehr unabhängig von der Plattform ist. Deshalb muß bei diesen Operationen in UP das Feld f vom Typ X oder XSTRING sein. Bei den Bitmaskenoperationen f O x, f Z x und f M x waren bisher für den linken Operanden f alle zahlartigen und damit auch alle characterartigen Typen erlaubt. In UP muß der Operand f nun den Typ X oder XSTRING haben. · Bei der Addition von Feldfolgen sind in UP Einschränkungen für folgende Anweisungen verbindlich: ADD n1 THEN n2 UNTIL nz [ ACCORDING TO sel ] GIVING m ... ADD n1 THEN n2 UNTIL nz TO m [ RANGE str ]. 1. Die Operanden n1, n2 und nz müssen zueinander typkompatibel sein. 2. Die Distanz zwischen nz und n1 muß ein ganzzahliges Vielfaches der Distanz zwischen n2 und n1 sein. 3. Ein Syntax- oder Laufzeitfehler erfolgt, wenn die Felder n1, n2 und nz nicht in einer Struktur liegen. Diese muß entweder statisch erkennbar sein oder deren zulässiger Bereich explizit durch den RANGE-Zusatz gekennzeichnet werden. 4. Zur Laufzeit wird sichergestellt, daß der RANGE-Bereich nicht verlassen wird. 20 ADD n1 FROM i1 GIVING m [ RANGE str ]. 1. Feld n1 muß innerhalb einer Struktur liegen. Diese muß durch den RANGEZusatz explizit definiert werden, falls dies statisch nicht erkennbar ist. 2. Auch bei dieser Variante wird zur Laufzeit geprüft, ob n1 und die angesprochenen Werte innerhalb der Struktur liegen. · Schleifen mit dem Zusatz VARY oder VARYING sind auch für Unicode problematisch, weil einerseits ein typgerechter Zugriff auf Speicherinhalte nicht sichergestellt ist, andererseits Seicher ungewollt überschrieben werden kann. DO ... VARYING f FROM f1 NEXT f2. Bei dieser Anweisung müssen die Felder f, f1 und f2 zueinander typkompatibel sein. Um das Überschreiben von Speicherinhalten zu verhindern, wird bei den folgenden Anweisungen implizit oder explizit ein RANGE für zulässige Zugriffe eingeführt: DO ... TIMES VARYING f FROM f1 NEXT f2 [ RANGE f3 ]. WHILE ... VARY f FROM f1 NEXT f2 [ RANGE f3 ]. Es wird wiederum ein Syntax- oder Laufzeitfehler ausgelöst, falls f1 oder f2 nicht von f3 umfaßt werden. Fehlt der Zusatz RANGE, dann wird dieser aus FROM f1 NEXT f2 implizit so bestmmt: 1. Sind sowohl f1 und f2 statisch erkennbare Komponenten der gleichen Struktur, dann wird der zulässige RANGE-Bereich aus der kleinsten Struktur bestimmt, die f1 und f2 umfaßt. 2. Ein Syntaxfehler wird ausgelöst, wenn statisch erkennbar ist, daß f1 und f2 nicht zur gleichen Struktur gehören. 3. Ein zulässiger Bereich muß explizit mittels RANGE angegeben werden, falls die Zusammengehörigkeit von f1 und f2 statisch nicht erkennbar ist. Wird als RANGE-Zusatz eine tiefe Struktur angegeben, dann wird bei jedem Schleifendurchlauf geprüft, daß innerhalb des gerade überstrichenen Bereiches keine Feld- und Objektreferenzen, Tabellen oder Strings liegen. · Bei der automatischen Erzeugung von Unterprogrammen mittels Anweisung GENERATE SUBROUTINE POOL itab NAME name erbt das generierte Programm den Inhalt des Unicode-Flags des generierenden Programms. · Bei der Anweisung INSERT REPORT kann das Unicodeflag durch den Zusatz UNICODE ENABLING uc explizit zur Laufzeit gesetzt werden. Ohne diesen Zusatz wird folgendermaßen verfahren: 1. 2. 3. 4. Ein UC-Programm erzeugt ebenfalls ein UC-Programm Ein NUC-Programm erzeugt wiederum ein NUC-Programm Ein NUC- wird ein UC-Programm nach Überschreiben durch ein UC-Programm Ein UC- bleibt ein UC-Programm nach Überschreiben durch ein NUCProgramm 21 · Bei den Anweisungen GET/SET PARAMETER ID pid FIELD f muß f zeichenartig sein. Für die Ablage nicht zeichenartiger Felder und Strukturen können EXPORT- und IMPORT-Anweisungen benutzt werden 5. Neue ABAP-Anweisungen für Unicode 5.1 Stringverarbeitung für Bytefolgen · Die String-Anweisungen für die Typen X und XSTRINGG werden durch den Zusatz IN BYTE MODE von den Zeichenkettenbefehlen unterschieden. Für die Varianten der Zeichenketten ist optional der Zusatz IN CHARACTER MODE möglich. Ist der Zusatz IN BYTE MODE angegeben, sind als Argumente nur X-Felder und XStrings erlaubt. Werden Argumente eines anderen Typs übergeben, so wird ein Syntax- oder ein Laufzeitfehler ausgelöst. CLEAR ... WITH IN BYTE MODE CONCATENATE x1 ... xn INTO x IN BYTE MODE FIND ... IN BYTE MODE REPLACE ... IN BYTE MODE REPLACE f WITH g INTO h IN BYTE MODE SEARCH x FOR x1 IN BYTE MODE SHIFT x ... IN BYTE MODE SPLIT ... IN BYTE MODE Bei allen String-Befehlen für Bytefolgen werden X-Felder immer in ihrer vollen Länge berücksichtigt, so daß Bytes mit Inhalt X'00' am Ende des Feldes niemals abgeschnitten werden. Für die Anweisungen FIND, SEARCH und REPLACE mit Zusatz IN BYTE MODE gibt es keine Varianten, die Suchmuster verwenden. · Die Stringlänge für Bytefolgen kann mit der Funktion XSTRLEN bestimmt werden. XSTRLEN liefert für X-Strings die aktuelle Länge und für X-Felder die definierte Länge in Bytes, wobei Nullbytes am Ende von Feldern mitgezählt werden. · Die X-Varianten der Stringvergleichsoperationen werden durch das Präfix BYTE- von den Zeichenkettenvarianten unterschieden. Als Argumente sind für diese Operationen nur X-Felder und Felder vom Typ XSTRING erlaubt. BYTE-CO BYTE-CN BYTE-CA BYTE-NA BYTE-CS BYTE-NS 22 5.2 Längen- und Abstandsermittlung Mit den Anweisungen DESCRIBE FIELD und DESCRIBE DISTANCE kann die Feldlänge oder der Abstand zwischen zwei Feldern ermittelt werden. Bei folgenden Varianten müssen unter Unicode die Zusätze IN BYTE/CHARACTER MODE angegeben werden: · DESCRIBE FIELD f LENGTH len IN BYTE MODE. Die Länge des Feldes f wird in Bytes ermittelt und in das Feld len übergeben. Diese Variante liefert für alle intern referenzierten Datentypen (Strings, Feldund Objektreferenzen) die Länge der Referenz und nicht die Länge des Inhalts. Für derartige Felder ist deshalb nur die Variante IN BYTE MODE erlaubt. · DESCRIBE FIELD f LENGTH len IN CHARACTER MODE. Hier wird die Länge des Feldes f in Zeichen zurückgegeben, falls das Argument rein zeichenartig ist. f darf jedoch nicht vom Typ STRING sein. Die betreffende Prüfung wird statisch und dynamisch durchgeführt und löst je nach Typ einen Syntax- oder Laufzeitfehler aus. · · DESCRIBE DISTANCE BETWEEN a AND b INTO x IN BYTE MODE. Diese Anweisung liefert im Feld x den Abstand zwischen den Feldern a und b in Bytes. DESCRIBE DISTANCE BETWEEN a AND b INTO x IN CHARACTER MODE. Diese Anweisung liefert den Abstand in Zeichen zurück, wobei das Ergebnis stets auf die Feldanfänge bezogen ist. Nur zur Laufzeit wird geprüft, ob der Abstand zwischen den Argumenten durch die plattformabhängige Länge eines Zeichens teilbar ist und die beiden Felder a und b das richtige Alignment besitzen. Anderenfalls wird ein Laufzeitfehler ausgelöst. 5.3 Zuweisungen an Feldsymbole Die ASSIGN-Anweisung erlaubte es bisher, mit Offset/Längenangaben über Feldgrenzen hinaus zu adressieren. Einen Laufzeitfehler gab es nur dann, wenn über die Grenzen des Datensegments hinaus adressiert wurde. Feldübergreifende Offset/Längenzugriffe bei ASSIGN konnten beispielsweise sinnvoll zur Bearbeitung von Wiederholungsgruppen eingesetzt werden. Mit Unicode ist dies allerdings problematisch, da nicht mehr sichergestellt ist, daß feldüberschreitende Offset- oder Längenangaben sowohl unter US als auch in NUS einheitlich und sinnvoll als Bytes oder Zeichen interpretiert werden können. Aus diesem Grund wurde die ASSIGN-Anweisung um die Zusätze RANGE und INCREMENT erweitert, während der Zusatz CASTING nunmehr alle Varianten dieser Anweisung unterstützt. Der RANGE-Zusatz wird für alle gültigen Varianten von ASSIGN angeboten und kann mit dem Zusatz CASTING kombiniert werden. 23 · ASSIGN feld1 TO <fs> RANGE feld2. Dieser Zusatz setzt explizit die Range-Grenzen. Dadurch ist es möglich, über Feldgrenzen hinaus zu adressieren, um beispielsweise mit der Anweisung ASSIGN INCREMENT Wiederholungsgruppen zu verarbeiten. 1. Als Range für <fs> werden die Feldgrenzen von feld2 genommen. 2. In UP müssen die durch die RANGE-Angabe spezifizierten Grenzen die RangeGrenzen umfassen, die sich sonst nach den oben beschriebenen Regeln ergeben würden. 3. Ist der Speicherbereich von feld1 nicht ganz in feld2 enthalten, so wird ein abfangbarer Laufzeitfehler ausgelöst. 4. Das Feld feld2, das den Range bestimmt, darf auch tief sein. Es können somit auch Wiederholungsgruppen mit tiefen Typen verarbeitet werden. · ASSIGN feld INCREMENT n TO <fs>. Das Feldsymbol wird ausgehend von der durch feld bestimmten Position um n mal die Länge von feld weitergesetzt. Zunächst wird aus der Länge von feld und der INCREMENT-Angabe der Bereich für den Zugriff entsprechend ASSIGN fld+n*sizeof[feld] (sizeof[fld]) TO <fs> bestimmt. Der angesprochene Bereich muß innerhalb der Range-Grenzen liegen. Kann die Zuweisung nicht durchgeführt werden, weil die Range-Grenzen verletzt wurden, so wird SY-SUBRC > 0 gesetzt und das Feldsymbol bleibt unverändert. Die Range-Grenzen für ASSIGN feld INCREMENT n TO <fs> werden genau so wie bei ASSGIN feld TO <f> bestimmt. Die INCREMENT-Angabe hat daher keinen Einfluß auf die Bestimmung der Range-Grenzen. * Schleife über ein elementares Feld DATA: c(10) TYPE C VALUE 'abcdefghij'. FIELD-SYMBOLS: <cf> TYPE C. ASSIGN c(2) TO <cf>. "Range-Grenzen c = DO 5 TIMES. "Feldgrenzen von cf WRITE / <cf>. ASSIGN <cf> INCREMENT 1 TO <c>. "Gleiche Grenzen <c> * ASSIGN <c>+2 TO <cf>. "Wie ASSIGN INCREMENT ENDDO. * Strukturierte Wiederholungsgruppe TYPES: BEGIN OF comp, f1 type string, ... END OF comp. DATA: BEGIN OF stru, x1(1) TYPE x, k1 TYPE comp, k2 TYPE comp, 24 k3 TYPE comp, k4 TYPE comp, END OF stru. FIELD-SYMBOLS: <comp> TYPE comp. ASSIGN stru-k1 TO <comp> RANGE stru. * Range-Grenzen feldübergreifend festlegen DO 4 TIMES. ... ASSIGN <comp> INCREMENT 1 TO <comp>. ENDDO. * Dynamischer Zugriff auf ein * Element einer Wiederholungsgruppe DATA: BEGIN OF stru, x1(1) TYPE x, k1 TYPE comp, k2 TYPE comp, k3 TYPE comp, k4 TYPE comp, END OF stru, incr TYPE i. FIELD-SYMBOLS: <comp> TYPE comp. incr = 4 - 1. ASSIGN stru-k1 INCREMENT incr TO <comp> RANGE stru. ... * <comp> steht jetzt auf stru-k4 · Bei allen Varianten der Anweisung ASSIGN ist der Zusatz CASTING erlaubt: ASSIGN ASSIGN ASSIGN ASSIGN ASSIGN feld feld feld feld feld TO TO TO TO TO <fs> <fs> <fs> <fs> <fs> CASTING. CASTING TYPE type. CASTING TYPE (typename) CASTING LIKE fld. CASTING DECIMALS dec. Durch ASSIGN ... CASTING ist es möglich, den Inhalt eines Felds über ein Feldsymbol als einen Wert eines anderen Typs zu betrachten. Eine Anwendung dieser Anweisung besteht beispielsweise darin, durch Casts auf verschiedene Typen unterschiedliche Sichten auf eine Struktur zur Verfügung zu stellen. Eine verbreitete ABAP-Technik besteht darin, C-Felder oder Strukturen als Container zum Speichern von Strukturen verschiedener, oft erst zur Laufzeit bekannter Typen zu verwenden. Die Selektion von Teilkomponenten der Struktur erfolgt dann durch Offset/Längenzugriffe auf den Container. Da diese Technik mit Unicode nicht mehr funktioniert, kann alternativ ein vorhandener Speicherbereich mittels ASSIGN ... CASTING über ein Feldsymbol als Container mit passender Typisierung betrachtet werden. Im nachfolgenden Beispiel wird ein bestimmtes Feld der Datenbanktabelle X031L gelesen, wobei Feld- und Tabellenname erst zur Laufzeit angegeben werden. 25 * Lesen eines Feldes der Tabelle X031L PARAMETERS: TAB_NAME LIKE TAB_COMP LIKE ANZAHL TYPE DATA: BEGIN OF BUFFER, ALIGNMENT TYPE C(8000) TYPE END OF BUFFER. SY-TNAME, X031L-FIELDNAME, I DEFAULT 10. "Tabellenname "Feldname "Zeilenanzahl F, C, "Alignment "Tabelleninhalt FIELD-SYMBOLS: <WA> TYPE ANY, <COMP> TYPE ANY. * Feldsymbol mit passender Typisierung * auf Pufferbereich setzen ASSIGN BUFFER TO <WA> CASTING TYPE (TAB_NAME). SELECT * FROM (TAB_NAME) INTO <WA> UP TO anzahl ROWS. ASSIGN COMPONENT TAB_COMP OF STRUCTURE <WA> TO <COMP>. WRITE: / TAB_COMP, <COMP>. ENDSELECT. In der Anweisung ASSIGN feld TO <f> CASTING ... wurde bisher geprüft, daß feld mindestens so lang ist wie der Typ, der dem Feldsymbol <f> zugeordnet ist, indem das Feldsymbol typisiert wurde oder durch eine direkte Typangabe mittels CASTING TYPE. Die bisher schon durchgeführte Längenprüfung wird im Syntaxcheck dahingehend verschärft, daß die Zuweisung nur noch erlaubt ist, wenn das Feld feld sowohl in einem US als auch in einem NUS mindestens so lang ist wie der Typ, der dem Feldsymbol <f> zugeordnet ist. Ist diese Bedingung verletzt, erfolgt ein Syntaxfehler. Zur Laufzeit wird dagegen wie bisher nur geprüft, ob die Längen im aktuellen System passen. Ist der Typ von feld oder von <f> eine tiefe Struktur, dann wurde außerdem geprüft, ob alle referenzartigen Komponenten bezüglich Offset und Typ im Bereich von feld, der durch <f> überdeckt wird, übereinstimmen. Die Prüfung der referenzartigen Komponenten wird im Syntaxcheck dahingehend verschärft, daß diese auf allen Plattformen mit ein, zwei oder vier Byte langen Zeichen passen müssen. Zur Laufzeit wird wiederum nur geprüft, ob die Referenzkomponenten im aktuellen System passen. Bei ASSIGN str TO <f> TYPE C/N und bei ASSIGN str TO <f> CASTING TYPE C/N kann in Unicode-Systemen außerdem der Fall auftreten, daß die Länge von str nicht ein Vielfaches der Zeichenlänge ist. In diesem Fall erfolgt ein Laufzeitabbruch. 26 5.4 Includes mit Gruppennamen Durch Redefinition von Strukturen unter Verwendung von INCLUDES mit Gruppennamen ist es möglich, Teile komponentenübergreifend auf symbolische Weise zu selektieren. Neben der Vereinbarung im ABAP-Programm besteht auch die Möglichkeit, Gruppennamen im Dictionary zu vergeben. Folgende Ausprägungen sind im ABAP verfügbar: INCLUDE TYPE t1 AS grpname[RENAMING WITH SUFFIX suffix]. INCLUDE STRUCTURE s1 AS grpname[RENAMING WITH SUFFIX suffix]. Durch die Einführung eines Gruppennamens für ein Include im DDIC oder durch den Zusatz AS grpname in ABAP kann der durch das Include definierte Teilbereich der Struktur symbolisch über den Gruppennamen angesprochen werden. Das folgende Beispiel faßt Teile einer ABAP-Struktur zu einer Gruppen zusammen, die an ein Unterprogramm übergeben wird: * Verwendung von Includes mit Gruppennamen TYPES: BEGIN OF name, vorname(20) TYPE C, nachname(30) TYPE C, END OF name. TYPES: BEGIN OF person, geschlecht(1) TYPE X. INCLUDE TYPE name AS pname. TYPES: alter TYPE I, gewicht TYPE P, END OF person. DATA: s2 TYPE person. PERFORM use_name USING s2-pname. 5.5 Dynamische Erzeugung von Datenobjekten · Mittels CREATE DATA ist es möglich, Felder eines vor- oder benutzerdefinierten Datentyps zu erzeugen. Folgende Varianten werden angeboten: CREATE CREATE CREATE CREATE CREATE DATA DATA DATA DATA DATA dref dref dref dref dref TYPE typ. TYPE (typname). LIKE feld. TYPE LINE OF itab. LIKE LINE OF itab. Im folgenden Beispiel wird wiederum ein bestimmtes Feld der Datenbanktabelle X031L gelesen, wobei Feld- und Tabellenname erst zur Laufzeit bekannt sind. 27 * Lesen eines Feldes der Tabelle X031L PARAMETERS: TAB_NAME LIKE SY-TNAME, TAB_COMP LIKE X031L-FIELDNAME, NUMBER TYPE I DEFAULT 10. FIELD-SYMBOLS: <WA> TYPE ANY, <COMP> TYPE ANY. DATA: WA_REF TYPE REF TO DATA. "Tabellenname "Feldname "Zeilenanzahl CREATE DATA WA_REF TYPE (TAB_NAME). "Passende Workarea ASSIGN WA_REF->* TO <WA>. SELECT * FROM (TAB_NAME) INTO <WA> UP TO NUMBER ROWS. ASSIGN COMPONENT TAB_COMP OF STRUCTURE <WA> TO <COMP>. WRITE: / TAB_COMP, <COMP>. ENDSELECT. · Mit einer weiteren Variante von CREATE DATA ist es möglich, zur Laufzeit Tabellenobjekte zu erzeugen. Zeilentyp und Schlüssel der Tabelle können dabei statisch oder dynamisch angegeben werden. CREATE DATA dref (TYPE [STANDARD|SORTED|HASHED] TABLE OF (LineType | (Name) |REF TO DATA | REF TO Obj)) | (LIKE [STANDARD|SORTED|HASHED] TABLE OF LineObj ) [ WITH (UNIQUE|NON-UNIQUE) ( KEY (k1 ... kn | (keytab) | TABLE_LINE ) | DEFAULT KEY ) ] [ INITIAL SIZE m ] Für diese Anweisung gelten die nachfolgende Einschränkungen: 1. m ist eine Variable oder eine Konstante ohne Vorzeichen, deren Inhalt zur Laufzeit vom Typ NUMLIKE sein muß. 2. keytab ist eine nicht leere Tabelle des Typs CHARLIKE, deren Komponenten keine Offset/Längen- oder überlappende Key-Angaben enthalten dürfen. Der Zusatz TABLE_LINE ist erlaubt, wenn die Tabelle nur eine Zeile enthält. 3. Ein Syntaxfehler erfolgt, wenn entweder die Typ- oder die Zeilen- und die Schlüsselangabe statisch sind. 4. Ist kein Schlüssel definiert, dann zieht der DEFAULT-KEY. · Bei CREATE DATA können auch die generischen Basistypen C, N, X und P verwendet werden. Durch Zusätze kann die Länge und bei Typ P auch die Zahl der Dezimalstellen spezifiziert werden. CREATE DATA dref TYPE (t | (typeName)) [ LENGTH len ] [ DECIMALS dec ]. Der Zusatz LENGTH ist nur bei den Typen C, N, X und P erlaubt und muß stets hinter dem Schlüsselwort TYPE stehen. Bei unsinniger Angabe von LENGTH oder DECIMALS wird ein abfangbarer Laufzeitfehler ausgelöst. 28 5.6 Dynamische Feldzuweisungen Bisher galt bei MOVE-CORRESPONDING struc1 TO struc2 die Einschränkung, daß die Feldtypen der beiden Strukturen zum Zeitpunkt der Generierung bekannt sein mussten. Diese Einschränkung wird unter Unicode aufgehoben. In NUS war die Zuweisung von Strukturen unterschiedlicher Fragmentsichten mittels MOVE bisher unproblematisch. Unter US führte eine solche Zuweisung jedoch trotz typgleicher Anfangsstücke zu einem Laufzeitfehler. BEGIN OF struc1, a(2) TYPE C, b TYPE I, c(1) TYPE C, d(4) TYPE X, END OF struc1. BEGIN OF struc2, a(2) TYPE C, b TYPE I, c(1) TYPE C, g(6) TYPE P, f(2) TYPE X, END OF struc2. struc1 a b c struc2 a b c d g f Wurde struc1 = struc2 zum Beispiel durchgeführt, um struc1 den Inhalt des typgleichen Anfangsstückes struc2-[a,c] zuzuweisen, so genügte eine einfache MOVE-Anweisung, wobei das Reststück von struc1 nach der Zuweisung möglicherweise unsinnige Werte enthielt. Da dieselbe Zuweisung unter Unicode aber wegen der unterschiedlichen Fragmentsichten zu einem Laufzeitfehler führt, kann nun ersatzweise mit MOVE-CORRESPONDING struc2 TO struc1 gearbeitet werden. Dasselbe Ergebnis wird unter Unicode genau dann erzielt, wenn die Feldnamen der Anfangsstücke zur Laufzeit in beiden Strukturen namensgleich sind. 5.7 Ablage von Daten als Cluster Zur Unterstützung heterogener Unicode-Umgebungen werden neue Varianten der IMPORT- und EXPORT-Anweisung angeboten. Diese erlauben es, Daten unabhängig vom Format der Plattform als Cluster in einem X-String abzulegen. Folgende Varianten können benutzt werden: · EXPORT {pi = dobji | pi FROM dobji } TO DATA BUFFER dbuf. EXPORT (itab) TO DATA BUFFER dbuf. Die Objekte dobj1 ... dobjn (Felder, flache und komplexe Strukturen oder Tabellen) werden als ein Cluster im Datenpuffer dbuf abgelegt, der vom Typ XSTRING sein muß. TYPES: BEGIN OF ITAB_TYPE, CONT TYPE C LENGTH 4, END OF ITAB_TYPE. 29 DATA: XSTR TYPE XSTRING, F1 TYPE C LENGTH 4, F2 TYPE P, ITAB TYPE STANDARD TABLE OF ITAB_TYPE. EXPORT P1 = F1 P2 = F2 TAB = ITAB TO DATA BUFFER XSTR. · Neuer Zusatz ... CODE PAGE HINT f1 Mit diesem Zusatz kann für EXPORT obj1 ... objn TO [ DATA BUFFER | DATABASE | DATASET ] bei mehrdeutigen Codepages angeben werden, mit welcher Codepage f1 die Importdaten zu interpretieren sind. · IMPORT {pi = dobji | pi FROM dobji } FROM DATA BUFFER dbuf. IMPORT (itab) FROM DATA BUFFER dbuf. Import der Datenobjekte dobj1 ... dobjn (Felder, flache und komplexe Strukturen oder Tabellen) aus dem Datenpuffer dbuf, der wiederum vom Typ XSTRING sein muß. Es werden alle Daten eingelesen, die zuvor über EXPORT ... TO DATA BUFFER im Datenpuffer dbuf abgelegt wurden. Auch hier wird die Übereinstimmung der Struktur bei EXPORT und IMPORT nicht geprüft. Im dynamischen Fall wird die Parameterliste in der zweispaltigen Indextabelle itab übergeben, deren Spalten vom Typ C oder STRING sein müssen. In der ersten Spalte von itab müssen die Namen der Parameter, in der zweiten die Datenobjekte aufgezählt werden. Falls die erste Spalte von itab leer ist, kommt es zu einer unbehandelbaren Ausnahme mit dem Laufzeitfehler DYN_IMEX_OBJ_NAME_EMPTY. 5.8 Dateischnittstelle In der Dateischnittstelle wurde die Anweisungen OPEN DATASET komplett überarbeitet und für US mit folgenden Ergänzungen versehen: · OPEN DATASET dsn IN TEXT MODE. Die Datei wird zum zeilenweisen Lesen und Schreiben geöffnet. Schließende Leerzeichen werden in diesem Modus abgeschnitten. 1. Zusatz ... ENCODING (DEFAULT | UTF-8 | NON-UNICODE) Das Schlüsselwort ENCODING bestimmt den Zeichensatz, mit dem die Daten bearbeitet werden. DEFAULT ist unter US stets UTF-8, unter NUS aber NONUNICODE. Die Angabe NON-UNICODE bewirkt, dass diejenige Nicht-UnicodeCodepage verwendet wird, die in einem NUS zu der Anmeldesprache oder der durch die Anweisung SET LOCALE LANGUAGE gesetzten Sprache passt oder passen würde. 30 2. Zusatz ... REPLACEMENT CHARACTER rc Dieser Zusatz bestimmt das Ersatzzeichen, welches verwendet wird, wenn ein Zeichen bei der Konvertierung im Zielzeichensatz nicht vorhanden ist. Ohne diese Angabe wird die Raute # als Ersatzzeichen eingesetzt. · OPEN DATASET dsn IN BINARY MODE. Die Datei wird ohne Zeilenumbruch zum Lesen und Schreiben geöffnet, wobei in US und NUS genau der Speicherinhalt übernommen wird. · OPEN DATASET dsn IN LEGACY TEXT MODE [(LITTLE | BIG) ENDIAN ] [ CODE PAGE cp ]. Die Datei wird zum zeilenweisen Lesen und Schreiben in einem Format geöffnet, das zum TEXT MODE in NUS kompatibel ist. Der optionale Zusatz ENDIAN bestimmt, in welcher Byte-Reihenfolge Zahlen der Typen I oder F verarbeitet werden. Fehlt dieser Zusatz, dann legt das Betriebssystem des Applikationsservers die Reihenfolge fest. Unterscheidet sich die angegebene Byte-Reihenfolge von derjenigen des Applikationsservers, dann werden bei den Anweisungen READ DATASET und TRANSFER entsprechende Konvertierungen durchgeführt. Auch hier ist ein REPLACEMENT CHARACTER rc möglich. Der Zusatz CODE PAGE gibt die Codepage an, in der Texte der Datei dsn dargestellt werden. Fehlt dieser Zusatz, wird diejenige Codepage genommen, die beim Lesen oder Schreiben der Datei gesetzt ist. · OPEN DATASET dsn IN LEGACY BINARY MODE [(LITTLE|BIG) ENDIAN)] [ CODE PAGE cp ]. Die Datei wird ohne Zeilenumbruch zum Lesen und Schreiben in einem Format geöffnet, das zum BINARY MODE in NUS kompatibel ist, wobei für den Zusatz ENDIAN und CODE PAGE die obigen Bestimmungen gelten. Der Zusatz REPLACEMENT CHARACTER rc ist auch hier wiederum erlaubt. Bei allen Varianten ist der Zusatz IGNORING CONVERSION ERRORS möglich, der Laufzeitfehler beim Lesen oder Schreiben der Datei unterdrückt, falls ein Konvertierungsfehler auftritt. Allgemein gilt, daß ein Lesen oder Schreiben einer Datei einen Laufzeitfehler auslöst, wenn diese nicht zuvor mittels OPEN DATASET geöffnet wurde. 5.9 Up- und Download von Dateien Die bisherigen Funktionsbausteine WS_UPLOAD und WS_DOWNLOAD gehören zwar nicht zum Standardbefehlssatz von ABAP, sie stellen aber die Dateischnittstelle auf dem Präsentationsserver dar. WS_UPLOAD und WS_DOWNLOAD sind in einem US nicht ablauffähig und werden daher ersetzt durch die Bausteine GUI_UPLOAD und GUI_DOWNLOAD. Die neuen Funktionsbausteine GUI_UPLOAD und GUI_DOWNLOAD besitzen eine Schnittstelle, die es ermöglicht, auch Unicode-Formate auf die lokale Platte zu schreiben. Eine Beschreibung der Schnittstellen enthält die Dokumentation zu 31 diesen Funktionsbausteinen, die unter SAP Easy Access -> Entwicklung -> Function Builder -> Springen -> Dokumentation aufgerufen werden kann. 5.10 Generische Typen für Feldsymbole und Parameter Für die Typisierung von Parametern und Feldsymbolen werden neue generische Datentypen zur Verfügung gestellt: · SIMPLE ist kompatibel zu den Typen, die auch zu CLIKE, XSEQUENCE oder NUMERIC kompatibel sind, also zu allen elementaren Typen einschließlich Cund X-Strings. Durch eine Typisierung mit SIMPLE ist sichergestellt, daß Parameter oder Feldsymbole mit WRITE ausgegeben oder in arithmetischen Operationen verwendet werden können. Bei der Verwendung in arithmetischen Operationen kann es allerdings inhaltsabhängig zu Konvertierungsfehlern kommen, wenn zum Beispiel ein C-Feld als aktueller Parameter übergeben wird und der Feldinhalt nicht als Zahl interpretiert werden kann. · CLIKE ist kompatibel zu den Typen C, N, D, T und STRING sowie zu rein zeichenartigen Strukturen. In NUP besteht außerdem Kompatibilität zu den Elementartypen X und XSTRING. Durch eine Typisierung mit CLIKE ist sichergestellt, daß Parameter oder Feldsymbole bei allen Operationen zur Zeichenkettenverarbeitung verwendet werden können, zum Beispiel bei den Anweisungen CONCATENATE, FIND oder REPLACE. Außerdem ist garantiert, daß bei Offset- und Längenzugriffe in Zeichen gezählt wird. Zudem sind diese im Bereich des gesamten Feldes und bei Typ STRING in der aktuellen Stringlänge erlaubt. · CSEQUENCE ist kompatibel zu den Typen C und STRING · XSEQUENCE ist kompatibel zu den Typen X und XSTRING. Durch diese Typisierung ist sichergestellt, daß Parameter oder Feldsymbole in Operationen zur Bytefolgenverarbeitung verwendet werden können, zum Beispiel bei der Anweisung CONCATENATE ... IN BYTE MODE. · NUMERIC ist kompatibel zu den Typen I, P, F und zu den nur im Dictionary vorhandenen Typen INT1 (1-Byte-Integer) und INT2 (2-Byte-Integer). Es ist zu beachten, daß Typ N nicht zu NUMERIC kompatibel ist. Durch die Typisierung mit NUMERIC ist sichergestellt, daß Parameter und Feldsymbole in arithmetischen Operationen verwendet werden können, ohne daß Typ- oder Konvertierungsfehler auftreten. 5.11 Aufbereitung von Listen · Einführung Die Anweisung WRITE schreibt den Inhalt von Datenobjekten auf eine Liste. Beim Schreiben mit der Anweisung WRITE wird die Ausgabe im Listenpuffer gespeichert und von dort beim Aufruf der Liste zur Anzeige gebracht. Bei jeder Ausgabe eines Datenobjekts mit WRITE wird implizit oder explizit eine Ausgabelänge festgelegt, wobei die implizite Ausgabelänge vom Datentyp abhängt. Mit der Ausgabelänge werden zwei Dinge definiert: · die Anzahl der im Listenpuffer für Zeichen zur Verfügung stehenden Stellen (oder Speicherplätze) 32 · die Anzahl der auf der eigentlichen Liste zur Verfügung stehenden Spalten (oder Zellen) Wenn die Ausgabelänge kleiner als die Länge des Datenobjekts ist, wird dessen Inhalt beim Schreiben in den Listenpuffer nach bestimmten Regeln verkürzt, wobei ein Wertverlust bei numerischen Feldern durch das Zeichen * angezeigt wird. Bei Anzeige oder Ausdruck einer Liste werden die im Listenpuffer abgelegten Inhalte wie folgt auf die Liste übertragen: · In NUS benötigt jedes Zeichen genau soviel Platz im Listenpuffer wie Spalten auf der Liste. In Single-Byte-Systemen belegt ein Zeichen ein Byte im Listenpuffer und eine Spalte auf der Liste, während ein Zeichen, das in Multi-Byte-Systemen mehrere Bytes im Listenpuffer belegt, auch die gleiche Anzahl an Spalten auf der Liste belegt. Deshalb werden in NUS alle im Listenpuffer abgelegten Zeichen auf der Liste dargestellt. · In US belegt jedes Zeichen in der Regel eine Stelle im Listenpuffer. Ein Zeichen kann aber auf der Liste mehr als eine Spalte belegen, was insbesondere für ostasiatische Zeichen gilt. Da auf der Liste aber nur genau so viele Spalten wie Stellen im Listenpuffer zur Verfügung stehen, können in diesem Fall nur weniger Zeichen auf der Liste dargestellt werden als im Listenpuffer abgelegt sind. Die Listenausgabe wird entsprechend verkürzt, wobei sich die Seite nach der Ausrichtung richtet und mit einem der Kennzeichen > oder < versehen wird. Auf einer angezeigten Liste kann dann über die Auswahl von System -> Liste -> Unicode-Anzeige der gesamte Inhalt zur Anzeige gebracht werden. Aus diesen Gründen ist die horizontale Position des Listen-Cursors nur in NUS gleichbedeutend zur Ausgabespalte einer dargestellten oder gedruckten Listen. In US ist dies nur für die jeweils unteren und oberen Ausgabegrenzen der einzelnen Ausgaben garantiert. · Regeln für die WRITE-Anweisung Um ungewolltes Abschneiden so weit wie möglich zu vermeiden, wurden die Regeln für die WRITE-Anweisung in UP angepasst und erweitert. 1. WRITE-Anweisung mit impliziter Ausgabelänge In UP verhält sich die WRITE-Anweisung ohne explizite Angabe der Ausgabelänge für alle ausgebbaren Datenobjekte mit Ausnahme von Textfeldliteralen und von Datenobjekten des Typs string wie in NUP. Dadurch kann es vorkommen, dass auf der Liste weniger Zeichen dargestellt werden als im Listenpuffer abgelegt sind. Bei Textfeldliteralen und bei Datenobjekten des Typs string wird davon ausgegangen, dass alle Zeichen dargestellt werden sollen. Deshalb wird die implizite Ausgabelänge anhand der im Datenobjekt enthaltenen Zeichen so berechnet, dass sie der Anzahl der auf der Liste benötigten Spalten entspricht. Wenn diese Ausgabelänge größer als die Länge des Datenobjekts ist, werden überzählige Stellen beim Schreiben in den Listenpuffer mit Leerzeichen aufgefüllt. Bei der Darstellung auf der Liste werden diese Leerzeichen wieder abgeschnitten, da die Darstellung der Zeichen die Ausgabelänge genau ausfüllt. 33 2. WRITE-Anweisung mit expliziter Ausgabelänge Wenn bei der WRITE-Anweisung ein numerisches Datenobjekt als explizite Ausgabelänge hinter dem Zusatz AT angegeben ist, wird der Wert dieser Zahl sowohl in US als auch in NUS als Ausgabelänge verwendet. In US kann sich die Anzahl der auf der Liste dargestellten Zeichen von der Anzahl der im Listenpuffer gespeicherten Zeichen unterscheiden. Seit Release 6.20 kann die Ausgabelänge außer über numerische Datenobjekte wie folgt angegeben werden: 1. WRITE AT (*) ... · Bei Datenobjekten der Typen c und string wird die Ausgabelänge auf die Anzahl der Spalten gesetzt, die auf der Liste zur Darstellung des gesamten Inhalts benötigt werden, wobei keine schließenden Leerzeichen bei Typ c berücksichtigt werden. Bei Datenobjekten vom Typ string ist dies gleichbedeutend zur impliziten Länge. · Bei Datenobjekten der Typen d und t wird die Ausgabelänge auf 10 und 8 gesetzt. · Bei Datenobjekten der numerischen Typen i, f und p wird die Ausgabelänge auf den Wert gesetzt, der nötig ist, um den aktuellen Wert einschließlich Tausendertrennzeichen auszugeben, wobei der Wert nach Anwendung der eventuellen Zusätze CURRENCY, DECIMALS, NO-SIGN, ROUND oder UNIT betrachtet wird. · Bei Datenobjekten der Typen n, x und xstring wird die implizite Ausgabelänge verwendet. 2. WRITE AT (**) ... · Bei Datenobjekten der Typen c wird die Ausgabelänge auf die doppelte Länge des Datenobjektes und bei Datenobjekten vom Typ string auf die doppelte Anzahl enthaltener Zeichen gesetzt. · Bei Datenobjekten der Typen d und t wird die Ausgabelänge auf 10 und 8 gesetzt. · Bei Datenobjekten der numerischen Typen i, f und p wird die Ausgabelänge auf den Wert gesetzt, der nötig ist, um die maximal möglichen Werte dieser Typen einschließlich Vorzeichen und Tausendertrennzeichen auszugeben, wobei der Wert nach Anwendung der eventuellen Zusätze CURRENCY, DECIMALS, NO-SIGN, ROUND oder UNIT betrachtet wird. · Bei Datenobjekten der Typen n, x und xstring wird die implizite Ausgabelänge verwendet. · Zusätze bei GET/SET CURSOR FIELD/LINE Die Zusätze DISPLAY OFFSET und MEMORY OFFSET berücksichtigen, dass Datenobjekte bei der Darstellung auf einer Liste (Display) und bei der Zwischenspeicherung im Listenpuffer (Memory) unterschiedliche Längen belegen können. In Unicode-Codepages gibt es zum Beispiel Zeichen, die im Listenpuffer nur eine Stelle belegen, bei der Anzeige aber zwei Ausgabespalten benötigen. 34 Dementsprechend wird der Cursor bei der Anweisung SET CURSOR { FIELD f | LINE l } durch den Zusatz DISPLAY OFFSET off in der Ausgabe und durch den Zusatz MEMORY OFFSET off im Listenpuffer gesetzt. In gleicher Weise überträgt die Anweisung GET CURSOR { FIELD f | LINE l } bei Verwendung des Zusatzes DISPLAY OFFSET off die Cursorposition innerhalb des angezeigten Feldes in das Datenobjekt off. Dagegen wird bei Verwendung des Zusatzes MEMORY OFFSET off die Cursorposition im Listenpuffer in das Datenobjekt off übertragen. Der Zusatz DISPLAY ist die Standardeinstellung und kann daher auch weggelassen werden. · Klasse für die Aufbereitung von Listen Für die Berechnung von Ausgabelängen, die Konvertierung von Werten aus dem Listenpuffer und die Definition von Feldgrenzen wurde die Klasse CL_ABAP_LIST_UTILITIES eingeführt. Mit den Rückgabewerten ihrer Methoden kann eine korrekte Spaltenausrichtung auf ABAP-Listen programmiert werden, auch wenn ostasiatische Schriften ausgegeben werden. · Listeneinstellungen Die Objekte einer Liste können in unterschiedlichen Ausgabelängen angezeigt werden, indem die gewünschte Länge im Menü System -> Liste -> UnicodeAnzeige eingestellt wird. Dies ist für vor allem bei Bildschirmlisten in US vorteilhaft, deren Ausgaben abgeschnitten wurden, was durch die Zeichen > oder < angezeigt wird. · Empfehlungen Damit Listen sowohl in US als auch in NUS gleiches Aussehen und Funktionalität besitzen, wird für die Programmierung von Listen die Einhaltung folgender Regeln empfohlen: · · · · Angabe einer ausreichenden Ausgabelänge Kein Überschreiben von Teilen eines Feldes Keine Verwendung von WRITE TO mit RIGHT-JUSTIFIED oder CENTERED mit nachfolgender WRITE-Ausgabe Bei selbstprogrammiertem horizontalen Blättern mit der Anweisung SCROLL sollten nur die untere oder obere Grenze von ausgegebenen Datenobjekten angegeben werden, da in US die Positionen im Listenpuffer und auf der dargestellten Liste nur für diese Feldgrenzen garantiert übereinstimmen. 6. Neue Klassen für Unicode 6.1 Ermittlung von Feldeigenschaften Die Klasse CL_ABAP_CHAR_UTILITIES bietet Attribute und Methoden an, die Eigenschaften einzelner Zeichen betreffen. Die Komponenten dieser Klasse sind alle statisch und öffentlich. Die Attribute sind schreibgeschützt und werden im Klassenkonstruktor initialisiert. 35 · Attribut CHARSIZE CHARSIZE TYPE I. Das Attribut CHARSIZE gibt die Länge eines C(1)-Feldes in Bytes an, also 1 Byte in einem NUS und 2 oder 4 Byte in einem US. · Attribute MINCHAR, MAXCHAR MINCHAR(1) TYPE C. MINCHAR enthält in einem NUS das Zeichen mit der Hexadezimaldarstellung X'00', in einem US das Unicodezeichen U+0000. MAXCHAR(1) TYPE C. MAXCHAR enthält in einem NUS das Zeichen mit der Hexadezimaldarstellung X'FF', in einem US das Unicodezeichen U+FFFD. Diese Werte dürfen nur in binären Vergleichen für folgende ABAP-Anweisungen benutzt werden: 1. SORT ohne Zusatz AS TEXT 2. IF mit den Operatoren <, >, <=, >= 3. IF f1 BETWEEN f2 AND f3. 4. IF f in sel. Bei binären Vergleichen ist allerdings darauf zu achten, daß die Ergebnisse von der Plattform abhängen. So gilt zum Beispiel im Zeichensatz ISO-8859-1 die Reihenfolge 1 < A < Z < a < Ä < ü, in EBCDIC jedoch Ä < a < A < ü < Z < 1. CLEAR feld WITH CL_ABAP_CHAR_UTILITIES=>MAXCHAR kann benutzt werden, um ein Feld mit einem Wert zu füllen, der größer oder gleich als alle Zeichenketten ist. Dies funktioniert auch auf Multibyte-NUS. MINCHAR und MAXCHAR sind im allgemeinen keine gültigen Zeichen des gegenwärtigen Zeichensatzes. Insbesonders darf TRANSLATE f TO UPPER CASE nicht auf diese Attribute angewendet werden, weil das Ergebnis undefiniert ist. Die gleichen Einschränkungen gelten für alle Operationen wie zum Beispiel CS, NS, CP, NP oder SEARCH, die implizit in Großbuchstaben wandeln. Außerdem sind Zeichensatzkonvertierungen mit MINCHAR und MAXCHAR nicht zulässig. Darüber hinaus ist nicht garantiert, daß MINCHAR auf Dynpros als Raute (#) ausgegeben wird. In manchen Fällen wird MINCHAR als Ende eines Textfeldes behandelt. · Byte Order Die Konvertierung von Zahlentypen und Unicode zwischen Little Endian und Big Endian wird durch die Konvertierungsklassen, die im Zusammenhang mit der Dateischnittstelle eingeführt werden, abgedeckt. Die hier beschriebenen Attribute dienen dazu, Byte-Order-Marks in X-Containern zu erkennen und zu schreiben. 36 Attribut ENDIAN ENDIAN(1) TYPE C. Hier wie auch in der klassenbasierten Dateischnittstelle werden in US und NUS die Werte B für Big Endian und L für Little Endian vergeben. Konstanten BYTE_ORDER_MARK_ BYTE_ORDER_MARK_LITTLE(2) BYTE_ORDER_MARK_BIG(2) BYTE_ORDER_MARK_UTF8(3) TYPE X TYPE X TYPE X Die Werte dieser Konstanten sind für US und NUS dieselben, nämlich X'FFFE' für Little Endian und X'FEFF' für Big Endian. BYTE_ORDER_MARK_UTF8 enthält die UTF8-Darstellung von U+'FEFF'. Die klassenbasierte Dateischnittstelle wird eine Byte-Order-Mark schreiben, wenn eine UTF16- oder UCS2-Textdatei zum Schreiben geöffnet wird. Wenn eine Textdatei zum Lesen oder Anfügen geöffnet wird, wird die Byte-Order-Mark benutzt, um den Endian zu bestimmen. Dabei wird die Byte-Order-Mark beim Einlesen jedoch nicht in die Zielfelder geschrieben. · Attribute NEWLINE, CR_LF und HORIZONTAL_TAB NEWLINE(1) TYPE C CR_LF(2) TYPE C HORIZONTAL_TAB(1) TYPE C Diese Attribute enthalten die jeweiligen plattformspezifischen Steuerzeichen 6.2 Konvertierung von Daten Diese Klassen dienen dazu, ABAP-Daten zwischen dem Systemformat und externen Formaten zu konvertieren. Dabei werden zeichenartige Daten in einen anderen Zeichensatz und numerische Daten möglicherweise in eine andere Bytereihenfolge (Endian) konvertiert. Für Daten in einem externen Format müssen Container der Typen X und XSTRING verwendet werden. Zeichensatz- und Endiankonvertierung werden auch von der Dateischnittstelle (OPEN DATASET mit neuen Zusätzen), dem RFC, den Funktionsbausteinen GUI_DOWNLOAD oder GUI_UPLOAD durchgeführt. Für speziellere Fälle, in denen die Möglichkeiten dieser Hilfsmittel nicht ausreichen, werden die hier beschriebenen Klassen zur Verfügung gestellt. Da diese Klassen mit Containern der Typen X und XSTRING arbeiten, können diese Container von der Dateischnittstelle, dem RFC und den Funktionsbausteinen GUI_DOWNLOAD und GUI_UPLOAD unkonvertiert übertragen werden. Die Klassen ersetzen die beiden folgenden Anweisungen: TRANSLATE c ...FROM CODE PAGE g1 ... TO CODE PAGE g2 TRANSLATE f ...FROM NUMBER FORMAT n1 ... TO NUMBER FORMAT n2 Eine ausführliche Beschreibung befindet sich in der Klassendokumentation des Class Builders. Im einzelner sind folgende Klassen sind verfügbar: 37 CL_ABAP_CONV_IN_CE: Lesen von Daten aus einem Container und Konvertieren in das Systemformat. Es ist auch möglich, Strukturen mit Daten zu füllen. CL_ABAP_CONV_OUT_CE: Konvertieren von Daten vom Systemformat in ein externes Format und Schreiben in einen Container. CL_ABAP_CONV_X2X_CE: Konvertieren von Daten von einem externen Format in ein anderes externes Format. 7. RFC und Unicode Im Zusammenhang mit der ABAP Unicode Umstellung wird auch die RFCSchnittstelle geändert. Die folgenden Ausführungen skizzieren in aller Kürze die allgemeinen Vorgaben. Damit der Remote Function Call in US wie auch in NUS funktioniert, wird in der Destination ein zusätzliches Attribut eingeführt, das beschreibt, ob der RFC in einem US oder NUS laufen soll. Benutzt ein ABAP-Programm Funktionsbausteine, die dynamisch Änderungen der RFC-Destination vornehmen, so muß diese neue Eigenschaft in einem weiteren obligatorischen Parameter versorgt werden. Bei der Übertragung von Textdaten in einem RFC-Aufruf können neue Ausnahmen der folgenden Art auftreten: · Ein Text kann nicht von der Quellcode- in die Zielcodepage konvertiert werden, weil die entsprechenden Zeichen in der Zielcodepage nicht vorhanden sind. · Das Feld im Zielsystem ist kürzer als das Feld im Quellsystem. Dies kann vorkommen, wenn Daten von einem US in ein Multibyte-System übertragen werden. · Grundsätzlich kann davon ausgegangen werden, dass Textdaten im sendenden und empfangenden System unterschiedliche Länge haben. Aus diesem Grund wird in erster Linie die Verwendung von Strings empfohlen. Wo immer die Möglichkeit besteht, sollten Längenangaben für Textdaten ausgeschlossen werden. Im Gegensatz dazu können binäre Daten ohne Probleme mit Längenangeben gesendet werden. 8. Abrundungsmaßnahmen Bisher wurde die Klassenhierarchie und die Interface-Implementierungsrelation bei der Prüfung und Konvertierung von Datentypen nur bei Einzelfeldern mit Klassenund Interface-Referenzen berücksichtigt. Dagegen war dies bei Strukturen, die Referenzen enthalten, nur sehr uneinheitlich geregelt. Bei der Konvertibilität und der Typ- und Vergleichskompatibilität tiefer Strukturen wurden deshalb die nachfolgenden Verallgemeinerungen vorgenommen. 38 1. Konvertibilität und Typkompatibilität für Importing-Parameter: · Elementare Komponenten von Strukturen müssen genau übereinstimmen. · Die Klassenhierarchie und die Interface-Implementierungsrelation werden auch für Interface- und Klassenreferenzen als Teilkomponenten berücksichtigt. · Tabellenkomponenten sind miteinander kompatibel, sofern der Zeilentyp typkompatibel und konvertibel ist. Das bedeutet, daß sich die Zugriffsarten der Tabellen unterscheiden dürfen und die Zeilentypen konvertibel sein müssen. Beispielsweise ist eine Strukturkomponente Tabelle über Integer mit einer Komponente Tabelle über Floats verträglich. 2. Vergleichskompatibilität: · Elementare Komponenten müssen genau übereinstimmen. · Beliebige Klassen- und Interface-Referenzkomponenten sind zueinander vergleichskompatibel. · Tabellenkomponenten sind miteinander vergleichskompatibel, wenn der Zeilentyp vergleichskompatibel ist. 39 9. Weitere Beispielprogramme zur Unicode-Umstellung 9.1 Zuweisung zwischen Strukturen: Umstellung durch Includes mit Gruppenamen Vor der Unicode-Umstellung: types: begin of T_STRUC, F1 type c, F2 type c, F3 type i, F4 type p, end of T_STRUC. data: begin of STRUC1. include type T_STRUC. data: F5 type x. data: end of STRUC1. data: begin of STRUC2. include type T_STRUC. data: F6 type p. data: end of STRUC2. ß Unicode-Fehler! STRUC1 = STRUC2. Es sei vorausgesetzt, dass in diesem Fall nur der Inhalt des Includes, also die Komponenten F1 bis F4 zugewiesen werden sollen. Es wurde bisher in Kauf genommen, dass die Komponente F5 mit eine unsinnigen Wert überschrieben wird. Nach der Unicode-Umstellung Durch die Einführung von Gruppennamen für die Includes und der Verwendung dieser Gruppennamen bei der Zuweisung kann diese Programmstelle einfach umgestellt werden. types: begin of T_STRUC, F1 type c, F2 type c, F3 type i, F4 type p, end of T_STRUC. data: begin of STRUC1. include type T_STRUC as PART1. data: F5 type x. data: end of STRUC1. data: begin of STRUC2. include type T_STRUC as PART1. data: F6 type p. data: end of STRUC2. 40 STRUC1-PART1 = STRUC2-PART1. ß ok 9.2 Zuweisung zwischen Strukturen: Umstellung durch Offset/LängenZugriffe Vor der Unicode-Umstellung: data: begin of STRUC1, F1(10) type c, F2(20) type c, F3 type i, F4 type p, end of STRUC1, begin of STRUC2, C1(10) type c, C2(20) type c, C3 type x, C4 type f, end of STRUC2. ß Unicode-Fehler! STRUC1 = STRUC2. In diesem Beispiel wird davon ausgegangen, dass nur der Inhalt der ersten beiden Komponenten C1 und C2 bei der Zuweisung an F1 und F2 übertragen werden soll, da die nachfolgenden Komponenten F3 und F4 sowieso durch unsinnige Werte überschrieben werden. Nach der Unicode-Umstellung Da das Anfangsstück der Strukturen, das für die beabsichtigte Zuweisung relevant ist, rein zeichenartig ist, können die Operanden der Zuweisung jeweils durch Offset-/Längenzugriffe selektiert werden: ... STRUC1(30) = STRUC2(30). ß ok 9.3 Offset/Längen-Zugriff auf Strukturen bei Zuweisung: Verwendung von Includes Vor der Unicode-Umstellung Durch Offset-/Längenzugriffe werden Teilbereiche von Strukturen selektiert, die einander zugeweisen werden sollen. Da die Strukturen mit nicht zeichenartigen Kompontenten beginnen, sind die Offset-/Längenzugriffe in unicodefähigen Programmen nicht mehr erlaubt. 41 data: begin of STRUC1, F0 type x, F1(10) type c, F2(20) type c, F3 type i, F4 type p, end of STRUC1, begin of STRUC2, C0 type i, C1(10) type c, C2(20) type c, C3 type x, C4 type f, end of STRUC2. STRUC1+1(30) = STRUC2+4(30). ß Unicode-Fehler! Nach der Unicode-Umstellung Durch die Einführung von Includes mit Gruppennamen können die entsprechenden Teilbereiche der Strukturen selektiert und einander zugewiesen werden. types: begin of PART1, F1(10) type c, F2(20) type c, end of PART1, begin of PART 2, C1(10) type c, C2(20) type c, end of PART 2. data: begin of STRUC1, F0 type x. include type PART1 as PART. data: f3 type i, f4 type p, end of STRUC1, begin of STRUC2, C0 type i. include type PART2 as PART. data: C3 type x, C4 type f, end of STRUC2. STRUC1-PART = STRUC2-PART. 42 ß ok 9.4 Offset/Längen-Zugriff auf Strukturen bei Zuweisung: IncludesLösung nicht möglich Vor der Unicode-Umstellung data: begin of STRUC1, F0(1) type x, F1(10) type c, F2(20) type c, F3 type i, F4 type p, end of STRUC1, begin of STRUC2, C0(1) type c, C1(10) type c, C2(20) type c, C3 type i, C4 type f, end of STRUC2, begin of STRUC3, G0(1) type c, G1(10) type c, G2(20) type c, end of STRUC3. STRUC1+1(35) = STRUC2+1(35). STRUC3 = STRUC2. ß Unicode-Fehler Umstellungsversuch: Einführung von INCLUDEs mit Gruppennamen types: begin of PART1, F1(10) type c, F2(20) type c, F3 type i, end of PART1, begin of PART2, C1(10) type c, C2(20) type c, C3 type i, end of PART2. data: data: data: begin of STRUC1, F0(1) type x. include type PART1 as PART. F4 type p, end of struc1. begin of STRUC2, C0(1) type c. 43 include type PART2 as PART. C4 type f, end of STRUC2, data: begin of STRUC3, G0(1) type c, G1(10) type c, G2(20) type c, end of STRUC3. STRUC1-PART = STRUC2-PART. STRUC3 = STRUC2. ß Neuer Unicode-Fehler! Durch die Einführung der Includes kann zwar die ursprüngliche Problemstelle Unicode-fähig umgestellt werden, es wird aber bei der danach folgenden Zuweisung ein neues Unicode-Problem erzeugt: Die Zuweisung von STRUC2 an STRUC3 ist nicht mehr möglich, da durch das Include in STRUC2 eine Alignmentlücke vor der Komponente C1 entsteht. Dies führt dazu, daß die UnicodeFragmentsichten von STRUC2 und STRUC3 nicht mehr zusammenpassen. Nach der Umstellung In diesem Fall bleibt nichts anderes mehr übrig, als die betroffenen Komponenten der Strukturen einzeln einander zuzuweisen: data: begin of STRUC1, F0(1) type x, F1(10) type c, F2(20) type c, F3 type i, F4 type p, end of STRUC1, begin of STRUC2, C0(1) type c, C1(10) type c, C2(20) type c, C3 type i, C4 type f, end of STRUC2, begin of STRUC3, G0(1) type c, G1(10) type c, G2(20) type c, end of STRUC3. STRUC1-F1 = STRUC2-C1. STRUC1-F2 = STRUC2-C2. STRUC1-F3 = STRUC2-C3. STRUC3 = STRUC2. 44 9.5 Zuweisung zwischen Struktur und Einzelfeld vom Typ N In Unicode-Programmen ist die Zuweisungen zwischen einen nicht zeichenartigen Struktur und einem Einzelfeld vom Typ N nicht mehr zulässig. Vor der Unicode-Umstellung data: begin of STRUC, NUMBER(20) type n, F2 type p, end of STRUC, NUMBER(20) type n. ß Unicode-Fehler! NUMBER = STRUC. Nach der Unicode-Umstellung Da hier die erste Komponenten der Struktur an das Einzelfeld zugewiesen werden soll, kann die Programmstelle einfach umgestellt werden, indem die Zuweisung der ganzen Struktur durch eine Zuweisung der ersten Strukturkomponente ersetzt wird. ... NUMBER = STRUC-NUMBER. 9.6 Zuweisung zwischen Struktur und Einzelfeld vom Typ D Vor der Unicode-Umstellung data: begin of STRUC, YEAR(4) type MONTH(2) type DAY(2) type F4 type end of STRUC, DATE n, n, n, p, type d. DATE = STRUC. ß Unicode-Fehler! In Unicode-Programmen ist die Zuweisungen zwischen einen nicht zeichenartigen Struktur und einem Einzelfeld vom Typ D nicht mehr zulässig. Nach der Unicode-Umstellung Durch einen Offset-/Längenzugriff auf das zeichenartige Anfangsstück der Struktur kann die Problemstelle einfach Unicode-fähig umgestellt weden. DATE = STRUC(8). ß ok! 45 9.7 Zuweisung zwischen Struktur und Einzelfeld: ASCII-Codes Zuweisungen zwischen Strukturen mit Komponenten vom Typ X und Einzelfeldern wurden früher auch dazu verwendet, um trickreich, z.B. wie in folgendem Beispiel, Zeichen zu einem ASCII-Code zu berechnen. Vor der Unicode-Umstellung data: begin of TAB, X(1) type x value '09', “ASCII horizontal tab end of TAB, C(10) type c. C+5(1) = TAB. ß Unicode-Fehler In Unicode-Programmen funktioniert dieser Trick nicht mehr. Durch die neuen vordefinierten Konstanten in Klasse CL_ABAP_CHAR_UTILITIES ist aber nun eine einfache und saubere Lösung möglich, die auf allen Plattformen funktioniert. Nach der Unicode-Umstellung class cl_abap_char_utilities definition load. c+5(1) = cl_abap_char_utilities=>horizontal_tab. Anmerkung: Sollte das verwendete Zeichen nicht als Konstante vordefiniert sein, kann man sich mit der Methode CL_ABAP_CONV_IN_CE=>UCCP beziehungsweise CL_ABAP_CONV_IN_CE=>UCCPI) zu einem Unicode-Codepoint das entsprechende Zeichen geben lassen. Es kann dabei die Eigenschaft ausgenützt werden, dass die Zeichen mit den ASCII-Codes 00 bis 7F den ersten 127 Unicode-Codepoints, also U+0000 bis U+007F) entsprechen. 9.8 Zuweisung zwischen Struktur und Einzelfeld: Containerfelder (1) Häufig wurden lange Felder vom Typ C als "Container" verwendet, in dem Daten unterschiedlicher Strukturen abgelegt werden. Zum Ablegen und Auslesen der Daten konnte direkt die Zuweisung zwischen Struktur und Einzelfeld verwendet werden. In Unicode-Programmen sind diese Zuweisungen nur noch erlaubt, wenn die Struktur rein zeichenartig aufgebaut ist. Vor der Unicode-Umstellung data: begin of STRUC, F1(3) type x, F2(8) type p, end of STRUC, CONTAINER(1000) type c. “Daten im Container ablegen 46 ß Unicode-Fehler CONTAINER = STRUC. ”Daten aus dem Container auslesen STRUC = CONTAINER. ß Unicode-Fehler Die Verwendung von C-Feldern als Container zur Speicherung nicht vollständig zeichenartiger Strukturen funktioniert nur noch dann, wenn sichergestellt ist, dass der Inhalt nur temporär innerhalb eines Applikationsservers verwendet wird. Daher darf der Inhalt des Containerfelds weder in der Datenbank abgelegt noch per RFC verschickt oder auf ein File geschrieben werden1. Außerdem darf nicht mit Offset oder Länge auf das Containerfeld zugegriffen werden, um Komponenten einer Struktur zu selektieren2. Sind diese Voraussetzungen erfüllt, kann das Füllen und Lesen der Daten folgendermaßen umgestellt werden, indem durch Casts Feldsymbole vom Typ X auf das Containerfeld und die Struktur gesetzt werden und danach die Zuweisung zwischen den Feldsymbolen erfolgt. Die Zuweisung bewirkt nun, daß der Rest des Containers mit Hex-00-Werten statt mit Leerzeichen aufgefüllt wird. Wenn das CFeld nur als Datenablage verwendet wird, sollte das aber kein Problem sein. Nach der Unicode-Umstellung field-symbols: <X_CONTAINER> type x, <X_STRUC> type x. assign CONTAINER to <X_CONTAINER> casting. assign STRUC to <X_STRUC> casting. “Daten im Container ablegen <X_CONTAINER> = <X_STRUC>. ß ok! ”Daten aus dem Container auslesen <X_STRUC> = <X_CONTAINER>. ß ok! Anmerkung: Es gibt die Klasse CL_ABAP_CONTAINER_UTILITIES, die generische Möglichkeiten bietet, um Strukturen in Containern vom Typ C oder STRING abzulegen. Bei Verwendung dieser Klassen ist aber zu berücksichtigen, daß durch die Klassenverschalung und die generische Lösung möglicherweise . PerformanceEinbußen in Kauf genommen werden müssen. Beim Ablegen auf beziehungsweise Lesen von der Datenbank oder beim RFC werden eventuell, abhängig von der Bytereihenfolge (little endian/big endian) der Applikationsserver-Hardware, automatisch die Bytes des Zeichenfelds vertauscht. Werden innerhalb des Zeichenfelds nicht zeichenartige Daten abgelegt, dann führt diese automatische Vertauschung dazu, dass der Inhalt verstümmelt wird. 1 2 Ein Zugriff mit Offset/Länge ist nicht mehr sinnvoll möglich, da die Offset- und Längenwerte auf Nicht-Unicode- und Unicode-Plattformen unterschiedlich sein können. Außerdem wird bei Zugriffen auf C-Felder immer in Zeichen gezählt, in den Strukturen aber auch Komponenten vorkommen können, die auf UnicodeSystemen ungerade Längen oder Offsets besitzen. 47 ... class CL_ABAP_CONTAINER_UTILITIES definition load. call method CL_ABAP_CONTAINER_UTILITIES =>FILL_CONTAINER_C exporting IM_VALUE = STRUC importing EX_CONTAINER = CONTAINER exceptions ILLEGAL_PARAMETER_TYPE = 1 others = 2. call method CL_ABAP_CONTAINER_UTILITIES =>READ_CONTAINER_C exporting IM_CONTAINER = CONTAINER importing EX_VALUE = STRUC exceptions ILLEGAL_PARAMETER_TYPE = 1 others = 2. 9.9 Zuweisung zwischen Struktur und Einzelfeld; Containerfelder (2) Ist sichergestellt, dass die Gesamtlänge der Strukturen, die im C-Container abgelegt werden, immer ein Vielfaches der Länge eines Zeichens ist - das ist dann der Fall, wenn die Struktur mindestens eine Komponente vom Typ C, N, D, T, I oder F enthält – dann kann die folgende, einfachere Lösung verwendet werden, die mit nur einem Feldsymbol auskommt. Vor der Unicode-Umstellung data: begin of STRUC, F1(3) type x, F2(8) type p, F3(10) type c end of STRUC, CONTAINER(1000) type c. “Daten im Container ablegen CONTAINER = STRUC. ß Unicode-Fehler! ”Daten aus dem Container auslesen STRUC = CONTAINER. ß Unicode-Fehler! Nach der Unicode-Umstellung field-symbols: <C_STRUC> assign STRUC type c. to <C_STRUC> “Daten im Container ablegen CONTAINER = <C_STRUC>. casting. ß ok ”Daten aus dem Container auslesen <C_STRUC> = CONTAINER. ß ok 48 9.10 Zuweisung zwischen Struktur und Einzelfeld: Nicht lokaler Container In diesem Beispiel wird zunächst eine Tabelle gefüllt, die pro Zeile jeweils den Namen einer DDIC-Struktur und den Inhalt einer solchen Struktur – abgelegt in einem Containerfeld - enthält. An einer anderen Programmstelle wird dann diese Tabelle weiterverarbeitet: Es werden die Werte der Strukturkomponenten ausgegeben, indem über einen Funktionsbaustein die Offsets und Längen der Strukturkomponenten bestimmt werden und dann durch Offset-/Längenzugriffe auf den Container die Komponenten selektiert werden. Vor der Unicode-Umstellung types: begin of T_VALUE_WA, TABNAME(30) type c, DUMMY_ALIGN type f, CONTAINER(1000) type c, end of T_VALUE_WA, T_VALUE_LIST type table of T_VALUE_WA. data: L_VALUES L_VALUE_WA L_D010SINF L_CO2MAP type type type type T_VALUE_LIST, T_VALUE_WA, D010SINF, CO2MAP. “Ablegen von verschiedenen Strukturen in einer Tabelle: L_VALUE_WA-TABNAME = 'D010SINF'. L_D010SINF-DATALG = 41. L_VALUE_WA-CONTAINER = L_D010SINF. ß Unicode-Fehler append L_VALUE_WA to L_VALUES. L_VALUE_WA-TABNAME L_CO2MAP-ID L_VALUE_WA-CONTAINER append L_VALUE_WA to = 'CO2MAP'. = 42. = L_CO2MAP. L_VALUES. ß Unicode-Fehler “Verarbeitung der Tabelle L_VALUES an einer “anderen Programmstelle: Generische Ausgabe der “Strukturkomponenten. data: L_DFIES_TAB type table of DFIES. field-symbols: <DT> type DFIES, <VALUE_WA> type T_VALUE_WA, <f>. clear L_VALUES_WA. loop at L_VALUES assigning <VALUE_WA>. “Komponenten mit Offset- und Länge bestimmen call function 'DDIF_NAMETAB_GET' 49 exporting tabname = <VALUE_WA>-TABNAME tables DFIES_TAB = L_DFIES_TAB. “Inhalt der Komponenten ausgeben loop at L_DFIES_TAB assigning <DT>. assign <VALUE_WA>-CONTAINER+<DT>-OFFSET(<DT>-INTLEN) to <F> type <DT>-INTTYPE. write <F>. endloop. endloop. Der Offset-/Längenzugriffe führen zwar nicht zu einem Syntax- oder Laufzeitfehler, würde aber in einem Unicode-System falsche Daten liefern, da die vom Funktionsbaustein zurückgelieferten Offsets und Längen in Bytes angegeben sind, beim Zugriff auf den C-Container aber in Zeichen gezählt wird. Mit den seit Release 4.6 zur Verfügung stehenden Möglichkeiten, Datenobjekte dynamisch zu erzeugen, kann das Programm deutlich vereinfacht und unicodefähig umgeschrieben werden. Als Container für den Inhalt der Stukturen wird hier ein X-String verwendet, der jeweils mit EXPORT ... TO DATA BUFFER ... gefüllt und mit IMPORT … FROM DATA BUFFER… ausgelesen wird. Damit ist sichergestellt, dass die Daten auch applikationsserverübergreifend verwendet werden können. Nach der Unicode-Umstellung types: begin of T_VALUE_WA, TABNAME(30) type c, XCONTAINER type xstring, end of T_VALUE_WA, T_VALUE_LIST type table of T_VALUE_WA. data: L_VALUES L_VALUE_WA L_D010SINF L_CO2MAP type type type type T_VALUE_LIST, T_VALUE_WA, D010SINF, CO2MAP. “Ablegen von verschiedenen Strukturen in einer Tabelle: L_D010SINF-DATALG = 41. L_VALUE_WA-TABNAME = 'D010SINF'. export VALUE from L_D010SINF to data buffer L_VALUE_WA-XCONTAINER. append L_VALUE_WA to L_VALUES. L_CO2MAP-ID = 42. L_VALUE_WA-TABNAME = 'CO2MAP'. 50 export VALUE from L_CO2MAP to data buffer L_VALUE_WA-XCONTAINER. append L_VALUE_WA to L_VALUES. “Verarbeitung der Tabelle L_VALUES an einer “anderen Programmstelle: generische Ausgabe der “Strukturkomponenten. data: DREF type ref to data, L_NUMBER type i, L_TYPE type c. field-symbols: <STRUC> type any, <COMP> type any. loop at L_VALUES into L_VALUE_WA. “Erzeugen eines passenden Datenobjekts create data DREF type (L_VALUE_WA-TABNAME). assign DREF->* to <STRUC>. “Datenobjekt mit Inhalt aus dem Container füllen import VALUE to <STRUC> from data buffer L_VALUE_WA-XCONTAINER. “Komponenten der Struktur ausgeben describe field <STRUC> type L_TYPE components L_NUMBER. do L_NUMBER times. assign component SY-INDEX of structure <STRUC> to <COMP>. write <COMP>. enddo. endloop. 9.11 Zeichenverarbeitung Im folgenden Beispiel werden Komponenten vom Typ X verwendet, um Zeichen abzulegen. In Unicode-Programmen ist dies nicht mehr möglich. Vor der Unicode-Umstellung data: begin of L_LINE, TEXT1(10) type MARK1(1) type TEXT2(10) type MARK2(1) type TEXT3(10) type MARK3(1) type BLANK(100) type end of L_LINE, c, x value '00', c, x value '00', c, x value '00', c, 51 HEX0(1) type x value '00', CRLF(2) type x value '0D0A'. L_LINE-TEXT 1 = 'SYSTEM: L_LINE-TEXT 2 = 'USER: L_LINE-TEXT 3 = 'CLIENT: '. '. '. replace: HEX0 with SY-SYSID into L_LINE, ß Unicode-Fehler HEX0 with SY-UNAME into L_LINE, ß Unicode-Fehler HEX0 with SY-MANDT into L_LINE. ß Unicode-Fehler condense L_LINE. concatenate L_LINE CRLF into L_LINE. ß Unicode-Fehler ß Unicode-Fehler *Weiterverarbeitung von L_LINE. Nach der Unicode-Umstellung Durch die Verwendung der Konstanten aus Klasse CL_ABAP_CHAR_UTILITIES kann die Verwendung von X-Feldern vollständig vermieden werden. class CL_ABAP_CHAR_UTILITIES definition load. data: begin of L_LINE, TEXT1(10) type c, MARK1(1) type c value CL_ABAP_CHAR_UTILITIES=>MINCHAR, TEXT2(10) type c, MARK2(1) type c value CL_ABAP_CHAR_UTILITIES=>MINCHAR, TEXT3(10) type c, MARK3(1) type c value CL_ABAP_CHAR_UTILITIES=>MINCHAR, BLANK(100) type c, end of L_LINE, HEX0(1) type c, CRLF(2) type c. HEX0 = CL_ABAP_CHAR_UTILITIES=>MINCHAR. CRLF = CL_ABAP_CHAR_UTILITIES=>CR_LF. L_LINE-TEXT1 = 'SYSTEM: L_LINE-TEXT2 = 'USER: L_LINE-TEXT3 = 'CLIENT: '. '. '. replace: HEX0 with SY-SYSID into L_LINE, HEX0 with SY-UNAME into L_LINE, HEX0 with SY-MANDT into L_LINE. 52 condense L_LINE. concatenate L_LINE CRLF into L_LINE. *Weiterverarbeitung von L_LINE. Anmerkung: Das vorgestellt Programm, das in ähnlicher Weise in einer "echten" Anwendung gefunden wurde, ist unnötig kompliziert und sicher kein Beispiel für einen guten Programmierstil. Eine viel klarere Lösung könnte folgendermaßen aussehen: class CL_ABAP_CHAR_UTILITIES definition load. data: L_LINE(133) type c. concatenate `SYSTEM: ` SY-SYSID ` USER: ` SY-UNAME ` CLIENT: ` SY-MANDT CL_ABAP_CHAR_UTILITIES=>CR_LF into L_LINE. 9.12 Öffnen von Dateien Vor der Unicode-Umstellung data: begin of STRUC, F1 type c, F2 type p, end of STRUC, DSN(30) type c value 'TEMPFILE'. STRUC-F1 = 'X'. STRUC-F2 = 42. * Daten auf Datei schreiben open dataset DSN in text mode. transfer STRUC to DSN. close dataset DSN. Read from file * Daten aus Datei einlesen clear STRUC. open dataset DSN in text mode. read dataset DSN into STRUC. close dataset DSN. write: / STRUC-F1, STRUC-F2. ß Unicode-Fehler ß Unicode-Fehler Das Programmbeispiel ist aus zwei Gründen nicht ablauffähig in Unicode. Zum einen muss in Unicode-Programmen bei OPEN DATASET das Dateiformat genauer spezifiziert werden, zum anderen dürfen nur noch rein zeichenartige Strukturen auf Text-Dateien geschrieben werden. 53 Je nachdem, ob das alte Dateiformat weiterhin gelesen werden können muß oder ob es möglich ist, die Daten in einem anderen, neuen Format abzulegen, sind verschiedene Umstellungsvarianten möglich, von denen zwei vorgestellt werden. Nach der Unicode-Umstellung - Fall 1: Neue textuelle Ablage im UTF-8-Format ... data: begin of STRUC2, F1 type c, F2(20) type c, end of STRUC2. * Daten in Textform bringen move-corresponding STRUC to STRUC2. * Daten auf Datei schreiben open dataset DSN in text mode for output encoding utf-8. transfer STRUC2 to DSN. close dataset DSN. * Daten aus Datei einlesen clear STRUC. open dataset DSN in text mode for input encoding utf-8. read dataset DSN into STRUC2. close dataset DSN. move-corresponding STRUC2 to STRUC. write: / STRUC-F1, STRUC-F2. Durch die textuelle Ablage im UTF8-Format wird sichergestellt, dass die erzeugten Dateien plattformunabhängig sind. Nach der Unicode-Umstellung - Fall 2: Altes Nicht-Unicode-Format muss beibehalten werden ... * Daten auf Datei schreiben open dataset DSN in legacy text mode for output. transfer STRUC to DSN. close dataset DSN. * read from file clear STRUC. open dataset DSN in legacy text mode for input. read dataset DSN into STRUC. close dataset DSN. write: / STRUC-F1, STRUC-F2. Durch die Verwendung von des LEGACY TEXT MODE ist sichergestellt, daß die Daten im alten Nicht-Unicode-Format abgelegt und gelesen werden. In diesem Modus ist es auch erlaubt, nicht zeichenartige Strukturen zu lesen oder zu schreiben. Es ist aber zu beachten, dass es in echten Unicode-Systemen zu Datenverlust und 54 Konvertierungsfehlern kommen kann, wenn in der Struktur Zeichen enthalten sind, die in der Nicht-Unicode-Codepage nicht repräsentiert werden können. 9.13 Ausgabe von Listen Nachträgliches überschreibendes Positionieren von SY-VLINE Schlechtes Coding: WRITE / AT 2 '일이삼'. WRITE AT 1 sy-vline. WRITE AT 4 sy-vline. WRITE AT 7 sy-vline. WRITE AT 10 sy-vline. Soll |일|이|삼| Ist: |일| >| | Empfohlene Lösung: WRITE AT 1 sy-vline. WRITE AT 2 '일'. WRITE AT 4 sy-vline. WRITE AT 5 '이'. WRITE AT 7 sy-vline. WRITE AT 8 '삼'. WRITE AT 10 sy-vline. Rechtsbündige Ausgabe mit RIGHT-JUSTIFIED: Schlechtes Coding: DATA text(10) TYPE c. text = '일이삼'. WRITE text TO text RIGHT-JUSTIFIED. WRITE text. Soll: xxxx일이삼 Ist: xxxxxxx일> Empfohlene Lösung: DATA text(10) type c. text = '일이삼'. WRITE text RIGHT-JUSTIFIED. 55 Ausgabe des vollständigen Inhaltes Schlechtes Coding: DATA text(10) TYPE c. text = 'OTTOS MOPS'. WRITE / text. text = '가갸거겨고교구규그기'. WRITE / text. Soll: OTTOS MOPS 가갸거겨고교구규그기 Ist: OTTOS MOPS 가갸거겨>x Empfohlene Lösung: DATA text(10) TYPE c. text = 'OTTOS MOPS'. WRITE / (*) text. text = '가갸거겨고교구규그기'. WRITE / (*) text. Blättern: Schlechtes Coding: TYPES t_line(100) DATA: line tab PARAMETERS scrolcol TYPE TYPE TYPE TYPE c. t_line, table of t_line. i DEFAULT 14. line = '이름1: xxxxxx 이름2: yyyyyy'. APPEND line TO tab. line = '이름1: 남명희 이름2: 조홍우'. APPEND line TO tab. LOOP AT tab INTO line. WRITE / line+scrolcol. ENDLOOP. Soll: 이름2: yyyyyy 이름2: 조홍우 Ist: 2: yyyyyy 조홍우 Empfohlene Lösung: 56 TYPES t_line(100) DATA: line tab PARAMETERS scrolcol TYPE TYPE TYPE TYPE c. t_line, table of t_line. i DEFAULT 14. line = '이름1: xxxxxx 이름2: yyyyyy'. APPEND line TO tab. line = '이름1: 남명희 이름2: 조홍우'. APPEND line TO tab. LOOP AT tab INTO line. WRITE / line. ENDLOOP. SCROLL LIST TO COLUMN scrolcol. Vermischen von Ausgabe- und Pufferlänge Das Beispiel bezieht sich auf die Datenbanktabelle ZCHNUMBERS im ABAP Dictionary, die als Inhalt die Bezeichnungen der Zahlen 1 bis 5 in Englisch und Koreanisch enthält. Schlechtes Coding: SELECT * FROM zchnumbers INTO wa ORDER BY num lang. WRITE wa-lang TO line(2). WRITE sy-vline TO line+2(1). WRITE wa-name TO line+3(5). WRITE sy-vline TO line+8(1). WRITE wa-num TO line+9(3) RIGHT-JUSTIFIED. WRITE / line. ENDSELECT. Soll: KO|하나 | 1 Ist KO|하나 | 1 EN|one | 1 EN|one | 1 KO|둘 | 2 KO|둘 EN|two | 2 EN|two | 2 KO|셋 | 3 EN|two | 2 EN|three| 3 KO|셋 KO|넷 | 4 EN|three| 3 EN|four | 4 KO|넷 KO|다섯 | 5 EN|four | 4 EN|five | 5 KO|다섯 | 5 |2 |3 |4 Empfohlene Lösung: DATA: offset_tab TYPE abap_offset_tab, 57 disp_line LIKE line. APPEND 3 TO offset_tab. APPEND 8 TO offset_tab. SELECT * FROM zchnumbers INTO wa. WRITE wa-lang TO line(2). WRITE sy-vline TO line+2(1). WRITE wa-name TO line+3(5). WRITE sy-vline TO line+8(1). WRIE wa-num TO line+9(3) RIGHT-JUSTIFIED. CALL METHOD cl_abap_list_utilities=>memory_to_display EXPORTING memory_data = line offset_tab = offset_tab IMPORTING display_data = disp_line. WRITE / disp_line. ENDSELECT. Missbrauch des Systemfeldes SY-CUCOL als Puffer-Offset Schlechtes Coding: DATA: off type i. AT LINE-SELECTION. off = sy-staco + sy-cucol – 3. sy-lisel+off(1) = '-'. MODIFY CURRENT LINE. START-OF-SELECTION. WRITE / '한국' WRITE at 50(14) '일-이-삼-사-오'. SCROLL LIST TO COLUMN 20. Wird der Cursor auf die Lücken zwischen den sichtbaren koreanischen Zeichen gestellt und danach ein Doppelklick mit der linken Maustaste ausgeführt, dann erscheint folgende Ausgabe: Soll: 012345678901234567890123456789일-이-삼-사-오 Ist: 01234567890123456789012345 일 이 -사 - - - Empfohlene Lösung: DATA: f TYPE string, mo TYPE i. AT LINE-SELECTION. GET CURSOR FIELD f MEMORY OFFSET mo. sy-lisel+mem_off(1) = '-'. MODIFY CURRENT LINE. 58 ... 59 10. Glossar Byteartig Die ABAP-Datentypen X und X-STRING Code Binäre Verschlüsselung von Buchstaben, Ziffern und Sonderzeichen Codepage Auswahl der verschlüsselten Zeichen für eine ausgewählte Umgebung Datencluster Zusammenstellung mehrerer Datenobjekte (Felder, Strukturen, Tabellen) DDIC ABAP Datenverzeichnis Endian Die Byte-Reihenfolge einer Zahl wird im Speicher mit abnehmenden Stellenwerten von links nach rechts (Big Endian) oder von rechts nach links (Little Endian) abgelegt. Frontend Präsentationsserver des Kernel In den Programmiersprachen C und C++ codierte Basisfunktionalität des NUP Nicht-Unicode-Programm: Programm, bei dem das Unicodeflag nicht gesetzt ist NUS Nicht-Unicode-System: -System, in dem Zeichen binär durch 1 Byte verschlüsselt werden. Restlänge Die Restlänge eines Feldes oder einer zeichenartigen Struktur errechnet sich aus der Differenz zwischen Gesamtlänge minus Offset. Surrogate Area Zeichenergänzung für alle Zeichen, die nicht im Standard-Unicode mit maximal 64 k Zeichen enthalten sind. Zu dem Bitmuster aus dem Standard-Unicode werden zwei weitere Bytes aus dieser Area zugelesen. Unicode-Fragmentsicht Einteilung von Strukturen in gleichartige Datenbereiche UP Unicode-Programm: ABAP-Programm, bei dem das Unicodeflag gesetzt ist US Unicode-System: System, in dem Zeichen binär durch 2 oder 4 Byte verschlüsselt werden. UTF-8 Datenformat für Kommunikation und Datenaustausch XML Extensible Markup Language: Auszeichnungssprache zur Darstellung beliebiger Dokumente im Internet Zeichen Buchstabe, Ziffer oder Sonderzeichen Zeichenartig Die ABAP-Datentypen C, N, D, T und STRING 60 11. Verzeichnis der Schlüsselbegriffe Append 14 Assign 10, 11, 23, 24, 25 At 9 Byte- 22 Casting 25 Charlen 16 Clear 22 Concatenate 15, 22 Condense 15 Convert Text 15 Create Data 27, 28, 29 Datentypen 5 Describe 19, 23 Delete dbtab 18 Export 29, 30 Fetch 18 Field-Symbols 11, 17 Find 22 Generate 21 Gen. Datentypen 32 Get Bit 20 If 14, 15 Import 29 Include 18, 27 Increment 24, 25 Insert dbtab 18 Insert itab 14 Insert report 21 Loop at 14, 20 Modify dbtab 18 Modify itab 14 Move 12, 13, 14 61 Move-Corresponding 29 Numofchar 16 Offset 9, 10, 11 Open Dataset 19, 30 Operatoren 16 Overlay 15 Perform 10, 17 Range 10, 20, 24 Read Dataset 19 Read Table 20 Refresh 20 Replace 15, 22 Search 15, 22 Select 18 Set Bit 20 Shift 15, 22 Split 15, 22 Stringoperatoren 16 Strlen 16 Structure 17 Transfer 19 Translate 15 Update dbtab 18 Vary 21 Varying 21 Write 17 Write To 17 XStrlen 22 62