what exactly is going on in this code?

Red Squirrel

No Lifer
May 24, 2003
69,489
13,179
126
www.anyf.ca
I'm trying to incorporate term.h (part of the picocom source) into one of my programs but I ran across something that wont compile:


Code:
static const char * const term_err_str[] = {
	[TERM_EOK]        = "No error",
	[TERM_ENOINIT]    = "Framework is uninitialized",
	[TERM_EFULL]      = "Framework is full",
    [TERM_ENOTFOUND]  = "Filedes not in the framework",
    [TERM_EEXISTS]    = "Filedes already in the framework",
    [TERM_EATEXIT]    = "Cannot install atexit handler",
    [TERM_EISATTY]    = "Filedes is not a tty",
    [TERM_EFLUSH]     = "Cannot flush the device",
	[TERM_EGETATTR]   = "Cannot get the device attributes",
	[TERM_ESETATTR]   = "Cannot set the device attributes",
	[TERM_EBAUD]      = "Invalid baud rate",
	[TERM_ESETOSPEED] = "Cannot set the output speed",
	[TERM_ESETISPEED] = "Cannot set the input speed",
	[TERM_EPARITY]    = "Invalid parity mode",
	[TERM_EDATABITS]  = "Invalid number of databits",
	[TERM_EFLOW]      = "Invalid flowcontrol mode",
    [TERM_EDTRDOWN]   = "Cannot lower DTR",
    [TERM_EDTRUP]     = "Cannot raise DTR",
	[TERM_EDRAIN]     = "Cannot drain the device",
	[TERM_EBREAK]     = "Cannot send break sequence"
};

What is going on here? I've never seen anything like this before. I understand that the TERM_ are defined in the .h file and are an enum, but what's with the square brackets, and how can it be assigned text?

And why is the function ending with a semicolon? Everything about this function is just so weird, and apparently invalid since it's not compiling.

I get

error: expected primary-expression before \u2018[\u2019 token

For each of those lines.
 

TheRyuu

Diamond Member
Dec 3, 2005
5,479
14
81
If you're using gcc you need to add -std=c99 to your command line (as pointed out). Well I guess you could change the syntax if you really wanted to. :p

If you're using msvc well that doesn't support c99 so you'll have to either change it to something that does compile or use a compiler that does support c99 syntax (ICL is the only msvc compatible one that does on windows IIRC). Or alternatively use gcc via mingw/cygwin or something (you can link gcc's object files/static libs in msvc but it can get annoying).

Well I don't think it's the latter since picocom looks like a *nix application.
 

Red Squirrel

No Lifer
May 24, 2003
69,489
13,179
126
www.anyf.ca
Good to know, so is this like a legacy thing? I think I'll just go ahead and change it as later down the line I'll forget that I had to put an extra command and wonder why it's not compiling.
 

TheRyuu

Diamond Member
Dec 3, 2005
5,479
14
81
Good to know, so is this like a legacy thing? I think I'll just go ahead and change it as later down the line I'll forget that I had to put an extra command and wonder why it's not compiling.

c99 is newer than what most compilers default to (c90).
 

piasabird

Lifer
Feb 6, 2002
17,168
60
91
Nevermind.

They are just filling a structure like an array. Based on an error code 0-? it would be used to output an error code. They are filling this constant :const term_err_str[] . Since it is a constant the values never change and cant be altered under normal conditions. Looks like they may be naming each constant value. I have seen such a stucture used for things like day of the week or month of the year.

Normally a constant is defined before the main body of the code. Where did you put this?
 
Last edited:

Glitchny

Diamond Member
Sep 4, 2002
5,679
1
0
Isn't this the normal way to fill out const structs like this? Or am I just confused?

What would be the c90 version of this?
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
What would be the c90 version of this?

There is no C90 equivalent, because there's no way to name array positions algebraically in C90 initializers.

Iff TERM_EOK was 0 and TERM_EBREAK was 19, and all the intervening symbols were numbered adjacently and in order, one could create the same array in C90 by dropping the [TERM_WHATEVER]= parts.

However, in C99, TERM_EOK through TERM_EBREAK can take non-adjacent, out-of-order values, and the indexing later will still work.

E.g., Suppose in "version 1," you have this:

Code:
#define FIRST 0
#define SECOND 1

static const char* const array[] = {
  [FIRST] = "Foo",
  [SECOND] = "Bar"
};

void meh() {
  printf("%s\n", array[FIRST]);
}

The above prints "Foo". But suppose in "version 2" some joker redefines FIRST to something else:
Code:
#define FIRST 2

In C99, meh() will still print "Foo". If you use a C90-style intialization:
Code:
static const char* const array[] = {
  "Foo",
  "Bar"
};
... then you get an undefined result with FIRST == 2.
 

Red Squirrel

No Lifer
May 24, 2003
69,489
13,179
126
www.anyf.ca
Nevermind.

They are just filling a structure like an array. Based on an error code 0-? it would be used to output an error code. They are filling this constant :const term_err_str[] . Since it is a constant the values never change and cant be altered under normal conditions. Looks like they may be naming each constant value. I have seen such a stucture used for things like day of the week or month of the year.

Normally a constant is defined before the main body of the code. Where did you put this?

Yeah I kinda figured that's what they were doing, I just thought it was odd the way it was being done. I did not put this anywhere, this is just code from picocom that I was looking at and I included the header in one of my programs so I can call stuff.

I just commented it out for now. I will probably replace it with a normal function using a switch with case statements. I guess I can kind of see why they did it this way as it's cleaner, though I prefer sticking to something standard that does not require to pass any special compile flags just to make it work.
 

Pia

Golden Member
Feb 28, 2008
1,563
0
0
There is no C90 equivalent, because there's no way to name array positions algebraically in C90 initializers.
You can't name the positions algebraically, but the closest C90 equivalent is manually positioning the wanted initializations as you like and copy-pasting the appropriate amount of dummy initializations in the gaps. That doesn't adapt to future changes in the enum ofc.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
You can't name the positions algebraically, but the closest C90 equivalent is manually positioning the wanted initializations as you like and copy-pasting the appropriate amount of dummy initializations in the gaps. That doesn't adapt to future changes in the enum ofc.

I would argue that it's still not "equivalent", in that the copy-and-paste approach isn't resilient to changes in the definitions of the indexes. The whole point of designated initialization is the maintainability boon of order-independent initialization.
 

Pia

Golden Member
Feb 28, 2008
1,563
0
0
I would argue that it's still not "equivalent", in that the copy-and-paste approach isn't resilient to changes in the definitions of the indexes. The whole point of designated initialization is the maintainability boon of order-independent initialization.
Hence, "closest equivalent". At least you get stuff initialized in arbitrary indices.
BTW, does this C99 feature zero out the rest of the indices or not? I know C is not in the habit of doing things automatically but in this case I can't really imagine a use case where you wouldn't want to zero out the rest.
 
Last edited:

Pia

Golden Member
Feb 28, 2008
1,563
0
0
Lookup table. Standard fare construct in C.
Why wouldn't you want the unpopulated parts of a static lookup table (partially populated using that syntax) zeroed? I don't think it would be a significant perf hit in any conditions since you are only going to construct the table once, and if the table was very sparse you would use a different data structure to begin with, whereas the error detection/handling advantage from nulling the entries is obvious.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Hence, "closest equivalent". At least you get stuff initialized in arbitrary indices.
BTW, does this C99 feature zero out the rest of the indices or not? I know C is not in the habit of doing things automatically but in this case I can't really imagine a use case where you wouldn't want to zero out the rest.

Whoops, sorry, missed the 'closest' part somehow.

As for initialization of unspecified indexes, it probably depends on the scope of the declaration, like other subtle C initialization semantics. And no, sorry, I don't know those by heart -- I always fully initialize.