11 Jan, 2009, quixadhal wrote in the 1st comment:
Votes: 0
Well, usually I find something strange and inspired by Cthulhu, every time I sit down and look at the ROM code for a bit. This time is no exception, but I figured I'd make a thread just for that kind of thing. :)

Today's "WTF" moment, comes from merc.h. You've all used our beloved MAX_STRING_LENGTH define, and I'm sure like myself, you never really bothered to look at what it was defined as. I mean, MAX_INPUT_LENGTH is 256, so some reasonable value like 1024, 2048, 4096, etc… right?

#define MAX_STRING_LENGTH 4608

W.T.F???

Where the hell does THAT number come from? I actually sat and tried to think of why they'd pick it. 4096 + 512 == 4608, but why the extra 512 overhead? Why not just make it 4096… or 8192 if that's not big enough? 4608 / 4 == 1152. Maybe they used a screen resolution of 1152 x 864???

Ok, well… eventually it won't matter, but for now I cared because the C++ format routine I have uses a pre-allocated stack buffer of a "usually works" size to avoid having to allocate memory for vsnprintf. I wanted to look up what value to put in there. :)
11 Jan, 2009, ghasatta wrote in the 2nd comment:
Votes: 0
I am only surprised that you even try to make sense of this in the first place…..Seriously, what were you expecting?? ;)
11 Jan, 2009, Fizban wrote in the 3rd comment:
Votes: 0
Hmm, now I'm curious what it is in tbaMUD….

#define MAX_STRING_LENGTH 49152 /**< Max length of string, as defined */


Overkill much?

96 * 512 = 49152, so sure it follows the pattern about as much as ROM does, but is well….stupidly large.
11 Jan, 2009, quixadhal wrote in the 4th comment:
Votes: 0
Are you suggesting that *I* am mad?



Reminds me of the scene in HHGTTG, where they go to meet Wonko the Sane, who lives outside The Asylum (which he defines as the rest of the world).
11 Jan, 2009, quixadhal wrote in the 5th comment:
Votes: 0
Fizban said:
Hmm, now I'm curious what it is in tbaMUD….

#define MAX_STRING_LENGTH 49152 /**< Max length of string, as defined */


*cough*
Well, I guess it's slightly better than the outright LIES that Smaug uses.

This is all well and good:
mud.h:#define MAX_STRING_LENGTH 4096 /* buf */

but, don't these make it a lie?
act_comm.c: char BUFF[MAX_STRING_LENGTH * 2];
color.c: if( d->pagesize > MAX_STRING_LENGTH * 16 )

and a few more :)

So, it's not *really* MAX_STRING_LENGTH, once you do that.

Oh, and don't feel bad Smaug… RaM has a few of those too… although that's about to change. :)
11 Jan, 2009, Fizban wrote in the 6th comment:
Votes: 0
quixadhal said:
Fizban said:
Hmm, now I'm curious what it is in tbaMUD….

#define MAX_STRING_LENGTH 49152 /**< Max length of string, as defined */


*cough*
Well, I guess it's slightly better than the outright LIES that Smaug uses.

This is all well and good:
mud.h:#define MAX_STRING_LENGTH 4096 /* buf */

but, don't these make it a lie?
act_comm.c: char BUFF[MAX_STRING_LENGTH * 2];
color.c: if( d->pagesize > MAX_STRING_LENGTH * 16 )

and a few more :)

So, it's not *really* MAX_STRING_LENGTH, once you do that.

Oh, and don't feel bad Smaug… RaM has a few of those too… although that's about to change. :)


I asked because I was curious and apparently it was that long so DG scripts don't overflow it any longer because I used to overflow it when it was smaller rather frequently with ~300 line DG Scripts.


EDIT: No "lies" at least:

$ grep "MAX_STRING_LENGTH " *
genmob.c: ldesc[MAX_STRING_LENGTH - 1] = '\0';
genmob.c: ddesc[MAX_STRING_LENGTH - 1] = '\0';
genmob.c: strip_cr(strncpy(ldesc, GET_LDESC(mob), MAX_STRING_LENGTH - 1));
genmob.c: strip_cr(strncpy(ddesc, GET_DDESC(mob), MAX_STRING_LENGTH - 1));
genolc.c: ldesc[MAX_STRING_LENGTH - 1] = '\0';
genolc.c: ddesc[MAX_STRING_LENGTH - 1] = '\0';
genolc.c: strip_cr(strncpy(ldesc, GET_LDESC(mob), MAX_STRING_LENGTH - 1));
genolc.c: strip_cr(strncpy(ddesc, GET_DDESC(mob), MAX_STRING_LENGTH - 1));
modify.c: if (diff > MAX_STRING_LENGTH - 3) /* 3=\r\n\0 */
modify.c: diff = MAX_STRING_LENGTH - 3;
objsave.c: char buf1[MAX_STRING_LENGTH +1];
structs.h:#define MAX_STRING_LENGTH 49152 /**< Max length of string, as defined */
structs.h:#define MAX_HELP_ENTRY MAX_STRING_LENGTH /**< Max size of help entry */
utils.c: while((rp - ret) < MAX_STRING_LENGTH && (*sp1 || *sp2)) {
utils.c: while((rp - ret) < MAX_STRING_LENGTH && *sp1 && !ISNEWL(*sp1))
utils.c: while((rp - ret) < MAX_STRING_LENGTH && *sp2 && !ISNEWL(*sp2))
11 Jan, 2009, quixadhal wrote in the 7th comment:
Votes: 0
I find some of them to be very amusing…. The first one I looked at was in the do_sockets() command. It declares a double-sized buffer so it can loop through all the descriptors, sprintf'ing socket data into a temp buffer… and then using page_to_char to send it to the user.

Ummmm, why not just use page_to_char inside the loop? It doesn't actually get sent until their buffer gets flushed in the update loop, so it's not like it'll come up half-finished…

I get the feeling that lots of people WRITE code for diku derivatives, but very few of them READ what's already there first. :)
11 Jan, 2009, Fizban wrote in the 8th comment:
Votes: 0
quixadhal said:
I find some of them to be very amusing…. The first one I looked at was in the do_sockets() command. It declares a double-sized buffer so it can loop through all the descriptors, sprintf'ing socket data into a temp buffer… and then using page_to_char to send it to the user.

Ummmm, why not just use page_to_char inside the loop? It doesn't actually get sent until their buffer gets flushed in the update loop, so it's not like it'll come up half-finished…

I get the feeling that lots of people WRITE code for diku derivatives, but very few of them READ what's already there first. :)


This one's facepalm worthy:

structs.h:#define MAX_STRING_LENGTH 49152 /**< Max length of string, as defined */
structs.h:#define MAX_SOCK_BUF (24 * 1024) /**< Size of kernel's sock buf */

The maximum output is half the size of the MAX_STRING_LENGTH…
12 Jan, 2009, David Haley wrote in the 9th comment:
Votes: 0
Eh, really, to be honest, these strings shouldn't be being allocated like this in the first place… :wink: I'm inclined to agree with ghasatta, I wouldn't spend too much time trying to figure out the deeper meaning behind these. :lol:
13 Jan, 2009, Tricky wrote in the 10th comment:
Votes: 0
Heh! Standard "maximum string length" for LPMuds using MudOS/FluffOS for the driver is 200000. Yes, 200k. Output length (ie what can be thrown at the user for viewing) is 8192 bytes.

49152! Hmm… I wonder if the coder that settled on that value used to code on a C64.

LOAD "DEMO",8,1
LIST
10 SYS 49152 REM 1337 D3MO!

:biggrin:

Tricky
14 Jan, 2009, ghasatta wrote in the 11th comment:
Votes: 0
Speaking of madness…

argall[0] = '\0';
while ( argument[0] != '\0' )
{
argument = one_argument( argument, argone );
if ( argall[0] != '\0' )
strcat( argall, " " );
strcat( argall, argone );
}


:stare:
14 Jan, 2009, kiasyn wrote in the 12th comment:
Votes: 0
ghasatta said:
Speaking of madness…

argall[0] = '\0';
while ( argument[0] != '\0' )
{
argument = one_argument( argument, argone );
if ( argall[0] != '\0' )
strcat( argall, " " );
strcat( argall, argone );
}


:stare:


This function will go over a string with many spaces separating words, and return it with only one space.
14 Jan, 2009, Tyche wrote in the 13th comment:
Votes: 0
So if it is indeed "madness" (arbitrary MAX_STRING_LENGTH), then what is the C solution?
14 Jan, 2009, elanthis wrote in the 14th comment:
Votes: 0
Non-arbitrary fixed-sized buffer lenghts, maybe? Using dynamically-allocated buffers where appropriate? Removing the use of buffers entirely where they shouldn't be used or where simpler solutions could be created?

I saw an example in another thread where a user wanted to colorize some output, so he had to create a buffer, call a function on the input string to spit the terminal control codes into the buffer. and then send that to a send_to_char function. Why not just make a send_to_char_color function that does that in one go, without a ton of extra copies and buffers?

I also see a lot of things like sprintf()ing a bunch of times into a buffer which is then passed to send_to_char. Why not a printf_to_char function? Why append to a buffer over and over and then pass that to send_to_char instead of just calling send_to_char directly several times? That would have less overhead with any sane implementation of send_to_char.
14 Jan, 2009, quixadhal wrote in the 15th comment:
Votes: 0
As far as picking an arbitrary size… I suppose one has to do that if you're going to use stack buffers… but why not pick a nice even power of two? Working under the assumption that computers like powers of two, and that the paging subsystem is likely going to allocate pages in powers of two, it seems to me that choosing something that will be evenly divisible by (or into) the page size is a good idea.

Since 4K seems to be roughly the number they were aiming for, 4096 seems like a good number to try.

However, I agree… the use of varargs functions was either outside the ancestral Diku coder's knowledge, or perhaps gcc didn't support such things back then (although I'm pretty sure it did).

One of the first things I do to a diku-base is make printf-style functions for all the various send_to_foo's and act. The more I work with one_argument(), the more I start wondering if a proper parser might be in order as well.
14 Jan, 2009, Lobotomy wrote in the 16th comment:
Votes: 0
quixadhal said:
The more I work with one_argument(), the more I start wondering if a proper parser might be in order as well.

Explain.
14 Jan, 2009, Cratylus wrote in the 17th comment:
Votes: 0
Lobotomy said:
quixadhal said:
The more I work with one_argument(), the more I start wondering if a proper parser might be in order as well.

Explain.


SIR YES SIR!

-Crat
14 Jan, 2009, Lobotomy wrote in the 18th comment:
Votes: 0
Cratylus said:
Lobotomy said:
quixadhal said:
The more I work with one_argument(), the more I start wondering if a proper parser might be in order as well.

Explain.


SIR YES SIR!

-Crat

:thinking:
14 Jan, 2009, Davion wrote in the 19th comment:
Votes: 0
Cratylus said:
Lobotomy said:
quixadhal said:
The more I work with one_argument(), the more I start wondering if a proper parser might be in order as well.

Explain.


SIR YES SIR!

-Crat


That was unnecessary Cratylus. Lobotomy already expressed his apology for his previous statement. Needless antagonizing is not wanted.
14 Jan, 2009, quixadhal wrote in the 20th comment:
Votes: 0
one_argument() take a string skips past leading whitespace, lobs off a chunk of it to pass back as a substring, using whitespace as a delimiter. It also attempts to handle quotes, although you can confuse it with things like [ pick up "Bob's shovel"]. It then continues to shovel past whitespace and returns the point in the string where it stops.

That's rather messy.

A proper parser would work by matching the structure of the line against known possibilities in the grammer. If you have a verb that requires 3 arguments, you just specify it that way. Since a diku is hard-coded anyways, rebuilding the grammer isn't an issue. I dunno, it's been a while since I worked with lex and yacc (flex and bison these days), so maybe it's harder than I remember.
0.0/31