[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: Top vs. bottom posting, solution proposal ;-)



On 10/15/06, Marko Vojinovic <vvmarko panet co yu> wrote:

Hi everybody, :-)

Please, don't hate me for bringing up this topic yet again. I do not wish to
start another flame, and have no preferences with respect to top/bottom
posting.

It's just that in several years on this list there were several long
discussions about that, and I guess we could do without them. :-)

So, I devoted a couple of hours of my time to write down some prototype of
top/bottom post converter, creatively named top2bottom.c :-) . I didn't even
bother to google-research for any already existing stuff of the kind, just
started from scratch and c-ed until it started working... The code is below.
(Sorry, I don't have a website to upload it and send you a link, it seems the
easiest way was to post it...) Also, below are some notes about it, for those
interested.

Try it, and if you like it, send me some feedback to make it better. Or do it
yourself. Consider this to be my $0.04 to the global benefit of the list.
Just imagine the scenario: somebody top-posts; he gets a kind reply to not
top-post; if he continues, top-post-annoyed people filter his messages
through top2bottom transparently, and there is no discussion about it any
more. There is peace on Earth, and good will among people... ;-)

Best regards, :-)
Marko

Still here? Ok. Read on... :-)

A couple of usage notes:
* This is c code. :-) I prefer it to assembly language, and don't have enough
skill to do it using bash.
* Compile it via "gcc top2bottom.c -o top2bottom", should work with any
version of gcc. Actually, I guess it is compiler/os/platform independent.
* It reads from stdin and writes to stdout. Feed it with the body of the
top-posted message to get it bottom-posted.

A couple of features/bugs:
* Top-posted messages become bottom-posted. By reversing the order of sorting,
one can make bottom-posted messages get converted to top-posted.
* "Interspersed" messages are not touched.
* The "Yesterday Jim wrote:" titles of quotes get from the top of the quote to
the bottom of it. This may make a message look a bit awkward or confusing,
but there is no easy way out of it. OTOH, when there are several successive
quotes, the titles are equally confusing being on the top, also (at least for
me).
* ">" is the sole quoting symbol recognized. If there is feedback that this
thing is useful, i'll be happy to include other quoting symbols, implement a
bunch of behaviour-changing options, clean up and optimize the code, etc.

A couple of technical notes:
* I am completely aware that this program is terribly inefficient,
unoptimized, slow, has insane memory usage, etc..., and that I have broken
virtually every programming rule that can apply in this case.
* That said, have in mind that this is just a proof-of-concept code, put
together in a couple of hours, and I don't want to do any real work on it
unless I get some feedback that it is useful to the others.
* That said, note that it works.
* If it doesn't work, tell me about it. If it segfaults, you probably need to
enlarge the 5000 characters-per-line limit and/or 5000 lines-per-message
limit... I know, it's a hack, it's ugly, it's awful, it's crap...
* If you need to know about licencing etc, consider this to be GNU GPL
software, although I don't really care. Use it, modify it, whatever...
* DO NOT learn how to program by looking at this. This is a VERY VERY BAD
example of code. :-)
* It's not that I am a bad programmer, I am just being lazy. Have other things
to do in life, a thesis to work on, etc...

YET STILL HERE??!! Ok, here goes the code. Note that it may look ugly due to
line wrapping, but it should work nevertheless... :-)

======== Beginning of the file top2bottom.c ============
#include <stdio.h>

#define MaxLine 5000  /* Maximum number of characters per line  */
#define MaxMesg 5000  /* Maximum number of lines per file */
#define EOLN '\n'    /* End of line character */

int interspersed;       /* indicator to say whether the message is
interspersed or not */
int NumberOfLines;      /* Counts the total number of lines in a message */

struct MessageStruct {
 int quoteorder;            /* The number of leading quote symbols in this
line */
 int linenumber;            /* The initial number of this line */
 char data[MaxLine];        /* The line string */
} line[MaxMesg];        /* An array of lines, ie. the whole message buffer */

void ReadTheMessage()
{
char c;
int n=0;                 /* Current line counter */
int i=0;                 /* Current character counter */
int endoffile=0;         /* End of file indicator */

 NumberOfLines=0;           /* Message is empty at this point */
 while((!endoffile)&&((c=getchar())!=EOF))        /* Read in the data from
stdin */
  {
   line[n].quoteorder=0;       /* Initialize the quote order. It will be
counted later... */
   i=0;                        /* Reset the character counter */
   while((c!=EOLN)&&(c!=EOF))  /* Read in the current line */
    {
     line[n].data[i] = c;         /* Feed the message buffer with the data */
     i++;                         /* Move to the next character */
     c=getchar();                 /* Read it, and repeat */
    }
   line[n].data[i] = EOLN;     /* Finish the string */
   line[n].linenumber=n;       /* Set the line number */
   n++;                        /* Move to the next line, and repeat */
   if(c==EOF) endoffile=1;     /* Handle the premature end of file */
  }
 NumberOfLines=n;           /* Save the number of lines and finish */
}

void WriteTheMessage()
{
int n=0;                  /* Current line counter */
int i=0;                  /* Current character counter */

 while(n<NumberOfLines)         /* Write the data to stdout */
  {
   i=0;                            /* Reset the character counter */
   while(line[n].data[i]!=EOLN)
     putchar(line[n].data[i++]);   /* Write the current line */
   putchar(EOLN);                  /* Write the end of line */
   n++;                            /* Move to the next line, and repeat */
  }
}

void AnalyzeTheMessage()
{
char c;
int n=0;                  /* Current line counter */
int i=0;                  /* Current character counter */
int k=0;                  /* Current quote order counter */
int orderlessthenk=0;     /* Indicator if there is a quoteorder less then k */
int maxquoteorder=0;      /* Maximum value for the quoteorder */

/*
Ok. First we count the so called "quote order" of each line,
which amounts to number of leading '>'s per line. In the process,
we need to account for the famous "From" bug in sendmail, and
decrement the quoteorder if the text starts with the word
"From", in order to get it right.
*/
 for(n=0;n<NumberOfLines;n++)      /* Go through the each line */
  {
   i=0;                                    /* Reset the character counter */
   c=line[n].data[i];                      /* Set the initial data */
   while( ((c=='>')||(c==' ')) &&(c!=EOLN) )  /* Count the leading '>'s, skip
spaces */
    {
     if (c=='>') line[n].quoteorder++;        /* Increment quoteorder for each
'>' */
     i++;                                     /* Go to the next character */
     c=line[n].data[i];                       /* Read it, and repeat */
    }
   if (  (c=='F')&&                        /* Check if the following string is
"From" */
         (line[n].data[i+1]=='r')&&        /* Now, this is very, very ugly...
*/
         (line[n].data[i+2]=='o')&&
         (line[n].data[i+3]=='m')  )
    line[n].quoteorder--;                     /* If yes, decrease the
quoteorder... */
  }
/*
Now we need to check if the message is interspersed or not. This is tricky,
as we need to find constructions of the form:

> > >
>
> > >

and similar, which amount to quoteorder being 3,1,3 and the like.
Simoultaneously, we *don't* want to find constrctions of the form:

>
> > >
>

because this can happen even if the message is not interspersed.
But that's life... ;-)
*/
 for(n=0;n<NumberOfLines;n++)           /* First find the biggest quote order
*/
  if (line[n].quoteorder>maxquoteorder) maxquoteorder=line[n].quoteorder;

 interspersed=0;     /* Assume message is not interspersed */

 for(k=1;k<maxquoteorder;k++)   /* We need to check the above construction for
all nonzero quote orders */
  {
   n=0;               /* Start from the begining of the message */
   while ((line[n].quoteorder!=k)&&(n<NumberOfLines)) n++;  /* Get to the
block of lines of quoteorder k */
   while ((line[n].quoteorder==k)&&(n<NumberOfLines)) n++;  /* Go through the
block */
        /* Now go down the rest ot the lines, and check if some line has
           quoteorder less then k, and another line after it the quoteorder
           equal to k again, which amounts to interspersed construction.
*/
   orderlessthenk=0;     /* Assume there are no quotes of order less then k */
   while (n<NumberOfLines)     /* For each of the remaining lines */
    {
     if (line[n].quoteorder<k) orderlessthenk = 1;  /* alert if there is a
quote of lesser order */
     if ((line[n].quoteorder==k)&&(orderlessthenk)) interspersed=1; /* We
found the interspersed construction!! */
     n++;                      /* Go check the next line */
    }
  }
/*
And that's it. If the message has interspersed structure on any level
of quoteorder, we have the indicator on. Otherwise, it is off.
*/
}

void SwitchLines(int i, int j)
{
int n;
int tempquoteorder;
int templinenumber;
char tempdata[MaxLine];

/* This switches line i with line j, as needed for sorting (sigh)... */
 n=0;                                    /* Copy line i to temp */
 tempquoteorder=line[i].quoteorder;
 templinenumber=line[i].linenumber;
 while(line[i].data[n]!=EOLN)
  tempdata[n]=line[i].data[n++];
 tempdata[n]=EOLN;
 n=0;                                    /* Copy line j to line i */
 line[i].quoteorder=line[j].quoteorder;
 line[i].linenumber=line[j].linenumber;
 while(line[j].data[n]!=EOLN)
  line[i].data[n]=line[j].data[n++];
 line[i].data[n]=EOLN;
 n=0;                                    /* Copy temp to line j */
 line[j].quoteorder=tempquoteorder;
 line[j].linenumber=templinenumber;
 while(tempdata[n]!=EOLN)
  line[j].data[n]=tempdata[n++];
 line[j].data[n]=EOLN;
}

void SortTheMessage()
{
int i,j;

/*
In order to make the message bottom-posted, we simply need to sort the lines
by quoteorder
descending. Further, we need to preserve the order of lines of the same
quoteorder,
which amounts in sorting same-quoteorder lines by line number, ascending.
N.B.: Maybe this can be done in a more clever way, but I am lazy to ponder
over it... :-)
*/

/* The algorithm is just a simple, stupid and slow bubble-sort, over
quoteorder and
linenumber simultaneously... */
 for(i=0;i<NumberOfLines;i++)
  for (j=0;j<=i;j++)
   {
    if(line[i].quoteorder>line[j].quoteorder) SwitchLines(i,j);

if((line[i].quoteorder==line[j].quoteorder)&&(line[i].linenumber<line[j].linenumber))
SwitchLines(i,j);
   }
}

int main()                /* This is self-explanatory, I hope... :-) */
{
 ReadTheMessage();
 AnalyzeTheMessage();
 if (!interspersed) SortTheMessage();
 WriteTheMessage();
}

======== End of the file top2bottom.c ================


Not that this debate really matters to me, lthough I do see the
benifits of bottom posting, I am willing to host this on my site
www.pembo13.com for you if you'd like.

--
Fedora Core 5 and proud


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]