f



gcc needs a curly bracket matching/counting function

This would potentially help a lot.

I had ONE extraneous closing curly bracket } in place in a function, and 
gcc -Wall threw 60+ warnings and errors.

Took me several minutes to find it, and once it was removed I got a 100% 
clean compile

A simple "error: mismatch in opening and closing curly brackets" would 
be nice.


{
  {
   {
    {
     {
      }
     }
    }
   }
  }
}


Or is this a function that should be in the editor?
0
DFS
12/20/2016 1:38:30 AM
comp.lang.c 30656 articles. 5 followers. spinoza1111 (3246) is leader. Post Follow

89 Replies
809 Views

Similar Articles

[PageSpeed] 19

On 20/12/16 01:38, DFS wrote:
> This would potentially help a lot.
>
> I had ONE extraneous closing curly bracket } in place in a function, and
> gcc -Wall threw 60+ warnings and errors.

This is actually quite a tricky problem for a compiler. But it's 
relatively easy for an editor.

>
> Took me several minutes to find it, and once it was removed I got a 100%
> clean compile
>
> A simple "error: mismatch in opening and closing curly brackets" would
> be nice.

vim/gvim: place the cursor on a brace and press % to move the cursor to 
the matching brace. If there is no match, the editor makes its best 
guess. if your indentation convention is logical (and any of several 
possibilities would qualify), it is then easy to spot which brace is not 
matched.

Emacs has about 37 different ways to do the same thing. Try 
Control-Meta-Shift-RandomKey, which might work. Or it might bring down a 
GPS satellite. You never can tell, with Emacs.

> Or is this a function that should be in the editor?

Yes.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 1:59:59 AM
DFS wrote:
> Or is this a function that should be in the editor?

Most editors have that feature (brace matching).

I've had the same problem before.  It's hard to track down by normal
compiler diagnostics.  I don't know of a good way to track that one down.  I've tried commenting out entire functions one by one until
the error stops, but that's a large manual effort.

A compiler should be able to cite mis-matched types in cases like an
"if (..) {" with a "} while (..);", etc.  But in cases of non-flow
brace expressions, it would be more difficult.

Best regards,
Rick C. Hodgin
0
Rick
12/20/2016 2:11:10 AM
On 12/19/2016 08:59 PM, Richard Heathfield wrote:
> On 20/12/16 01:38, DFS wrote:
>> This would potentially help a lot.
>>
>> I had ONE extraneous closing curly bracket } in place in a function, and
>> gcc -Wall threw 60+ warnings and errors.
>
> This is actually quite a tricky problem for a compiler. But it's
> relatively easy for an editor.


Counting open and close {} brackets is of course very easy for a 
compiler.  A count mismatch would generate an error.

Pointing out where the mismatch occurs is more difficult, as you say, 
but I just had an epiphany.  I'm gonna try to code it right now.

It seems kind of easy in my mind.  Which means it will probably turn out 
to be a mess.

If I write a successful, workable routine, do you think the gcc 
maintainers will incorporate it?



>> Took me several minutes to find it, and once it was removed I got a 100%
>> clean compile

short example: one extra closing } in otherwise clean code.

=========================================================================
[dfs@manjaro dev]$ gcc -Wall test.c -o test
test.c:46:1: warning: data definition has no type or storage class
  end = clock();
  ^~~

test.c:46:1: warning: type defaults to ‘int’ in declaration of ‘end’ 
[-Wimplicit-int]

test.c:46:7: error: initializer element is not constant
  end = clock();
        ^~~~~
test.c:47:1: warning: data definition has no type or storage class
  seconds = (double)(end - start)/CLOCKS_PER_SEC;
  ^~~~~~~

test.c:47:1: warning: type defaults to ‘int’ in declaration of ‘seconds’ 
[-Wimplicit-int]

test.c:47:26: error: ‘start’ undeclared here (not in a function)
  seconds = (double)(end - start)/CLOCKS_PER_SEC;
                           ^~~~~
test.c:48:8: error: expected declaration specifiers or ‘...’ before 
string constant
  printf("Run Time: %g seconds\n\n\n", seconds);
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

test.c:48:47: error: expected declaration specifiers or ‘...’ before 
‘seconds’
  printf("Run Time: %g seconds\n\n\n", seconds);
                                                ^~~~~~~
test.c:50:1: error: expected identifier or ‘(’ before ‘return’
  return(0);
  ^~~~~~
test.c:52:1: error: expected identifier or ‘(’ before ‘}’ token
  }
  ^
=========================================================================

Definitely confusing and worrying to see that, even though you know not 
all those issues are present.



>> A simple "error: mismatch in opening and closing curly brackets" would
>> be nice.
>
> vim/gvim: place the cursor on a brace and press % to move the cursor to
> the matching brace. If there is no match, the editor makes its best
> guess. if your indentation convention is logical (and any of several
> possibilities would qualify), it is then easy to spot which brace is not
> matched.
 >
> Emacs has about 37 different ways to do the same thing. Try
> Control-Meta-Shift-RandomKey, which might work. Or it might bring down a
> GPS satellite. You never can tell, with Emacs.
>
>> Or is this a function that should be in the editor?
>
> Yes.


I'd rather the compiler do at least a quick count for me.



I saw your name on a book: C Unleashed.

Did you get rich off that tome?


0
DFS
12/20/2016 3:30:44 AM
On 20/12/16 02:38, DFS wrote:
> This would potentially help a lot.
> 
> I had ONE extraneous closing curly bracket } in place in a function, and
> gcc -Wall threw 60+ warnings and errors.
> 
> Took me several minutes to find it, and once it was removed I got a 100%
> clean compile
> 
> A simple "error: mismatch in opening and closing curly brackets" would
> be nice.
> 
> 
> {
>  {
>   {
>    {
>     {
>      }
>     }
>    }
>   }
>  }
> }
> 
> 
> Or is this a function that should be in the editor?

A lot of editors not only have syntax highlighting, but have on-the-fly
basic C syntax checking.  A good editor or IDE can save you a lot of
time, and help spot simple mistakes as early possible.  I don't want to
get in an editor war by making recommendations - I will merely recommend
that you look at some large, full-featured IDE's as you main editor.
(It is still a good idea to get used to lighter and simpler editors on
your OS of choice - sometimes these are more convenient.  But most work
can be done within the main editor/IDE.)

0
David
12/20/2016 7:56:40 AM
On Tuesday, 20 December 2016 02:00:09 UTC, Richard Heathfield  wrote:

> 
> Emacs has about 37 different ways to do the same thing. Try 
> Control-Meta-Shift-RandomKey, which might work. Or it might bring down a 
> GPS satellite. You never can tell, with Emacs.

I always remap that function to the space bar.
0
mark
12/20/2016 8:50:35 AM
On Tuesday, December 20, 2016 at 1:38:38 AM UTC, DFS wrote:
> This would potentially help a lot.
> 
> I had ONE extraneous closing curly bracket } in place in a function, and 
> gcc -Wall threw 60+ warnings and errors.
> 
> Took me several minutes to find it, and once it was removed I got a 100% 
> clean compile
> 
> A simple "error: mismatch in opening and closing curly brackets" would 
> be nice.
> 
> 
> {
>   {
>    {
>     {
>      {
>       }
>      }
>     }
>    }
>   }
> }
> 
> 
> Or is this a function that should be in the editor?
>
Rule of three.

Parentheses may have only three levels of nesting. Use of goto
for error-handling flow control helps. Use i, ii, iii as loop
counter or i, j, k. If you need iv or l (which looks like a 1)
then consider breaking out into a subroutine.

If code isn't human-understandable it is far less valuable.
0
Malcolm
12/20/2016 10:26:57 AM
On 20/12/16 10:26, Malcolm McLean wrote:
> On Tuesday, December 20, 2016 at 1:38:38 AM UTC, DFS wrote:
>> This would potentially help a lot.
>>
>> I had ONE extraneous closing curly bracket } in place in a function, and
>> gcc -Wall threw 60+ warnings and errors.
>>
>> Took me several minutes to find it, and once it was removed I got a 100%
>> clean compile
>>
>> A simple "error: mismatch in opening and closing curly brackets" would
>> be nice.
>>
>>
>> {
>>   {
>>    {
>>     {
>>      {
>>       }
>>      }
>>     }
>>    }
>>   }
>> }
>>
>>
>> Or is this a function that should be in the editor?
>>
> Rule of three.
>
> Parentheses may have only three levels of nesting.

Citation required.

> Use of goto
> for error-handling flow control helps.

Citation required.

> Use i, ii, iii as loop
> counter or i, j, k. If you need iv or l (which looks like a 1)
> then consider breaking out into a subroutine.
>
> If code isn't human-understandable it is far less valuable.

Those two paragraphs contradict each other.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 10:41:11 AM
On 20-12-16 04:30, DFS wrote:
> On 12/19/2016 08:59 PM, Richard Heathfield wrote:
>> On 20/12/16 01:38, DFS wrote:
>>> This would potentially help a lot.
>>>
>>> I had ONE extraneous closing curly bracket } in place in a function, and
>>> gcc -Wall threw 60+ warnings and errors.
>>
>> This is actually quite a tricky problem for a compiler. But it's
>> relatively easy for an editor.
>
>
> Counting open and close {} brackets is of course very easy for a
> compiler.  A count mismatch would generate an error.
>
> Pointing out where the mismatch occurs is more difficult, as you say,
> but I just had an epiphany.  I'm gonna try to code it right now.
>
> It seems kind of easy in my mind.  Which means it will probably turn out
> to be a mess.

Counting the brackets for a mismatch is easy (don't forget to ignore
brackets in chars, strings and comments though), finding the mismatch in
random code is very hard. However, if you teach yourself to indent your code
in a standard way, you can check if opening and closing brackets with the
same amount of indentation match. In your example, you can see that the
inner most closing bracket is not preceded by an opening bracket with the
same indentation.

-- 
Robert Spanjaard
0
Robert
12/20/2016 10:46:23 AM
On 20/12/2016 01:38, DFS wrote:
> This would potentially help a lot.
>
> I had ONE extraneous closing curly bracket } in place in a function, and
> gcc -Wall threw 60+ warnings and errors.
>
> Took me several minutes to find it, and once it was removed I got a 100%
> clean compile
>
> A simple "error: mismatch in opening and closing curly brackets" would
> be nice.

Get hold of a few other compilers and use them when stumped on an error 
message.

gcc has a particular problem with this, as it allows nested functions. 
So a missing } or extra { in a function near the start of a file, means 
it doesn't report an error until the end of the file thousand of lines 
and hundreds of functions later. But there should be a way of turning 
that off.

> Or is this a function that should be in the editor?

That too if it supports it. But that doesn't mean compilers don't need 
to bother with more useful diagnostics.

-- 
Bartc
0
BartC
12/20/2016 10:46:57 AM
On Tuesday, December 20, 2016 at 10:41:23 AM UTC, Richard Heathfield wrote:
> On 20/12/16 10:26, Malcolm McLean wrote:
>
> > Use i, ii, iii as loop
> > counter or i, j, k. If you need iv or l (which looks like a 1)
> > then consider breaking out into a subroutine.
> >
> > If code isn't human-understandable it is far less valuable.
> 
> Those two paragraphs contradict each other.
> 
i, j, k is a mathematical convention. I prefer i, ii, iii so I
can use j as a secondary counter rather than an inner one.
But I'm idiosyncratic there.

The names aren't meaningful outside the context of the function,
if that's what you mean. But since we only allow three levels of 
nesting, most functions will be quite short. The reader doesn't
get lost. 

0
Malcolm
12/20/2016 10:52:32 AM
On 20/12/16 10:52, Malcolm McLean wrote:
> On Tuesday, December 20, 2016 at 10:41:23 AM UTC, Richard Heathfield wrote:
>> On 20/12/16 10:26, Malcolm McLean wrote:
>>
>>> Use i, ii, iii as loop
>>> counter or i, j, k. If you need iv or l (which looks like a 1)
>>> then consider breaking out into a subroutine.
>>>
>>> If code isn't human-understandable it is far less valuable.
>>
>> Those two paragraphs contradict each other.
>>
> i, j, k is a mathematical convention. I prefer i, ii, iii so I
> can use j as a secondary counter rather than an inner one.
> But I'm idiosyncratic there.

Idiosyncrasies can be appropriate in some limited circumstances, but in 
general they make for code that is less readable, whereas you were 
touting this particular idiosyncrasy as if it made code /more/ readable. 
It doesn't.

> The names aren't meaningful outside the context of the function,

Or indeed within it.

> if that's what you mean. But since we only allow three levels of
> nesting,

Citation required.

> most functions will be quite short. The reader doesn't
> get lost.

Counter-examples abound. For example, consider a three-nested loop that 
iterates through a phase space (say: shelf number, aisle number, and 
warehouse number) searching for a particular tag number. Which phase 
space dimension is associated with which of i, ii, iii? Answer: you 
can't tell just by looking at the code.

So much for readable code.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 11:00:40 AM
W dniu wtorek, 20 grudnia 2016 03:11:24 UTC+1 u=C5=BCytkownik Rick C. Hodgi=
n napisa=C5=82:
> DFS wrote:
> > Or is this a function that should be in the editor?
>=20
> Most editors have that feature (brace matching).
>=20
> I've had the same problem before.  It's hard to track down by normal
> compiler diagnostics.  I don't know of a good way to track that one down.=
  I've tried commenting out entire functions one by one until
> the error stops, but that's a large manual effort.
>=20
> A compiler should be able to cite mis-matched types in cases like an
> "if (..) {" with a "} while (..);", etc.  But in cases of non-flow
> brace expressions, it would be more difficult.
>=20
my editor has this matching but it hihglights matched one (one red)
where maybe it would be better to highlight a block (becouse when blocks=20
are big they are ofscreen and you dont quite know what ios mathed, with blo=
ckhightlighting it could be more visible)
0
fir
12/20/2016 11:00:48 AM
On Tuesday, December 20, 2016 at 11:00:49 AM UTC, Richard Heathfield wrote:
> On 20/12/16 10:52, Malcolm McLean wrote:
> > On Tuesday, December 20, 2016 at 10:41:23 AM UTC, Richard Heathfield wrote:
> 
> > i, j, k is a mathematical convention. I prefer i, ii, iii so I
> > can use j as a secondary counter rather than an inner one.
> > But I'm idiosyncratic there.
> 
> Idiosyncrasies can be appropriate in some limited circumstances, but in 
> general they make for code that is less readable, whereas you were 
> touting this particular idiosyncrasy as if it made code /more/ readable. 
> It doesn't.
> 
My view is that i, ii, iii is more readable because it makes it
obvious that the Roman numeral represent levels of nesting. However
i, j, k is more common. So I wouldn't represent my own view as
something established, or for which there is a consensus.

Rule of three is established. The clue is that after k comes l,
and programmers who use i,j,k are understandably reluctant to
go up to l. I formalised the rule of three and called it "the
rule of three" but I didn't just invent it. It's a commonplace
that functions and expressions shouldn't be allowed to go over
a certain level of complexity.

> > The names aren't meaningful outside the context of the function,
> 
> Or indeed within it.
> 
> Counter-examples abound. For example, consider a three-nested loop that 
> iterates through a phase space (say: shelf number, aisle number, and 
> warehouse number) searching for a particular tag number. Which phase 
> space dimension is associated with which of i, ii, iii? Answer: you 
> can't tell just by looking at the code.
> 
> So much for readable code.
> 

typedef struct
{
   char barcode[32];
   int N;
} ITEM:

typedef struct
{
   ITEM *items;
   int Nitems;
} SHELF;

typedef struct
{
   SHELF *shelf;
   int Nshelves;
} AISLE;

typedef struct
{
    AIsle *aisle;
   int Naisles;
} WAREHPUSE;

/*
   count the number of items we have in our warehouse;
*/
int countitems(WAREHOUSE *wh, char *barcode)
{
   int i, ii, iii;
   int answer = 0;

   for(i=0;i<wh->Naisles;i++)
     for(ii=0;ii<wh->aisle[i].Nshelves;ii++)
       for(iii=0;iii<wh->aisle[i]->shelf[ii].Nitems;iii++)
         if(!strcmp(wh->aisle[i]->shelf[ii]->item[iii].barcode, barcode))
           answer += wh->aisle[i]->shelf[ii]->item[ii].N;
  
    return answer;
}

/*
   Count the number of items we have in our warehouse system
*/

int countitems_insystem(WAREHOUSE *wh, int Nwarehouses, char *barcode)
{
   int answer = 0;
   int i;

   for(i=0;i<Nwarehouses;i++)
     answer += countitems(&wh[i], barcode);

   return answer;
}

Going through the entire system would entail four nested loops. So
one is broken out. As is another with the strcmp().
0
Malcolm
12/20/2016 11:19:04 AM
On 20/12/16 11:19, Malcolm McLean wrote:
> On Tuesday, December 20, 2016 at 11:00:49 AM UTC, Richard Heathfield wrote:
>> On 20/12/16 10:52, Malcolm McLean wrote:
>>> On Tuesday, December 20, 2016 at 10:41:23 AM UTC, Richard Heathfield wrote:
>>
>>> i, j, k is a mathematical convention. I prefer i, ii, iii so I
>>> can use j as a secondary counter rather than an inner one.
>>> But I'm idiosyncratic there.
>>
>> Idiosyncrasies can be appropriate in some limited circumstances, but in
>> general they make for code that is less readable, whereas you were
>> touting this particular idiosyncrasy as if it made code /more/ readable.
>> It doesn't.
>>
> My view is that i, ii, iii is more readable because it makes it
> obvious that the Roman numeral represent levels of nesting.

Far better would be to choose identifiers that identify the /meaning/ of 
the nesting.

> However
> i, j, k is more common. So I wouldn't represent my own view as
> something established, or for which there is a consensus.

(a) No, meaningful names are more common --- i, j, k are used in very 
limited circumstances.
(b) You touted your view as being an established view, and now you say 
(quite rightly) that it isn't. It would have been better not to claim it 
in the first place, of course.

> Rule of three is established.

Citation required.

> The clue is that after k comes l,

How is that better than saying what k and l actually mean?

> and programmers who use i,j,k are understandably reluctant to
> go up to l.

Programmers who use meaningful names are understandably reluctant to go 
up to j. I do sometimes use i, but only when there is no possibility 
whatsoever that it could ever, ever mean more than one thing. I use j 
very rarely indeed. In fact, if I get as far as j, I find myself 
thinking that more meaningful names would be sensible.

> I formalised the rule of three and called it "the
> rule of three" but I didn't just invent it. It's a commonplace
> that functions and expressions shouldn't be allowed to go over
> a certain level of complexity.

Citation required.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 11:31:19 AM
On Tuesday, December 20, 2016 at 11:00:55 AM UTC, fir wrote:
> W dniu wtorek, 20 grudnia 2016 03:11:24 UTC+1 u=C5=BCytkownik Rick C. Hod=
gin napisa=C5=82:
> > DFS wrote:
> > > Or is this a function that should be in the editor?
> >=20
> > Most editors have that feature (brace matching).
> >=20
> > I've had the same problem before.  It's hard to track down by normal
> > compiler diagnostics.  I don't know of a good way to track that one dow=
n.  I've tried commenting out entire functions one by one until
> > the error stops, but that's a large manual effort.
> >=20
> > A compiler should be able to cite mis-matched types in cases like an
> > "if (..) {" with a "} while (..);", etc.  But in cases of non-flow
> > brace expressions, it would be more difficult.
> >=20
> my editor has this matching but it hihglights matched one (one red)
> where maybe it would be better to highlight a block (becouse when blocks=
=20
> are big they are ofscreen and you dont quite know what ios mathed, with=
=20
> blockhightlighting it could be more visible)
>
If you need special software to enable you to understand code, it's
time to take a deep breath, throw the code and the special software
away, and rewrite with a normal editor.

0
Malcolm
12/20/2016 11:50:38 AM
W dniu wtorek, 20 grudnia 2016 12:50:44 UTC+1 u=C5=BCytkownik Malcolm McLea=
n napisa=C5=82:
> On Tuesday, December 20, 2016 at 11:00:55 AM UTC, fir wrote:
> > W dniu wtorek, 20 grudnia 2016 03:11:24 UTC+1 u=C5=BCytkownik Rick C. H=
odgin napisa=C5=82:
> > > DFS wrote:
> > > > Or is this a function that should be in the editor?
> > >=20
> > > Most editors have that feature (brace matching).
> > >=20
> > > I've had the same problem before.  It's hard to track down by normal
> > > compiler diagnostics.  I don't know of a good way to track that one d=
own.  I've tried commenting out entire functions one by one until
> > > the error stops, but that's a large manual effort.
> > >=20
> > > A compiler should be able to cite mis-matched types in cases like an
> > > "if (..) {" with a "} while (..);", etc.  But in cases of non-flow
> > > brace expressions, it would be more difficult.
> > >=20
> > my editor has this matching but it hihglights matched one (one red)
> > where maybe it would be better to highlight a block (becouse when block=
s=20
> > are big they are ofscreen and you dont quite know what ios mathed, with=
=20
> > blockhightlighting it could be more visible)
> >
> If you need special software to enable you to understand code, it's
> time to take a deep breath, throw the code and the special software
> away, and rewrite with a normal editor.

i understand code but when you do edits you sometimes can mistakenly=20
delete one } to much (in some long functions yet within doble for loops yet=
 with if blocks  ) or left one } undeleted
- then compiling this you got cascade of errors, and if you search for
errors this pair-highligting is not as good as block highlighting=20
would probably be
0
fir
12/20/2016 1:20:06 PM
On 20/12/2016 03:30, DFS wrote:

> I'd rather the compiler do at least a quick count for me.

The compiler is handicapped by the language. This has the right number 
of { and } braces and compiles fine:

     if (a) {
         if (b)
             puts("B1");
             puts("B2");
         }

But when a is 1 and b is 0, it doesn't do what is suggested by the 
indentation. In busy code spanning more lines, and many other sets of { 
and }, it can be hard to spot.

The problem here is that { and } are optional around a single statement.

-- 
Bartc


0
BartC
12/20/2016 1:20:35 PM
On 20/12/16 13:20, BartC wrote:
> On 20/12/2016 03:30, DFS wrote:
>
>> I'd rather the compiler do at least a quick count for me.
>
> The compiler is handicapped by the language. This has the right number
> of { and } braces

That's arguable.

> and compiles fine:

Yes. The compiler is under no obligation to enforce best practice. 
That's the programmer's job.

>
>     if (a) {
>         if (b)
>             puts("B1");
>             puts("B2");
>         }
>
> But when a is 1 and b is 0, it doesn't do what is suggested by the
> indentation.

So the indentation is wrong. So don't write it like that.

> In busy code spanning more lines, and many other sets of {
> and }, it can be hard to spot.

All the more reason to use a sensible indentation style.

> The problem here is that { and } are optional around a single statement.

Whether they are optional is optional. You get to choose whether or not 
to write confusing code.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 1:30:43 PM
On Tuesday, December 20, 2016 at 8:20:47 AM UTC-5, Bart wrote:
> On 20/12/2016 03:30, DFS wrote:
> 
> > I'd rather the compiler do at least a quick count for me.
> 
> The compiler is handicapped by the language. This has the right number 
> of { and } braces and compiles fine:
> 
>      if (a) {
>          if (b)
>              puts("B1");
>              puts("B2");
>          }

It's also possible that with the macro language things will not align
in raw source code, but only when macros are expanded.  Some editors
can handle this (as David Brown points out), but most can't.

> But when a is 1 and b is 0, it doesn't do what is suggested by the 
> indentation. In busy code spanning more lines, and many other sets of { 
> and }, it can be hard to spot.
> 
> The problem here is that { and } are optional around a single statement.

Something Supercat talks about often is the ability for the compiler to
generate useful diagnostics which can help the developer make better
choices in their development.  He wants it primarily for creating better
optimized code, but I was thinking an extension of that ability might
also work here.

I think most developers write their code in small increments, recompile,
and continue on.  Most compilers today are fast enough that I do this
every few minutes.  It gives me an early cue about where I might've
made a mistake.  I also make all kinds of ongoing little mistakes in
my code that aren't representative of my thought processes, but are
representative of some error in translation from thought to fingers
in typing.  I even type things like >= when I meant > only, etc.  It's
very strange.  I spend so much time tracking down bugs that I know
from my thought processes aren't there.  I have to look at things
line-by-line to find the errors because it was only an error in
typing, and not an error in thinking.  It's so frustrating sometimes.

In any event ... having the ability to generate a type of flow control
map which an editor could coordinate alongside the original source
code would be nice.  The editor could then analyze the code and the
generated map based on things like indentation convention and flag
possible cases where things are weird.  Have them show up in red, or
with another some filterable quantity.

In any event ... I could've used this type of catching several times
in the past.

Best regards,
Rick C. Hodgin
0
Rick
12/20/2016 1:35:57 PM
DFS <nospam@dfs.com> writes:

> On 12/19/2016 08:59 PM, Richard Heathfield wrote:
>> On 20/12/16 01:38, DFS wrote:
>>> This would potentially help a lot.
>>>
>>> I had ONE extraneous closing curly bracket } in place in a function, and
>>> gcc -Wall threw 60+ warnings and errors.
>>
>> This is actually quite a tricky problem for a compiler. But it's
>> relatively easy for an editor.
>
>
> Counting open and close {} brackets is of course very easy for a
> compiler.  A count mismatch would generate an error.
>
> Pointing out where the mismatch occurs is more difficult, as you say,
> but I just had an epiphany.  I'm gonna try to code it right now.
>
> It seems kind of easy in my mind.  Which means it will probably turn
> out to be a mess.

Yup!  You have to get the lexing right:

/* /* { ignore */
// and the next\
{

which varies by language standard:

  {a//*}*//b}

Then there are

void f() <%  ??>

to contend with, and if that were not enough there's the prepossessor:

#define OPEN {

int main(void) OPEN }

<snip>
-- 
Ben.
0
Ben
12/20/2016 5:04:43 PM
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
[...]
> Rule of three.
>
> Parentheses may have only three levels of nesting.

Balderdash.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 5:07:31 PM
On 20/12/16 17:07, Keith Thompson wrote:
> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> [...]
>> Rule of three.
>>
>> Parentheses may have only three levels of nesting.
>
> Balderdash.

Citation required.

But hang on, I think I have one here:

5.2.4.1 Translation limits: "63 nesting levels of parenthesized 
expressions within a full expression".

(That's a minimal maximum.)

And of course we were originally talking about braces. From the same 
paragraph: "127 nesting levels of blocks".

(Again, that's a minimal maximum.)

Hypothesis confirmed. Malcolm is indeed talking balderdash.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 5:14:44 PM
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:

> On Tuesday, December 20, 2016 at 11:00:49 AM UTC, Richard Heathfield wrote:
>> On 20/12/16 10:52, Malcolm McLean wrote:
>> > On Tuesday, December 20, 2016 at 10:41:23 AM UTC, Richard Heathfield wrote:
>> 
>> > i, j, k is a mathematical convention. I prefer i, ii, iii so I
>> > can use j as a secondary counter rather than an inner one.
>> > But I'm idiosyncratic there.
>> 
>> Idiosyncrasies can be appropriate in some limited circumstances, but in 
>> general they make for code that is less readable, whereas you were 
>> touting this particular idiosyncrasy as if it made code /more/ readable. 
>> It doesn't.
>> 
> My view is that i, ii, iii is more readable because it makes it
> obvious that the Roman numeral represent levels of nesting.
<snip>

> int countitems(WAREHOUSE *wh, char *barcode)
> {
>    int i, ii, iii;
>    int answer = 0;
>
>    for(i=0;i<wh->Naisles;i++)
>      for(ii=0;ii<wh->aisle[i].Nshelves;ii++)
>        for(iii=0;iii<wh->aisle[i]->shelf[ii].Nitems;iii++)
>          if(!strcmp(wh->aisle[i]->shelf[ii]->item[iii].barcode, barcode))
>            answer += wh->aisle[i]->shelf[ii]->item[ii].N;
>   
>     return answer;
> }

It's interesting that you have exactly the kind of bug I would expect to
see in this sort of code.  With Richard's more meaningful names I don't
think you'd have made it.

And what happened to the rule of three?  Are saying that omitting the
{}s round single-statement block actually makes the code clearer so
blocks may be more deeply nested?  If so, what's the number in the rule
for these things?

<snip>
-- 
Ben.
0
Ben
12/20/2016 5:21:18 PM
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 20/12/16 17:07, Keith Thompson wrote:
>> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>> [...]
>>> Rule of three.
>>>
>>> Parentheses may have only three levels of nesting.
>>
>> Balderdash.
>
> Citation required.
>
> But hang on, I think I have one here:
>
> 5.2.4.1 Translation limits: "63 nesting levels of parenthesized 
> expressions within a full expression".
[...]
> Hypothesis confirmed. Malcolm is indeed talking balderdash.

To be fair, it's pretty clear that Malcolm wasn't claiming that
the language forbids more than 3 levels of nesting.  His claim is
about some rule outside the language standard, presumably some kind
of stylistic rule.  (Sorry if I'm spoiling the joke.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 5:33:56 PM
On 20/12/16 17:33, Keith Thompson wrote:
> (Sorry if I'm spoiling the joke.)

That's okay. I've been on Usenet for a while now, so I'm used to it.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 5:39:16 PM
On Tuesday, December 20, 2016 at 12:33:42 PM UTC-5, Keith Thompson wrote:
> To be fair, it's pretty clear that Malcolm wasn't claiming that
> the language forbids more than 3 levels of nesting.  His claim is
> about some rule outside the language standard, presumably some kind
> of stylistic rule.  (Sorry if I'm spoiling the joke.)

It was evident to everyone.  Well ... almost everyone.  Alright.  I
was evident a preponderance of the people involved.  A weighty heft
of understanding against the frail few of misunderstanding.  Yes.
That is at least close to what it was like.

(Note:  This comes from the man who totally missed Jacob Navia's
subtle humor/sarcasm the other day, and in so doing metaphorically
fell from the sky in a grand display of flames, smoke and periodic
ejectiles, before, again metaphorically, crashing and burning
amongst the rocky outcroppings below ... a metaphorical disaster.)

Yes, I metaphor.  (Can you use "metaphor" as a verb?  Oh well...)
Enjoy the day.  (I wonder how you say that in Latin?  Not "that," but
rather "Enjoy the day."  You understand.  Do you?  Oh well...)

Best regards,
Rick C. Hodgin
0
Rick
12/20/2016 5:45:02 PM
On 20/12/16 17:21, Ben Bacarisse wrote:
> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>
<snip>

>>    int i, ii, iii;
>>    int answer = 0;
>>
>>    for(i=0;i<wh->Naisles;i++)
>>      for(ii=0;ii<wh->aisle[i].Nshelves;ii++)
>>        for(iii=0;iii<wh->aisle[i]->shelf[ii].Nitems;iii++)
>>          if(!strcmp(wh->aisle[i]->shelf[ii]->item[iii].barcode, barcode))
>>            answer += wh->aisle[i]->shelf[ii]->item[ii].N;
>>
>>     return answer;
>> }
>
> It's interesting that you have exactly the kind of bug I would expect to
> see in this sort of code.

Sharp eyes indeed. (In case other people haven't spotted it, look 
carefully at the most deeply nested statement. I didn't see it either 
until Ben mentioned that there was a bug to find.)

> With Richard's more meaningful names I don't
> think you'd have made it.

Or at least the rest of us would have had a fighting chance of spotting it.

>
> And what happened to the rule of three?

Clearly he isn't bound by it any more than anyone else is.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 5:49:15 PM
In article <lnfulih6lo.fsf@kst-u.example.com>,
Keith Thompson  <kst-u@mib.org> wrote:
>Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>[...]
>> Rule of three.
>>
>> Parentheses may have only three levels of nesting.
>
>Balderdash.

If Malcolm was your boss, you wouldn't say that.

-- 
The randomly chosen signature file that would have appeared here is more than 4
lines long.  As such, it violates one or more Usenet RFCs.  In order to remain
in compliance with said RFCs, the actual sig can be found at the following URL:
	http://user.xmission.com/~gazelle/Sigs/Aspergers
0
gazelle
12/20/2016 5:56:51 PM
On Tuesday, December 20, 2016 at 12:56:57 PM UTC-5, Kenny McCormack wrote:
> In article <lnfulih6lo.fsf@kst-u.example.com>,
> Keith Thompson  <kst-u@mib.org> wrote:
> >Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> >[...]
> >> Rule of three.
> >>
> >> Parentheses may have only three levels of nesting.
> >
> >Balderdash.
> 
> If Malcolm was your boss, you wouldn't say that.

Unless .... unless he was switching topics and suggesting (in that
admittedly awkward moment) that they should now begin playing a
recreational game:

    https://images-na.ssl-images-amazon.com/images/I/51678WW56PL.jpg

Then it might be completely appropriate.  Or not.  I don't know. I'd
need some more details of the situation to make a completely solid
analysis other people could rely upon.  I'd say at least a half an
hour of unrestricted access to the players involved so as to question
them under direct inquiry.  And when I say, "players," I don't mean
the people who ultimately may or may not have wound up playing the
Balderdash game, but rather those people who were involved in the
initial discussion which used the word "Balderdash," as indicated
above.

Best regards,
Rick C. Hodgin

PS - There are some people who appreciate my humor.  At least, that's
     what I remember seeing that night in the dream. :-)  Oh well...
0
Rick
12/20/2016 6:01:39 PM
On 12/20/16 11:26 PM, Malcolm McLean wrote:
>>
> Rule of three.
>
> Parentheses may have only three levels of nesting.

Why?

> Use of goto for error-handling flow control helps.

...you write spaghetti code.

If you choose to restrict nesting, extract code the would be in an inner 
loop to a function.

> Use i, ii, iii as loop
> counter or i, j, k. If you need iv or l (which looks like a 1)
> then consider breaking out into a subroutine.

This suggestion is horrible: use meaningful names for loop counters as 
you should for any variable.

> If code isn't human-understandable it is far less valuable.

It wont be human-understandable if you follow your suggestions!

-- 
Ian
0
Ian
12/20/2016 6:44:50 PM
On 12/19/2016 09:11 PM, Rick C. Hodgin wrote:
> DFS wrote:
>> Or is this a function that should be in the editor?
>
> Most editors have that feature (brace matching).

The one in geany doesn't do what I'm thinking about.  It always flags 
the very last closing bracket as the mismatched one, when the real 
problem is in the middle somewhere.



> I've had the same problem before.  It's hard to track down by normal
> compiler diagnostics.  I don't know of a good way to track that one down.

I thought I was onto something.

This is a valid set of 14 (seven pairs) of opening and closing curly 
brackets.


{
   {
   }
     {
       {
         {
         }
         {
         }
         {
         }
       }	
     }
}


use O and C for easier visualization (OOCOOOCOCOCCCC)



O
   O
   C
      O
         O
            O
            C
            O
            C
            O
            C
         C
      C
C



Now be the bug and insert an extraneous bracket (Open or Close) anywhere 
in the structure.


O
   O
   C
      O
        X      <--
         O
            O
            C
            O
            C
            O
            C
         C
      C
C


This will probably cause gcc to throw a massive number of errors and 
warnings.

So how do you identify that exact bracket as the problematic one?

Maybe it can be done, but not by me so far.

I tried various algorithms:

* remove the outside OC pairs until you have none, then remove the OC
   pairs starting from the bottom and work up until you're left with one
   OC pair, and the last C is the culprit.

* start at the top and remove all OC pairs in one pass

* attack it differently based on having more Open or more Close
   brackets.

I was always able to break it.

Oh well, it's fun to work on for a while!
	


> I've tried commenting out entire functions one by one until
> the error stops, but that's a large manual effort.


"I spent almost a day going through 4000 lines trying to find the 
missing } in R..."

http://unix.stackexchange.com/questions/10267/how-to-find-unmatched-brackets-in-a-text-file



0
DFS
12/20/2016 6:46:25 PM
On 20/12/2016 17:04, Ben Bacarisse wrote:
> DFS <nospam@dfs.com> writes:
>
>> On 12/19/2016 08:59 PM, Richard Heathfield wrote:
>>> On 20/12/16 01:38, DFS wrote:
>>>> This would potentially help a lot.
>>>>
>>>> I had ONE extraneous closing curly bracket } in place in a function, and
>>>> gcc -Wall threw 60+ warnings and errors.
>>>
>>> This is actually quite a tricky problem for a compiler. But it's
>>> relatively easy for an editor.
>>
>>
>> Counting open and close {} brackets is of course very easy for a
>> compiler.  A count mismatch would generate an error.
>>
>> Pointing out where the mismatch occurs is more difficult, as you say,
>> but I just had an epiphany.  I'm gonna try to code it right now.
>>
>> It seems kind of easy in my mind.  Which means it will probably turn
>> out to be a mess.
>
> Yup!  You have to get the lexing right:
>
> /* /* { ignore */
> // and the next\
> {
>
> which varies by language standard:
>
>   {a//*}*//b}
>
> Then there are
>
> void f() <%  ??>
>
> to contend with, and if that were not enough there's the prepossessor:
>
> #define OPEN {
>
> int main(void) OPEN }

You make the problems sound insurmountable (and you left out conditional 
code!).

But I think a useful brace matching routine can be written, although it 
might not find all mismatches or it can come up with false positives. 
(It won't good enough to go into gcc but it could helped the OP track 
down their error.)

If people use OPEN for {, then they will use CLOSE for }. And you don't 
worry about that (as it's their lookout)!

I doubt you're going to come across trigraphs, if that's what the <% ??> 
example means (and again, there will be a trigraph for the other brace).

And unbalanced { or } within a comment are going to be rare. (They're 
more likely to come up in lexing code funnily enough:

   if (c == '{')  // now look for }

)

That leaves unbalanced { and } within string literals and perhaps within 
#define like your example. But strings and #defines are easy to identify.

-- 
Bartc
0
BartC
12/20/2016 6:46:28 PM
On 12/20/2016 12:04 PM, Ben Bacarisse wrote:
> DFS <nospam@dfs.com> writes:
>
>> On 12/19/2016 08:59 PM, Richard Heathfield wrote:
>>> On 20/12/16 01:38, DFS wrote:
>>>> This would potentially help a lot.
>>>>
>>>> I had ONE extraneous closing curly bracket } in place in a function, and
>>>> gcc -Wall threw 60+ warnings and errors.
>>>
>>> This is actually quite a tricky problem for a compiler. But it's
>>> relatively easy for an editor.
>>
>>
>> Counting open and close {} brackets is of course very easy for a
>> compiler.  A count mismatch would generate an error.
>>
>> Pointing out where the mismatch occurs is more difficult, as you say,
>> but I just had an epiphany.  I'm gonna try to code it right now.
>>
>> It seems kind of easy in my mind.  Which means it will probably turn
>> out to be a mess.
>
> Yup!  You have to get the lexing right:
>
> /* /* { ignore */
> // and the next\
> {
>
> which varies by language standard:
>
>   {a//*}*//b}
>
> Then there are
>
> void f() <%  ??>

For now I'm only worried about curly brackets, since in my limited 
experience a mismatch in them throws a lot of errors/warnings.


> to contend with, and if that were not enough there's the prepossessor:

Is 'prepossessor' a joke or geek slang?




> #define OPEN {
>
> int main(void) OPEN }
>
> <snip>

This one's easy: delete or ignore the #define line and replace ' OPEN ' 
with an opening curly bracket every time it's found.  When I say delete 
I don't mean alter the source of course.




0
DFS
12/20/2016 6:52:16 PM
On 20/12/2016 18:46, DFS wrote:

> This will probably cause gcc to throw a massive number of errors and
> warnings.

With compilers I only look at the first error.

-- 
bartc
0
BartC
12/20/2016 6:59:15 PM
On 20/12/16 18:46, DFS wrote:
<snip>
>
> This is a valid set of 14 (seven pairs) of opening and closing curly
> brackets.
>
>
> {
>   {
>   }
>     {
>       {
>         {
>         }
>         {
>         }
>         {
>         }
>       }
>     }
> }

That looks wrong. Within the main block there are two sub-blocks, and 
the second sub-block is indented one level too deeply. If you pull that out:

{
   {
   }
   {
     {
       {
       }
       {
       }
       {
       }
     }
   }
}

it's a lot clearer, and a lot easier to spot interlopers.

>
>
> use O and C for easier visualization (OOCOOOCOCOCCCC)

No, thank you.

>
> Now be the bug and insert an extraneous bracket (Open or Close) anywhere
> in the structure.

Okay.

{
   {
   }
   {
     {
       {
       }
       {
       {
       }
       {
       }
     }
   }
}

and it sticks out like a sore thumb, even without any code.

> So how do you identify that exact bracket as the problematic one?

You look. If your indentation is right, it's not a problem. If your 
indentation is wrong, pretty-print it. Then it's right. /Then/ look for 
the wayward brace.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 7:02:57 PM
On 20/12/16 18:52, DFS wrote:
> On 12/20/2016 12:04 PM, Ben Bacarisse wrote:
>> DFS <nospam@dfs.com> writes:
>>
>>> On 12/19/2016 08:59 PM, Richard Heathfield wrote:
>>>> On 20/12/16 01:38, DFS wrote:
>>>>> This would potentially help a lot.
>>>>>
>>>>> I had ONE extraneous closing curly bracket } in place in a
>>>>> function, and
>>>>> gcc -Wall threw 60+ warnings and errors.
>>>>
>>>> This is actually quite a tricky problem for a compiler. But it's
>>>> relatively easy for an editor.
>>>
>>>
>>> Counting open and close {} brackets is of course very easy for a
>>> compiler.  A count mismatch would generate an error.
>>>
>>> Pointing out where the mismatch occurs is more difficult, as you say,
>>> but I just had an epiphany.  I'm gonna try to code it right now.
>>>
>>> It seems kind of easy in my mind.  Which means it will probably turn
>>> out to be a mess.
>>
>> Yup!  You have to get the lexing right:
>>
>> /* /* { ignore */
>> // and the next\
>> {
>>
>> which varies by language standard:
>>
>>   {a//*}*//b}
>>
>> Then there are
>>
>> void f() <%  ??>
>
> For now I'm only worried about curly brackets,

That's precisely what he's talking about.

Do you count braces inside comments, as he illustrates?

And don't forget that <% is a punctuator that has the same semantics as 
{ or that ??> is a trigraph that has the same semantics as }


> since in my limited
> experience a mismatch in them throws a lot of errors/warnings.

Is there a mismatch in this code?

int main(int argc, char **argv)
{
   if(argc > 1)
   <%
     printf("Hello, world!\n");
   }
   return 0;
}

>
>> to contend with, and if that were not enough there's the prepossessor:
>
> Is 'prepossessor' a joke or geek slang?

Probably a typo.

>> #define OPEN {
>>
>> int main(void) OPEN }
>>
>> <snip>
>
> This one's easy: delete or ignore the #define line and replace ' OPEN '
> with an opening curly bracket every time it's found.  When I say delete
> I don't mean alter the source of course.

Okay, so now your simple brace-checker includes its own rudimentary 
pre-processor. Not quite so simple after all, is it?

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 7:09:38 PM
On 20/12/2016 18:52, DFS wrote:
> On 12/20/2016 12:04 PM, Ben Bacarisse wrote:

>> #define OPEN {
>>
>> int main(void) OPEN }
>>
>> <snip>
>
> This one's easy: delete or ignore the #define line and replace ' OPEN '
> with an opening curly bracket every time it's found.  When I say delete
> I don't mean alter the source of course.

It's a bit harder than that. OPEN could result from expanding another macro.

Or there could be 100 macros all defined as {, or that include { in 
their definition.

You also now have to scan and look up all identifiers, as well as having 
to actually deal with #define and #undef.

But OPEN could also be defined inside an #include file. Or is part of a 
conditional block so that it might be defined as { or } or anything else 
according to some compiler option.

So you can't deal with it 100% without implementing a full 
pre-processor, and even that might depend on how a compiler is invoked.

-- 
Bartc
0
BartC
12/20/2016 7:14:26 PM
On 20-12-16 19:46, DFS wrote:
[...]
> Now be the bug and insert an extraneous bracket (Open or Close) anywhere
> in the structure.
>
>
> O
>    O
>    C
>       O
>         X      <--
>          O
>             O
>             C
>             O
>             C
>             O
>             C
>          C
>       C
> C
>
>
> This will probably cause gcc to throw a massive number of errors and
> warnings.
>
> So how do you identify that exact bracket as the problematic one?

As I said: it doesn't have a matching closing bracket with the same indentation.

-- 
Robert Spanjaard
0
Robert
12/20/2016 7:35:40 PM
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 20/12/16 18:46, DFS wrote:
[...]
>> So how do you identify that exact bracket as the problematic one?
>
> You look. If your indentation is right, it's not a problem. If your 
> indentation is wrong, pretty-print it. Then it's right. /Then/ look for 
> the wayward brace.

If there's a missing brace at an intermediate level, pretty-printing
(which typically assumes the braces are correct) can mess things up.
In at least some cases, it's better to assume that the indentation
is correct, and use that to find the missing brace.

If the indentation and braces are both incorrect, you'll just have
to study the code enough to understand its intended structure.

To prevent this, try very hard to keep the indentation and braces
correct as you make incremental changes.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 8:13:53 PM
BartC <bc@freeuk.com> writes:
> On 20/12/2016 18:52, DFS wrote:
>> On 12/20/2016 12:04 PM, Ben Bacarisse wrote:
>>> #define OPEN {
>>>
>>> int main(void) OPEN }
>>>
>>> <snip>
>>
>> This one's easy: delete or ignore the #define line and replace ' OPEN '
>> with an opening curly bracket every time it's found.  When I say delete
>> I don't mean alter the source of course.
>
> It's a bit harder than that. OPEN could result from expanding another macro.
>
> Or there could be 100 macros all defined as {, or that include { in 
> their definition.
>
> You also now have to scan and look up all identifiers, as well as having 
> to actually deal with #define and #undef.
>
> But OPEN could also be defined inside an #include file. Or is part of a 
> conditional block so that it might be defined as { or } or anything else 
> according to some compiler option.
>
> So you can't deal with it 100% without implementing a full 
> pre-processor, and even that might depend on how a compiler is invoked.

Yes, but dealing with it 99% is probably good enough.

If the code doesn't use macros, digraphs, or trigraphs to hide braces,
existing tools can be used to find any missing braces.  If it does, I
probably don't care about fixing it.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 8:16:38 PM
On 20/12/16 20:13, Keith Thompson wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>> On 20/12/16 18:46, DFS wrote:
> [...]
>>> So how do you identify that exact bracket as the problematic one?
>>
>> You look. If your indentation is right, it's not a problem. If your
>> indentation is wrong, pretty-print it. Then it's right. /Then/ look for
>> the wayward brace.
>
> If there's a missing brace at an intermediate level, pretty-printing
> (which typically assumes the braces are correct) can mess things up.

Yes, I hadn't considered that, mostly because I don't need to do it on 
my own code. When I'm looking at other people's code, generally this 
isn't the problem they're having, so pretty printing works fine. So yes, 
you're quite right.

> In at least some cases, it's better to assume that the indentation
> is correct, and use that to find the missing brace.

It depends just how screwed the indentation is.

In any case, most of the time % will find the problem, as I pointed out 
up-thread.

(With regard to my libellous attack on the Emacs equivalent of %, all I 
can say in my defence is that the lurkers support me in email. No, 
really they do!)

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
0
Richard
12/20/2016 8:25:12 PM
Keith Thompson <kst-u@mib.org> writes:

> If the code doesn't use macros, digraphs, or trigraphs to hide braces,
> existing tools can be used to find any missing braces.  If it does, I
> probably don't care about fixing it.

The only code that I've seen that
a) doesn't (ab)use the features you mention above
b) confuses bracket matchers (emacs, specifically)

#ifdef CAUTIOUS_DOOHICKEY_FROBNICATION
   if(doohickey != NULL && FROBNICATION_DEPTH < 3) {
#else
   if(doohickey != NULL) {
#endif
      /// Refrobnicate the doohickey
      frobnicate(doohickey);
   }

That's not a style I would use, or recommend, but I have worked on
codebases with constructs like that in it, and sometimes so many that
refactoring becomes quite an intrusive change.
0
Gareth
12/20/2016 8:53:23 PM
On Tuesday, 20 December 2016 20:15:28 UTC, Keith Thompson  wrote:
> BartC <bc@freeuk.com> writes:

> > It's a bit harder than that.
> Yes, but dealing with it 99% is probably good enough.

I said as much in a reply to Ben.

This is about the OP's idea of detecting and expanding macros such as:

  #define OPEN {

You can't deal with this completely without (1) implementing a preprocessor; (2) supplying it with the same command-line macro defs as will be given to the compiler.

-- 
Bartc
0
bart4858
12/20/2016 9:25:27 PM
On Tuesday, December 20, 2016 at 9:25:39 PM UTC, bart...@gmail.com wrote:
> On Tuesday, 20 December 2016 20:15:28 UTC, Keith Thompson  wrote:
> > BartC <bc@freeuk.com> writes:
> 
> > > It's a bit harder than that.
> > Yes, but dealing with it 99% is probably good enough.
> 
> I said as much in a reply to Ben.
> 
> This is about the OP's idea of detecting and expanding macros such as:
> 
>   #define OPEN {
> 
> You can't deal with this completely without (1) implementing a
> preprocessor; (2) supplying it with the same command-line macro 
> defs as will be given to the compiler.
> 
But you shouldn't need to implement a C pre-processor. It's not
as if you're the only person in the world who has ever had to
pre-process C code. Just take one, hook it up to a simple stack-
based matcher, put in a bit of escape logic for strings and 
comments, and you're done.
0
Malcolm
12/20/2016 9:39:46 PM
Gareth Owen <gwowen@gmail.com> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> If the code doesn't use macros, digraphs, or trigraphs to hide braces,
>> existing tools can be used to find any missing braces.  If it does, I
>> probably don't care about fixing it.
>
> The only code that I've seen that
> a) doesn't (ab)use the features you mention above
> b) confuses bracket matchers (emacs, specifically)
>
> #ifdef CAUTIOUS_DOOHICKEY_FROBNICATION
>    if(doohickey != NULL && FROBNICATION_DEPTH < 3) {
> #else
>    if(doohickey != NULL) {
> #endif
>       /// Refrobnicate the doohickey
>       frobnicate(doohickey);
>    }
>
> That's not a style I would use, or recommend, but I have worked on
> codebases with constructs like that in it, and sometimes so many that
> refactoring becomes quite an intrusive change.

If I felt the need to write code like that, I'd probably put the { on
its own line:

#ifdef CAUTIOUS_DOOHICKEY_FROBNICATION
   if(doohickey != NULL && FROBNICATION_DEPTH < 3)
#else
   if(doohickey != NULL)
#endif
   {
      /// Refrobnicate the doohickey
      frobnicate(doohickey);
   }

I might even consider writing something like this:

   if (doohickey != NULL
#ifdef CAUTIOUS_DOOHICKEY_FROBNICATION
                         && FROBNICATION_DEPTH < 3
#endif
                                                  ) {
      /// Refrobnicate the doohickey
      frobnicate(doohickey);
   }

though I'd be sympathetic to charges that it's too freaking ugly.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 9:51:39 PM
BartC <bc@freeuk.com> writes:

> On 20/12/2016 17:04, Ben Bacarisse wrote:
<snip>
>> ...  You have to get the lexing right:
>>
>> /* /* { ignore */
>> // and the next\
>> {
>>
>> which varies by language standard:
>>
>>   {a//*}*//b}
>>
>> Then there are
>>
>> void f() <%  ??>
>>
>> to contend with, and if that were not enough there's the [preprocessor]:
>>
>> #define OPEN {
>>
>> int main(void) OPEN }
>
> You make the problems sound insurmountable (and you left out
> conditional code!).

I was only getting started!

I didn't want to make it sound insurmountable -- I wanted to make it
sound interesting, and to encourage some simplification.  Emacs's C mode
gets confused by most of these things and it doesn't bother me a bit.
In fact, I use it as a sign that I should redesign.

<snip>
> I doubt you're going to come across trigraphs, if that's what the <%
> ??> example means (and again, there will be a trigraph for the other
> brace).

The <% and %> are not trigraphs but alternative spellings.  You can
write if (x) <% ... %> but puts("<%%>") will not print {}.  In contrast,
puts("??<??>") must print {}.

> And unbalanced { or } within a comment are going to be rare. (They're
> more likely to come up in lexing code funnily enough:
>
>   if (c == '{')  // now look for }

Yes.  I used to set a simplified version of this as an exercise and the
final test case was all the students' programs.

> That leaves unbalanced { and } within string literals and perhaps
> within #define like your example. But strings and #defines are easy to
> identify.

Strings are not always obvious:

#define S(a,b) #a#b
....
puts(S(},{));

(I once had to write a lot of test cases for a C compiler.)

-- 
Ben.
0
Ben
12/20/2016 9:55:21 PM
On 20/12/2016 21:39, Malcolm McLean wrote:
> On Tuesday, December 20, 2016 at 9:25:39 PM UTC, bart...@gmail.com wrote:
>> On Tuesday, 20 December 2016 20:15:28 UTC, Keith Thompson  wrote:
>>> BartC <bc@freeuk.com> writes:
>>
>>>> It's a bit harder than that.
>>> Yes, but dealing with it 99% is probably good enough.
>>
>> I said as much in a reply to Ben.
>>
>> This is about the OP's idea of detecting and expanding macros such as:
>>
>>   #define OPEN {
>>
>> You can't deal with this completely without (1) implementing a
>> preprocessor; (2) supplying it with the same command-line macro
>> defs as will be given to the compiler.
>>
> But you shouldn't need to implement a C pre-processor. It's not
> as if you're the only person in the world who has ever had to
> pre-process C code. Just take one, hook it up to a simple stack-
> based matcher, put in a bit of escape logic for strings and
> comments, and you're done.

You make it sound so simple!

I think I would find it easier to write a pre-processor than try and 
source, build and interface to someone else's.

But if the OP is using gcc, they can get preprocessed output out of it 
using gcc -E, and play around with that.

That wouldn't be a satisfactory solution for me as it would need to be 
self-contained, and more efficient. If I run gcc -E on this 2-line program:

#include <windows.h>
int main(void) {MessageBox(0,"There","Hi",0);}

I get 82,000 lines of preprocessed output.


-- 
Bartc
0
BartC
12/20/2016 9:58:32 PM
On 2016-12-20, DFS <nospam@dfs.com> wrote:
> This would potentially help a lot.
>
> I had ONE extraneous closing curly bracket } in place in a function, and 
> gcc -Wall threw 60+ warnings and errors.
>
> Took me several minutes to find it, and once it was removed I got a 100% 
> clean compile

What's the problem? It took you a few minutes this time, and it
will probably take you a few seconds when it happens again because
you have learned from the previous experience.

It's surprising that (see elsethread) so much commotion is caused by
something as futile as an unmatched curly brace. 
0
Ike
12/20/2016 10:00:47 PM
On Tuesday, December 20, 2016 at 9:58:44 PM UTC, Bart wrote:
> On 20/12/2016 21:39, Malcolm McLean wrote:
> > On Tuesday, December 20, 2016 at 9:25:39 PM UTC, bart...@gmail.com wrote:
> >> On Tuesday, 20 December 2016 20:15:28 UTC, Keith Thompson  wrote:
> >>> BartC <bc@freeuk.com> writes:
> >>
> >>>> It's a bit harder than that.
> >>> Yes, but dealing with it 99% is probably good enough.
> >>
> >> I said as much in a reply to Ben.
> >>
> >> This is about the OP's idea of detecting and expanding macros such as:
> >>
> >>   #define OPEN {
> >>
> >> You can't deal with this completely without (1) implementing a
> >> preprocessor; (2) supplying it with the same command-line macro
> >> defs as will be given to the compiler.
> >>
> > But you shouldn't need to implement a C pre-processor. It's not
> > as if you're the only person in the world who has ever had to
> > pre-process C code. Just take one, hook it up to a simple stack-
> > based matcher, put in a bit of escape logic for strings and
> > comments, and you're done.
> 
> You make it sound so simple!
> 
> I think I would find it easier to write a pre-processor than try and 
> source, build and interface to someone else's.
> 
> But if the OP is using gcc, they can get preprocessed output out of it 
> using gcc -E, and play around with that.
> 
> That wouldn't be a satisfactory solution for me as it would need to be 
> self-contained, and more efficient. If I run gcc -E on this 2-line
> program:
> 
> #include <windows.h>
> int main(void) {MessageBox(0,"There","Hi",0);}
> 
> I get 82,000 lines of preprocessed output.
> 
An important skill is the ability to sniff out competently-written 
modules of software. Pretty much anything authored by me, obviously.
But there are also other people out there who know what they are 
doing. Modules written in pure C89 with no dependencies, and exporting
as few symbols as possible. usually contained in a single source file.
0
Malcolm
12/20/2016 10:05:52 PM
BartC <bc@freeuk.com> writes:

> On 20/12/2016 21:39, Malcolm McLean wrote:
>> On Tuesday, December 20, 2016 at 9:25:39 PM UTC, bart...@gmail.com wrote:
>>> On Tuesday, 20 December 2016 20:15:28 UTC, Keith Thompson  wrote:
>>>> BartC <bc@freeuk.com> writes:
>>>
>>>>> It's a bit harder than that.
>>>> Yes, but dealing with it 99% is probably good enough.
>>>
>>> I said as much in a reply to Ben.
>>>
>>> This is about the OP's idea of detecting and expanding macros such as:
>>>
>>>   #define OPEN {
>>>
>>> You can't deal with this completely without (1) implementing a
>>> preprocessor; (2) supplying it with the same command-line macro
>>> defs as will be given to the compiler.
>>>
>> But you shouldn't need to implement a C pre-processor. It's not
>> as if you're the only person in the world who has ever had to
>> pre-process C code. Just take one, hook it up to a simple stack-
>> based matcher,

A stack is bit over the top.  I'd use a counter.  (Yes, logically it is
a stack-like algorithm.)

>> put in a bit of escape logic for strings and
>> comments, and you're done.

It all depends on what cases you want to ignore.  You can certainly
make it simple if you ignore enough corner cases.

> You make it sound so simple!
>
> I think I would find it easier to write a pre-processor than try and
> source, build and interface to someone else's.
>
> But if the OP is using gcc, they can get preprocessed output out of it
> using gcc -E, and play around with that.

Not just gcc, I hope.  I'd expect every C compiler to have something
similar.

> That wouldn't be a satisfactory solution for me as it would need to be
> self-contained, and more efficient. If I run gcc -E on this 2-line
> program:
>
> #include <windows.h>
> int main(void) {MessageBox(0,"There","Hi",0);}
>
> I get 82,000 lines of preprocessed output.

Other than removing duplicate white space, there not much alternative.
Your own solution will have to process the same number of lines, even if
you can avoid the IO round trip.

I don't think duplicating the behaviour of a C pp phase should be
undertaken lightly.  For one thing you need to implement all the logic
for finding files which can very from compiler to compiler and even
version to version (and depend on command line arguments).  Users of the
tool will expect the tool to duplicate the behaviour of the compiler
they are using, and the simplest way to be sure of that is to use the -E
flag (or equivalent).

-- 
Ben.
0
Ben
12/20/2016 10:17:57 PM
BartC <bc@freeuk.com> writes:
[...]
> I think I would find it easier to write a pre-processor than try and 
> source, build and interface to someone else's.

Seriously??

> But if the OP is using gcc, they can get preprocessed output out of it 
> using gcc -E, and play around with that.
>
> That wouldn't be a satisfactory solution for me as it would need to be 
> self-contained, and more efficient. If I run gcc -E on this 2-line program:
>
> #include <windows.h>
> int main(void) {MessageBox(0,"There","Hi",0);}
>
> I get 82,000 lines of preprocessed output.

And how many lines of output would you expect to get from your own
preprocessor?  If you don't get 82,000 lines, you're probably doing
something wrong.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 10:31:42 PM
On 20/12/2016 22:31, Keith Thompson wrote:
> BartC <bc@freeuk.com> writes:
> [...]
>> I think I would find it easier to write a pre-processor than try and
>> source, build and interface to someone else's.
>
> Seriously??
>
>> But if the OP is using gcc, they can get preprocessed output out of it
>> using gcc -E, and play around with that.
>>
>> That wouldn't be a satisfactory solution for me as it would need to be
>> self-contained, and more efficient. If I run gcc -E on this 2-line program:
>>
>> #include <windows.h>
>> int main(void) {MessageBox(0,"There","Hi",0);}
>>
>> I get 82,000 lines of preprocessed output.
>
> And how many lines of output would you expect to get from your own
> preprocessor?  If you don't get 82,000 lines, you're probably doing
> something wrong.

That's an interesting question. In this case the header file used 
'belongs' to a particular C compiler. So with gcc, the outut is 82,000 
lines; with lccwin, it's 70,000 lines. And both files contain loads of 
blank lines.

With an independent preprocessor program, the first problem would be to 
source a suitable set of standard header files (C headers and ones like 
windows.h). Or, if the source file being analysed is to be compiled by 
compiler X anyway, I might use the headers for X.

But I might also decide, for this purpose (analysing braces), not to 
bother with header files that are enclosed in angle brackets: <stdio.h>.

Or, if they have to be taken account of, I would try and cache the 
results and/or somehow partition the expanded forms of system headers 
from user code. Since I know that system headers will be debugged, they 
don't need checking. I will need to determine the likelihood of they 
containing macros that could inject unbalanced { or } braces into user code.

Again, that can be checked once, so that if I see #include <windows.h>, 
I might be able to remember those results without having to 
re-preprocess it or re-scan the output.

-- 
Bartc
0
BartC
12/20/2016 11:21:25 PM
BartC <bc@freeuk.com> writes:
> On 20/12/2016 22:31, Keith Thompson wrote:
>> BartC <bc@freeuk.com> writes:
>> [...]
>>> I think I would find it easier to write a pre-processor than try and
>>> source, build and interface to someone else's.
>>
>> Seriously??
>>
>>> But if the OP is using gcc, they can get preprocessed output out of it
>>> using gcc -E, and play around with that.
>>>
>>> That wouldn't be a satisfactory solution for me as it would need to be
>>> self-contained, and more efficient. If I run gcc -E on this 2-line program:
>>>
>>> #include <windows.h>
>>> int main(void) {MessageBox(0,"There","Hi",0);}
>>>
>>> I get 82,000 lines of preprocessed output.
>>
>> And how many lines of output would you expect to get from your own
>> preprocessor?  If you don't get 82,000 lines, you're probably doing
>> something wrong.
>
> That's an interesting question. In this case the header file used 
> 'belongs' to a particular C compiler. So with gcc, the outut is 82,000 
> lines; with lccwin, it's 70,000 lines. And both files contain loads of 
> blank lines.
>
> With an independent preprocessor program, the first problem would be to 
> source a suitable set of standard header files (C headers and ones like 
> windows.h). Or, if the source file being analysed is to be compiled by 
> compiler X anyway, I might use the headers for X.

Then you risk getting different results than the user gets from whatever
implementation they're using.

> But I might also decide, for this purpose (analysing braces), not to 
> bother with header files that are enclosed in angle brackets: <stdio.h>.
>
> Or, if they have to be taken account of, I would try and cache the 
> results and/or somehow partition the expanded forms of system headers 
> from user code. Since I know that system headers will be debugged, they 
> don't need checking. I will need to determine the likelihood of they 
> containing macros that could inject unbalanced { or } braces into user code.

Macros defined in standard headers can inject unbalanced braces
indirectly:

    #include <stdint.h>
    #ifdef UINT64_MAX
    {
    #endif

Without processing *all* included headers, preferably the exact same
headers the user is using, you don't have a 100% solution.

> Again, that can be checked once, so that if I see #include <windows.h>, 
> I might be able to remember those results without having to 
> re-preprocess it or re-scan the output.

Unless the header is affected by things defined before it's #included.
<assert.h> is the obvious example.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/20/2016 11:51:23 PM
On 20/12/2016 23:51, Keith Thompson wrote:
> BartC <bc@freeuk.com> writes:

>> Or, if they have to be taken account of, I would try and cache the
>> results and/or somehow partition the expanded forms of system headers
>> from user code. Since I know that system headers will be debugged, they
>> don't need checking. I will need to determine the likelihood of they
>> containing macros that could inject unbalanced { or } braces into user code.
>
> Macros defined in standard headers can inject unbalanced braces
> indirectly:
>
>     #include <stdint.h>
>     #ifdef UINT64_MAX
>     {
>     #endif
>
> Without processing *all* included headers, preferably the exact same
> headers the user is using, you don't have a 100% solution.

I don't think a solution that is guaranted to 100% match a subsequent 
compile is going to be possible. The brace-checking on a module may be 
done with one compiler and a set of include files, then compiled by 
someone else 6 months later on the other side of the world.

But, are there many instances of debugged, distributed source code 
suddenly failing to compile due to brace-mismatching, even though the 
source has not been touched? And due to the use of macros from the 
standard headers?

I bet that up to now, no one had even considered the possibility!

If I had been thinking of a solution for my own use, I'd only be 
interested in my own code and my own headers; that's why I wasn't too 
bothered about standard headers.

BTW how do smart editors managed it: do they scan the tens of thousands 
of lines of include files, and expand all the macros, in order to be 
able to detect unbalanced braces?

>> Again, that can be checked once, so that if I see #include <windows.h>,
>> I might be able to remember those results without having to
>> re-preprocess it or re-scan the output.
>
> Unless the header is affected by things defined before it's #included.
> <assert.h> is the obvious example.

I was thinking of compile options such as:

   gcc -DABC=1234 program.c

ABC is a macro that might affect how conditional code is compiled.

Then there are things such as __TIME__, which can be different each 
time, although I'm not sure how that would be used to influence 
conditional code. With the use of __LINE__, I can do this:

#if __LINE__ == 10
   #define OPEN {
#else
   #define OPEN }
#endif

Written so that the #if is on line 10, then deleting or inserting any 
line  before that can reverse the definition of OPEN.

-- 
Bartc
0
BartC
12/21/2016 12:38:25 AM
On 20/12/16 14:35, Rick C. Hodgin wrote:
> On Tuesday, December 20, 2016 at 8:20:47 AM UTC-5, Bart wrote:
>> On 20/12/2016 03:30, DFS wrote:
>>
>>> I'd rather the compiler do at least a quick count for me.
>>
>> The compiler is handicapped by the language. This has the right number 
>> of { and } braces and compiles fine:
>>
>>      if (a) {
>>          if (b)
>>              puts("B1");
>>              puts("B2");
>>          }

C gives you the ability to write code in an ugly, confusing and
error-prone manner.  So do all programming languages I have ever seen.
The details of how you can write confusing and bad code with legal
syntax varies from language to language, but it is always possible.

You avoid this particular problem with a simple rule - a for, if or
while statement should always have brackets.  And you need a consistent
bracing and indenting style - I recommend the One True Brace Style as a
starting point, but variations are possible.

> 
> It's also possible that with the macro language things will not align
> in raw source code, but only when macros are expanded.  Some editors
> can handle this (as David Brown points out), but most can't.

You can put things like brackets in macro definitions, but it is usually
regarded as a /really/ bad idea.

> 
>> But when a is 1 and b is 0, it doesn't do what is suggested by the 
>> indentation. In busy code spanning more lines, and many other sets of { 
>> and }, it can be hard to spot.
>>
>> The problem here is that { and } are optional around a single statement.
> 
> Something Supercat talks about often is the ability for the compiler to
> generate useful diagnostics which can help the developer make better
> choices in their development.  He wants it primarily for creating better
> optimized code, but I was thinking an extension of that ability might
> also work here.

One of the nicest new features of gcc 6 (IMHO) is the
"-Wmisleading-indentation" warning.  It will mark code such as Bart's
code above with a warning.  I can't answer for Supercat, but /I/ like
such warnings as they help developers write clear, correct code and help
spot potential errors as soon as possible.

> 
> I think most developers write their code in small increments, recompile,
> and continue on.  Most compilers today are fast enough that I do this
> every few minutes.  It gives me an early cue about where I might've
> made a mistake.  I also make all kinds of ongoing little mistakes in
> my code that aren't representative of my thought processes, but are
> representative of some error in translation from thought to fingers
> in typing.  I even type things like >= when I meant > only, etc.  It's
> very strange.  I spend so much time tracking down bugs that I know
> from my thought processes aren't there.  I have to look at things
> line-by-line to find the errors because it was only an error in
> typing, and not an error in thinking.  It's so frustrating sometimes.

Compilers (and "smart" editors) can be useful for spotting some of these
mistakes.  I compile my code regularly while writing it, even though I
might not be planning on running it on the target for a while.  Compiler
error and warning messages are helpful.

But don't rely on it /too/ much - it's easy to write something that is
perfectly legal, passes all the warning checks, and is still not what
you meant.

> 
> In any event ... having the ability to generate a type of flow control
> map which an editor could coordinate alongside the original source
> code would be nice.  The editor could then analyze the code and the
> generated map based on things like indentation convention and flag
> possible cases where things are weird.  Have them show up in red, or
> with another some filterable quantity.
> 
> In any event ... I could've used this type of catching several times
> in the past.
> 
> Best regards,
> Rick C. Hodgin
> 

0
David
12/21/2016 11:07:01 AM
On 20/12/16 18:49, Richard Heathfield wrote:
> On 20/12/16 17:21, Ben Bacarisse wrote:
>> Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
>>
> <snip>
> 
>>>    int i, ii, iii;
>>>    int answer = 0;
>>>
>>>    for(i=0;i<wh->Naisles;i++)
>>>      for(ii=0;ii<wh->aisle[i].Nshelves;ii++)
>>>        for(iii=0;iii<wh->aisle[i]->shelf[ii].Nitems;iii++)
>>>          if(!strcmp(wh->aisle[i]->shelf[ii]->item[iii].barcode,
>>> barcode))
>>>            answer += wh->aisle[i]->shelf[ii]->item[ii].N;
>>>
>>>     return answer;
>>> }
>>
>> It's interesting that you have exactly the kind of bug I would expect to
>> see in this sort of code.
> 
> Sharp eyes indeed. (In case other people haven't spotted it, look
> carefully at the most deeply nested statement. I didn't see it either
> until Ben mentioned that there was a bug to find.)

Nor did I.

How is it possible for someone to talk about "making code more
readable", without knowing how to use the biggest key on the keyboard.


0
David
12/21/2016 11:25:28 AM
On 21/12/2016 11:07, David Brown wrote:
> On 20/12/16 14:35, Rick C. Hodgin wrote:
>> On Tuesday, December 20, 2016 at 8:20:47 AM UTC-5, Bart wrote:
>>> On 20/12/2016 03:30, DFS wrote:
>>>
>>>> I'd rather the compiler do at least a quick count for me.
>>>
>>> The compiler is handicapped by the language. This has the right number
>>> of { and } braces and compiles fine:
>>>
>>>      if (a) {
>>>          if (b)
>>>              puts("B1");
>>>              puts("B2");
>>>          }
>
> C gives you the ability to write code in an ugly, confusing and
> error-prone manner.  So do all programming languages I have ever seen.

In the syntax I normally use, this example is impossible to write 
without invoking an error.

> The details of how you can write confusing and bad code with legal
> syntax varies from language to language, but it is always possible.
>
> You avoid this particular problem with a simple rule - a for, if or
> while statement should always have brackets.

Unfortunately that doesn't always work, as the language won't not cooperate.

If you forget the braces, it won't tell you as it knows nothing about 
your rule, unless it can't match them. You can also put in extra braces, 
and that's OK provided the extra brace is matched elsewhere.

It doesn't help that the same } brace can close an if-block, for-block, 
while-block, do-block, switch-block, function-block, a data-block, and 
just a block-block.

So it's a language design issue; it's not true that all languages are 
the same. Not regarding this block-delimiting anyway.

And people aren't going to follow the rule as it's far too tempting to 
just write:

     if (!fp) return 0;

(leaving this open to brace-matching and dangling else problems).

   And you need a consistent
> bracing and indenting style - I recommend the One True Brace Style as a
> starting point, but variations are possible.

Yes, everyone uses /their own/ consistent style!


-- 
Bartc
0
BartC
12/21/2016 12:46:34 PM
On 21/12/16 13:46, BartC wrote:
> On 21/12/2016 11:07, David Brown wrote:
>> On 20/12/16 14:35, Rick C. Hodgin wrote:
>>> On Tuesday, December 20, 2016 at 8:20:47 AM UTC-5, Bart wrote:
>>>> On 20/12/2016 03:30, DFS wrote:
>>>>
>>>>> I'd rather the compiler do at least a quick count for me.
>>>>
>>>> The compiler is handicapped by the language. This has the right number
>>>> of { and } braces and compiles fine:
>>>>
>>>>      if (a) {
>>>>          if (b)
>>>>              puts("B1");
>>>>              puts("B2");
>>>>          }
>>
>> C gives you the ability to write code in an ugly, confusing and
>> error-prone manner.  So do all programming languages I have ever seen.
> 
> In the syntax I normally use, this example is impossible to write
> without invoking an error.

As I said, the details vary from language to language.  But no language
is immune from programmers who write confusing code.  Languages, tools,
coding standards, programmer education and good practice all combine to
reduce the risk of such errors.  For historical reasons, C has a number
of ways to make silly mistakes that many other languages don't have -
this is one of them.  But a decent editor can make this slightly harder
to type (since you get used to indents being generated automatically).
Good tools (gcc 6 spots this, as will many linters and more advanced C
static error checkers).  No coding standard would accept such code.  And
of course if the programmer has been taught properly and is used to
writing code sensibly, then it is very unlikely that they will make such
a mistake.

Mistakes of all sorts /do/ happen, with /all/ programming languages.
Don't pretend that any particular language eliminates typos, bad design,
poor programming habits, or other errors - a  good language design can
greatly reduce the risk of /some/ types programming errors, but that is
all.  And don't confuse weaknesses in a language design with an
inability or unwillingness to use tools to help write correct code.
Just because C /lets/ you write this sort of thing, does not make it any
less /your/ fault if you write it.

Personally, I would have been happier if the C language insisted on
brackets on "if", "while", and "for" statements - it would reduce other
people's mistakes.  (I don't make such mistakes.  I make /other/
mistakes in my coding, but I don't get brackets and indentation wrong.)
 But I can also understand that some people are happy that they are
optional.

> 
>> The details of how you can write confusing and bad code with legal
>> syntax varies from language to language, but it is always possible.
>>
>> You avoid this particular problem with a simple rule - a for, if or
>> while statement should always have brackets.
> 
> Unfortunately that doesn't always work, as the language won't not
> cooperate.

It /always/ works, because the language does not prevent you writing
correct code.

The language does not stop you writing incorrect code, but that's
another matter entirely.

> 
> If you forget the braces, it won't tell you as it knows nothing about
> your rule, unless it can't match them. You can also put in extra braces,
> and that's OK provided the extra brace is matched elsewhere.

It is not the language's job to make sure your code is correct - it is
/your/ job.  And if you can't do it reliably on your own, then it is
/your/ job to make sure you have appropriate tools to help.

> 
> It doesn't help that the same } brace can close an if-block, for-block,
> while-block, do-block, switch-block, function-block, a data-block, and
> just a block-block.

That works just fine.

> 
> So it's a language design issue; it's not true that all languages are
> the same. Not regarding this block-delimiting anyway.

As I said, /all/ languages let you write incorrect or confusing code,
but the details vary.

There are a few things about C that make it easier than necessary to
write incorrect code - this is one of them.  Others include the
automatic fall-through in switch cases, and that "if (x = y)" is legal
code.  But it is still not hard to avoid these potential problems.

> 
> And people aren't going to follow the rule as it's far too tempting to
> just write:
> 
>     if (!fp) return 0;

Many people (including me) see that as fine - /if/ there are no "else"
clauses involved.

> 
> (leaving this open to brace-matching and dangling else problems).
> 
>   And you need a consistent
>> bracing and indenting style - I recommend the One True Brace Style as a
>> starting point, but variations are possible.
> 
> Yes, everyone uses /their own/ consistent style!
> 

You can use existing styles and coding standards, or make your own -
that is up to you.  The point is that having a consistent style is the
key to clear coding her - the details of that style do not matter much.

0
David
12/21/2016 2:10:44 PM
David Brown <david.brown@hesbynett.no> writes:
[...]
> You can put things like brackets in macro definitions, but it is usually
> regarded as a /really/ bad idea.

(I presume that by "brackets" you mean {curly braces}.)

Why is it a bad idea?  I've seen (and written) plenty of macro
definitions like:

    #define FOO do { /* blah blah */ } while(0)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/21/2016 4:52:31 PM
BartC <bc@freeuk.com> writes:
> On 21/12/2016 11:07, David Brown wrote:
>> On 20/12/16 14:35, Rick C. Hodgin wrote:
>>> On Tuesday, December 20, 2016 at 8:20:47 AM UTC-5, Bart wrote:
>>>> On 20/12/2016 03:30, DFS wrote:
>>>>
>>>>> I'd rather the compiler do at least a quick count for me.
>>>>
>>>> The compiler is handicapped by the language. This has the right number
>>>> of { and } braces and compiles fine:
>>>>
>>>>      if (a) {
>>>>          if (b)
>>>>              puts("B1");
>>>>              puts("B2");
>>>>          }
>>
>> C gives you the ability to write code in an ugly, confusing and
>> error-prone manner.  So do all programming languages I have ever seen.
>
> In the syntax I normally use, this example is impossible to write 
> without invoking an error.

That would be some other language than C, right?

>> The details of how you can write confusing and bad code with legal
>> syntax varies from language to language, but it is always possible.
>>
>> You avoid this particular problem with a simple rule - a for, if or
>> while statement should always have brackets.
>
> Unfortunately that doesn't always work, as the language won't not cooperate.

Sure it does.  It doesn't always diagnose failures to follow that rule,
but it doesn't get in the way of following it yourself.

> If you forget the braces, it won't tell you as it knows nothing about 
> your rule, unless it can't match them. You can also put in extra braces, 
> and that's OK provided the extra brace is matched elsewhere.

So don't do that.

> It doesn't help that the same } brace can close an if-block, for-block, 
> while-block, do-block, switch-block, function-block, a data-block, and 
> just a block-block.

I've never found that to be a problem, as long as I use braces
consistently -- which is not at all difficult to do.  (I sometimes have
some difficulty when I'm working on code written by others.  Such is
life.)

> So it's a language design issue; it's not true that all languages are 
> the same. Not regarding this block-delimiting anyway.

Did anybody say that all languages are the same?

Perl, for example, requires braces on all compound statements.
(Personally, that's one thing I like about Perl.)  But if Perl
didn't require braces, I'm entirely capable of using them anyway,
just as I do in C.

> And people aren't going to follow the rule as it's far too tempting to 
> just write:
>
>      if (!fp) return 0;
>
> (leaving this open to brace-matching and dangling else problems).

In fact, a lot of people *do* follow the rule.  I sometimes (rarely)
omit braces on one-line statements.  It doesn't cause brace-matching or
dangling else problems, because I consistently use braces on multi-line
statements.

>    And you need a consistent
>> bracing and indenting style - I recommend the One True Brace Style as a
>> starting point, but variations are possible.
>
> Yes, everyone uses /their own/ consistent style!

Yes, the lack of consistency of brace styles can be a problem.  Pick a
style and follow it consistently for your own code (I like the 1TBS, but
I don't complain if you prefer something else).  If you're working on
existing code, consistently follow that code's existing style.

Once again, you seem to be inventing problems just so you can complain
about them.

The solution to this particular problem is not "change the language,
breaking decades of existing code, so the compiler will diagnose
missing braces".  The solution is "exercise a bit of discipline
when writing code".

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/21/2016 5:04:19 PM
On 21/12/2016 14:10, David Brown wrote:
> On 21/12/16 13:46, BartC wrote:

> For historical reasons, C has a number
> of ways to make silly mistakes that many other languages don't have -
> this is one of them.

It seems to excel in this.

> It is not the language's job to make sure your code is correct - it is
> /your/ job.  And if you can't do it reliably on your own, then it is
> /your/ job to make sure you have appropriate tools to help.

Why should it be necessary to introduce extra tools to fix deficiencies 
in the language? There are loads of things in C that can lead to 
inadvertent errors that could so easily have been fixed.

This is a small selection, together with whether the design of C allows 
various errors to be detected, compared with one of my languages:

                                        C               X

Use the wrong sort of } brace          Not detected    Detected

Index a pointer that is supposed       Not detected    Detected
to be just a pointer

Use octal 0125 instead of decimal      Not detected    Is decimal

= instead of ==  if (a=b)              Not detected    Less likely

== instead of =  a==b;                 Not detected    Detected

"abc"[1]='X';                          Not detected    Detected

defau1t: instead of default:           Not detected    Can't happen

if (p==NULL); exit(0);                 Not detected    Can't happen

Write 100000 instead of 1000000        Not detectable  Use 1_000_000

Think a<<b+c means (a<<b+c)            Not detected    Means (a<<b+c)

You still think the language bears no responsibility, and it should be 
up to you, or up to extra tools that you are obliged to use?

>> It doesn't help that the same } brace can close an if-block, for-block,
>> while-block, do-block, switch-block, function-block, a data-block, and
>> just a block-block.
>
> That works just fine.

No it doesn't. Suppose you miss out the closing } of a while-block. The 
next } the compiler sees is the one /you/ think closes the function, but 
the compiler assumes closes the while-block. So, with gcc which allows 
nested functions, it might not raise the alarm until 1000 lines later at 
the end of the file.

With a language that insists on different block-endings such as 'end 
while' and 'end function', it is impossible to mix them up without the 
compiler complaining.

Even leaving compilation aside, it will be more obvious to the human 
reader of the code.

(I suppose you will just say use a style such as "} //end while", which 
although it might help a bit, no-one is going to do, and it is not 
checked by the compiler.)

>> So it's a language design issue; it's not true that all languages are
>> the same. Not regarding this block-delimiting anyway.
>
> As I said, /all/ languages let you write incorrect or confusing code,
> but the details vary.
>
> There are a few things about C that make it easier than necessary to
> write incorrect code - this is one of them.  Others include the
> automatic fall-through in switch cases, and that "if (x = y)" is legal
> code.  But it is still not hard to avoid these potential problems.

Well it would have been less hard if the language had done it right in 
the first place! (Algol68, which got block handling correct, came out in 
1968; C was a couple of years later at least, but decided to go with {, 
} and nothing.)

>> And people aren't going to follow the rule as it's far too tempting to
>> just write:
>>
>>     if (!fp) return 0;
>
> Many people (including me) see that as fine - /if/ there are no "else"
> clauses involved.

And if one is added later? It is also common to start with this:

        if (!fp)
           return 0;

and turn it into this:

        if (!fp)
           puts("Can't open file");
           return 0;

especially if most other ifs use braces. If you have rules you need to 
stick to them!

-- 
Bartc
0
BartC
12/21/2016 5:10:45 PM
On 21/12/2016 17:04, Keith Thompson wrote:
> BartC <bc@freeuk.com> writes:

>> If you forget the braces, it won't tell you as it knows nothing about
>> your rule, unless it can't match them. You can also put in extra braces,
>> and that's OK provided the extra brace is matched elsewhere.
>
> So don't do that.

"So don't make mistakes"

Brilliant!

> Once again, you seem to be inventing problems just so you can complain
> about them.

The problems exist, I don't need to invent them. But people seem to be 
in denial.

There's no solution that involves fixing the language as it's far too 
late. But it would nice if someone would agree once in a while that 
there might be some issues with the design of the language.

> The solution to this particular problem is not "change the language,
> breaking decades of existing code, so the compiler will diagnose
> missing braces".  The solution is "exercise a bit of discipline
> when writing code".

People /will/ make mistakes. But the language design stops some mistakes 
being diagnosed because it is still legal code. This can happen in other 
languages but seems to be particularly easy to do in C.

-- 
Bartc

0
BartC
12/21/2016 5:24:48 PM
BartC <bc@freeuk.com> writes:
[...]
> There's no solution that involves fixing the language as it's far too 
> late.

I'm glad you realize that.

>       But it would nice if someone would agree once in a while that 
> there might be some issues with the design of the language.

Apparently you haven't been paying attention.  Yes, there are issues
with the design of the language; nobody denies that.  There are
design decisions that, with the benefit of hindsight, I would have
made differently.  I, and others, have discussed at considerable
length ways to deal with C's very real problems, such as using a
consistent brace style even though the language doesn't require it.

Are you happy now?

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/21/2016 5:41:46 PM
On 21/12/16 18:10, BartC wrote:
> On 21/12/2016 14:10, David Brown wrote:
>> On 21/12/16 13:46, BartC wrote:
>
>> For historical reasons, C has a number
>> of ways to make silly mistakes that many other languages don't have -
>> this is one of them.
>
> It seems to excel in this.
>
>> It is not the language's job to make sure your code is correct - it is
>> /your/ job.  And if you can't do it reliably on your own, then it is
>> /your/ job to make sure you have appropriate tools to help.
>
> Why should it be necessary to introduce extra tools to fix deficiencies
> in the language? There are loads of things in C that can lead to
> inadvertent errors that could so easily have been fixed.

You seem to be confusing C with something else.  C is a language that is 
about 40 years old, based partly on even older languages.  Backwards 
compatibility has always been of critical importance to C, both the 
standards and the implementations.

This means that C has not been able to take advantage of many of the 
ideas of programming language design over the last 4 decades.  It means 
that some aspects of it's design are based on how computers and 
compilers were used at that time - such as relying on extra tools for 
things that might be built into a language designed today.  And it also 
means that /none/ of the problems of C are particularly bad or hard to 
avoid, since it is still around today and for many types of programming 
work it is clearly the best (or only!) choice.

And when you say things "could so easily have been fixed", I presume you 
mean that they could have been fixed 40 years ago - since backwards 
compatibility means few changes can be made now?

>
> This is a small selection, together with whether the design of C allows
> various errors to be detected, compared with one of my languages:
>
>                                        C               X
>
> Use the wrong sort of } brace          Not detected    Detected
>

C only has one type of brace, so there is no problem here.

> Index a pointer that is supposed       Not detected    Detected
> to be just a pointer
>

I have never found that to be a problem.  But then, I understand how 
arrays and pointers work in C.  I would have been happy to see arrays 
being first-class types independent of pointers, but I can understand 
why they are the way they are in C, and I have no problem using them.

> Use octal 0125 instead of decimal      Not detected    Is decimal
>

That's an annoying one.  I would very much like gcc to have a warning on 
the use of octal constants (other than 0, of course).  Support for octal 
cannot be removed from the language, for backward compatibility.

> = instead of ==  if (a=b)              Not detected    Less likely
>

Almost all compilers will spot that one.

> == instead of =  a==b;                 Not detected    Detected
>

Almost all compilers will spot that one.

> "abc"[1]='X';                          Not detected    Detected
>

Almost all compilers will spot that one.

> defau1t: instead of default:           Not detected    Can't happen
>

Compilers can give warnings on missing default, and editors with syntax 
highlighting will make this mistake obvious.  You might also like to buy 
a keyboard where the lower case "l" and the digit "1" are somewhat 
separated, reducing the risk of making this typo to virtually zero.

> if (p==NULL); exit(0);                 Not detected    Can't happen
>

This is avoided by writing correct code.  It is also avoided by having a 
habit of always using brackets on your conditionals.  C does not require 
that - but you are free to do so.

> Write 100000 instead of 1000000        Not detectable  Use 1_000_000
>

I too would like a digit separator.  But I can live without it.

> Think a<<b+c means (a<<b+c)            Not detected    Means (a<<b+c)
>

Writing "a<<b+c" is, IMHO, simply bad coding.  Write either "(a << b) + 
c", or "a << (b + c)" according to what you mean.  It's not hard.

> You still think the language bears no responsibility, and it should be
> up to you, or up to extra tools that you are obliged to use?

If those are the things you find hard, then yes - I think the language 
bears no significant responsibility here.  These "extra tools" are a 
"decent editor" and a "compiler" - both of which are quite important to 
productive C programming.  There are more advanced tools you can buy 
that do more checking, but they are not needed for this level of checking.

>
>>> It doesn't help that the same } brace can close an if-block, for-block,
>>> while-block, do-block, switch-block, function-block, a data-block, and
>>> just a block-block.
>>
>> That works just fine.
>
> No it doesn't. Suppose you miss out the closing } of a while-block. The
> next } the compiler sees is the one /you/ think closes the function, but
> the compiler assumes closes the while-block. So, with gcc which allows
> nested functions, it might not raise the alarm until 1000 lines later at
> the end of the file.
>

A decent editor will help you spot the problem early.  And failing that, 
the compiler will at least see that there is a problem.  So it works 
fine - and it is a lot simpler and easier than having different sorts of 
close brackets for different uses.  I agree that compiler warnings could 
always be better - and I am happy that this is something the gcc 
developers put a great deal of effort into.

> With a language that insists on different block-endings such as 'end
> while' and 'end function', it is impossible to mix them up without the
> compiler complaining.
>
> Even leaving compilation aside, it will be more obvious to the human
> reader of the code.
>

That is only an issue if you fail to indent properly or write functions 
that are too long to be easily comprehended.

> (I suppose you will just say use a style such as "} //end while", which
> although it might help a bit, no-one is going to do, and it is not
> checked by the compiler.)
>

You can use such a style if you like - some people do write that sort of 
thing.  It is common with #ifdef/#endif pairs, since they sometimes span 
large ranges of code.  Similarly, it is common in C++ for class 
declarations, namespaces, etc.  But normal functions should not be so 
long that these sorts of comments are useful.

>>> So it's a language design issue; it's not true that all languages are
>>> the same. Not regarding this block-delimiting anyway.
>>
>> As I said, /all/ languages let you write incorrect or confusing code,
>> but the details vary.
>>
>> There are a few things about C that make it easier than necessary to
>> write incorrect code - this is one of them.  Others include the
>> automatic fall-through in switch cases, and that "if (x = y)" is legal
>> code.  But it is still not hard to avoid these potential problems.
>
> Well it would have been less hard if the language had done it right in
> the first place! (Algol68, which got block handling correct, came out in
> 1968; C was a couple of years later at least, but decided to go with {,
> } and nothing.)
>
>>> And people aren't going to follow the rule as it's far too tempting to
>>> just write:
>>>
>>>     if (!fp) return 0;
>>
>> Many people (including me) see that as fine - /if/ there are no "else"
>> clauses involved.
>
> And if one is added later?

Then you add the brackets when you add a second line.  It's not rocket 
science.

> It is also common to start with this:
>
>        if (!fp)
>           return 0;

I see that as a common bad habit.

>
> and turn it into this:
>
>        if (!fp)
>           puts("Can't open file");
>           return 0;
>

No, it is not common to write such code.  I agree that it is a fairly 
common style to allow a single indented statement on the line after an 
"if", with no brackets.  But when working with that code, if you add 
another statement to the inside of the conditional, you add the braces. 
Sometimes mistakes are made here, but it is not common.

But using a better brace convention means that you /don't/ make such 
mistakes at all.


> especially if most other ifs use braces. If you have rules you need to
> stick to them!
>

Yes, you have to stick to your rules - that's what "consistency" means. 
It does not mean that you have to have the minimum number of rules - 
it's okay to be a little bit smart.

0
David
12/21/2016 6:50:46 PM
On 21/12/16 17:52, Keith Thompson wrote:
> David Brown <david.brown@hesbynett.no> writes:
> [...]
>> You can put things like brackets in macro definitions, but it is usually
>> regarded as a /really/ bad idea.
>
> (I presume that by "brackets" you mean {curly braces}.)
>
> Why is it a bad idea?  I've seen (and written) plenty of macro
> definitions like:
>
>     #define FOO do { /* blah blah */ } while(0)
>

Sorry - I understood the point being macros that had /unmatched/ braces. 
  Otherwise there would be no problem with macros when counting braces, 
as the macro invocations would all cancel themselves out.

So I meant it was usually a bad idea to have /unmatched/ braces in macros.


0
David
12/21/2016 7:16:02 PM
On 21/12/2016 18:50, David Brown wrote:
> On 21/12/16 18:10, BartC wrote:

> You seem to be confusing C with something else.  C is a language that is
> about 40 years old, based partly on even older languages.

I mentioned Algol-68 which is older. That one got braces right.

> Backwards
> compatibility has always been of critical importance to C, both the
> standards and the implementations.
>
> This means that C has not been able to take advantage of many of the
> ideas of programming language design over the last 4 decades.

Unlike Fortran, Ada, C++ and even Pascal which have all evolved? And 
what are the compatibility issues in allowing 1000_000!

>                                        C               X
>>
>> Use the wrong sort of } brace          Not detected    Detected
>>
>
> C only has one type of brace, so there is no problem here.

You losing the opportunity to detect a missing block-end delimiter of 
the right type.

>> = instead of ==  if (a=b)              Not detected    Less likely
>>
>
> Almost all compilers will spot that one.
> Almost all compilers will spot that one.
> Almost all compilers will spot that one.

/Some/ compilers, and with the right set of options.

It's funny how the C Standard usually has the last word in this group. 
But with practical problems like these, the Standard goes out the 
window. Instead we need the right compiler, the right options, the right 
editor, the right analysers, the right Cdecl program, the right 
guidelines...

>> if (p==NULL); exit(0);                 Not detected    Can't happen

> This is avoided by writing correct code.  It is also avoided by having a
> habit of always using brackets on your conditionals.

Like: if (p=NULL); {exit(0);} ?

>> You still think the language bears no responsibility, and it should be
>> up to you, or up to extra tools that you are obliged to use?
>
> If those are the things you find hard, then yes - I think the language
> bears no significant responsibility here.  These "extra tools" are a
> "decent editor" and a "compiler" - both of which are quite important to
> productive C programming.

I wonder what tools were available 40 years ago?

-- 
Bartc
0
BartC
12/21/2016 8:15:45 PM
On 2016-12-21, BartC <bc@freeuk.com> wrote:
> On 21/12/2016 18:50, David Brown wrote:
>> On 21/12/16 18:10, BartC wrote:
>
>> You seem to be confusing C with something else.  C is a language that is
>> about 40 years old, based partly on even older languages.
>
> I mentioned Algol-68 which is older. That one got braces right.

Can you elaborate? Where does Algol-68 use braces?
0
Ike
12/21/2016 10:36:55 PM
On 21/12/2016 22:36, Ike Naar wrote:
> On 2016-12-21, BartC <bc@freeuk.com> wrote:
>> On 21/12/2016 18:50, David Brown wrote:
>>> On 21/12/16 18:10, BartC wrote:
>>
>>> You seem to be confusing C with something else.  C is a language that is
>>> about 40 years old, based partly on even older languages.
>>
>> I mentioned Algol-68 which is older. That one got braces right.
>
> Can you elaborate? Where does Algol-68 use braces?

I didn't express it well. That language solves the braces problem by 
using a different scheme (that doesn't use braces):

A68: if a;b then c;d;e elif f then g elif h then i;j else k fi

C:   if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;

- C needs 3 grouping methods for serially-evaluated elements:
   (), {} and nothing, compared with one (and uses either "," as
   [effective] separator or ";" as terminator).

- C allows single elements to either be inside {} or not, adding
   variability to code (and introducing the problems that have been
   discussed when code subsequently is edited). Elements that are
   conditional expressions must use ().

- C leaves itself open to the dangling else problem

- If C closes an if-statement with }, then it has the problem that
   it can get mixed up with a closing brace from another kind of
   statement (not possible using 'fi' or 'end if').

- There are probably more placement styles for { and } than are
   possible with the A68 scheme; yet more variability in code.

But apart from all that, there's not much in it...

-- 
bartc
0
BartC
12/21/2016 11:46:41 PM
BartC <bc@freeuk.com> writes:

> On 21/12/2016 22:36, Ike Naar wrote:
>> On 2016-12-21, BartC <bc@freeuk.com> wrote:
<snip>
>>> I mentioned Algol-68 which is older. That one got braces right.
>>
>> Can you elaborate? Where does Algol-68 use braces?
>
> I didn't express it well. That language solves the braces problem by
> using a different scheme (that doesn't use braces):
>
> A68: if a;b then c;d;e elif f then g elif h then i;j else k fi
>
> C:   if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;
<snip>
> - There are probably more placement styles for { and } than are
>   possible with the A68 scheme; yet more variability in code.

I think you are forgetting.  Did you write BEGIN ... END, 'begin'
.... 'end' or .BEGIN ... .END?  And you can use (...)  instead of begin
.... end, just as there's no need to use 'IF' 'THEN' 'ELSE' either since
you might choose to use ( | and ).  And what were the options for
writing multiplication and so on in your favourite compiler?  And, of
course, then there is white space in identifiers...

Algol 68 has plenty of ways to introduce variability in code.

-- 
Ben.
0
Ben
12/22/2016 1:54:13 AM
On 12/22/16 06:24 AM, BartC wrote:
> On 21/12/2016 17:04, Keith Thompson wrote:
>> BartC <bc@freeuk.com> writes:
>
>>> If you forget the braces, it won't tell you as it knows nothing about
>>> your rule, unless it can't match them. You can also put in extra braces,
>>> and that's OK provided the extra brace is matched elsewhere.
>>
>> So don't do that.
>
> "So don't make mistakes"
>
> Brilliant!


It's called writing unit tests...


-- 
Ian
0
Ian
12/22/2016 5:10:39 AM
On 21/12/16 20:16, David Brown wrote:
> On 21/12/16 17:52, Keith Thompson wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>> [...]
>>> You can put things like brackets in macro definitions, but it is usually
>>> regarded as a /really/ bad idea.
>>
>> (I presume that by "brackets" you mean {curly braces}.)

Yes, I meant curly braces here.  However, my corrected point applies to
round parentheses and square brackets too - I think it is usually a bad
idea for a macro to have unmatched bracketing of any kind.

(And I say "usually" intentionally - there are exceptions.)

>>
>> Why is it a bad idea?  I've seen (and written) plenty of macro
>> definitions like:
>>
>>     #define FOO do { /* blah blah */ } while(0)
>>
> 
> Sorry - I understood the point being macros that had /unmatched/ braces.
>  Otherwise there would be no problem with macros when counting braces,
> as the macro invocations would all cancel themselves out.
> 
> So I meant it was usually a bad idea to have /unmatched/ braces in macros.
> 
> 

0
David
12/22/2016 8:41:21 AM
On 22/12/2016 01:54, Ben Bacarisse wrote:
> BartC <bc@freeuk.com> writes:

>> A68: if a;b then c;d;e elif f then g elif h then i;j else k fi
>>
>> C:   if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;
> <snip>
>> - There are probably more placement styles for { and } than are
>>   possible with the A68 scheme; yet more variability in code.
>
> I think you are forgetting.  Did you write BEGIN ... END, 'begin'
> ... 'end' or .BEGIN ... .END?

I don't remember BEGIN...END in that language. I used them in Algol and 
Pascal and they were just as annoying as {...} in C.

   And you can use (...)  instead of begin
> ... end, just as there's no need to use 'IF' 'THEN' 'ELSE' either since
> you might choose to use ( | and ).  And what were the options for
> writing multiplication and so on in your favourite compiler?  And, of
> course, then there is white space in identifiers...
>
> Algol 68 has plenty of ways to introduce variability in code.

Yes, actual A68 implementations with their various 'stropping' schemes 
resulted in some very ugly source code; it's not surprising it didn't 
catch on. And I didn't care much for the rest of the language.

But I'm actually thinking of my own syntax which is derived from Algol 
68 (just like C's could have been) which doesn't have those issues you 
mentioned. You don't have to literally copy everything including all the 
warts.

(As for the short-forms such as (a|b|c) for 'if-then-else-fi', I only 
allow those in expressions.)

A few years ago I was using a thin wrapper around C source code which 
replaced {,} around statement blocks with 'then', 'do' and so on.

Here are two example functions; although they don't look like it, the 
code is actually C apart from the block delimiters**:

http://pastebin.com/UanK17aH

And this is the translation to actual C; notice the line numbers 
correspond exactly, as it is a line-at-a-time translation:

http://pastebin.com/vQ621sGs

It really doesn't take much to turn C syntax into an Algol-68 lookalike! 
The translator was about 400 lines of code.


(** There were few other things that were different:

* := used in place of =

* = used in place of ==, and <> for !=

* Empty macros such as 'function', 'proc' and 'global' are used

* 'FORD' is a macro for a down-counting A to B for-statement

* The translator also extracted local functions prototypes into a .cl
   file (included in the same module), and global ones into a .cx file
   (included in some common header).)

-- 
Bartc

0
BartC
12/22/2016 12:16:02 PM
BartC <bc@freeuk.com> writes:
<snip>
>> BartC <bc@freeuk.com> writes:
>
>>> A68: if a;b then c;d;e elif f then g elif h then i;j else k fi
>>>
>>> C:   if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;
>> <snip>
>>> - There are probably more placement styles for { and } than are
>>>   possible with the A68 scheme; yet more variability in code.
<snip>
> But I'm actually thinking of my own syntax which is derived from Algol
> 68

Ah.  It's a shame you wrote A68 then.

-- 
Ben.
0
Ben
12/22/2016 1:06:28 PM
>>> C:   if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;

C: if(a,b)c,d,e;else if(f)g;else if(h)i,j;else k;
0
asetofsymbols
12/22/2016 1:25:40 PM
BartC wrote:
>  if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;

Doesn't C also handle this thusly:

    if (a,b)
       (c, d, e);
    else if (f)
        g;
    else if (h)
        (i, j);
    else
        k;

....which could be rewritten:

    if (a,b) (c, d, e); else if (f) g; else if (h) (i, j); else k;

Best regards,
Rick C. Hodgin
0
Rick
12/22/2016 1:33:21 PM
On 22/12/2016 13:25, asetofsymbols@gmail.com wrote:
>>>> C:   if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;
>
> C: if(a,b)c,d,e;else if(f)g;else if(h)i,j;else k;
>

More variability...

But this is not quite the same, as a,b,c, etc represent arbitrary 
expressions and, when terminated with ";", arbitrary statements. So you 
can't change a;b; to a,b; in all cases.

-- 
Bartc
0
BartC
12/22/2016 1:34:14 PM
BartC wrote: 
>  if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;

Or rather:

    if ((a,b))   // Result from b used for conditional
       (c, d, e); 
    else if (f) 
        g; 
    else if (h) 
        (i, j); 
    else 
        k; 

You can't put flow statements in there, but by calling a function and
using return values, the equivalent is possible, and with much clear
syntax for debugging and maintenance.

Best regards,
Rick C. Hodgin
0
Rick
12/22/2016 1:41:16 PM
On 22/12/2016 13:41, Rick C. Hodgin wrote:
> BartC wrote:
>>  if (a,b) {c;d;e;} else if (f) g; else if (h) {i;j;} else k;
>
> Or rather:
>
>     if ((a,b))   // Result from b used for conditional
>        (c, d, e);
>     else if (f)
>         g;
>     else if (h)
>         (i, j);
>     else
>         k;
>
> You can't put flow statements in there, but by calling a function and
> using return values, the equivalent is possible, and with much clear
> syntax for debugging and maintenance.

As I mentioned in my reply to asetofsymbols, a,b,c etc are just 
placeholders for actual expressions and statements.

In general, you can't write 3 statements as (c,d,e). Only if they happen 
to be expressions. But 3 expressions could be written as {c;d;e;}.

We want to reduce the number of possibilities not increase them!

c,d,e as expressions in a block context could be written as::

     c, d, e;
    (c, d, e);
    {c; d; e;}
    {c, d, e;}
    {c, d; e;}  // etc

Plus there are any number of ways of splitting them across multiple 
lines. Or adding extra {} and ().

When I worked on my lightweight translator I had to insist on source 
code looking like this:

   if (a) then
     ....
   else
     ....
   fi      // or endif

Even if there was just one statement in each branch. But it paid off 
since you knew the input was always going to be written consistently, so 
it looked good and was easy to detect, and the resultant C wasn't too 
bad either, as it would use the same {,} placement scheme. And there 
would always be {,}.

-- 
Bartc
0
BartC
12/22/2016 2:53:01 PM
What you write remember me
 Axiom all is parentizated using
indentation...
As in
if a=1 then
        r.1:=1
        r.2:=2
else r.1:=0
     r.2:=1

One can write that in one line as

if a=1 then(r.1:=1;r.2:=2)else(r.1:=0;r.2:=1)


0
asetofsymbols
12/22/2016 4:11:58 PM
What is the difference from
a;b;
and
a,b;

You say are different...
I remember that first than 'b'
it is executed 'a'
0
asetofsymbols
12/22/2016 4:16:10 PM
Bartc wrote:
> In general, you can't write 3 statements as (c,d,e). Only if they happen
> to be expressions.

What do you mean?  Apart from declarators and flow control ... what
can't you put in there?

Best regards,
Rick C. Hodgin
0
Rick
12/22/2016 4:27:54 PM
On 22/12/2016 16:27, Rick C. Hodgin wrote:
> Bartc wrote:
>> In general, you can't write 3 statements as (c,d,e). Only if they happen
>> to be expressions.
>
> What do you mean?  Apart from declarators and flow control ... what
> can't you put in there?

Statements such as while, for, if, return, goto, label and switch.

Unless you're using gcc or clang and you put statements inside ({...}).

-- 
Bartc

0
BartC
12/22/2016 4:48:13 PM
On 12/19/2016 8:38 PM, DFS wrote:
> This would potentially help a lot.
>
> I had ONE extraneous closing curly bracket } in place in a function, and gcc
> -Wall threw 60+ warnings and errors.
>
> Took me several minutes to find it, and once it was removed I got a 100%
> clean compile
>
> A simple "error: mismatch in opening and closing curly brackets" would be nice.
>
>
> {
>  {
[...]
>  }
> }
>
>
> Or is this a function that should be in the editor?

Many editors have a keystroke to move the cursor to the matching brace. 
However, that only shows you the *actual* matching brace.  There is no way, 
in the general sense, to know where the extra/missing brace should go.

However, I do find the "show matching brace" feature of editors to be very 
useful in tracking down the missing/extra brace.  (Step 1 -- put the cursor 
on the open-brace of a function, press the key, and verify that it goes to 
the function's close brace.)

-- 
Kenneth Brody

0
Ken
12/22/2016 5:12:52 PM
On Thursday, December 22, 2016 at 11:48:34 AM UTC-5, Bart wrote:
> On 22/12/2016 16:27, Rick C. Hodgin wrote:
> > Bartc wrote:
> >> In general, you can't write 3 statements as (c,d,e). Only if they happen
> >> to be expressions.
> >
> > What do you mean?  Apart from declarators and flow control ... what
> > can't you put in there?
> 
> Statements such as while, for, if, return, goto, label and switch.
> 
> Unless you're using gcc or clang and you put statements inside ({...}).

({...}) looks like a three-eyed alien primate of some kind. :-)

This missing ability in C is why I defined casks in CAlive.  Here is
a utility cask, which is an arbitrary block of code execution block
that can be defined and injected anywhere.  It is surrounded by ~| on
the left, and |~ on the right:

    ~| /*any code goes here*/ |~

Those can be injected anywhere in code, and are executed wherever they
are inserted, even in the middle of otherwise syntactically correct
expressions:

    if (x == ~|printf("Hi, mom!\n");|~ z)
    {
        // Code here
    }

In this case, it would break out fundamental un-optimized operations as:

    load z
    push "Hi, mom!\n"
    call printf()
    load x
    compare [x, z]
    jump to after the block if not equal
    Whatever is in the block goes here

Other casks are:

    (|reference casks|)      // Refers to existing things
    [|definition casks|]     // Defines new things, or augments others
    <|logic casks|>          // Used where logic yields true/false results
    // And there are others

More here if interested:

    https://github.com/RickCHodgin/libsf/blob/master/books/rdc/rdc.odt

Best regards,
Rick C. Hodgin
0
Rick
12/22/2016 5:27:09 PM
asetofsymbols@gmail.com writes:
> What is the difference from
> a;b;
> and
> a,b;
>
> You say are different...
> I remember that first than 'b'
> it is executed 'a'

Bart already explained that.  In
    a;b;
a and b must be statements.  In
    a,b;
a and b must be expressions.  Any expression can be turned into
a statement by adding a semicolon, but not all statements can be
turned into expressions.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
0
Keith
12/22/2016 5:30:49 PM
On Thursday, December 22, 2016 at 11:30:35 AM UTC-6, Keith Thompson wrote:

> Bart already explained that.  In
>     a;b;
> a and b must be statements.  In
>     a,b;
> a and b must be expressions.  Any expression can be turned into
> a statement by adding a semicolon, but not all statements can be
> turned into expressions.
> 

Agreed. And the saving grace (before you say it)
is that *many* statements can be turned into
expressions by wrapping them in a function and
calling the function in the expression.

-- 
note the weasel word
0
luser
12/22/2016 5:40:53 PM
DFS <nospam@dfs.com> writes:

> This would potentially help a lot.
>
> I had ONE extraneous closing curly bracket } in place in a function,
> and gcc -Wall threw 60+ warnings and errors.
>
> Took me several minutes to find it, and once it was removed I got a
> 100% clean compile

Wasn't it the first error in the compile?

> A simple "error: mismatch in opening and closing curly brackets" would
> be nice.
>
>
> {
>  {
>   {
>    {
>     {
>      }
>     }
>    }
>   }
>  }
> }
>
>
> Or is this a function that should be in the editor?

It's already in most editors used for programming.  Emacs in C mode
certainly has it.
0
Joe
12/22/2016 7:59:27 PM
"Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:

<snip>
> This missing ability in C...

<snip>
>     if (x == ~|printf("Hi, mom!\n");|~ z)

or you could write

  if (x == (printf("Hello, mother\n"), z))

and start using it today (since it's then just C).  Maybe you intended
to give an example that can't be written in standard C.

<snip>
-- 
Ben.
0
Ben
12/22/2016 8:12:39 PM
On Thursday, December 22, 2016 at 3:12:47 PM UTC-5, Ben Bacarisse wrote:
> "Rick C. Hodgin" <rick.c.hodgin@gmail.com> writes:
> 
> <snip>
> > This missing ability in C...
> 
> <snip>
> >     if (x == ~|printf("Hi, mom!\n");|~ z)
> 
> or you could write
> 
>   if (x == (printf("Hello, mother\n"), z))
> 
> and start using it today (since it's then just C).  Maybe you intended
> to give an example that can't be written in standard C.

Yeah.  You mentioned that before.  I was unaware of it at that time.
And that does replicate similar functionality to the example I gave,
but it is woefully short of the full ability of the ~|utility|~ cask,
let alone the other ones.

Should I ever get CAlive completed, Ben, you know you never have to
use it, right?  You're completely free to not use it.  It won't affect
me either way.  In fact, if you did use it even one time ... I think
I'd probably faint (or is it feint? ... it would depend on how
adversarial we are at that point LOL).

Ben, (may I call you "Ben?") ... hi. :-)

Best regards,
Rick C. Hodgin
0
Rick
12/22/2016 8:18:13 PM
Reply: