# What my entry is It's very similar to `wc(1)` except that it also prints max line length which at least for Linux is done - but only if the `-L` option is specified (that option is not in macOS but I don't know if any other implementations do not have that option or for that matter have that option with a different meaning). There are some other differences that I'm aware of: 1. No GNU long options (I don't think this is a problem). In fact no options at all: every field is printed for every file as well as (if there is more than one file - this is just like `wc`) the total (this does not of course include the max length; the max length for the total is the width that is the longest of all the files). 2. There is no distinction between 'chars' and 'bytes' like there is in `wc`. This is in part because I either don't have a system where it differs or I'm unaware of what chars need be in a file to see a difference; all I can think of is the fact that a byte does not always equate to 8 bits. I can say that wc considers wide chars and my entry does not (I discuss this later). 3. It appears to me that `wc` aligns the width of columns dependent on the max size of each column; that is to say if there are three files two of which that have three digit word counts and the other with four digit word counts then the column for word count is aligned for 4. My entry does not do this because it makes use of the variables in a loop and does not use the values of the first file for alignment (it appears that might be how wc does it; I'm not sure: I thought it was all printed at the end but it's not the case which specifying a file then `-` then another file demonstrates). # Other differences I discuss these more thoroughly in Extra features but a quick glance at three features I have added. 1. A feature of my program is that if the first char of the basename of the entry starts with the (digit) '1' then it will compare the line count and char count with the defined (at compile time) values `L` and `C` respectively. This has to do with IOCCC entries. 2. If all lines of the file are of the same length mark it; for the total if they're all the same length for every file total then it's also marked. 3. Similarly to #2 there is something to do with primes since the judges love primes. For both #2 and #3 in the examples below you will see both `*`s and `+`s but I do not explain these in full until further on; this is because I want to focus on the values compared to wc first before explaining the additional details. # Examples (wc and my entry) The format for `wc` is always in this order: newline, word, character, byte, maximum line length. My entry is the same order but the alignment is different (as above). At the time of writing this version of the remarks the following can be said on my prog.c (i.e. if they mismatch I changed something): $ ./prog tab test file prog.c 2* 0 4 8 tab + 11* 18 68 8 test 0 0 0 0 file + 43* 230 1707 72 prog.c 56 248 1779 72 total $ wc -l -c -w -L tab test file prog.c 2 0 4 8 tab 11 18 68 8 test 0 0 0 0 file 43 230 1707 72 prog.c 56 248 1779 72 total As you can see comparing wc and my entry side by side and the values are the same. The file tab has (iirc - I've changed it at least one time in different testing) - a `'\t'`, a newline and then another `'\t'` in it; I've tested the other isspace() chars i.e. `'\n'` (obviously), `'\f'`, `'\v'` and `'\r'` and the counts with `wc` are consistent to my entry. Because of things I've seen with `'\r'` before (telnet related and DOS files as well) I did also `"\r\n"` (and also `"\n\r`" even though it's, iirc, not following the RFC for telnet some still send it) and it appears to be fine too. To show what I mean, under Linux (it seems in macOS that you don't need the `-e` flag to echo for this): $ echo -e "\f\v\n\t\r\n\n\n\r" > spaces $ ./prog spaces 5* 0 10 8 spaces $ wc -l -w -c -L spaces 5 0 10 8 spaces But what about the other invocation? It looks like this: $ ln -s prog 1 $ ./1 tab test file prog.c 2* 0 4 8 tab + (no) 11* 18 68 8 test (no) 0 0 0 0 file + (yes) 43* 230 1707 72 prog.c (no) 56 248 1779 72 total In other words the files 'tab', 'test' and 'prog.c', having (no), would not fit in the current definition of the judges' vague opinion on what a one liner is. On the other hand the file 'file' would be. Not that it's actually C code (unless you count the brilliant smallest self replicating program, I suppose ...) would be considered one line (except that that program maybe didn't even have a line at all: but the test isn't `==` but `>`). The point is the same either way. # My inspiration for this program There haven't been any winning entries that do what amounts to `wc` (or close to?) and because during this contest I learnt that macOS does not have the `-L` option to `wc` (this is useful to help verify if all lines are specific width for e.g. the IOCCC - although admittedly empty lines will be counted but that's because `wc` also counts empty lines) after some time considering things that might be interesting I thought maybe this could be done. Whether it's interesting enough to win is another matter entirely but it was interesting to see how `wc` considers different chars (including C escape chars) etc. At first I tried matching the output by observation but running into some issues I checked (as I discuss below) the wonderful book 'The C Programming Language'. But then after that trying to get the binary counts to match (which I did at least make one consistent as noted) I looked at the wc source itself. Why would I have wanted `wc -L`? To make sure that the max length is a specific number of course (see also Extra features for this)! # Compiling The following CFLAGS are used: -Wall -Wextra -Weverything -Wno-missing-variable-declarations -Wno-comma -Wno-unreachable-code -DL=1 -DC=120 These warnings are frivolous (except maybe the unreachable code one but this is very intentional too which I discuss a bit in the Obfuscation section) and as for the possible 'abuse' of the comma operator it's quite intended as it compacts things a bit and makes it harder (though certainly not hard) to follow. But there's actually a very valid use of the comma operator even beside; it's an important one that not only allows me to not use an `if` but at the same time prevents a segfault. This is how it went: if the file is stdin we obviously cannot close the file; this was already prevented by doing: (f!=stdin&&fclose(f)); However what to do about it when the next 'pass' in the 'loop' would read from `f`? Well in this version of the program (as you will notice there's another submission of the same program but with the difference of two features not being there) I in tiredness yesterday set `f=0;` right after making sure it was valid. Well that's of course stupid but be that as it may I had that anyway. I fixed the above part and then found it curious that it still segfaulted. Then I noticed the `f=0;` before the `getc()` call. Removed that and all was good. What is the other fix? After the other fix of course. Because there was also a `f=0;` after closing the file: stdin or otherwise! This was obviously a problem and by a happy chance I tried this when testing this version. So the question is how do I not have to have an if but also make sure to only set f to NULL if it is not stdin? If I were to do: (f!=stdin&&fclose(f)&&f=0); It would result in a compiler error along the lines of it's not an assignable location. What can be done? Well the comma operator to the rescue! It became instead: (f!=stdin&&fclose(f),f=0); Now f is only set to NULL if f != stdin! This is because the boolean AND will not continue if f == stdin which means the expression `,f=0` will not be reached because it's - I'm going to call it - 'dependent' on the AND operation and since it's short-circuited the problem is solved. Recompile and test and all is good! The warning about the unused values is also frivolous (and I discuss this in Obfuscation also). I've compiled it with Clang and gcc. `gcc` with -Wall has a stupid warning about misleading indentation but I would think that for this contest that would be bonus points since entries should be misleading! :) In either case there is no way to disable it because the devs are - well I won't get into that. I think some of the warnings only exist in Clang and so the `-Wno-` flags aren't there for gcc but gcc conveniently only warns about it rather than errors out. # Portability I have tested it under C99 and C11 as well as C90. But for the latter I get the warnings (if the lines differ then I changed something; I have two layouts also as I note somewhere here): prog.c:13:57: warning: initializer for aggregate is not a compile-time constant [-Wc99-extensions] main(int n, char **v) { int i; uintmax_t l[2]={0},m[2]={*l},x=*m,c[ ^~ prog.c:14:5: warning: initializer for aggregate is not a compile-time constant [-Wc99-extensions] 2]={*m},w[2]={*c},V=*w,t=*l,P=*m,d[2]={*w},y=x; FILE *f=0; char *W= ^~ prog.c:14:15: warning: initializer for aggregate is not a compile-time constant [-Wc99-extensions] 2]={*m},w[2]={*c},V=*w,t=*l,P=*m,d[2]={*w},y=x; FILE *f=0; char *W= ^~ prog.c:14:40: warning: initializer for aggregate is not a compile-time constant [-Wc99-extensions] 2]={*m},w[2]={*c},V=*w,t=*l,P=*m,d[2]={*w},y=x; FILE *f=0; char *W= ^~ 4 warnings generated. It still seems to work though but as an extension. I therefore am only saying it works under C99 and C11 even though it appears to be fine for C90. # Differing counts from wc Out of curiosity I tried running wc and my program on the program itself (i.e. the executable) and wc reported a different word count and line length count too (at this time). I suspect that this has to do with a technicality of what constitutes these things or possibly the way the files are read in wc versus my entry. I don't know that binary files are actually one that most people would try running wc on though so although it does bother me I don't think it's bother enough to not consider submitting. Of course if I knew the reasoning that would be better but I feel it's best I point it out. I can say the following things I have done to try and figure it out - and what I have figured out and resolved (so it seems). First is that I tested it on a log file with at least some ANSI escape sequences; the counts were consistent between my entry and wc. Second is that I took an ELF binary and (in vim without option -b) deleted the second and subsequent lines: the output still differed. On the other hand removing part of line one all the way through the end of the file and the counts were the same. Still not sure what it sees differently I tried chars with a circumflex and an umlaut and I still got the same results (equal to wc)! What could I do to try and make it more correct? I could look at the wc.c file and so I finally did. Looking first at the line length I noticed a few things. Whereas I had only newlines test if the current max line width was shorter than the current line wc.c says also `'\f'` and `'\r'`. I added this and now the max line length matches! I was getting somewhere now. I also noticed (and I pondered this beforehand) that the counts were of type `uintmax_t` - so I updated the counts to that type. Now I decided to look further at word counts. This proved to be a problem for binary files (maybe others but only of the binary files did I notice the problem). My only guess is it has to do with wide chars or some such but to the best of my knowledge this entry does work fine for regular text files. But then using a word counter on a file that has a lot of escape chars is rather silly and even *The C Programming Language* implementation of wc does not account for this! If it's good for K&R I think it's good enough for all other purposes! :) After all without K&R would we even have our wonderful C? :) Well maybe we could throw in Ken Thompson &c but still the fact remains that if The C Programming Language wc matches my entry (on text files) and is actually less accurate (for certain definitions of 'accurate') than my entry then it should say that my entry is not only functional but the standard wc of today is not! :)) Besides that the K&R version doesn't consider line widths and *also gets word count wrong on binary files; my entry **does** get line width right on binary files (that I tested ...though again what is 'right' here?) and only differs on word count in binary files (i.e. doesn't match wc)!* Or to put this into perspective, maybe, my entry does not support wide chars (or rather does not use `wchar_t` or whatever it was). In other comparisons: the K&R wc requires to do something like: cat file | ./cpl-wc cat | ./cpl-wc ./cpl-wc < file ./cpl-wc [...] The standard wc can do those as well as e.g.: wc file file1 fileN The standard wc invocation above prints out the file names; if you were to specify also '-' it shows that: the K&R wc does not ever print the file name. My entry can do all of the above and that includes the printing of the file names ('-' if specified otherwise the file names specified aside else nothing just like the K&R wc and the standard wc when no files are specified directly). So as you can see there are a number of additional ways my entry is superior to even K&R wc! If *that's* not portable, complete and worthy of an award I don't know what is! :) You might even say it's more than complete but that would introduce possible paradoxes and other philosophical discussions so I won't go there even though I enjoy such things. # Bugs * This isn't a bug but rather an error check I do that differs from wc: because actually it's not an error at all; on the other hand wc reports it as an error (or maybe warning?) but then happily prints the counts regardless. That is that `fopen()` will happily open a directory under certain conditions and those conditions are met in my entry (I don't request write access for example) - not that it amounts to anything as such but it's still technically not an error. Iirc wc.c does an fstat()/stat() and as a simpler implementation I do not. As I noted this is an improved version of the K&R wc but still not the same as the standard wc in all cases. But even so I think that - at least for the binary files - it is debatable what is correct as far as what a word constitutes; and as the book says it's a loose definition of 'word'! The dictionary would hardly consider these things words so why should I worry about it?! :) But back to the point: `fopen()` has no problem opening a directory in certain conditions that my entry meets so there is no error to report as far as I am concerned: what, print an error for something that's not an error? :) That's just stupid. Whatever the case it differs from standard wc in: $ ./prog < . 0 0 0 0 + $ wc < . wc: 'standard input': Is a directory 0 0 0 Furthermore if you specify other files including stdin in addition you see (the file 'f' has no read access): $ ./prog - . test f test 1 1 5* 4 - + 0 0 0 0 . + 11* 18 68 8 test prog: f: Permission denied 12 19* 73* 8 total $ wc -w -l -c -L - . test f test 1 1 5 4 - wc: .: Is a directory 0 0 0 0 . 11 18 68 8 test wc: f: Permission denied 12 19 73 8 total So the difference here is that if it's a directory wc prints an error but still prints the count; my entry does not print it as an error *because it is NOT an error!* - but it also prints the count. Why would it print the count if it's not to be read? And as you see when there is a real error it does not print anything e.g. with the file `f` as above and also (by itself): $ ./prog f prog: f: Permission denied $ wc f wc: f: Permission denied (It should be obvious but just in case I do indeed use `basename()` on the `0[argv]` hence not having the path but just the name of the program.) In the end I wrote the following script to find any differences and I was happy to find no output ('no news is good news'!): #!/bin/bash mkdir -p logs function show() { echo "\$ ${*}" } show "./prog tab test file prog.c xy xy test temp < prog.c" ./prog tab test file prog.c xy xy test temp < prog.c |sed -e 's/\+//g' -e 's/\*//g' |tr -s '[[:space:]]'|sed -e 's/\s$//g' > logs/prog.log show "wc -l -w -c -L tab test file prog.c xy xy test temp < prog.c" wc -l -w -c -L tab test file prog.c xy xy test temp < prog.c |sed -e 's/\+//g' -e 's/\*//g'|tr -s '[[:space:]]'|sed -e 's/\s$//g' > logs/wc.log diff -c5 logs/prog.log logs/wc.log show "./prog-c tab test file prog.c xy xy test temp < prog.c" ./prog-c tab test file prog.c xy xy test temp < prog.c |sed -e 's/\+//g' -e 's/\*//g' |tr -s '[[:space:]]'|sed -e 's/\s$//g' > logs/prog-c.log diff -c5 logs/prog-c.log logs/wc.log Running it only shows the prompts and invocation of each command: $ ./tests.sh $ ./prog tab test file prog.c $ wc -l -w -c -L tab test file prog.c # Lints Clang scan-check does report the fact that the value of a variable (V?) initialisation is never read (oddly in the other version I submitted another variable is reported this way but from looking at it it seems to be the same and I've not found any functional difference except again for what I have explained in Extra features). But it's a habit of mine to initialise variables as declaration and I do not consider these bugs despite the fact scan-check does. It's a good habit to get into and it's even better when you're going out of your way to make it harder to follow! As it is I accidentally trimmed a `|` off a `||` when formatting it the way it is and so it's very easy to break things: best to be safe with initialisation! Except for pointers of course... Well perhaps those too :) `splint` is far too verbose and warns over the most ridiculous things; the more I use it the more I view it with contempt. Here's a fun example! This is its idea of a possible NULL pointer dereference: > Null storage W passed as non-null param: printf (..., W ? W : > *v, ...) Why would I want a `%s` parameter to be anything but NULL? As for `*v` it's also not NULL but there's a reason I check W and a very good reason: it's initialised to NULL (as it should be as a pointer) and only if `argc < 2` is it set to non-NULL namely an empty string. Ah, it must be because it's not allocated? I don't know but in any case this is safe as I have no need to allocate anything as I don't write to the string: it's either NULL or empty. I believe I could, looking at it as I'm writing this, actually just have an int set to 0 and then if it's 1 print an empty string as in `""` but it works and so I'm not changing it lest I mess something up (it could happen even if it's not likely!). All the other things it suggests are nonsense or otherwise nothing that needs to be paid attention to. It doesn't even know the `%zu` format specifier. # Extra features * I noted that if the program name starts with '1' there is an additional output. The constants (passed to the compiler) L and C are currently `-DL=1` and `-DC=120`. Why? These are the current values for one liners in the IOCCC. Technically it's not even needed to have the defines but the idea was that it could be changed for whatever purpose you wanted to compare the number of lines and the columns. The 1 is obvious for one liners but what about the 120? > One line programs should be short one line programs: say around 80 to 120 > octets long. Going well beyond 140 octets is a bit too long to be called > a one-liner in our vague opinion. The inspiration for this is that I had at first thought of making this a one liner itself but I wanted to do more with my entry - and I am not sure at this time a one-liner would be something I'd be good at obfuscating. But since I was thinking of a one liner and also wc (which also counts lines and chars) I thought of this idea. See Examples section for this invocation. * Is it actually the case that if the totals match with wc that the output will be the same (after squeezing the spaces)? Actually no. If you notice the filtering in my test script above it's more than just squeezing the spaces. Why is that? I took the algorithm of determining a prime to do something special. Disclaimer: I am not making any claim at all on the algorithm; I simply saw the algorithm in Python, converted it to C which amounted to changing data types, simplifying some things (some possibly because of features not in Python but I do not know) and ultimately did what I call C-ifying code though usually this is C++ to C (because I find C++ extremely ugly to say the least and saying the least is saying too much for my liking but it's actually not enough). Why am I not making any claim at all on the algorithm? Because the judges make it very clear that they don't like any statements about primes that are incorrect so ask yourself this: if I make no claims at all can they say I made a false claim? :) So by saying nothing other than the function is an algorithm that's not mine - and is from Python so didn't exist as C (that I am aware of at least?) - the judges cannot possibly say that I'm wrong about primes: because I said nothing about them! But what is this special thing to do with primes? Well if the algorithm I took is correct then the counts that are prime will have a `*` to the right of it. This is special because the judges love primes so it says to them: 'Look at this! The count(s) in this file are actually primes!' This applies to each file and - if there's more than one file - then it's also printed in such a way. The inspiration for this is the IOCCC entries, of course! Can I say that the counts are prime (according to the algorithm that I'm still not going to state anything about its accuracy!)? * There is another special thing here though. The wc `-L` option (that's not enabled by default) shows the maximum line length of the file. But what if you want to know if every line is of the same length? For instance what if you are trying to get your source code (for the IOCCC of course! :)) to all be the same width for every line (that was the inspiration for it actually)? For instance you also want every line to be of prime width. If every line in the file is the same width then a `+` is added to the file name (actually separated by a space then a `+`). And how do you define this for the total? If every line in every file together is of the same length then it is also for the total. What this means is you could see output like this: $ ./prog xy xy - 1 0 2* 1 xy + 1 0 2* 1 xy + ' 1 1 2* 1 - + 3* 1 6 1 total + $ wc -w -l -c -L xy xy - 1 0 2 1 xy 1 0 2 1 xy ' 1 1 2 1 - 3 1 6 1 total From that you can see that the file `xy` has 1 line, 0 words, 2 chars and the column length is 1. At the same time what I typed in for stdin is also 1 line, 0 words, 2 chars (the newline is counted) and 1 column (the newline is not counted here) which is why for my entry there is a `+` on every column including total and also there are the `*`s! Now if you are to specify something different it might look like this instead: $ ./prog xy xx temp 1 0 2* 1 xy + 2* 0 2* 0 xx + 2* 0 2* 0 temp + 5* 0 6 1 total $ wc -l -w -c -L xy xx temp 1 0 2 1 xy 2 0 2 0 xx 2 0 2 0 temp 5 0 6 1 total In the above example you can see that my entry and wc match as far as counts but you can see from my entry that the files aren't all of the same length lines. $ ./prog xy xx test 1 0 2* 1 xy + 2* 0 2* 0 xx + 11* 18 68 8 test 14 18 72 8 total $ wc -l -w -c -L xy xx test 1 0 2 1 xy 2 0 2 0 xx 11 18 68 8 test 14 18 72 8 total And above you can get the same idea. But something that should be noted on the total row: whereas the lines, words and chars are tallied the maximum width is not: because it's a maximum of all. # Obfuscation A few things to note at the very least: 1. There are some statements that are used instead of an `if` e.g.: `(n>1&&printf("%5zu %5zu %5zu %5zu total\n", l[1],w[1],c[1],1[m]));` Note also that `n` is `argc` which is immediately set to 0 and only if there is more than one file is that line called (since it's essentially an `if (n > 1)`). Of course the fact `argv` is incremented is of no matter as far as knowing whether or not to print a file name (as in was one specified - which the invocations that match the K&R wc do not [print out a file name]) and what the file name is. 2. Abuse of the fact that index[array] is the same thing as array[index]. 3. Combine the comma operator with the above technique. This includes swapping the order of element access e.g. you see `1[l]+=l[0]` (and the next line starts out in the opposite order) and after each is a comma and resetting to 0 (except that the last one, for `m`, updates only if the current max line length is less than the line length of the file that was just processed). In that block of code there is also technique #1 right above it: to close the file (if and only if it's not stdin). 4. Ternary operator instead of `if` but with nonsense added to it e.g.: `x+=i=='\t'&&1-1==0?(8-x%8):0;`. Looking at the code at a quick glance (and some fonts probably make it more problematic) it's possible you can read the '0' as '8'. But then of course the `&&1-1==0` is just a distraction more than anything else. There are other places where the ternary operator is used but without nonsense added. There also is at least one place where there is a nested ternary operator. This is something I've read is really frustrating and 'bad practise' in the minds of many (I think they just need improve their ability to read C but that's me) and that's sort of what the contest is about so it should be encouraged! :) Well I have done it for this reason. Of course since it's a 'constant' assignment (as in it always needs to be 0) part of it will never be reached hence disabling the `-Wunreachable-code` warning. 5. It's mostly not all that modular. I had the thought of moving the prime function into main() itself but I had some thoughts that made me think to keep it where it is. Besides that by doing this it helps my point about not saying anything one way or another about the prime testing! :) 6. The array elements are accessed differently: specifically element 0 e.g. `0[array]`, `array[0]` and `*array`. 7. The atrocious use of `goto`s. This is partly to 'simplify' things but I'm not sure that I would say it really 'simplifies' things; I would certainly never use it in a program that's meant to be stylish. Unless perhaps I was using Stroustrup style; the idea of '`char* p;` makes me want to vomit it's just so ugly. And the same thing with the suggestion of having one variable declaration per line. But I would never do those - not even in the IOCCC; I would be ashamed of it actually. On the other hand doing `char*p;` in IOCCC is sometimes necessary or useful e.g. to get line length a certain length. And yes there most certainly is a difference between `char*p;` and `char* p;` and I do not refer to the added space (though that does remind me of something funny which I'll cite later)! Either way the first goto jumps into what was originally part of a loop (nothing but variable assignments etc. before it) and then at the end - whether or not that first goto was called - jumps back to the while loop itself which only `goto`s the place the first `goto` went to?! And then just under it there is another `goto` too. Where to? Why to `whilE`' of course! Where else is there to go to? :) And that brings me to the next point. 8. Since I (unfortunately? :)) cannot reuse the keywords I had to resolve to use similar looking keywords. But I had some fun with these. The label I just referred to is called `dO` and the first thing there is a `do ... while` loop. So it amounts to: `dO:do`. And just above that there are the three lines: Do:while (f||*++v) goto dO; goto whilE; Then inside the dO:do it does the opening and counting of the file(s). And no. It's not a reference to the dodo bird nor is it a reference to something else that some other people might think of. I'm not saying it couldn't be interpreted it that way - anything can be twisted into anything one wants even with very little creativity - but then if it distracts anyone so much the better. It was used solely because it's lexicographically similar to 'Do' (which is above) and also 'do' which is right after it. Similarly the whilE was chosen since it's lexicographically close to 'while'. Anyway at the very end of the loop there is `goto Do;` which goes back to a while() loop that only has `goto dO` (which is technically an infinite do while loop except that it's left at the end and only re-entered if the first while loop is entered. Otherwise it goes to ... whilE! This then means the loop ends like so: goto Do; } while (1); whilE:(n>1&&printf("%5zu%s %5zu%s %5zu%s %5zu%s total%2s\n", l[1],p(l[1])?"*":" ",w[1],p(1[w])?"*":" ",c[1],p(1[c])?"*":" ",1[m],p(m[1])?"*":" ",1[d]?" ":"+")); And syntax highlighting could also make it seem like a loop (colouring dependent of course) and all the more if you miss the ':' after the 'whilE'. So what does this all mean? Well basically the do while loop isn't even a loop; instead it's the while loop above that does only a `goto dO:do ... while`! Well it's a loop but it's never actually continued in iteration; it's just entered from the top while another loop is entered! 9. If you ask at least Clang there is misuse (or was it 'abuse' ?) of the comma operator. I don't know that I would call this confusing but there must be some reason along those lines that compilers warn about that kind of nonsense. 10. On the subject of using boolean expressions instead of `if` there is the case where you can get the error that it's not an assignable location. The simple solution is - it had to do with `++` - is to simply make it an assignment e.g. `(i=='\n'&&(*l=*l+1));`. 11. How to get the less confusing `++*w; t = 1;` to a more simple expression? More abuse of the comma operator of course! The earlier 'abuse' did not use the left hand side of the comma as part of the right hand side directly. Here however it does. If I need to increment `*w` and I also need to set `t` to 1 then why not make use of the fact `t` is now 1 i.e. make it `t=1, *w+=t;`. But then if I'm going to do that why not instead make use of a variable that's set to 0 and never modified (used in one of the ternary operator examples above) to do this instead? Thus it becomes instead `t=1, *w+=P+1;`. But then why bother with using `+1` when I can just invert the 0? Thus it becomes `t=1, *w+=!P;`. But then why do `t=1` when `t` is `t == 0`? Why not instead set it to `!t`? Because using XOR is more confusing (even if not confusing). Thus it now became `t^=1`. But then why not do `t^=!t`? But now I can use `t` for the increment of `*w` in the same expression: so it became `t^=!t, *w+=t;`. I feel that's more confusing than the others: it uses XOR on `t` to set `t` to 1 (more correctly it's `t^=!t` and we know that at this part `t == 0` which means `t ^= 1` which is 1!) and then uses `t` as the increment value for `*w`. But then why not extend this to other assignments to 0? So I did that too. Thus `x=0;` becomes `x=P^0;` and so on. 12. Continuing the theme of assigning 0 to variables why bother using 0 literally after having another variable as 0? For instance why not change the `={0}` for `uintmax_t[2]`s to be more like: `uintmax_t l[2]={0},m[2]={*l},x=*m,c[2]={*m},w[2]={*c},V=*w,t=*l,P=*m;`. That is certainly better than just using `{0}`s for them all. And from there I could also do `*l*=P;` and then do `*c*=*l;*w*=*c;` (and that's not the only case I do this type of thing) which is harder to read (as in the characters are easier to miss and you might have to go back up to look at what `P` is - not to mention that you're doing a compact `*=` to a dereferenced `uintmax_t[2]` and the rhs is also the first element of another `uintmax_t [2]` by way of dereferencing it i.e. it's a `*` followed by `=` and then `*` again). BTW: GNU indent assumes that the `*=` in the way it is used as the old style operator as in `=*` etc. (see the wondrous [C history document][] by Dennis Ritchie himself for an explanation of this). It must be said that `indent` still does not mess up the code but it finds it dubious I guess you might say. 13. Minor maybe but in some cases the `:` for labels are on a different line; maybe even I mentioned this - I don't recall as I made a number of revisions and that was something I changed a number of times back and forth. Either way it isn't anything much except that it can look out of place at times (it might also be this way for the ternary operator; I'm not sure if that did happen). # Layout of the source code Because the judges love primes and because I took an algorithm that is said to (but not by me!) determine if a number is prime and because I mark those numbers and finally because I've seen the letter P refer to prime in some contexts e.g. [Euclid's theorem][] I have tried to make the layout as close to a P as possible. But with a bit more to it all. First as for the `#include`s there isn't much I can do there at least as far as having more than one on one line. But the layout consists of many primes (for these I used the BSD 'utility' `primes(6)` as well as checking Google so when I say 'it's prime' I'm saying that others say 'it's prime'). If you note that counting the comment line there is a block of 7 lines. These lines start at column 43 and end at 67. These are prime. Then there are 2 blank lines; 2 is also prime. Then there is a block of 7 lines; these form the top loop of the P. These lines end on column 67. The next block is 7 lines and this forms the hole in the P. However if you observe the column before the first space is 17; another prime! The next non-space char is at column 47. Yet another prime. These lines end on column 67 and as already said it's prime. Next there is another block of 7 lines forming the bottom part of the loop in the P: and these also have the same prime columns as the top part (above the hole)! But there are more to observe! The vertical part of the P is 13 lines: another prime. And the ending column is the same as earlier: 17. Prime. But how many lines is the source file? 43. A prime! And if that's not enough the iocccsize is also a prime: $ ./iocccsize -i < prog.c 1163 This is all intentional; it took some work but well worth it! But this was not enough for me - not after working on the layout of the other version (the one with fewer features). In that one I had a nicely formed C with prime too and I liked it so much that I decided to make the same program formatted as a C, also, and also prime. I believe I have succeeded here too (and my test script was extended to compare the output of the logs for this version to the other and it appears fine too so I believe I didn't mess anything up doing this in that way either but it's just an additional layout for more creativity). Observe the following about the file prog-c.c: * There are six `#include`s and a comment above it forming 7 lines. The `#include` (before the file part) ends at column 17 and the `/*` part 'ends' at column 17 also. For the comment there is text in between but the `*` in the `*/` is at column 47. So is the `<` for the file names in the `#include`s. Why? It just seemed rather aesthetically pleasing to my eyes to have the end and beginning of the first and second part 'match' or 'align' with the hole of the P. Note also that the part of the first letter of the comment `IOCCC 26` starts at column 29 which is the last non-space char in the vertical part of the C and also of course prime. * Following this there are 2 blank lines. * The next segment, the top of the C, consists of 11 lines; the first column is 7 and the final column is 61. * The next segment is 11 lines starting and ending at columns 7 and 29. * Following that the next segment is like the top of the C only the bottom instead: 11 lines starting at column 7 and ending at column 61. * The next line is a comment with a call to `exit()` with a made up constant `EXIT_PRIME_TIME_PRIME_LINE`. This is line 43 - the same number of lines the prog.c (my entry) has. * And the iocccsize is 1181. The fact the judges love primes and the fact the entry marks amongst other things primes inspired me to show how many ways IOCCC entries can refer to primes (and I'm sure other ways too). Not just show but show at prime time too. # Humour Larry Wall... What's to like? He created Perl! Well I'm not going to say anything about Perl but he is extraordinarily funny for sure. I have to tip my hat to him even as someone who can make almost anyone laugh under almost every circumstance imaginable from horrible to wonderful. I noted earlier that I did not refer to the space being the difference when visibly *that was the only difference* - and then I remembered this funny (to me) and very clever quote of Larry Wall: > And don't tell me there isn't one bit of difference between null and space, > because that's exactly how much difference there is. :-) > [Usenet article][] <10209@jpl-devvax.JPL.NASA.GOV> (1990) [Usenet article]: http://groups.google.com/groups?selm=10209@jpl-devvax.JPL.NASA.GOV&hl=en And while I'm on the subject of Usenet you might find this thread about '42' very interesting at the least; it has some interesting C things too: [Why 42 ?][]. Yes he was on Usenet for a time if you did not know! [Why 42 ?]: https://groups.google.com/forum/#!topic/alt.fan.douglas-adams/595nPukE-Jo [C history document]: https://www.bell-labs.com/usr/dmr/www/chist.html [Euclid's theorem]: https://en.wikipedia.org/wiki/Euclid%27s_theorem