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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 <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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 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 |
![]() |
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 |
![]() |
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 |
![]() |
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 <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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 <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 |
![]() |
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 |
![]() |
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 |
![]() |
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 <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 |
![]() |
>>> 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 |
![]() |
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 |
![]() |
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 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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
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 |
![]() |
"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 |
![]() |
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 |
![]() |