<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
        {font-family:"Apple Color Emoji";
        panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:Menlo-Regular;
        panose-1:2 11 6 9 3 8 4 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="DE-CH" link="blue" vlink="purple" style="word-wrap:break-word;-webkit-nbsp-mode: space;line-break:after-white-space">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">Hans<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">As Chris wrote a few mails ago, in Oberon-07 you normally write:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">   PROCEDURE AsciiCAP(ch: CHAR): CHAR; RETURN CHR(ORD(ch) - 32) END AsciiCAP;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">The compiler generates a SUB.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">However, if you want the compiler to generate an AND you write:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">    PROCEDURE AsciiCAP(ch: CHAR): CHAR; RETURN CHR(ORD(SYSTEM.VAL(SET, ORD(ch)) - {5})) END AsciiCAP;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">The above assumes your compiler has the same size for INTEGER and SET.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">On RISC5 both functions generate one instruction (so have the same length) and have the same execution time as SUB and ANN both need one cycle.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Because of this, I prefer the first form over the last.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">br<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Jörg<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">Von:
</span></b><span style="font-size:12.0pt;color:black">Oberon <oberon-bounces@lists.inf.ethz.ch> im Auftrag von Hans Klaver <hklaver@dds.nl><br>
<b>Datum: </b>Sonntag, 7. August 2022 um 21:53<br>
<b>An: </b>ETH Oberon and related systems <oberon@lists.inf.ethz.ch><br>
<b>Betreff: </b>Re: [Oberon] Bit-fiddling: SETs and type casts in Oberon-07<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt">Chris, Florian and Jörg, thanks for your answers so far! <o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Maybe I was not clear enough. <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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. <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Florian wrote:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">EXCL(SYSTEM.VAL(SET, ch), 5)<o:p></o:p></span></p>
</blockquote>
</blockquote>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt"><br>
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.<o:p></o:p></span></p>
</blockquote>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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. <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  VAR ch: CHAR;  b: BYTE;  i: INTEGER;  <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  ...<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  EXCL(SYSTEM.VAL(SET, ch), 5)   (* error: "casting not allowed" *)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  ...<o:p></o:p></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  b := SYSTEM.VAL(BYTE, ch);<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  EXCL(SYSTEM.VAL(SET, b), 5)    (* error: "casting not allowed" *)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  ...<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  i := SYSTEM.VAL(BYTE, ch);     (* cast CHAR to BYTE and assign to INTEGER *)<br>
  EXCL(SYSTEM.VAL(SET, i), 5)    (* clear bit 5 *)<br>
  RETURN SYSTEM.VAL(CHAR, i)     (* cast INTEGER directly back to CHAR *)<o:p></o:p></span></p>
</div>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Only the last three lines are accepted by this compiler, and return the desired result (bit 5 of ch cleared). <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Unexpectedly (for me) the casting back from INTEGER to CHAR *is* allowed by this compiler! <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">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:<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  VAR ch: CHAR;  b: BYTE;  i: INTEGER;  s: SET;<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  ...<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">  </span><span style="font-size:11.0pt;font-family:Menlo-Regular">EXCL(SYSTEM.VAL(SET, ch), 5) (* error: "variable expected in substitution of parameter 1: EXCL" *)</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">  ...</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">  s := SYSTEM.VAL(SET, ch);    (* cast CHAR to SET *)<br>
  EXCL(s, 5)                   (* clear bit 5 *)       <br>
  RETURN SYSTEM.VAL(CHAR, s)   (* cast SET back to CHAR *)</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">I find this code still is a bit convoluted.</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">I would rather have my Oberon-07 compiler to accept the following (my responsibility for the correct result): </span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular"> VAR ch: CHAR;<br>
 ...<br>
 EXCL(SYSTEM.VAL(SET, ch), 5)   (* cast CHAR to SET and clear bit 5 *)<br>
 RETURN ch<br>
 ...</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">My questions now are: <br>
- the behaviour regarding SYSTEM.VAL and EXCL of which of the two above mentioned compilers do you like best?<br>
- do you know an Oberon-07 compiler that could compile the last lines of code, and what do you think of it?</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">In other words: what is your opinion about the desired behaviour of procedures SYSTEM.VAL and EXCL in an ideal Oberon-07 compiler?</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">Regards,</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Menlo-Regular">Hans</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><br>
<br>
<o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt">On 7 Aug. 2022, at 07:48 <a href="mailto:joerg.straube@iaeth.ch">
joerg.straube@iaeth.ch</a> wrote:<br>
<br>
We are in heavy grey zone here </span><span style="font-size:11.0pt;font-family:"Apple Color Emoji"">😊</span><span style="font-size:11.0pt"><br>
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>
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>
US-ASCII: ORD(“M”) = 041H<br>
EBCDIC: ORD(“M”) = 0D4H<br>
ISO-5428: ORD(“M”) = 04FH<br>
 <br>
The only thing in Oberon-07 we know for sure:   ch = CHR(ORD(ch))<br>
 <br>
Second, what is the definition of CAP?<br>
Does CAP() only convert (so the input is a small letter) or does it check as well?<br>
Let’s assume you want to program a module Strings.Cap(s). Do you write:<br>
i := 0; WHILE s[i] # 0X DO s[i] := CAP(s[i]); INC(i) END;<br>
or do you write<br>
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>
 <br>
br<br>
Jörg<br>
 <br>
 <br>
Von: Oberon <<a href="mailto:oberon-bounces@lists.inf.ethz.ch">oberon-bounces@lists.inf.ethz.ch</a>> im Auftrag von Chris Burrows <<a href="mailto:cfbsoftware@gmail.com">cfbsoftware@gmail.com</a>><br>
Datum: Sonntag, 7. August 2022 um 03:51<br>
An: ETH Oberon and related systems <<a href="mailto:oberon@lists.inf.ethz.ch">oberon@lists.inf.ethz.ch</a>><br>
Betreff: Re: [Oberon] Bit-fiddling: SETs and type casts in Oberon-07<br>
<br>
 <br>
 <br>
On Sun, Aug 7, 2022 at 11:14 AM Chris Burrows <<a href="mailto:cfbsoftware@gmail.com">cfbsoftware@gmail.com</a>> wrote:<br>
 <br>
Oops!  <br>
 <br>
 IF (ch >= "a") & (ch <= "z") THEN cap := CHR(ORD(ch) - 32) ELSE cap := ch END;<br>
 <br>
Third time lucky? ;-)<br>
 <br>
  PROCEDURE CAP(ch: CHAR): CHAR;<br>
  BEGIN<br>
    IF (ch >= "a") & (ch <= "z") THEN ch := CHR(ORD(ch) - 32) END;<br>
    RETURN ch<br>
  END CAP;<br>
 <br>
--<br>
Oberon@lists.inf.ethz.ch mailing list for ETH Oberon and related systems<br>
https://lists.inf.ethz.ch/mailman/listinfo/oberon<o:p></o:p></span></p>
</blockquote>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
</div>
</div>
</body>
</html>