Heater
Posts: 13126
Joined: Tue Jul 17, 2012 3:02 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 3:35 pm

C++ is an enigma and a paradox to me.

When I read Stroustrup's books everything sounds perfectly reasonable. He explains why things are as they are in the language and why there is this rule or that and so on. It's a glorious logical argument. I nod my head and think "Yep, perfect". Stroustrup's books are brilliant.

Then, I come to write some C++ code. If I try to do anything a bit out of the ordinary I'm immediately mired in a swamp of indecipherable and verbose error messages. After googling around a bit I find I have broken some rule that I have forgotten, or more likely never memorized in the first place.

I don't think I'm ever going to be able to write anything that uses templates. After encountering a thousand lines of error messages for one simple mistake for the umpteenth time I give up. Not to mention that compilation takes forever which makes the whole process miserable.

Then, I come to read C++ code others have written. Yeah Gods. Always something that I don't have a clue about in there. Not to mention that the code gets to look like line noise with all it's "::", "->", "&" and so on.

It's amazing that the Arduino guys use C++. They have been smart enough to almost never mention that the Arduino is programmed in C++ by name. Their documentation restricts itself to an easy to comprehend subset of C++. Excellent.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 5:06 pm

Ok I guess I will step back in.
On operator overloading
There are some C compilers that even allow for operator overloading, and work quite well with base types as well as user types. It is usualy recommended to use a user defined type for overloading operators.

And in C++ (unless something has changed that I do not know), it is acceptable to use operator overloading for any user defined types, with the limit on operator=() having to be a member of a class (one I did not know till today). That is indeed how I learned operator overloading, originaly by making a simple string type (eg typedef char * string) and implementing operator+() to concatenate two strings.


On readability of code
I am in the middle of writing a very quick example in C and BASIC that I will be asking if qualifies as readable and modern in another thread. I am attempting to closely follow the same rules and structure in both examples, though to me the BASIC example looks a bit off.

Anyway the examples (untested, and not done commenting) as they stand are:
IN C:

Code: Select all

//FILE: readable.c
//Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
//  Intended as a small quick example of readable code.  This code is RISC OS
//  Specific.
#include <string.h>
#include "sys/wimpcalls.h"

//Constant Definitions:
#define TASK_MAGIC 0x4B534154   //Magic number needed for tasks.
#define WIMP_VER 310            //Minamal version of WIMP.
#define TASK_NAME "Readable\0"  //Name to regester task as in WIMP.
#define BARICON_NAME "!readable" //Sprite name for our Icon bar icon.
#define ICONF_SPRITE 0x02       //Flag saying Icon is sprite, in readable.h
#define ICONF_BUTTONCLICK 0x3000 //Flag meaning Icon Button type is click.
#define TEMP_SIZE 256           //Size in bytes of temperary work space.

long TaskHandle;    //Handle for this task.
ICON_BLOCK *Icon;   //The Icon definition.
void *TempWork;     //Temperary Workspace.
long IconHandle     //Remember the Icon Handle.



void poll(void){
  short quit = 0xFF; //Quit flag, while true we run, when false we quit.
  while(quit){  //Our very simple poll loop.
    int reason;
    reason = Wimp_Poll(MIN_POLL,TempWork);
    switch (reason){
     case 6:   //If it is a mouse click. Quit if our IconBar icon is clicked.
       if (((long *)TempWork)[3] == -2) quit = 0; break;
     case 17:
     case 18: //User messages, quit if recieve quit message.
       if (((long *)TempWork)[4] == 0) quit = 0; break;
    }
  }
}



int main(void){    //Entry Point for our program.

  if (!(TempWork = malloc(TEMP_SIZE))) return 1;
  
  TaskHandle = Wimp_Initialize(WIMP_VER, TASK_MAGIC, TASK_NAME, 0)
  
  //Setup our IconBar Icon.
  icon = (ICON_BLOCK *) TempWork;
  icon->window = -1;
  icon->x0 = 0; icon->y0 = 0;    //Minimum x and y coords of the Icon.
  icon->x1 = 64; icon->y1 = 64;  //Maximum x and y coords of the Icon.
  //Set the Icon Flags.
  icon->flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcp(icon->data.text, BARICON_NAME);   //Set the Icon name.
  
  IconHandle = Wimp_CreateIcon(icon);
  
  Poll();  //Call our poll loop.
  
  Wimp_CloseDown(TaskHandle,TASK_MAGIC);
  free(temp_work);
}
And in ARM BASIC (BBC BASIC V):

Code: Select all


REM > !RunImage
ON ERROR PRINT "LINE : " + STR$(ERL) + " ERROR : " + REPORT$ : END


TASKMAGIC%       = &4B534154
WIMPVER%         = 310
TASKNAME$        = "Readable" :REM Name for WIMP task.
BARICONNAME$     ="!readable" :REM Name of IconBar Icon.
ICONFSPRITE%     = &2     :REM Icon flag is Sprite.
ICONFBUTTONCLICK%= &3000  :REM Icon Flag button type click.
TEMPSIZE%        = 256    :REM Size of Temp Work space.
POLLMIN%         = &2301  :REM Poll flags, for minimum CPU.

TaskHandle% = 0
Icon% = 0
DIM TempWork% TEMPSIZE%
IconHandle% = 0

quit% = FALSE

PROCStart
END


DEF PROCPoll
  REPEAT
   SYS "Wimp_Poll",POLLMIN%,TempWork% TO reason%
   CASE reason% OF
   WHEN 6:        :REM If clicked on our Icon, quit.
            IF TempWork%!8 = -2 THEN quit% = TRUE
   WHEN 17,18:
            IF !TempWork% = 0 THEN quit% = TRUE
  UNTIL quit%
ENDPROC


DEF PROCStart
  LOCAL ix0%,iy0%,ix1%,iy0%,iflags%,idata%
  ix0% = 4: iy0% = 8: ix1% = 12: iy0% = 16
  iflags% = 20: idata% = 24
  SYS "Wimp_Initialise",WIMPVER%,TASKMAGIC%,TASKNAME%,0 TO TaskH
dle%

  Icon%         = TempWork%
  !Icon%        = -1   : REM Window handle of IconBar.
  Icon%!ix0%    = 0    : Icon%!iy0%    = 0
  Icon%!ix1%    = 64   : Icon%!iy1%    = 64
  Icon%!iflags  = ICONFBUTTONCLICK% OR ICONFSPRITE%
  $(Icon%+idata%) = BARICONNAME$
  SYS "Wimp_CreateIcon",,Icon% TO IconHandle%

  PROCPoll

  SYS "Wimp_CloseDown",TaskHandle%,TASKMAGIC%
ENDPROC
So before I continue on to testing are these examples at least considered to be readable by modern methods of programming? I ask as I am intending to release stuff that I want others to be able to read, and modify.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

ejolson
Posts: 3438
Joined: Tue Mar 18, 2014 11:47 am

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 5:20 pm

DavidS wrote:No such information. I think that this one was written by verious people at the school I attended at the time, may be wrong. Though I got it by it being passed around at school, and improved on every week for a few years.
I searched online and not a trace of cppc.prg is to be found. It sounds like it was a nice project that may implement an historically interesting version of C++. Do you still have source code for cppc.prg or just the executable? If the others who worked on the project agree, maybe it can be added to some repository of software for Atari emulators. Since it generates portable C code, maybe it was also written in portable C code and could be compiled to run natively on the Pi. From a software preservation point of view, a translator not based on cfront that implements an early version of C++ is worth keeping.

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 5:46 pm

DavidS wrote: So before I continue on to testing are these examples at least considered to be readable by modern methods of programming? I ask as I am intending to release stuff that I want others to be able to read, and modify.
I made some small changes to the C version if you are interested.

"while(quit)" doesn't read well, its the wrong way round!

I think its easier on the eye if there is a space after //

I don't like the horrid aliasing of tempWork - you keep it as a void * and it points to both an icon and an array of longs. Also, could you malloc( sizeof(ICON_BLOCK) ) or something rather than the random 256 bytes? Longs might change in size by the way.

Comments like
"long IconHandle; // remember the IconHandle"
don't add anything.

In general I strive to make the code itself readable, simple, and obviously easy to understand.
Having done that (very difficult) there is less need for comments. Certainly assembler style commenting of every line is poor style (as you know, its needed with assembler because things like "umaddl x2, w0, w4, x3" mean absolutely nothing to the reader).

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is RISC OS Specific.
 */
#include <string.h>
#include <stdlib.h> 
#include <stdbool.h>
#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC 0x4B534154    // Magic number needed for tasks.
#define WIMP_VER 310             // Minamal version of WIMP.
#define TASK_NAME "Readable\0"   // Name to regester task as in WIMP.
#define BARICON_NAME "!readable" // Sprite name for our Icon bar icon.
#define ICONF_SPRITE 0x02        // Flag saying Icon is sprite, in readable.h
#define ICONF_BUTTONCLICK 0x3000 // Flag meaning Icon Button type is click.
#define TEMP_SIZE 256            // Size in bytes of temporary work space.

static long TaskHandle;    // Handle for this task.
static ICON_BLOCK *Icon;   // The Icon definition.
static void *TempWork;     // Temporary Workspace.
static long IconHandle;    

/*
 *  Describe poll
 */
static void poll(void)
{
  bool run = true; // while true we run, when false we quit.
  do
  {
	switch( Wimp_Poll( MIN_POLL, TempWork ) )
	{
	  case 6:  // If it is a mouse click. Quit if our IconBar icon is clicked.
		run = ((long *)TempWork)[3] != -2;
		break;
	  case 17:
	  case 18:  // User messages, quit if recieve quit message.
		run = ((long *)TempWork)[4] != 0;
	}
  }
  while( run );  // Our very simple poll loop.
}


/*
 *  Entry Point for our program.
 */
int main( void )
{

  if( (TempWork = malloc(TEMP_SIZE)) == NULL )
	return EXIT_FAILURE;

  TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

	// Setup our IconBar Icon.
  icon = TempWork;
  icon->window = -1;
  icon->x0 = icon->y0 = 0;    // Minimum x and y coords of the Icon.
  icon->x1 = icon->y1 = 64;   // Maximum x and y coords of the Icon.
	// Set the Icon Flags.
  icon->flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( icon->data.text, BARICON_NAME );   // Set the Icon name.

  IconHandle = Wimp_CreateIcon(icon);

  Poll();  // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );
  free(temp_work);

  return EXIT_SUCCESS;
}
Last edited by jahboater on Sun Nov 20, 2016 6:08 pm, edited 5 times in total.

Heater
Posts: 13126
Joined: Tue Jul 17, 2012 3:02 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 5:49 pm

I could not find cppc.prg either. It's amazing what a small time capsule DavidS lives in :)

I think that is a great idea from a software history preservation point of view.

Like it's great that Leor Zolman open sourced his BDSC C compiler for CP/M. A work of art.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 5:56 pm

ejolson wrote:
DavidS wrote:No such information. I think that this one was written by verious people at the school I attended at the time, may be wrong. Though I got it by it being passed around at school, and improved on every week for a few years.
I searched online and not a trace of cppc.prg is to be found. It sounds like it was a nice project that may implement an historically interesting version of C++. Do you still have source code for cppc.prg or just the executable? If the others who worked on the project agree, maybe it can be added to some repository of software for Atari emulators. Since it generates portable C code, maybe it was also written in portable C code and could be compiled to run natively on the Pi. From a software preservation point of view, a translator not based on cfront that implements an early version of C++ is worth keeping.
The source is no more for me. It was written in Pascal, which is kind of a thing of its own, I do not remember which compiler was used anymore (as we all know that Pascal tends not to follow the standard very well).
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 6:08 pm

jahboater wrote:
DavidS wrote: So before I continue on to testing are these examples at least considered to be readable by modern methods of programming? I ask as I am intending to release stuff that I want others to be able to read, and modify.
I made some small changes to the C version if you are interested.

"while(quit)" doesn't read well, its the wrong way round!
Thank you for that. I can see that issue.

I think its easier on the eye if there is a space after //

I don't like the horrid aliasing of tempWork - you keep it as a void * and it points to both an icon and an array of longs. Also, could you malloc( sizeof(ICON_BLOCK) ) or something rather than the random 256 bytes?
That is down to how the WIMP works. It needs to be a block of at least 256 bytes that can be used for many different structures/combinitians of structures/arays of values, as it gets changed often depending on the responce from WIMP calls. It saves memory using the same 256 byte block for all the temperary WIMP work space, though it could be divided into two or three seperate 256 byte blocks for different kinds of calls, would still need to be of varying type though.
Comments like
"long IconHandle; // remember the IconHandle"
don't add anything.

In general I strive to make the code itself readable, simple, and obviously easy to understand.
Having done that (very difficult) there is less need for comments. Certainly assembler style commenting of every line is poor style (as you know, its needed with assembler because things like "umaddl x2, w0, w4, x3" mean absolutely nothing to the reader).
Thank you for that. I am in the habbit of writing Assembly, and BASIC, so commenting in a way that most lines are commented is habbit.

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is RISC OS Specific.
 */
#include <string.h>
#include <stdlib.h> 
#include <stdbool.h>
#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC 0x4B534154    // Magic number needed for tasks.
#define WIMP_VER 310             // Minamal version of WIMP.
#define TASK_NAME "Readable\0"   // Name to regester task as in WIMP.
#define BARICON_NAME "!readable" // Sprite name for our Icon bar icon.
#define ICONF_SPRITE 0x02        // Flag saying Icon is sprite.
#define ICONF_BUTTONCLICK 0x3000 // Flag meaning Icon Button type is click.
#define TEMP_SIZE 256            // Size in bytes of temporary work space.

static long TaskHandle;    // Handle for this task.
static ICON_BLOCK *Icon;   // The Icon definition.
static void *TempWork;     // Temporary Workspace.
static long IconHandle;    

/*
 *  Describe poll
 */
static void poll(void)
{
  bool run = true; // while true we run, when false we quit.
  do
  {
	switch( Wimp_Poll( MIN_POLL, TempWork ) )
	{
	  case 6:  // If it is a mouse click. Quit if our IconBar icon is clicked.
		run = ((long *)TempWork)[3] != -2;
		break;
	  case 17:
	  case 18:  // User messages, quit if recieve quit message.
		run = ((long *)TempWork)[4] != 0;
	}
  }
  while( run );  // Our very simple poll loop.
}


/*
 *  Entry Point for our program.
 */
int main( void )
{

  if( (TempWork = malloc(TEMP_SIZE)) == NULL )
	return EXIT_FAILURE;

  TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

	// Setup our IconBar Icon.
  icon = TempWork;
  icon->window = -1;
  icon->x0 = icon->y0 = 0;    // Minimum x and y coords of the Icon.
  icon->x1 = icon->y1 = 64;   // Maximum x and y coords of the Icon.
	// Set the Icon Flags.
  icon->flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( icon->data.text, BARICON_NAME );   // Set the Icon name.

  IconHandle = Wimp_CreateIcon(icon);

  Poll();  // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );
  free(temp_work);

  return EXIT_SUCCESS;
}
Only problem I see with that code is that it is unicode, and contains tab charactors (they show up here as a block with 0009 in it). I did remove a bug in the copy of your post that is quoted here, you had a copy of the line static long IconHandle; appended to the line #include <string.h>.

Though thank you very much for the suggestions, that helps a good bit.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 6:13 pm

Heater wrote:Data General Nova
Eeeeagh!

We had one of those at the technical college I attended. 8 terminals, multiplexed to 64, with some of those multiplexed to (IIRC) 4 300 baud dial in lines for the local schools. Horrible thing, but it was a scream working out interesting ways to abuse and / or crash it.

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 6:17 pm

DavidS wrote: Only problem I see with that code is that it is unicode, and contains tab characters (they show up here as a block with 0009 in it).
Is this better? Its not unicode by the way.

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is RISC OS Specific.
 */
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC 0x4B534154    // Magic number needed for tasks.
#define WIMP_VER 310             // Minimal version of WIMP.
#define TASK_NAME "Readable\0"   // Name to register task as in WIMP.
#define BARICON_NAME "!readable" // Sprite name for our Icon bar icon.
#define ICONF_SPRITE 0x02        // Flag saying Icon is sprite, in readable.h
#define ICONF_BUTTONCLICK 0x3000 // Flag meaning Icon Button type is click.
#define TEMP_SIZE 256            // Size in bytes of temporary work space.

/*
 *  Describe poll ...
 */
static void poll(void)
{
  long workspace[TEMP_SIZE/sizeof(long)]; 
  bool run = true; // while true we run, when false we quit.
  do
  {
   switch( Wimp_Poll( MIN_POLL, workspace ) )
   {
     case 6:  // If it is a mouse click. Quit if our IconBar icon is clicked.
      run = (workspace[3] != -2);
      break;
     case 17:
     case 18:  // User messages, quit if recieve quit message.
      run = (workspace[4] != 0);
   }
  }
  while( run );  // Our very simple poll loop.
}

/*
 *  Entry Point for our program.
 */
int main( void )
{
  ICON_BLOCK icon;

 const long TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

   // Setup our IconBar Icon.
  icon.window = -1;
  icon.x0 = icon.y0 = 0;    // Minimum x and y coords of the Icon.
  icon.x1 = icon.y1 = 64;   // Maximum x and y coords of the Icon.
   // Set the Icon Flags.
  icon.flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( icon.data.text, BARICON_NAME );   // Set the Icon name.

  const long IconHandle = Wimp_CreateIcon( &icon );

  Poll();  // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );

  return EXIT_SUCCESS;
}
Sorry couldn't resist tweaking it to remove the aliasing and the global variables! Hope it still works.

User avatar
Paeryn
Posts: 2636
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 6:56 pm

DavidS wrote:On operator overloading
There are some C compilers that even allow for operator overloading, and work quite well with base types as well as user types. It is usualy recommended to use a user defined type for overloading operators.
C sort of supports overloading of functions with type-generics from C11 (with the _Generic operator), though it really it just chooses the function to call depending on the type of the first parameter to _Generic(). No way of doing that for operators though without being non-conformant. Altering the behaviour of built in operators is asking for trouble (which is why C++ removed the ability early on).
DavidS wrote:And in C++ (unless something has changed that I do not know), it is acceptable to use operator overloading for any user defined types, with the limit on operator=() having to be a member of a class (one I did not know till today). That is indeed how I learned operator overloading, originaly by making a simple string type (eg typedef char * string) and implementing operator+() to concatenate two strings.
Overloaded operators have to have at least one of their arguments to be a user-defined class / enum, you can't for example do

Code: Select all

int operator+(int a, char b);
The four operators = () [] -> all have to be members of a class, they can't be defined globally (because they all need the left hand side to be the object being operated on).

You can't overload any of the following operators

Code: Select all

. .* ?: :: sizeof alignof typeid static_cast<> dynamic_cast<> const_cast<> reinterpret_cast<>
She who travels light — forgot something.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 7:04 pm

jahboater wrote:
DavidS wrote: Only problem I see with that code is that it is unicode, and contains tab characters (they show up here as a block with 0009 in it).
Is this better? Its not unicode by the way.

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is RISC OS Specific.
 */
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC 0x4B534154    // Magic number needed for tasks.
#define WIMP_VER 310             // Minimal version of WIMP.
#define TASK_NAME "Readable\0"   // Name to register task as in WIMP.
#define BARICON_NAME "!readable" // Sprite name for our Icon bar icon.
#define ICONF_SPRITE 0x02        // Flag saying Icon is sprite.
#define ICONF_BUTTONCLICK 0x3000 // Flag meaning Icon Button type is click.
#define TEMP_SIZE 256            // Size in bytes of temporary work space.

/*
 *  Describe poll ...
 */
static void poll(void)
{
  long workspace[TEMP_SIZE/sizeof(long)]; 
  bool run = true; // while true we run, when false we quit.
  do
  {
   switch( Wimp_Poll( MIN_POLL, workspace ) )
   {
     case 6:  // If it is a mouse click. Quit if our IconBar icon is clicked.
      run = (workspace[3] != -2);
      break;
     case 17:
     case 18:  // User messages, quit if recieve quit message.
      run = (workspace[4] != 0);
   }
  }
  while( run );  // Our very simple poll loop.
}

/*
 *  Entry Point for our program.
 */
int main( void )
{
  ICON_BLOCK icon;

 const long TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

   // Setup our IconBar Icon.
  icon.window = -1;
  icon.x0 = icon.y0 = 0;    // Minimum x and y coords of the Icon.
  icon.x1 = icon.y1 = 64;   // Maximum x and y coords of the Icon.
   // Set the Icon Flags.
  icon.flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( icon.data.text, BARICON_NAME );   // Set the Icon name.

  const long IconHandle = Wimp_CreateIcon( &icon );

  Poll();  // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );

  return EXIT_SUCCESS;
}
Sorry couldn't resist tweaking it to remove the aliasing and the global variables! Hope it still works.
That should work, as far as I can tell, at a glance. Though it will be dificult to extend, as the the global variables are not global anymore, and these are needed in many places to do other things. I do not like the use of an extra 36 bytes of memory for the ICON_BLOCK, though that is me.

I had thought about using an array for the TempWork, though I thought others would complain about that, it still needs to be global though.

The veriables Icon, TempWork, IconHandle. TaskHandle, and run should be global to make extending the program easier. I would expect that, even though it is written for the reason of asking about readability, someone will extend it eventualy.

I may even extend it to show how to build up a WIMP program step by step, in a way that most will agree is readable. So that is a bit of a problem.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 7:19 pm

jahboater wrote: Is this better?

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is RISC OS Specific.
 */
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC 0x4B534154    // Magic number needed for tasks.
#define WIMP_VER 310             // Minimal version of WIMP.
#define TASK_NAME "Readable\0"   // Name to register task as in WIMP.
#define BARICON_NAME "!readable" // Sprite name for our Icon bar icon.
#define ICONF_SPRITE 0x02        // Flag saying Icon is sprite, in readable.h
#define ICONF_BUTTONCLICK 0x3000 // Flag meaning Icon Button type is click.
#define TEMP_SIZE 256            // Size in bytes of temporary work space.

/*
 *  Describe poll ...
 */
static void poll(void)
{
  long workspace[TEMP_SIZE/sizeof(long)]; 
  bool run = true; // while true we run, when false we quit.
  do
  {
   switch( Wimp_Poll( MIN_POLL, workspace ) )
   {
     case 6:  // If it is a mouse click. Quit if our IconBar icon is clicked.
      run = (workspace[3] != -2);
      break;
     case 17:
     case 18:  // User messages, quit if recieve quit message.
      run = (workspace[4] != 0);
   }
  }
  while( run );  // Our very simple poll loop.
}

/*
 *  Entry Point for our program.
 */
int main( void )
{
  ICON_BLOCK icon;

 const long TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

   // Setup our IconBar Icon.
  icon.window = -1;
  icon.x0 = icon.y0 = 0;    // Minimum x and y coords of the Icon.
  icon.x1 = icon.y1 = 64;   // Maximum x and y coords of the Icon.
   // Set the Icon Flags.
  icon.flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( icon.data.text, BARICON_NAME );   // Set the Icon name.

  const long IconHandle = Wimp_CreateIcon( &icon );

  Poll();  // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );

  return EXIT_SUCCESS;
}
Sorry couldn't resist tweaking it to remove the aliasing and the global variables! Hope it still works.
Looking a little closer you did completely break a couple of things, which tells me it was not as clear as it should be.

First where did you define EXIT_SUCCESS?

Second the line:

Code: Select all

    case 17:
     case 18:  // User messages, quit if recieve quit message.
      run = (workspace[4] != 0);
Would cause the program to quit for any user message other than 0. Never mind I missread that.

Third where did you define true?

And fourth, why are you putting those extra includes in there?

Number 5: where did you typedef bool? Obviously it is a signed integer type as you are assigning the result of a comparison directly to a variable of that type.

And on poll():

Code: Select all

/*
* Loop on Wimp_Poll, responding to events given by the poll reason code.
*/
That is one of the comments I had not yet added.

Though thank you much for that. Very helpful.
Last edited by DavidS on Sun Nov 20, 2016 7:34 pm, edited 1 time in total.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 7:30 pm

Paeryn wrote:
DavidS wrote:On operator overloading
There are some C compilers that even allow for operator overloading, and work quite well with base types as well as user types. It is usualy recommended to use a user defined type for overloading operators.
C sort of supports overloading of functions with type-generics from C11 (with the _Generic operator), though it really it just chooses the function to call depending on the type of the first parameter to _Generic(). No way of doing that for operators though without being non-conformant. Altering the behaviour of built in operators is asking for trouble (which is why C++ removed the ability early on).
DavidS wrote:And in C++ (unless something has changed that I do not know), it is acceptable to use operator overloading for any user defined types, with the limit on operator=() having to be a member of a class (one I did not know till today). That is indeed how I learned operator overloading, originaly by making a simple string type (eg typedef char * string) and implementing operator+() to concatenate two strings.
Overloaded operators have to have at least one of their arguments to be a user-defined class / enum...
Ok something has changed then. Last I knew newer C++ compilers would allow for ANY USER DEFINED type in at least one argument, it was not restricted to classes and enum types.
, you can't for example do

Code: Select all

int operator+(int a, char b);
There is no user type there, so that is a given. I knew that that had changed, though I do not like it.
The four operators = () [] -> all have to be members of a class, they can't be defined globally (because they all need the left hand side to be the object being operated on).
I thought that you could not overload the (), [], ->, ., ?:, or unary * operators at all. Could you give a short example of how they are overloaded in a meaningful way?
You can't overload any of the following operators

Code: Select all

. .* ?: :: sizeof alignof typeid static_cast<> dynamic_cast<> const_cast<> reinterpret_cast<>
Other than * , ?: , sizeof , and :: I have never heard of those operators, I am guessing these are additions to C++ that I missed?
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 7:40 pm

It was just some some ideas hopefully you might find interesting, you can ignore them of course.

I generally minimise the scope of everything and only later (perhaps when the program is extended as you say) change a variable to be global - and only when absolutely necessary.

Globals are slow. The compiler may well treat them as volatile. In any case they need to be loaded to and from memory all the time. Local variables are more likely (extremely likely on ARM64 with 31 registers) to be kept in a register which as you know is much faster and uses no memory at all.

Why do you say "run" should be global for example? I cant see why.
If you are concerned about memory: I guarantee "run" will be kept in a register if you leave it local.

I hate controlling loops with boolean's anyway, so I would rather get rid of "run". BTW "do while" is slightly faster than a plain while, one less jump - and it reads better in this case.

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 7:51 pm

DavidS wrote: Looking a little closer you did completely break a couple of things, which tells me it was not as clear as it should be.

First where did you define EXIT_SUCCESS?
#include <stdlib.h>
Its just "1" in practice, but looks nicer.
DavidS wrote:Third where did you define true?
#include <stdbool.h>
DavidS wrote:And fourth, why are you putting those extra includes in there?
see above!
DavidS wrote:Number 5: where did you typedef bool? Obviously it is a signed integer type as you are assigning the result of a comparison directly to a variable of that type.
again its in stdbool.h. There is a boolean type in C99. Its probably called _Bool. The standard header stdbool.h provides more reasonable names. Its usually a single byte. Its defined to convert to 1 or 0 when used in an integer expression.

All this stuff is portable and standards compliant.

New C features seem to be called _<cap>xxx.
C11 introduces _Noreturn, _Alignas, _Alignof etc.
and then provide a standard header such as <stdalign.h> with nicer names.

You probably spotted that:

run = (workspace[4] != 0);

is equivalent to:

if( workspace[4] != 0 )
run = true;
else
run = false;

You could also say

run = workspace[4];

but I don't like it so much in this context.
Last edited by jahboater on Sun Nov 20, 2016 8:12 pm, edited 1 time in total.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:05 pm

@jahboater:
Maybe something more like:

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is
 *   RISC OS Specific.
 */

#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC        0x4B534154  // Magic number needed for tasks.
#define WIMP_VER          310         // Minimal version of WIMP.
#define TASK_NAME        "Readable\0" // Name to register task as in WIMP.
#define BARICON_NAME     "!readable"  // Sprite name for our Icon bar icon.
#define ICONF_SPRITE      0x02        // Flag saying Icon is sprite.
#define ICONF_BUTTONCLICK 0x3000      // Flag: Icon Button type is click.
#define TEMP_SIZE         256         // Size in bytes of work space.
#define TRUE              -1          // True condition.
#define FALSE             0           // False condition.

int Run = TRUE; // while true we run, when false we quit.
long WorkSpace[TEMP_SIZE/sizeof(long)];
static long TaskHandle, IconHandle;

/*
 *  Loop on Wimp Poll, responding to events returned in the poll reason code.
 */
static void poll(void)
{
  do                                  // Our very simple poll loop.
  {
   switch( Wimp_Poll( MIN_POLL, workspace ) )
   {
     case 6:                          // On mouse click on IconBar Icon quit.
              if (WorkSpace == -2) Run = FALSE;
      //Broken:  Run = (WorkSpace[3] != -2);
      break;
     case 17:
     case 18:                         // User messages, quit if quit message.
      Run = (workspace[4] != 0);
   }
  }
  while( run );
}

/*
 *  Entry Point for our program.
 */
int main( void )
{
  ICON_BLOCK Icon;

 TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

   // Setup our IconBar Icon.
  Icon.window = -1;                   //The window is the IconBar.
  Icon.x0 = Icon.y0 = 0;              // Minimum x and y coords of the Icon.
  Icon.x1 = Icon.y1 = 64;             // Maximum x and y coords of the Icon.
   // Set the Icon Flags.
  Icon.flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( Icon.data.text, BARICON_NAME );   // Set the Icon name.

  IconHandle = Wimp_CreateIcon( &Icon );

  Poll();                             // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );

  return 0;
}
While I still have not yet tested it, as I need to write the veneers for Wimp_CreateIcon(), Wimp_CloseDown(), and Wimp_Initialise as well as the struct for the ICON_BLOCK type, I do think that this is a lot better. You see in RISC OS these calls are made by making SWI calls.

Actually I have already written the veneers and structs a long time ago, though they needed to be updated for this kind of readability.

I would use OS_Lib if I could ever figure out how to get it to work, though for now I am using my own veneers and headers.

Thinking about readability:
Is there a way to get these forums to use a fixed width font for code posts?
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
rpdom
Posts: 15042
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:08 pm

jahboater wrote:
DavidS wrote: First where did you define EXIT_SUCCESS?
#include <stdlib.h>
Its just "1" in practice, but looks nicer.
No, it's just "0". "1" is EXIT_FAILURE.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:16 pm

jahboater wrote:It was just some some ideas hopefully you might find interesting, you can ignore them of course.

I generally minimise the scope of everything and only later (perhaps when the program is extended as you say) change a variable to be global - and only when absolutely necessary.

Globals are slow. The compiler may well treat them as volatile. In any case they need to be loaded to and from memory all the time. Local variables are more likely (extremely likely on ARM64 with 31 registers) to be kept in a register which as you know is much faster and uses no memory at all.

Why do you say "run" should be global for example? I cant see why.
If you are concerned about memory: I guarantee "run" will be kept in a register if you leave it local.
Because the poll loop would get way way to big to manage as things are extended if you did not have it call out to other functions as you expend the program. And many of those can be the source of a quit condition.

For example when handling mouse clicks, once you have multiple windows open, the mouse click could be in any of n windows, and on any of n icons in each window.

For reference in RISC OS an icon can define a image (called a sprite) like here, or a text field, label, button, exclusive selection button, or just about any other comon control (except a menu [which contains Icons for each item], window, or scroll bars).
I hate controlling loops with boolean's anyway, so I would rather get rid of "run". BTW "do while" is slightly faster than a plain while, one less jump - and it reads better in this case.
If you know a better way to do it while keeping it expandable, I am all ears.

If I knew a better way, while keeping it expandable, I would do so.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:19 pm

DavidS wrote:You see in RISC OS these calls are made by making SWI calls.
Yes, I have realised the attraction of the RISC-OS providing graphics calls directly, no huge library like Qt or GTK needed, no library needed at all for a small program I guess.
DavidS wrote:Thinking about readability:
Is there a way to get these forums to use a fixed width font for code posts?
Sorry, I don't know that.

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:23 pm

jahboater wrote:
DavidS wrote: Looking a little closer you did completely break a couple of things, which tells me it was not as clear as it should be.

First where did you define EXIT_SUCCESS?
#include <stdlib.h>
Its just "1" in practice, but looks nicer.
DavidS wrote:Third where did you define true?
#include <stdbool.h>
DavidS wrote:And fourth, why are you putting those extra includes in there?
see above!
DavidS wrote:Number 5: where did you typedef bool? Obviously it is a signed integer type as you are assigning the result of a comparison directly to a variable of that type.
again its in stdbool.h. There is a boolean type in C99. Its probably called _Bool. The standard header stdbool.h provides more reasonable names. Its usually a single byte. Its defined to convert to 1 or 0 when used in an integer expression.

All this stuff is portable and standards compliant.

New C features seem to be called _<cap>xxx.
C11 introduces _Noreturn, _Alignas, _Alignof etc.
and then provide a standard header such as <stdalign.h> with nicer names.

You probably spotted that:

run = (workspace[4] != 0);

is equivalent to:

if( workspace[4] != 0 )
run = true;
else
run = false;

You could also say

run = workspace[4];
While yes you could have it would be very unreadable. Thankfully user message 0 is quit. I only included that one because it is the correct way to do it, if the OS asks you to quit you should probably quit.

but I don't like it so much in this context.
Neither do I. I do like the solution of Run = (WorkSpace[4] != 0) it is very readable, and a lot better formed than the if statement, withouth using a ?: operator.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
rpdom
Posts: 15042
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:25 pm

DavidS wrote:Thinking about readability:
Is there a way to get these forums to use a fixed width font for code posts?
I see them in fixed width. I use Firefox as a browser and the [ code] blocks are in Monospace font.

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:33 pm

How about this, just an idea ....

Code: Select all

#define repeat for(;;)
#define elif else if


static void poll(void)
{
  repeat    // Our very simple poll loop.
  {
    const int rc = Wimp_Poll( MIN_POLL, workspace );

    if( rc == 6 )
    {
        // mouse click on IconBar Icon quit.
      if( WorkSpace[3] == -2 )
        break;
    }
    elif( rc == 17 || rc == 18 )
    {
        // User messages, quit if quit message.
      if( workspace[4] == 0 )
        break;
    }
  }
}

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:35 pm

Sorry about the reapeat, though I realized a lot of posts fast.
@jahboater:
Maybe something more like:

Code: Select all

/*
 *  FILE: readable.c
 *  Puts an icon on the IconBar and quits as soon as said Icon is clicked on.
 *   Intended as a small quick example of readable code.  This code is
 *   RISC OS Specific.
 */

#include "sys/wimpcalls.h"

  // Constant Definitions:
#define TASK_MAGIC        0x4B534154  // Magic number needed for tasks.
#define WIMP_VER          310         // Minimal version of WIMP.
#define TASK_NAME        "Readable\0" // Name to register task as in WIMP.
#define BARICON_NAME     "!readable"  // Sprite name for our Icon bar icon.
#define ICONF_SPRITE      0x02        // Flag saying Icon is sprite.
#define ICONF_BUTTONCLICK 0x3000      // Flag: Icon Button type is click.
#define TEMP_SIZE         256         // Size in bytes of work space.
#define TRUE              -1          // True condition.
#define FALSE             0           // False condition.

int Run = TRUE; // while true we run, when false we quit.
long WorkSpace[TEMP_SIZE/sizeof(long)];
static long TaskHandle, IconHandle;

/*
 *  Loop on Wimp Poll, responding to events returned in the poll reason code.
 */
static void poll(void)
{
  do                                  // Our very simple poll loop.
  {
   switch( Wimp_Poll( MIN_POLL, workspace ) )
   {
     case 6:                          // On mouse click on IconBar Icon quit.
              if (WorkSpace == -2) Run = FALSE;
      //Broken:  Run = (WorkSpace[3] != -2);
      break;
     case 17:
     case 18:                         // User messages, quit if quit message.
      Run = (workspace[4] != 0);
   }
  }
  while( run );
}

/*
 *  Entry Point for our program.
 */
int main( void )
{
  ICON_BLOCK Icon;

 TaskHandle = Wimp_Initialize( WIMP_VER, TASK_MAGIC, TASK_NAME, 0 );

   // Setup our IconBar Icon.
  Icon.window = -1;                   //The window is the IconBar.
  Icon.x0 = Icon.y0 = 0;              // Minimum x and y coords of the Icon.
  Icon.x1 = Icon.y1 = 64;             // Maximum x and y coords of the Icon.
   // Set the Icon Flags.
  Icon.flags = ICONF_BUTTONCLICK | ICONF_SPRITE;
  strcpy( Icon.data.text, BARICON_NAME );   // Set the Icon name.

  IconHandle = Wimp_CreateIcon( &Icon );

  Poll();                             // Call our poll loop.

  Wimp_CloseDown( TaskHandle, TASK_MAGIC );

  return 0;
}
While I still have not yet tested it, as I need to write the veneers for Wimp_CreateIcon(), Wimp_CloseDown(), and Wimp_Initialise as well as the struct for the ICON_BLOCK type, I do think that this is a lot better. You see in RISC OS these calls are made by making SWI calls.

Actually I have already written the veneers and structs a long time ago, though they needed to be updated for this kind of readability.

I would use OS_Lib if I could ever figure out how to get it to work, though for now I am using my own veneers and headers.

Thinking about readability:
Is there a way to get these forums to use a fixed width font for code posts?
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

User avatar
DavidS
Posts: 4334
Joined: Thu Dec 15, 2011 6:39 am
Location: USA
Contact: Website

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:44 pm

jahboater wrote:How about this, just an idea ....

Code: Select all

#define repeat for(;;)
#define elif else if


static void poll(void)
{
  repeat    // Our very simple poll loop.
  {
    const int rc = Wimp_Poll( MIN_POLL, workspace );

    if( rc == 6 )
    {
        // mouse click on IconBar Icon quit.
      if( WorkSpace[3] == -2 )
        break;
    }
    elif( rc == 17 || rc == 18 )
    {
        // User messages, quit if quit message.
      if( workspace[4] == 0 )
        break;
    }
  }
}
That is an idea to play with. Not very readable as is, though definitiely a good idea.

Perhaps more like:

Code: Select all

static void poll(void)
{
  for(;;){    // Our very simple poll loop.

    const int rc = Wimp_Poll( MIN_POLL, workspace );

    if( rc == 6 )  // mouse click on IconBar Icon quit.
      if( WorkSpace[3] == -2 ) break;
    else if( rc == 17 || rc == 18 )  // User messages, quit if quit message.
      if( workspace[4] == 0 ) break;
  }
}
I think that is more readable, while still using your trick, obvious in retrospect.

Thank you.
RPi = The best ARM based RISC OS computer around
More than 95% of posts made from RISC OS on RPi 1B/1B+ computers. Most of the rest from RISC OS on RPi 2B/3B/3B+ computers

jahboater
Posts: 4613
Joined: Wed Feb 04, 2015 6:38 pm

Re: Solution to X-Toolkit and portability.

Sun Nov 20, 2016 8:48 pm

and perhaps something like this which uses no stack,
and the icon is set up at compile time.

Code: Select all

 
int main( void ) {
  // Setup our IconBar Icon.
static const ICON_BLOCK Icon = {
  .window = -1,                  // The window is the IconBar.
  .x0 = 0, .y0 = 0,              // Minimum x and y coords of the Icon.
  .x1 = 0, .y1 = 64,             // Maximum x and y coords of the Icon.
  .flags = ICONF_BUTTONCLICK | ICONF_SPRITE,
  .data.text = BARICON_NAME
};

IconHandle = Wimp_CreateIcon( &Icon );

Return to “Other programming languages”