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 ================ -- fedora-list mailing list fedora-list@xxxxxxxxxx To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list