Rexx: Problem mit hex-00 im String

(DE) Projekte für OS/2, eCS und ArcaOS
(EN) OS/2, eCS and ArcaOS related projects
User avatar
LotharS
Posts: 674
Joined: Sun 29. Dec 2013, 20:07
Location: Düsseldorf

Rexx: Problem mit hex-00 im String

Post by LotharS » Sat 27. Jun 2020, 19:10

Eine Frage an die Rexxperten unter uns:
Heute bin ich beim Testen einer Rexx-Prozedur ins Grübeln gekommen...
In der OS2.INI kommen Schlüsselwerte vor, die aus mit '00'x aneinander geketteten Teilstrings bestehen. Das funktioniert auch. Dies sei im folgenden simplen Script nachgestellt, mit eingestreuten 'SAY's zum Testen:

Code: Select all

/* aabb.cmd */
a0='AA'
b0='BB'
say 'a0='a0
say 'b0='b0
x0='00'x
s0=a0||x0||b0||x0
say 's0='s0
parse var s0  a1 '00'x b1 '00'x .
say 'a1='a1
say 'b1='b1
exit
Der simple Output auf der Kommandozeile wie erwartet (das '00'x ist ja nicht druckbar):

Code: Select all

[C:\]aabb
a0=AA
b0=BB
s0=AA BB 
a1=AA
b1=BB
Eigentlich aber soll die Funktion (so ähnlich...) unter PM-Kontrolle laufen, (konkret war's VisproRexx, aber) PMRexx reicht. Wer mag bitte selber probieren: Der Output sieht anders aus! Und noch anders wenn ich unter PMRexx trace. => Was mag nur der Grund sein??
Mir ist so weit klar, dass man einen 'String' an eine _externe_ Funktion \0-terminiert übergeben soll. Dieses Prinzip scheint sich unter PM auf 'say' (oder genauso 'lineout') auszuwirken; aber nur da, denn der volle String war ja gemäß 'parse var ...' intakt.
Nicht dass ich dieses "Problem" nicht notfalls zu umgehen wüsste, aber länger genervt hat mich der seltsame Test doch. Hab' ich irgendeine Dokumentation dazu übersehen?

aschn
Posts: 947
Joined: Wed 25. Dec 2013, 22:47

Post by aschn » Sat 27. Jun 2020, 19:57

Du kannst keine Strings, die '00'x enthalten, ausgeben. Das liegt wohl daran, das bei C Strings mit '00'x abgeschlossen werden. Auch die REXX-Befehle benutzen intern C. Diese musst Du erst umwandeln:

Code: Select all

str1 = 'abc'
str2 = '123'

str = str1'00'x''str2'00'x

say 'str = 'translate( str, '.', '00'x)

rest = str
do while rest <> ''
   parse var rest next '00'x rest
   say 'next = 'next
end
charout könnte aber jedes Zeichen ausgeben.
Zuletzt geändert von aschn am Sat 27. Jun 2020, 21:26, insgesamt 1-mal geändert.
Andreas Schnellbacher

User avatar
LotharS
Posts: 674
Joined: Sun 29. Dec 2013, 20:07
Location: Düsseldorf

Post by LotharS » Sat 27. Jun 2020, 22:45

aschn wrote:
Sat 27. Jun 2020, 19:57
Du kannst keine Strings, die '00'x enthalten, ausgeben. Das liegt wohl daran, das bei C Strings mit '00'x abgeschlossen werden. Auch die REXX-Befehle benutzen intern C. Diese musst Du erst umwandeln:
Zum Parsen brauche ich zuvor nichts umzuwandeln; zum Glück auch nach Auswerten eines str=SysIni(....).

Auf der Kommandozeile ausgeführt ließ sich der concatenierte String ja ausgeben (bis auf Nicht-Druckbares, ok), 'C' hin oder her.
In PM[Rexx] jedoch scheint das 'SAY' beim ersten '00'x abzuschneiden, und in Verbindung mit Trace macht's sogar noch irgendwie anders.
Ich versuche es mir so zu erklären: fürs Abschneiden sorgt die C-konforme Weitergabe des Strings an die PM-Applikation: intern wird "bekanntlich" noch ein \0 _an_gehängt, aber ein \0 zwischendurch heißt in C halt ebenfalls String-Ende (wenn man von vorne sucht)... Oder welche bessere Erklärung gibt es für den _Unterschied_?

Jedenfalls habe ich in mein Rexx-Buch eine Warnung notiert :geek:

aschn
Posts: 947
Joined: Wed 25. Dec 2013, 22:47

Post by aschn » Sat 27. Jun 2020, 23:19

Das erste \0-Zeichen markiert das Ende eines C-Strings. Wenn man mit solchen Zeichenketten hantiert, darf man nicht die String-Funktionen verwenden.
Andreas Schnellbacher

User avatar
wilfried
Posts: 646
Joined: Mon 23. Dec 2013, 18:26
Location: Barsinghausen

Post by wilfried » Sun 28. Jun 2020, 14:50

Ich umgehe solche Probleme mit Transfer() und setze die '00'x auf Space um.

erdmann
Posts: 343
Joined: Mon 4. Jan 2016, 14:36

Post by erdmann » Mon 29. Jun 2020, 05:13

Es stimmt nicht,dass REXX Strings wie C behandelt, auch wenn viele REXX DLLs in C programmiert sind. Vielmehr behandelt REXX einen String eher wie ein Byte Array mit beliebigem Inhalt und mit einem zusätzlichen Längenfeld (also eher so wie Pascal nur daß der String nahezu beliebig lang sein kann und das Längenfeld nicht direkt vor dem String stehen muss) und es ist Aufgabe des Programmierers, das korrekt umzusetzen,egal welche Programmiersprache benutzt wird.
Das ist auch der Grund warum ein String in Teile zerlegt werden kann auch wenn ein Zero Terminator dazwischen ist wie dies das Eingangsbeispiel auch demonstriert.
Wenn dann die Ausgabe "schiefgeht", dann liegt es am Ausgabeprogramm. Es ist nirgendwo definiert wie ein Ausgabeprogramm beliebigen binären Inhalt darstellen soll.
Es ist also eine gute Idee,alle Zeichen die nicht druckbar sind durch druckbare Zeichen zu ersetzen.
Zuletzt geändert von erdmann am Mon 29. Jun 2020, 05:19, insgesamt 1-mal geändert.