<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">Chris, Florian and Jörg, thanks for your answers so far! <div class=""><br class=""></div><div class="">Maybe I was not clear enough. </div><div class="">My questions are not so much about capitalization algorithms (that was just an illustration of a use case) but more about how several Oberon-07 compilers differ in their implementation of the (function) procedures SYSTEM.VAL and INCL. </div><div class=""><br class=""></div><div class="">I am aware that Oberon-07 does not define a certain character set. But even then a function along the lines of the classic CAP function of Pascal, Modula-2 and Oberon-90 (which just clears a bit of a CHAR, without checking its input) will be useful as part of more elaborate capitalization algorithms. This is because several often used parts of many character encodings (like ASCII, ISO-8859-1 (8-bit single byte encoded Latin-1) and the least significant byte of UTF-8 characters) can be capitalized by flipping one or a few bits of several ranges of characters.</div><div class=""><br class=""></div><div class="">Given that fact I tried to write a simple Oberon-07 CAP function which just clears bit 5 of a byte, and stumbled upon the different implementations of SYSTEM.VAL and INCL in the two compilers I use regularly.</div><div class=""><br class=""></div><div class="">Florian wrote:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" style="font-family: Menlo-Regular;" class=""><blockquote type="cite" class="">EXCL(SYSTEM.VAL(SET, ch), 5)</blockquote></blockquote><blockquote type="cite"><br class="">All compilers I know access the variable ch as if it was declared as a SET in this case. This means that EXCL actually overwrites SIZE(SET) bytes rather than SIZE(CHAR) which may definitely lead to undefined behavour if these sizes don't match.</blockquote></div><div class=""><br class=""></div><div class="">That's OK; I could still do useful things, but of course implementation-dependent. As a programmer I am warned for this because the VAL function is from the SYSTEM pseudomodule; that's one nice feature of Oberon I like very much. </div><div class=""><br class=""></div><div class="">My problem though is that neither of the two Oberon-07 compilers I checked accepts the above statement. Which was a bit of a surprise to me. After all it is a SYSTEM function, so now it is the responsability of the programmer to check if the desired result is reached.</div><div class=""><br class=""></div><div class="">In one of the two compilers SYSTEM.VAL(SET, ...) only is allowed INTEGER variables as second parameter, so a CHAR variable of an ASCII character set first has to make a detour via BYTE and INTEGER:</div><div class=""><br class=""></div><div class=""> VAR ch: CHAR; b: BYTE; i: INTEGER; </div><div class=""> ...</div><div class=""> EXCL(SYSTEM.VAL(SET, ch), 5) (* error: "casting not allowed" *)</div><div class=""> ...</div><div class=""><blockquote type="cite" style="font-family: Menlo-Regular;" class=""></blockquote></div><div class=""><div class=""> b := SYSTEM.VAL(BYTE, ch);</div><div class=""> EXCL(SYSTEM.VAL(SET, b), 5) (* error: "casting not allowed" *)</div><div class=""> ...</div><div class=""><br class=""></div><div class=""> i := SYSTEM.VAL(BYTE, ch); (* cast CHAR to BYTE and assign to INTEGER *)<br class=""> EXCL(SYSTEM.VAL(SET, i), 5) (* clear bit 5 *)<br class=""> RETURN SYSTEM.VAL(CHAR, i) (* cast INTEGER directly back to CHAR *)</div></div><div class=""><br class=""></div><div class="">Only the last three lines are accepted by this compiler, and return the desired result (bit 5 of ch cleared). </div><div class="">Unexpectedly (for me) the casting back from INTEGER to CHAR *is* allowed by this compiler! </div><div class=""><br class=""></div><div class="">The other compiler I checked does allow the direct casting of CHAR to SET, but (in contrast to the above compiler) requires a variable as first parameter of procedure EXCL:</div><div class=""><br class=""></div><div class=""> VAR ch: CHAR; b: BYTE; i: INTEGER; s: SET;</div><div class=""> ...</div><div class=""> <span style="font-family: Menlo-Regular;" class="">EXCL(SYSTEM.VAL(SET, ch), 5) (* error: "variable expected in substitution of parameter 1: EXCL" *)</span></div><div class=""><span style="font-family: Menlo-Regular;" class=""> ...</span></div><span style="font-family: Menlo-Regular;" class=""> s := SYSTEM.VAL(SET, ch); (* cast CHAR to SET *)</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> EXCL(s, 5) (* clear bit 5 *) </span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> RETURN SYSTEM.VAL(CHAR, s) (* cast SET back to CHAR *)</span><div class=""><font face="Menlo-Regular" class=""><br class=""></font></div><div class=""><font face="Menlo-Regular" class="">I find this code still is a bit convoluted.</font></div><div class=""><font face="Menlo-Regular" class=""><br class=""></font></div><div class=""><font face="Menlo-Regular" class="">I would rather have my Oberon-07 compiler to accept the following (my responsibility for the correct result): </font></div><div class=""><font face="Menlo-Regular" class=""><br class=""></font></div><div class=""><font face="Menlo-Regular" class=""> VAR ch: CHAR;</font><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> ...</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> EXCL(SYSTEM.VAL(SET, ch), 5) (* cast CHAR to SET and clear bit 5 *)</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> RETURN ch</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class=""> ...</span></div><div class=""><span style="font-family: Menlo-Regular;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo-Regular;" class="">My questions now are: </span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">- the behaviour regarding SYSTEM.VAL and EXCL of which of the two above mentioned compilers do you like best?</span><br style="font-family: Menlo-Regular;" class=""><span style="font-family: Menlo-Regular;" class="">- do you know an Oberon-07 compiler that could compile the last lines of code, and what do you think of it?</span></div><div class=""><span style="font-family: Menlo-Regular;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo-Regular;" class="">In other words: what is your opinion about the desired behaviour of procedures SYSTEM.VAL and EXCL in an ideal Oberon-07 compiler?</span></div><div class=""><font face="Menlo-Regular" class=""><br class=""></font><div class=""><span style="font-family: Menlo-Regular;" class="">Regards,</span></div><div class=""><br class=""></div><div class=""><span style="font-family: Menlo-Regular;" class="">Hans</span></div><div class=""><span style="font-family: Menlo-Regular;" class=""><br class=""></span></div><div class=""><span style="font-family: Menlo-Regular;" class=""><br class=""></span></div><div class=""><br class=""><blockquote type="cite" class="">On 7 Aug. 2022, at 07:48 <a href="mailto:joerg.straube@iaeth.ch" class="">joerg.straube@iaeth.ch</a> wrote:<br class=""><br class="">We are in heavy grey zone here 😊<br class="">First, Oberon-07 does not define any character set. Whether the compiler internally uses US-ASCII, EBCDIC, ISO-5428 (Greek) is not defined by Oberon-07<br class="">We only know that CHR and ORD are opposite function and ORD returns an INTEGER. Oberon-07 does not define the size of an INTEGER, so we don’t know how many characters we have. It’s up to the compiler<br class="">US-ASCII: ORD(“M”) = 041H<br class="">EBCDIC: ORD(“M”) = 0D4H<br class="">ISO-5428: ORD(“M”) = 04FH<br class=""> <br class="">The only thing in Oberon-07 we know for sure: ch = CHR(ORD(ch))<br class=""> <br class="">Second, what is the definition of CAP?<br class="">Does CAP() only convert (so the input is a small letter) or does it check as well?<br class="">Let’s assume you want to program a module Strings.Cap(s). Do you write:<br class="">i := 0; WHILE s[i] # 0X DO s[i] := CAP(s[i]); INC(i) END;<br class="">or do you write<br class="">i := 0; WHILE s[i] # 0X DO IF (“a” <= s[i]) AND (s[i] <= “z”) THEN s[i] := CAP(s[i]) END; INC(i) END;<br class=""> <br class="">br<br class="">Jörg<br class=""> <br class=""> <br class="">Von: Oberon <<a href="mailto:oberon-bounces@lists.inf.ethz.ch" class="">oberon-bounces@lists.inf.ethz.ch</a>> im Auftrag von Chris Burrows <<a href="mailto:cfbsoftware@gmail.com" class="">cfbsoftware@gmail.com</a>><br class="">Datum: Sonntag, 7. August 2022 um 03:51<br class="">An: ETH Oberon and related systems <<a href="mailto:oberon@lists.inf.ethz.ch" class="">oberon@lists.inf.ethz.ch</a>><br class="">Betreff: Re: [Oberon] Bit-fiddling: SETs and type casts in Oberon-07<br class=""><br class=""> <br class=""> <br class="">On Sun, Aug 7, 2022 at 11:14 AM Chris Burrows <<a href="mailto:cfbsoftware@gmail.com" class="">cfbsoftware@gmail.com</a>> wrote:<br class=""> <br class="">Oops! <br class=""> <br class=""> IF (ch >= "a") & (ch <= "z") THEN cap := CHR(ORD(ch) - 32) ELSE cap := ch END;<br class=""> <br class="">Third time lucky? ;-)<br class=""> <br class=""> PROCEDURE CAP(ch: CHAR): CHAR;<br class=""> BEGIN<br class=""> IF (ch >= "a") & (ch <= "z") THEN ch := CHR(ORD(ch) - 32) END;<br class=""> RETURN ch<br class=""> END CAP;<br class=""> <br class="">--<br class="">Oberon@lists.inf.ethz.ch mailing list for ETH Oberon and related systems<br class="">https://lists.inf.ethz.ch/mailman/listinfo/oberon<br class=""></blockquote><br class=""></div></div></body></html>