Disclaimer: First, I'm aware that this is C++ code and this is a C# forum, I'm not all that familiar with C++ and was hoping someone here could explain the example below in C#.

I was browsing the very complex source code of the open source project MySQL and saw this bit of code (see attachment for full file, original extension was cc, not cpp):

/* A structure which contains information on the commands this program
   can understand. */

typedef struct {
  const char *name;		/* User printable name of the function. */
  char cmd_char;		/* msql command character */
  int (*func)(String *str,char *); /* Function to call to do the job. */
  bool takes_params;		/* Max parameters for command */
  const char *doc;		/* Documentation for this function.  */
} COMMANDS;

I understand everything except for line 7:

int (*func)(String *str,char *); /* Function to call to do the job. */

The code moves on immediately after in this type of fashion:

static COMMANDS commands[] = {
  { "?",      '?', com_help,   1, "Synonym for `help'." },
  { "clear",  'c', com_clear,  0, "Clear command."},
  { "connect",'r', com_connect,1,
/* SNIPPED FOR BREVITY */
  { "lock tables",      0, 0, 0, ""},
  { "unlock tables",    0, 0, 0, ""},
  /* generated 2006-12-28.  Refresh occasionally from lexer. */
  { "ACTION", 0, 0, 0, ""},
  { "ADD", 0, 0, 0, ""},
  { "AFTER", 0, 0, 0, ""},
  { "AGAINST", 0, 0, 0, ""},
  { "AGGREGATE", 0, 0, 0, ""},
  { "ALL", 0, 0, 0, ""},
  { "ALGORITHM", 0, 0, 0, ""},
  { "ALTER", 0, 0, 0, ""},
  { "ANALYZE", 0, 0, 0, ""},
  { "AND", 0, 0, 0, ""},
  { "ANY", 0, 0, 0, ""},
  { "AS", 0, 0, 0, ""},
  { "ASC", 0, 0, 0, ""},
/* ETC... */
  { "WEEKDAY", 0, 0, 0, ""},
  { "WEEKOFYEAR", 0, 0, 0, ""},
  { "WITHIN", 0, 0, 0, ""},
  { "X", 0, 0, 0, ""},
  { "Y", 0, 0, 0, ""},
  { "YEARWEEK", 0, 0, 0, ""},
  /* end sentinel */
  { (char *)NULL,       0, 0, 0, ""}
};

Even though I don't understand line 7, why would anyone waste time creating a struct like this if everything (seriously over 100 lines) all contain 99% of the same data. Am I missing something? Can anyone shed any light here, or even throw out a guess?

Recommended Answers

All 12 Replies

Line 7 is a reference to a function that takes a pointer to a string, a pointer to a character and returns an integer. In C# we call these delegates.

It looks to be some form of SQL parser.

Hmm...I don't get how they are constructing it then.

In the example above, the first code snippet on line 2 they set that value to "com_help" and then on line 6 and on it is set to "0"

I understand now that it's a delegate, but I don't get how you can set that field to either a string (which I'm assuming points to the name of the function to call) or to an integer. I understand that the function is supposed to return an integer, but I wasn't aware that you could just skip calling a function and just return 0.

Maybe I don't fully understand.

I must say, as a side note, and no offense to anyone who may have contributed, but that source code has got to be the most disorganized mess I've ever read. I got the biggest headache just trying to locate references. But then again I'm not a C++ programmer so meh.

In line 2 they set it to com_help which is a function (not a string). So when it is compiled it puts the address of com_help in that spot. One thing to note about C/C++ is that pointers (which this is) are integer types. They can be set to any number you like, and 0 usually means 'no pointer' (or void *). If you are trying to learn C/C++ just wait until you get to pointer math. Or pointer pointers.

Yes, the code is messy :)

I'm not necessarily trying to learn C/C++, my current project is in C# and that's where it will remain until it is finished, maybe after I'll consider learning C/C++.

The reason I was even looking at this code was to find out how the SQL server processed commands from clients...and even now, after hours of reading, browsing (literally) thousands of files and consuming more aspirin than should legally be allowed I still don't know how it's done.

"COMMANDS" is mis-named. It's a wrapper for a single command. The long list of similar statements in your 3rd snippet populates an array with a whole pile of commands, one per line. The first couple look sensible: the command "clear" has the command character "c", calls com_clear, takes 0 parameters and has the documentation string "Clear command." So far so good. But then there are a whole pile that have a name but no associated action or documentation so it seems that they don't do anything except occupy memory. I think the clue is in the comment "generated 2006-12-28. Refresh occasionally from lexer." This stuff is all machine generated. The lexer knows those keywords, so they're in the list, but no action is associated with them so they're all set to no command character, no action, no parameters, no documentation string.

digitig,

Is "lexer" something that is supposed to be common knowledge that I am oblivious to? What I mean is, is it something specific to this application or is it a function of some sort, a website, service...something?

"Lexer" is a standard thing, but it's only common knowledge to those who get involved with turning plain text into computer representation. It's the first step in the process, which breaks the text into individual words that the program will hopefully recognise. Look up the documentation on the Unix utility "Lex" (or the gnu version "Flex").

It's most likely referring to something like Lex

I see now.

I'm assuming then that the "commands" that have no function to call, only the keyword is set...the "command" that is performed when that keyword is used is generated by Lexer, and not the programmer?

I guess what I mean is, when the command "ADD" is sent (from the example above), the code that is executed is generated by Lexer, not the programmer that created the COMMANDS array? Though I guess they COULD be the same person, but...it's something external is what I'm getting at.

Is that right?

Generally, something like Lex takes a set of rules and actions. It then parses the input it gets based on the rules and performs the actions. A lot of times the actions are left out so that the user of Lex can then use the generated code in YACC (or it's like) to create a compiler or interpreter of the commands.

Since you said this had something to do with parsing SQL commands, I suspect there is another module somewhere that is using this as a parser of SQL commands then performing actions based on the parsed output.

Meh, you lost me...it's really not important at the moment I guess. It was more of a curiosity thing.

Thanks for trying to explain it :)

Code Snip, Also Know as a Code Snippet. Is A small Piece of Code That Can be used in Different Applications To Get A result. There is No Way to Know what the snippet was intentionnaly ment for it could be used for many things as to extract certain data from an sql database and so forth like this snippet that i use alot in c# which is not as elaborate as the one shown above.

private string getName(OpenFileDialog dlg)
{
string s = "";
string[] name = dlg.FileName.Split('\\');
for (int i=0;i<name.Length;i++)
{
s = name;
}
return s;
}

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.