Rexx: Problem mit hex-00 im String

(DE) Projekte für OS/2, eCS und ArcaOS
(EN) OS/2, eCS and ArcaOS related projects
Antworten
Benutzeravatar
LotharS
Beiträge: 970
Registriert: So 29. Dez 2013, 20:07
Wohnort: Düsseldorf
Kontaktdaten:

Rexx: Problem mit hex-00 im String

Beitrag von LotharS »

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: Alles auswählen

/* 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: Alles auswählen

[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?
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

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: Alles auswählen

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 Sa 27. Jun 2020, 21:26, insgesamt 1-mal geändert.
Andreas Schnellbacher
Benutzeravatar
LotharS
Beiträge: 970
Registriert: So 29. Dez 2013, 20:07
Wohnort: Düsseldorf
Kontaktdaten:

Beitrag von LotharS »

aschn hat geschrieben: Sa 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:
Benutzeravatar
aschn
Beiträge: 1363
Registriert: Mi 25. Dez 2013, 22:47

Beitrag von aschn »

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
Benutzeravatar
wilfried
Beiträge: 667
Registriert: Mo 23. Dez 2013, 18:26
Wohnort: Barsinghausen
Kontaktdaten:

Beitrag von wilfried »

Ich umgehe solche Probleme mit Transfer() und setze die '00'x auf Space um.
erdmann
Beiträge: 594
Registriert: Mo 4. Jan 2016, 14:36

Beitrag von erdmann »

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 Mo 29. Jun 2020, 05:19, insgesamt 1-mal geändert.
Antworten