Another 'else' without a previous 'if'

Heya, folkies.

I never expected myself to be in this position. I can generally work through nearly any error message tossed at me.

Here's the situation: I'm building an interface with which to scavenge data from an old (!) ESDI hard drive (I'm sure there will be scoffers, but I have no doubt that a Mega2560 can do the job if programmed well).

Now... my code includes the following:

#define ESDI_OUT_PORT      PORTC
// ...
#define ESDI_DRIVESEL  B00100000
// ...
#define ESDI_SET_DRIVESEL  ESDI_OUT_PORT |=  ESDI_DRIVESEL;
#define ESDI_CLR_DRIVESEL  ESDI_OUT_PORT &= ~ESDI_DRIVESEL;
// ...
bool ESDIClass::Select (bool SelectTF)
{
   if (SelectTF)
      ESDI_SET_DRIVESEL;
   else
      ESDI_CLR_DRIVESEL;

   delay (1);
   return (ESDI_IS_SELECTED);
}

If I try to compile that, I get hammered with an 'else' without a previous 'if' error, obviously at the only "else" in that code.

However, if I modify that code slightly thus:

#define ESDI_OUT_PORT      PORTC
// ...
#define ESDI_DRIVESEL  B00100000
// ...
#define ESDI_SET_DRIVESEL  ESDI_OUT_PORT |=  ESDI_DRIVESEL;
#define ESDI_CLR_DRIVESEL  ESDI_OUT_PORT &= ~ESDI_DRIVESEL;
// ...
bool ESDIClass::Select (bool SelectTF)
{
   if (SelectTF)
      ESDI_OUT_PORT |= ESDI_DRIVESEL;
   else
      ESDI_CLR_DRIVESEL;

   delay (1);
   return (ESDI_IS_SELECTED);
}

... the error goes away.

Maybe it's just my old eyes failing to spot the difference between '!' and '|' or failing to notice ...

...oh, wait.

Never mind.

It's the double semicolon that I end up with that's botching things.

ESDI_SET_DRIVESEL;

expands to

ESDI_OUT_PORT |=  ESDI_DRIVESEL;;

resulting in

   if (SelectTF)
      ESDI_OUT_PORT |= ESDI_DRIVESEL;;      // (note the double semicolon terminator)
   else
      ESDI_CLR_DRIVESEL;

One cannot have two uncurlied semicolons between "if" and "else". The second semicolon finalizes the "if".

Thanks. Once in a while I just need to talk things out a little... and since I've written his, I might as well post it; someone else may benefit from it someday.

Use const declarations instead of #define. Then, things like this are not possible.

Nice. Others may indeed benefit, if only because they are reminded to think about something for a bit before giving up.

I won’t tell you how many times I’ve not posted after carefully preparing my case or making a minimum reproducible example to present here and in the process finding the problem, too often “obvious” it turns out.

a7

The trick I’ve seen to make a macro that acts as a statement:

#define ESDI_SET_DRIVESEL  do{ESDI_OUT_PORT |=  ESDI_DRIVESEL;}while(0)
#define ESDI_CLR_DRIVESEL  do{ESDI_OUT_PORT &= ~ESDI_DRIVESEL;}while(0)

it is

  if (SelectTF)
     ESDI_OUT_PORT |= ESDI_DRIVESEL;
  ;     
  else
     ESDI_CLR_DRIVESEL;

two advises from a pro:

always use a block with if else

  if (SelectTF) {
     ESDI_SET_DRIVESELL;
  }  else {
     ESDI_CLR_DRIVESEL;
  }

and never put a ; at the end of a macro

Juraj:
two advises from a pro:

always use a block with if else

  if (SelectTF) {

ESDI_SET_DRIVESELL;
 }  else {
    ESDI_CLR_DRIVESEL;
 ]

A real pro would end the else compound statement with a } and not with a ]

:sunglasses: 8) :grin: