Files

683 lines
29 KiB
C

/*
* although not strictly deobfuscated it is commented to try and explain it more
*
* Please note that I have tried to keep this consistent with the 'final
* product' but I had to make fixes and so some of this might be out of date.
* Still I am trying to redo it all; but some comments might not be strictly
* correct. In which case I hope you can then fully appreciate just how twisted
* this code is (and you probably will anyway)!
*
* Also it is true that some of the variables in the code (which are in the
* submission itself, I believe but perhaps not) are not used. This was a
* mistake but it's not worth the effort to try and find them all, especially as
* it can also cause confusion to people. Trying to parse the code once let
* alone several times (which I did) was not something I wanted to repeat again.
*
* And on that note: there indeed might be things wrongly stated. I tried but
* failed to completely understand what I wrote years back. I have no idea how I
* managed some of this and I don't know what I did in every case so any
* incorrect statements are simply a sign of the obfuscation - a good thing!
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#ifndef DICT
#define DICT "dict"
#endif
/*
* English -> Navajo.
*
* I am sorry but I can't even begin to fathom TRYING to do this again for the
* alt code (X=1), especially as a lot of it is the same but with some subtle
* differences.
*/
#define X 0
/*
* the struct a is the holder of state but the state is, as will be seen soon,
* mostly anonymous. Even the function pointers array has a different order per
* function call! The only time (I think) that there is some form of consistency
* is the *k and *c of the struct a which is the linked list of words for either
* deciphering (alt version with -DX=1) or enciphering (with -DX=0)
*/
struct a {
/*
* some of these are consistent if they're only used in a single function. I
* believe this applies in particular to:
*
* a - for Z(), which parses main() args and acts on them - it is that
* part of main()'s body instead of in main(), this so I could make it
* harder to follow with anonymous and inconsistent ordering and
* variables.
* N - first field in dictionary file.
* S - second field in dictionary file.
* A - temporary buffer when reading in dictionary file (which S and N use).
*
* Like I said the order of v changes depending on the function.
*
* However as for S and N it's not so simple because these char *'s are not
* directly strdup()d! Instead the function that does this, called by F()
* but not by those names (I will explain this later) set the 's' (below) in
* an anonymous structure to either S or N in the call. The function being
* called in all cases (even though it does not look like it) is the same in
* every case even though it doesn't look like it; that function is w().
*/
char *w, *c, *s, *x, *t, *u, **h, *S, *N, *A,*(*v[9])(struct a *), *y;
struct a *e, *a, *z, *k, *j;
int l;
} *f, *c;
/* ^ the linked list pointers - f is the list and c each node as the list is
* created. The ->e is the next node which is why this is consistent, at least
* in f.
*/
/*
* this is the alphabet of the language and it's translated for exact matches in
* the alt version especially (it might be used in the encipher - regular -
* version but I'm no longer sure of this).
*
* As can be seen the first element, element 0, is the letter, and the second
* element, element 1, is the translation. The word for C for instance is MOASI
* and it translates to 'cat'. When prog.alt encounters this it will report
* 'cat'. If however prog encounters it it will translate the letters as it's
* not in the dictionary. As well if prog.alt encounters something not in the
* dictionary, say IOCCC, it will spell out the letters.
*
* If one does something like:
*
* ./prog.alt $(./prog ioccc)
*
* then it should print out 'ioccc' (w/o quotes of course).
*/
char *B[][2] = {
{ "A", "WOL-LA-CHEE" } , { "B", "SHUSH" } , { "C", "MOASI" } , { "D", "CHINDI" } ,
{ "E", "DZEH" } , { "F", "CHUO" } , { "G", "JEHA" } , { "H", "TSE-GAH" } ,
{ "I", "YEH-HES" } , { "J", "AH-YA-TSINNE" } , { "K", "BA-AH-NE-DI-TININ" } , { "L", "NASH-DOIE-TSO" } ,
{ "M", "BE-TAS-TNI" } , { "N", "TSAH" } , { "O", "A-KHA" } , { "P", "CLA-GI-AIH" } ,
{ "Q", "CA-YEILTH" } , { "R", "DAH-NES-TSA" } , { "S", "KLESH" } , { "T", "D-AH" } ,
{ "U", "NO-DA-IH" } , { "V", "A-KEH-DI-GLINI" } , { "W", "GLOE-IH" } ,
{ "X", "AL-NA-AS-DZOH" } , { "Y", "TSAH-AS-ZIH" } , { "Z", "BESH-DO-TLIZ" } ,
} , *Y(struct a *) ;
int z, J, C, k, H, D, s, L; size_t n, o; FILE *g;
/*
* these variables would not fit in the structs as they are needed in multiple
* functions. Besides the next node of the linked list we can use the other
* members of the struct anonymously and differently depending on the function
* (to make it extremely hard to keep track of what is what).
*
* Now it would be possible to have these in as different variables but that
* would go well beyond the size limit of rule 2!
*
* I will tell what these are as we encounter them.
*/
char *I(struct a *a)
{
/*
* okay this is truly dreadful.
*
* What z is set to is actually 0. That's it.
*
* Remember that a->z is actually a->j which is f. Well okay you can't know
* that yet but you will.
*/
for (a->a = a->z, z = 0**"1"; a->a; a->a = a->a->e)
{
/*
* the function called (a->v[2] (and remember a is anonymous in this
* function, created by the calling function at time of calling it) is
* Y(). Y() also takes a struct a * but we create it as we call the
* function itself, just like what happened when we were called. We set
* .w to a->a->w (a->a is the current node in the linked list) and .c to
* a->x. But what are these?
*
* Well a->w is assigned (will talk about this later) the first field OR
* second field of the dictionary depending on if we are deciphering or
* enciphering. Of course this file is enciphering but that only adds to
* confusion! As I see it right now, if deciphering (X==1) (which again
* does not happen here) then it is the second field (S in that struct);
* else it is the first field (N in that struct).
*
* And what was 'x'? I am sorry but I can't figure that out but I can
* say that Y() checks if two strings are equal but ignoring !isalpha().
* What this implies is it is either the first or second string as Y()
* acts on exact matches of letters as noted earlier.
*
* Okay doing an fprintf() suggests that it is the input. For instance
* if I were to do ./prog.alt shush the a->x is shush itself.
*/
if (a->v[2](&(struct a){ .w=a->a->w, .c=a->x} ))
{
/*
* just to make sure we print out the stuff before in case there is
* a non-alpha character (or characters)
*/
while (!isalpha(*a->x) && *(a->x)) { L=putchar(*a->x); ++a->x; }
/*
* okay this is also really nasty. Remember that z starts out at 0
* and a->c is (I think!) the first field if X==1 (which is false)
* and the second field if X==0 (enciphering mode, true). Well okay
* so this part is not the nasty part; it's the body of the loop.
*/
while ((z++)[a->a->c])
/*
* this is truly awful. First of all remember that z starts out
* at 0 here and we want to set 's' to something terrible. But
* what in the world is '-*"1"-*"1"- -97? It is -1. But why do I
* want s to be -1? Well I don't. Remember that I'm adding it to
* s which starts out at 0. Thus the first pass this will be
* indeed -1, second pass 0 etc. But why start out at -1 when it
* seems like we're indexing into a->c (a char *)? This is
* extremely nasty too.
*
* Let us break this down a bit more. If s is -1 the !s (will
* end up being?) false. That means the !isupper(a->x[0**"z"])
* will not be called the first time (or perhaps it will, I
* don't know now). Okay but we have to back up a bit. What is
* 0**"z"? That is 0, as you'd expect. So what is a->x[1]? This
* is also very ugly. I believe (but I am no longer sure!) that
* the calling code is:
*
* (((*a->h[--a->l]=='e'-':')&&(*a->v)(&(struct a){ .v[0]=I,
* .s=((a->l)[a->h])+1} ) &&++a->l)||(a->v[1](&(struct a){
* .v[2]=Y,.x=((a->l)[a->h])} ),++a->l)); if (g) puts(""); }
*
* Okay actually I'm sorry. I have absolutely no idea what this
* is. But the numbers at least can be explained. Also we can
* break the code down more though, just not determine all the
* values. If !s and isupper(a->x[1]) we will index a->a->c[s].
* But when it's not we will call tolower(a->a->c[s]). Now you
* might ask how in the world a->a->c[s] is legal on the first
* pass. I'm sorry but once again I have no clue I just know it
* does not evaluate to invalid indexing. Even more baffling is
* if the index starts out at 0 (i.e. - -98 instead of - - 97),
* the code does not work! Of course it might not be baffling at
* all but seems that way after trying to parse this nasty nasty
* code.
*/
s=z+-*"1"-*"1"- -97,L=putchar(!s&&isupper(a->x[0**"z"])?a->a->c[s]:tolower(a->a->c[s]));
goto n;
}
}
/*
* if we get here it means that the word is not in the dictionary. And of
* course this is also extremely nasty, the expressions. The 2/ *"z"
* evaluates to 0 and the 1+0**"1" evaluates to 1.
*
* Okay and the number[pointer] indexing is used. As noted above I believe
* K->x is the actual input. I'll try and parse the loop but no guarantees I
* get everything! Much of this was written years ago.
*/
for (z = 2/ *"z", s=1+0**"1"; z[a->x]; ++z)
{
/*
* okay the first part is simple enough. For each !isalpha() char in
* a->x we simply print the char via putchar(). Again I'm unclear what
* a->x is however.
*/
if (!isalpha(z[a->x]))
L=putchar(z[a->x]);
else
{
/*
* so C is if the current char of the current input is lower case. I
* am not sure if we actually need to save this or not but it's
* quite possible we do. It might just be to save bytes (or it might
* not save bytes).
*/
C = islower(z[a->x]);
/*
* This is even nastier than before I guess.
*
* The first one is easy: J is set to 0 and while J < 26 and ...
* hold on, what are we checking against now?
*
* Well remember that B is the letter <-> Navajo word for that
* letter array. So B[J][0] would be the letter itself and B[J][1]
* will be the word itself. But now we have the other horrible
* expressions! Remember that if X (it's always 0 in this file) is
* non-zero it's deciphering and if it's 0 (always 0 here) it's
* enciphering. But what is:
*
* 1/ *"1"+s/
* *"1"+1/ *"1"+s/ *"1"+1+(s-s)**"1"+(s*(s-s))**"1"
*
* ? Well first of all let's clarify that this is actually:
*
* 1/ *"1"+s/ *"1"+1/ *"1"+s/ *"1"+1+(s-s)**"1"+(s*(s-s))**"1"
*
* Observe too how a space removed in several places will turn it
* into a comment!
*
* I can try and parse some of this but I'm not really sure of all
* of it. For instance, how is (s*(s-s)) parsed? It would appear that
* it's s * 0 and it might very well be. Assuming that s is 0 (for
* example) it is 1; assuming it is 1 it is ... 1? So it seems. And
* assuming it is 2 is .... 1 again? So it seems! So how in the
* world does this work? Well remember what we're trying to get:
* either the first element or the second, and in this place we
* always need 1. Let's evaluate the other part (I'm sure you can
* figure it out though after this first one): 0! Okay but there's
* something really sneaky here (and above): ask yourself if 's' is
* actually incremented. Got your answer? Okay good! In fact if you
* were to update it you will get bad answers! For instance what
* happens if it's 2? I got 5764801. And then what if it's 0?
* -5764801.
*/
for (J = *"1"-*"1"; J < 26 && B[J][X?1/ *"1"+s/
*"1"+1/ *"1"+s/ *"1"+1+(s-s)**"1"+(s*(s-s))**"1":((((s-1)**"1")**"1")**"1")**"1"]; ++J)
{
/*
* oh dear did I do it again? Yup. I did. But in this case you
* can probably figure it out. Even so I'll evaluate these for
* you. Yes: 0+*"1"-*"1" is 0.
*/
if (*B[J][0+*"1"-*"1"] == toupper(z[a->x]))
{
/*
* Not again! Okay to help out let's remember s is 1. So s *
* 2 is 2. It's the other stuff that's a nightmare.
*
* (s*2)**"9"-171+*"9" == 0
*
* And you probably want to kill me but what is:
*
* *"1"-49 ?
*
* It is 0. And since you killed me you probably now want to
* chop me up into tiny bits but before you do that I guess
* you want to know what s/ *"1"+s/ *"1"+1/ *"1"+(s*s*s) is?
* That evaluates to 1.
*/
for (k = (s*2)**"9"-171+*"9"; H=B[J][X?*"1"-49:s/ *"1"+s/ *"1"+1/ *"1"+(s*s*s)][k]; ++k)
putchar(C?tolower(H):toupper(H));
/*
* this is putchar(' ')
*/
L=putchar(('\0'+'!'-1));
break;
}
}
}
}
/*
* we jumped here if a word was in the dictionary and translated, as
* explained earlier but we also get here if we don't (obviously)
*/
n:
/*
* if the last char we pushed on the stream is a space, don't add a space
*/
if (!isspace(L))
putchar(' ');
return a->s;
}
/*
* Z() used to be the parsing of args in main() and it's also truly dreadful, I
* know. Unfortunately I am not sure if I can explain it all but I will try.
*/
char *Z(struct a *a)
{
/*
* it would appear that a->l was argc of main() (c) and a->h is the argv
* (a) so the condition of the loop is going through all the args. However
* before we can continue we need to see how this function was called:
*
* Z(&(struct a){ .v = { t, I } ,.k=0, .l=c, .h=a, .j=f} );
*
* This means that a->v[0] == t() and a->v[1] == I and a (our struct)'s l is
* c (argc in main()) and our a->l is argv in main(). Additionally a->j is
* the linked list of words.
*/
while (a->h[a->l++])
/*
* I() :-) no longer can parse this completely (as in I don't know all
* of what it does) but I'll still try breaking it down a bit. I make no
* promises however. I will break the line up to help out, though it
* might not do that much good.
*/
/*
* first notice how where the loop condition (postfix) increments argc
* (a->l) the body of the loop immediately decrements (prefix decrement)
* and compares the first char of the current arg to - what? The
* expression 'e'-':' evaluates to '+'. This is checking for file as
* input.
*/
(((*a->h[--a->l]=='e'-':')&&
/*
* Okay remember what I said above about x->v[0] being t() ? That means
* that this is calling t().
*/
(*a->v)
/*
* ...and here we create the anonymous struct * for t(). As you can see
* the first function pointer in the v[] array is I(). Observe how in
* _this_ function v[0] is a different function! In this function v->[0]
* is t() but in this next function (t() itself!) it will be I()! But how
* do we construct it? Well...
*
* The &(struct a) is important because we can't do:
*
* (struct a *)
*
* because it is an error:
*
* prog.c:67:41: error: initialization of non-aggregate type 'struct a *'
* with a designated initializer list.
*
* (Okay the line numbers are different but you get the idea.)
* But since we need a pointer we can use & to get the address of the
* anonymous struct.
*/
(&(struct a)
/*
* Now the fun part! The object we create is in the {}s (of course). Each
* field, even pointers use '.' (which as shown above is required as we
* can't do { ->s=... } as it's also illegal and this is why we make it a
* struct that's not a pointer and take its address to get past that
* problem).
*
* Here we are saying that in the anonymous struct we're passing to t()
* the v[0] is I() and the s (a char *) is - what? Well this is awful. Do
* you remember that a->l is argc and a->h is argv from main()? So
*
* ((a->l)[a->h])
*
* is argv[argc]. Now the usual C programmer would point out that that is
* NULL. But something *extremely* nasty was done before we called this
* function. I will explain it (or rather try to) in main() but it looks
* like this:
*
* F((c=((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u),c&=9u,&(struct a){ .l=1, .s=a[c],.v= { &w, &w } } ));
*
* Remember that c in main() (or our a->l) is argc. So this horrible call
* resets c to some value, in particular 1 though that line does a lot
* more.
*
* So what this part does is, again, set OUR v[0] to I() which we are now
* calling, remember, and set OUR s (a char *) that is a->s to beyond
* (argv[argc])+1 (starting out with argc == 1). This also sets .j to
* a->k which is actually - what? This is sneaky. In main() when calling
* Z() a->j is set to f (the linked list) but here we're setting a->j (in
* the function call) to a->k. But in main() in calling Z() a->k is set
* to NULL! Further down though we will do .z=a->j so this might (or
* might not) be called a red herring.
*
* But of course we're not done!
*/
{ .v[0]=I, .j=a->k, .s=((a->l)[a->h])+1} )
/*
* I'm sure that some people are screaming by now, if they even got this
* far, but here we are doing something sneaky (imagine that) too.
*
* Remember how the loop condition incremented argc but the loop body
* immediately decremented it (since we needed to check the first char
* of the first arg, not the next)? Well the problem is now that we have
* checked that we nee to get x-> (argc) incremented again, but prefix.
*/
&&++a->l)||
/*
* But of course if these (what are these? Please go back up and check, I
* too am getting tired of trying to parse all this and I have a lot more
* to do!) did not succeed we still have more nastiness.
*
* a->v[1] is I() so now main() is (or rather we, Z(), are on behalf of
* main()) calling t with - yup, ANOTHER anonymous struct a *!
*/
(a->v[1](&(struct a)
/*
* The good news at least is you know how the struct is constructed but
* what are we doing here and why?
*
* Well here we are saying that in the call to I() that v[2] is Y() (not
* again) and x (a char *, not like x here which is a struct a *) is set
* to the current argv[argc].
*
*/
{ .v[2]=Y,.x=((a->l)[a->h]),.z=a->j}
/*
* this is the end of the function call but we're not actually done just
* yet.
*
* Observe how we are prefix incrementing a->l again (argc in main())!
*/
),++a->l));
/*
* Okay but you might ask yourself: how come we're using the comma
* operator here? Well because at this point although we do need to
* call I() we also need to increment argc (a->l) yet again!
*
* But...why? After all the body of the loop does this! Not quite. It
* does do this but that was on the left hand side (lhs) of the body
* of the loop and the beginning of the body of the loop decremented
* it! So in order to get argc back to the next one we have to
* increment it as a side effect!
*/
/*
* we only do this because we need to return a char *; a simple return
* 0 would also work and so would a return NULL.
*/
return "";
}
/*
* this function is simpler though there still are some potentially confusing
* things going on here. Yes this looks kind of like a rot13 implementation but
* the dictionary file actually has Z -> A, Y -> B, X -> C etc. But what was r
* formed of? Actually this is extremely sneaky.
*/
char *w(struct a *a)
{
/*
* Okay but you might notice I did something nasty again. Okay I did
* multiple nasty things! You probably can figure these out at least though.
* Anyway, 1/ *"s" is 0 and 'k'-'*' evaluates, as you might have guessed, to
* 'A'.
*
* That means start out at 0, go through a->s - well you get the idea. But
* what is a->s? Well that is the dictionary file of course but that'll be
* discussed in the respective function.
*/
for (D = 1/ *"s"; a && a->s && D[a->s] && (a->s[D]) &&
(a->s[D] = isupper(a->s[D])?("ZYXWVUTSRQPONMLKJIHGFEDCBA"
)[(a->s[D] - ('k'-'*'))]:D[a->s]); ++D) ;
/*
* at one point it was possible for a to be NULL so we checked here. It
* shouldn't be needed now though.
*/
return a?a->s:"";
}
/*
* this is kind of like strcasecmp() except that it ignores !isalpha(). There is
* only one thing that might not be immediately obvious so I'll only comment on
* that. Well okay as you'll see a->w is the first string and a->c is the
* second. But besides that it's pretty easy.
*/
char *Y(struct a *a)
{
if (*a->w && *a->c && a->w[1] && a->c[1])
while (*a->w && *a->c)
{
while (!isalpha(*a->w) && *a->w++);
while (!isalpha(*a->c) && *a->c++);
if (!*a->c || !*a->w || tolower(*a->w) != tolower(*a->c))
break;
++a->w; ++a->c;
}
/*
* remember that we need to return a char * so what this does is it
* evaluates to either a 'true' value (non NULL string) or a NULL pointer.
* This can be checked as if an int but matching the requirement that it
* returns a char * (for the function pointer array).
*/
return !*a->w&&!*a->c?"":0;
}
/*
* This function reads in the dictionary file as the first line might suggest.
*/
char *F(struct a *a)
{
g = fopen(DICT, "r");
if (g)
{
/*
* We use getline(3) even though there is the bug I mentioned in the
* remarks file because we can have it dynamically allocate memory. It
* stores the newline but so does fgets() and we don't really care about
* it. In fact we do not want to remove the newline!
*/
while (getline(&a->A, &n, g) != -1)
/*
* So we were called like this:
*
* F((c=((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u),c&=9u,&(struct a){ .l=1, .s=a[c],.v= { &w, &w } } ));
*
* I am not going to explain the first part until main() but the
* second part, which can only happen by the comma operator (like in
* other places) and which we use as we need the other thing to be
* done first, it sets up our struct a *a's .l to 0, v[0] to &w and
* v[1] to &w. Why both? To mislead of course!
*/
/*
* this part is easy but note how we use a->A and a->S as the first
* and second column. They are not really needed except to have them
* also in the struct (and even if they were not NULL we assign them
* first).
*/
if ((a->N = strtok(a->A, "\t")) && (a->S = strtok(0, "\t")))
{
/*
* Oh no! Not another bonkers calculation! Well fortunately you can
* probably put together what it is but if not it evaluates to 1.
* Basically we're allocating a struct a *.
*/
c = calloc(1**"0"-47, sizeof *c);
/*
* more fun with anonymous structs here as we populate the struct a *
* we just created. As I might have said elsewhere if X is non-zero
* (never true here) it means decipher and otherwise it means encipher.
* means. But observe how c->w can be one or the other just like
* c->c. That's because the X check is done in other places too.
*
* Now about these structs being created. For c->w it is a strdup()d
* copy of the result of calling w() on either a->S or a->N.
* Similarly we are doing the same thing (but opposite order) for
* c->c. But hold on a moment you might think. Why then are we
* assigning multiple values? Well actually we're not. This is just
* the copy but both are always assigned to the w()'s struct a *'s s
* (a char *).
*
* As for the function calls:
*
* a->l is 0 and a->e is NULL but even if it wasn't it would
* evaluate to 1 and so a->v[a->l], a->v[a->e==0] (as 1 or 0)
* and a->v[1] all point to w()!
*/
c->w = strdup(X?a->v[a->l](&(struct a){ .s=a->S} ):a->v[a->e==0](&(struct a){ .s=a->N} ));
c->c = strdup(X?a->v[1](&(struct a){ .s=a->N} ):a->v[a->l](&(struct a){ .s=a->S} ));
c->e = f;
f = c;
}
free(a->A);
a->A = 0;
fclose(g);
g = 0;
}
else puts("couldn't open dict");
return "";
}
/*
* fortunately t() is a bit easier - although you might remember the call to it
* is not.
*/
char *t(struct a *a)
{
/*
* this assigns o with 0
*/
o = *"";
g = fopen(a->s, "r");
a->A = 0;
while (g && getline(&a->A, &o, g) != -1)
{
/*
* the usual suspect: we're using a->S as a temporary value for strtok()
* to extract the first field (space or tab delimited)
*/
a->S = strtok(a->A, " \t");
while (a->S)
/*
* strdup() is useful here
*/
if ((a->y=strdup(a->S))) {
/*
* if a token was found then we will call a->v[0] which is I don't
* even know; I'm really tired doing this and I have more to parse
* for you - sorry! Anyway in that function v[2] will be Y() and w
* will be S (the token we extracted).
*/
(*a->v)(&(struct a){ .v[2]=Y, .x=a->y} );
/*
* get next token for this line
*/
a->S = strtok(0, " \t"); free(a->y); a->y=0;
/*
* if the last char we pushed on the stream is a space
* don't add a space
*/
if (L!='\n')putchar(' ');
}
}
if(g) { clearerr(g); fclose(g); g = 0; free(a->A); a->A= 0; }
return "";
}
/*
* Good news: we've reached the last function!
*
* Bad news: it's also dreadful, really dreadful!
*/
int main(int c, char **a)
{
/*
* Do I have to try and parse this? Okay well I did explain in one function
* (F() itself) the second half but I did not explain the first half so I'll
* try here.
*
* Remember how I said (I think I said anyway) that argc is set to 1? Well
* that is because:
*
* ((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u)
*
* evaluates to 113 and 113 & 9 is 1. The other parts are just a
* distraction.
*
* Notice the double {} there (that's not the only place this occurs though
* I think).
*/
F((c=((~~!!~!9u|2**"9"-15u/ *"0"-2u)<<~~!~!~9u),c&=9u,&(struct a){ .l=1, .s=a[c],.v= { &w, &w } } ));
/*
* This was the one that processes the args. It is not a hard call to deal
* with (the function Z() itself is of course): call Z() with an anonymous
* struct a * with v[0] == t(), v[1] == I(), l == c (argc), a == a
* (argv) and k == 0 (NULL) and j == f (linked list of words)
*/
Z(&(struct a){ .v = { t, I } ,.k=0, .l=c, .h=a, .j=f} );
puts("");
/*
* Now go have some good chocolate or some great pie! You deserve it!
*/
}