Pelles C forum

Pelles C => Feature requests => Topic started by: frankie on August 17, 2005, 04:22:36 PM

Title: Substructure member list
Post by: frankie on August 17, 2005, 04:22:36 PM
Pelle,
I don't know if it's an actual limitation or just my way of coding, but if I define a structure or union the IDE member list automatic feature doesn't suggest list members unless I declare indirectly the structure/union in a typedef. I mean:
Code: [Select]
struct tst1 { float a; int b};  /* Indirect declaration */
typedef struct tst1 TypTst1;  /*This works*/

typedef struct { float a; int b} TypTst2;  /* direct declaration don't work */

typedef struct tst2 { float a; int b} TypTst2;  /* defining the tag name don't work either */

If my structure union contains other structure/unions as in:
Code: [Select]
struct tst {
          struct a1 {
                           float f1;
                           int    i1;
                        };
          union a2 {
                           int    c1;
                           float c2;
                        }
           };
typedef struct tst TypTst;

I cannot have the member list of the substructures! :cry:
Anythyng you can do?
Thank-you
Title: Re: Substructure member list
Post by: Pelle on August 17, 2005, 06:55:03 PM
Quote from: "frankie"
I don't know if it's an actual limitation or just my way of coding, but if I define a structure or union the IDE member list automatic feature doesn't suggest list members unless I declare indirectly the structure/union in a typedef.

Mostly limitations, I guess.

You must have a tag name, otherwise it will never work. If the structure is defined in the current source file, the IDE should be able to find it - unless there is a syntax error, like in you example (maybe a typo?):
Code: [Select]

typedef struct tst2 { float a; int b} TypTst2;

- no ; after "int b".

If the definition isn't in the current file, the project must be built - for the browse info database to be updated...

Nested struct/unions are not supported. It has been on the wishlist for a long time, but I'm not sure if/when it will be supported. This will require some changes to the database format, among other things. This, in turn, means I will (probably) have to convert existing databases - not very funny...

Pelle
Title: Substructure member list
Post by: frankie on August 17, 2005, 07:40:31 PM
Pelle wrote:
Quote
unless there is a syntax error, like in you example (maybe a typo?):
Code:

typedef struct tst2 { float a; int b} TypTst2;
 

- no ; after "int b".

Yes it's a typo the program I used for test is compiled correctly.
I see that this is very complicate becouse you need indexing for subtypes in database and this is a rather hard work, but this could be a very useful feature when working with large and complex structures and union.
Anyway thanks and I hope the day you will have time for this is not very far away.
Title: Substructure member list
Post by: Pelle on August 17, 2005, 09:17:31 PM
Maybe in the next version...

I seem to be messing with the browse info in every release - I'm starting to get rather tired of that. A better, and more stable, solution is really needed.

For version 4.0 I researched the possibility to use the compiler to build browse info, rather than a separate tool (pobr), but in the end this was much worse than the current solution.

Maybe it's best to continue with pobr, and extend it with support for nested structures and so on, but I'm not absolutely sure about this...

Pelle
Title: Re: Substructure member list
Post by: Pelle on August 17, 2005, 10:12:21 PM
Frankie,

One other thing - before showing the member list, I try to rebuild browse info for the current source file - but I can only use the current disk image. If the struct definition hasn't been saved to disk yet (you just typed it), this means it will not be found.

I will add a check if the general option 'Save files without prompting before build' is used, and in this case save the file before building the browse info (otherwise I think the user should decide when to save, and when not to...).

This will at least catch some more cases...

Pelle
Title: Substructure member list
Post by: frankie on August 18, 2005, 08:58:24 AM
Pelle,
I always saved my files and made a full compilation before trying the member list feature (that becouse I got aware that you build browsing info's during compilation).
I understand that this task is not easy, but I was wondering if the problem is not in way you handle symbols. I mean actually you collect much information about each of them, but maybe by simplifying the approach you can get the goal. When you meet a structure union you have simply to browse the names inside, if it contains any tag or is named structure you can create a new symbol with that names as if it was and independent structure. If the inner member is nameless you don't need to create another symbol, but simply put all the names together. On member list side it could be just a recursive search, i.e. when the user type the symbol and it is a structure you can show the members related to it, when the user types the structure member restart checking this symbol if it's another structure, and in that case show its membership. What I mean is that to get the complete efficency you don't need complicate relations between database records, but simply to break down to the atom each part and search recursively each time (with a reentrancy limit anyway, I have seen other compiler loop inside the browser generator and stuck).
About the browsing info generation have you thought about using a background task with low priority that continuosly checks and updates the database?
Title: Substructure member list
Post by: Pelle on August 18, 2005, 06:37:14 PM
Quote from: "frankie"
I understand that this task is not easy, but I was wondering if the problem is not in way you handle symbols. I mean actually you collect much information about each of them, but maybe by simplifying the approach you can get the goal. When you meet a structure union you have simply to browse the names inside, if it contains any tag or is named structure you can create a new symbol with that names as if it was and independent structure. If the inner member is nameless you don't need to create another symbol, but simply put all the names together.

On member list side it could be just a recursive search, i.e. when the user type the symbol and it is a structure you can show the members related to it, when the user types the structure member restart checking this symbol if it's another structure, and in that case show its membership. What I mean is that to get the complete efficency you don't need complicate relations between database records, but simply to break down to the atom each part and search recursively each time (with a reentrancy limit anyway, I have seen other compiler loop inside the browser generator and stuck).

Part of the problem is that since declarations can be "recursive", so is the code in POBR. It's actually a chain of functions, and I would have to pass around additional information to know something about "outer scopes". It would be both messy and ugly. It's easier to write each struct/union as a separate item.

I think tag names will always be needed for "top level" structures, especially if it's also a typedef name. I can probably parse the "free text" field, containing the variable declaration, for substructures (especially since it's cleaned up and normalized in v4.0) - but I will not try that right now.

I have, however, rewritten two functions to be recursive, and as long as all structs/unions have tag names, even sub-structs/unions - it seem to work.

For the following code:
Code: [Select]

name1.name2.name3.


when the last . is typed, I scan backwards all the way to name1, and build at list of names - this list is passed to the database search function. It will try to nest into the struct/union. This also means, like before, that you can type name1.name2.name3, move away in the code for a while, get back to the position after name3, press ., and it will still work - in other words, not in a specific "mode" while typing.

Requiring tag names is of course not perfect, but it's surely much better than before. I will include the changes in beta 3 - probably at the beginning of next week.

Quote from: "frankie"

About the browsing info generation have you thought about using a background task with low priority that continuosly checks and updates the database?

Yes - I might do it some day, but I'm a little bit afraid about synchronization problems.

Pelle
Title: Substructure member list
Post by: frankie on August 19, 2005, 10:29:02 AM
Pelle,
About the tag names we can consider that when the tag is missing you cannot reuse the structure definition for another variable (unless you rewrite the whole structure). So the structure name should be unique in the scope. In this case you can use the name assigned to the structure as a tag.
Do you think that this could work?
To reduce the charge on the software could be helpfull to trigger the member list search on user request (by keypress) instead of start it automatically?
Title: Substructure member list
Post by: Pelle on August 19, 2005, 06:24:10 PM
Frankie,

Quote from: "frankie"
About the tag names we can consider that when the tag is missing you cannot reuse the structure definition for another variable (unless you rewrite the whole structure). So the structure name should be unique in the scope. In this case you can use the name assigned to the structure as a tag.
Do you think that this could work?

This might work. The problem here is that since the tag name is found first (if any), I can tag each member as they are found. If I'm going to use the identifier, found last, I will either have to "cache" all members before writing them to the database (more complicated code), or write temporary records to the database and later "patch" them (slow/slower).

Quote from: "frankie"

To reduce the charge on the software could be helpfull to trigger the member list search on user request (by keypress) instead of start it automatically?

Maybe. The most obvious things is of course to use "." or "->" as the trigger - you don't have to learn yet another key combination. Also, any new hotkey means changes to Customize -> Keyboard, which will affect resources and translations - it starts a chain of changes.

My computer may still be on the "top half", although several years old, but I can't notice any slowness here (except perhaps when caching the database for the very first call...)

Pelle
Title: Substructure member list
Post by: frankie on August 19, 2005, 08:53:32 PM
Pelle,
maybe it's me that miss something, but when you found a struct keyword you already know that a struct is following, if a tag is present you can use it, if not you can use a placeholder to update when you meet the name.
Moreover if the substruct is unnamed you can leave the placeholder so while browsing you know that you're working on an unnamed struct.
About the key to trigger the search was an idea based on the fact that if the browser generator code grow-up bigger you can avoid some problems. Anyway I too don't experience any slow-down on my computer for the member list searching.
Title: Substructure member list
Post by: Pelle on August 19, 2005, 09:28:58 PM
What I try to say is that today, in POBR, parsing is intermixed with writing database records. Each structure member will have it's own record.

If the variable name is to be used as a tag, when there is no "real" tag, I will have written all members to the database before the parser sees the variable name. In this case I will have to search the database and update each member record with the new tag. This will take more time, possibly much more time, than today...

Another approach is to build an internal list of all member names and line numbers, and write everything when the entire struct have been parsed. This is at least complicated by the fact that the type parsing is recursive.

Pelle
Title: Substructure member list
Post by: frankie on August 20, 2005, 12:21:31 PM
I understand now, what is still not clear to me is if in the member record you put a reference to the structure tag/name (used as access key for the database) or the reference to the record (in this case a unique record number access key). In the first case it will be a nightmare to update the database, in the second case, if the tag is missing, you can create a dummy record with a placeholder name for the structure while the members will point to this record with a direct record access key. The dummy record could be adjusted when the structure scanning is finished modifying just one record. Of course there could be a difficulty, due to recursion, to know when the scanning is really finished and to trace down the placeholder.
I wan't bother you, I'm just trying to give you some ideas (helpfull I hope). Anyway I'm sure you'll find a very smart solution.
Title: Substructure member list
Post by: Pelle on August 20, 2005, 06:41:06 PM
To make a long story short: I think it's working now. In the end I decided to use fabricated tag names (when they are missing), and fabricated source code in the free text field (to avoid a database conversion nightmare). A bit of a hack, but as I said, it seem to work...

Quote

I wan't bother you, I'm just trying to give you some ideas (helpfull I hope).

Yes, I understand - and I'm grateful for that. It's easy to get stuck in one solution - this discussion has been very useful to me...

Pelle
Title: Substructure member list
Post by: frankie on August 20, 2005, 06:52:37 PM
I'm very happy that you found a good solution  =D> (I just declared that I have no doubt! :wink: ).
When you talk about a fabricated tag name you mean what I called a placeholder (a unique name automatically generated using some structure reference)?
And last I'm very happy to have been of some help.
Hope to see next beta in short (next week as stated above?)
Title: Substructure member list
Post by: Pelle on August 20, 2005, 07:55:04 PM
Quote from: "frankie"

When you talk about a fabricated tag name you mean what I called a placeholder (a unique name automatically generated using some structure reference)?

It's something like: __pobr_tag_sourcefile_nnnn. I added the source file name to make it a bit more unique - and nnnn is just a unique number.

When I want a list of all members, I just search the tag field for members with the given tag - when going deeper into nested structures, I search for a specific member and tag name, then look in text field for "struct tagname" or "union tagname" which will give me (hopefully) a new tag for the next level - and the recursion continues...

Quote from: "frankie"

Hope to see next beta in short (next week as stated above?)

Yes - it looks like monday.

Pelle
Title: Substructure member list
Post by: frankie on August 21, 2005, 05:04:00 PM
Great! :D
Title: Substructure member list
Post by: frankie on August 23, 2005, 12:19:10 PM
Pelle,
as first you made a great job with the new release.
About the memberlist I made some checks with the following:
Code: [Select]
#include <stdio.h>
#include <stdlib.h>

struct ___parts
{
unsigned mantissa:23;
unsigned exponent:8;
unsigned sign:1;
};
typedef struct ___parts T__parts;

union __tst
{
float val;
T__parts parts;
};
typedef union __tst _tst;

union __tst1
{
float val;
struct
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
};
};

union __tst2
{
float val;
struct
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
} parts;
};

union __tst3
{
float val;
struct ___llf
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
   };
};

union __tst4
{
float val;
struct ___llf1
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
   } parts;
};

typedef union __tst1 tst1_typedef;
typedef union __tst2 tst2_typedef;
typedef union __tst3 tst3_typedef;
typedef union __tst4 tst4_typedef;

union __tstArray
{
float val;
struct
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
} parts[10];
} tst10;


int main(int argc, char **argv)
{
union __tst1 tst1;
union __tst2 tst2;
union __tst3 tst3;
union __tst4 tst4;
tst1_typedef tst5;
tst2_typedef tst6;
tst3_typedef tst7;
tst4_typedef tst8;
union __tstArray tst9;
_tst         tst;

tst1.val        = 0.0; //here only member 'val' is found
tst2.parts.sign = 0; //all fields are found!
tst3.val        = 0.0; //here only member 'val' is found
tst4.parts.sign = 0; //here too all fields are found!
tst.val         = 0.0; //in this case the members of parts are not found!
tst5.val        = 0.0; //here only member 'val' is found
tst6.parts.sign = 0; //all fields are found!
tst7.val        = 0.0; //here only member 'val' is found
tst8.parts.sign = 0; //all fields are found!
tst9.parts[1].sign = 0; //all fields are found!
tst10.val        = 0.0; //When the variable is global (outside the scope of a function)
//no member will be found!!!
return 0;
}

As you can see probably some adjustment is still required. In particular if you define a global structure variable (outside scope of any function) the member list don't works. I haven't test with struct pointers (I expect the same behaviour) and limited the check to two levels of structure nesting.
Title: Substructure member list
Post by: frankie on August 23, 2005, 04:41:58 PM
Pelle,
in the meanwhile I tested with pointers to structures, once again if the pointer is a local variable (defined in the function scope) member list works, if it's a global variable the option don't work!
Title: Substructure member list
Post by: Pelle on August 23, 2005, 07:34:16 PM
OK, I will look at it.

Globals have an empty 'text' field right now, so initializing it in the same way as for locals will probably work.

Both globals and locals have a potential problem: I don't attempt to handle the scope, so it's possible to confuse one variable with another. Not sure how common this is - fixing it will be rather complicated, so I would prefer to skip this headache...

Having a struct/union without an identifier (MS specific) is somewhat problematic since I will (again) assign one (possibly fabricated) tag before I know there is no identifier. I might be able to handle it...

Pelle
Title: Substructure member list
Post by: Pelle on August 23, 2005, 11:18:14 PM
The attached version seem to work here - but needs more testing.

Pelle
Title: Substructure member list
Post by: frankie on August 24, 2005, 05:44:49 PM
Pelle,
very good job  :) .
Now it works with the test that follows, fails only when a typedef'd structure contains another typedef'd structure.
Code: [Select]
#include <stdio.h>
#include <stdlib.h>

struct ___parts
{
unsigned mantissa:23;
unsigned exponent:8;
unsigned sign:1;
};
typedef struct ___parts T__parts;

union __tst
{
float val;
T__parts parts;
};
typedef union __tst _tst;

union __tst1
{
float val;
struct
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
};
};

union __tst2
{
float val;
struct
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
} parts;
};

union __tst3
{
float val;
struct ___llf
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
   };
};

union __tst4
{
float val;
struct ___llf1
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
   } parts;
};

typedef union __tst1 tst1_typedef;
typedef union __tst2 tst2_typedef;
typedef union __tst3 tst3_typedef;
typedef union __tst4 tst4_typedef;

union __tstArray
{
float val;
struct
{
unsigned mantissa;
unsigned exponent;
unsigned sign;
} parts[10];
} tst10;

union __tstArray *tst12;
typedef union __tstArray TypedefTest;

void tst(union __tstArray *passedStruct, _tst *passedStruct2)
{
union __tst1 tst1;
union __tst2 tst2;
union __tst3 tst3;
union __tst4 tst4;
tst1_typedef tst5;
tst2_typedef tst6;
tst3_typedef tst7;
tst4_typedef tst8;
union __tstArray tst9;
union __tstArray *tst11;
TypedefTest typedeftst;
_tst         tst;

tst1.sign           = 0; //OK
tst2.parts.sign     = 0; //OK
tst3.sign           = 0; //OK
tst4.parts.sign     = 0; //OK
tst.val             = 0.0; //still not working
tst5.sign           = 0; //OK
tst6.parts.sign     = 0; //OK
tst7.sign           = 0; //OK
tst8.parts.sign     = 0; //OK
tst9.parts[1].sign  = 0; //OK
tst10.parts[2].sign = 0; //OK

tst11 = &tst10;
tst12 = &tst10;
tst11->parts[2].sign = 0; //OK
tst12->parts[3].sign = 0; //OK

passedStruct->parts[1].sign = 0; //OK
passedStruct2->val = 0.0; // NOT OK!

typedeftst.parts[2].sign = 0; //OK
}

I'll keep you updated about next tests.
Title: Substructure member list
Post by: Pelle on August 25, 2005, 08:35:31 PM
The cases:
Code: [Select]

tst.parts.
passedStruct2->parts.

should work now. It's possible to create an even longer chain of typedef's, that will not work, but I'm not sure it is very common. This will in any case slow things down enough to make it nearly useless. To handle most practical cases, rather than every theoretical case, is probably enough for now...

Have you found anything else not working...?

Pelle
Title: Substructure member list
Post by: frankie on August 26, 2005, 12:45:16 PM
Pelle,
I made the following further tests (code added to the previous posted test):
Code: [Select]
typedef unsigned _NewType;

union __tst02
{
float val;
struct ___parts;
_NewType NewType;
};

union __tst03
{
float val;
struct ___parts parts;
_NewType NewType;
};

typedef union __tst03 _tst03;

.... .... .... .... .... ....

void tst(union __tstArray *passedStruct, _tst *passedStruct2)
{
union __tst1 tst1;
union __tst2 tst2;
union __tst3 tst3;
union __tst4 tst4;
tst1_typedef tst5;
tst2_typedef tst6;
tst3_typedef tst7;
tst4_typedef tst8;
union __tstArray tst9;
union __tstArray *tst11;
TypedefTest typedeftst;
_tst         tst;
union __tst  tst01;
union __tst02 tst02;
union __tst03 tst03;
_tst03 TypeDeftst03;

tst1.sign           = 0; //OK
tst2.parts.sign     = 0; //OK
tst3.sign           = 0; //OK
tst4.parts.sign     = 0; //OK
tst.val             = 0.0; //still not working (members of parts not found)
tst5.sign           = 0; //OK
tst6.parts.sign     = 0; //OK
tst7.sign           = 0; //OK
tst8.parts.sign     = 0; //OK
tst9.parts[1].sign  = 0; //OK
tst10.parts[2].sign = 0; //OK

tst11 = &tst10;
tst12 = &tst10;
tst11->parts[2].sign = 0; //OK
tst12->parts[3].sign = 0; //OK

passedStruct->parts[1].sign = 0; //OK
passedStruct2->parts.sign = 0; // NOT OK! (members of parts not found)

typedeftst.parts[2].sign = 0; //OK

tst01.parts.sign = 0; //NOT OK (members of parts not found)
tst02.NewType = 0; //OK
tst03.parts.sign = 0; //OK
TypeDeftst03.parts.sign = 0;//OK
}

Definitely the browser is not working when a typedef'd structure is inserted in another structure. With typedef'd basic variables (as the freshly added NewType) it still works.
Everything works fine if the tag name is used.
Title: Substructure member list
Post by: frankie on August 29, 2005, 10:56:36 AM
Pelle,
I made other checks, and fund that memberlist doesn't work if an inner structure is contained in a header file not directly included by the c file. This means that access to substructure members defined ia a header included by another header are not accessible.
Anyway I immagine that this is already known (becouse actually you don't scan included files).
Title: Substructure member list
Post by: Pelle on August 29, 2005, 06:29:52 PM
Yes, pobr will never scan #include files directly. When building a project, I try to add all dependent files (even #include files) for scanning. This require that the dependency information is up-to-date - "Update all dependencies" is important here...

I also can't see how it can be useful to reference fields from a definition that isn't included - sounds like it should be hard to compile... ;-)

Pelle
Title: Substructure member list
Post by: frankie on August 31, 2005, 03:40:18 PM
Pelle I mean **not directly included** not not included at all, i.e.:
Code: [Select]
FILE MAIN.C:
#include "definitions.h"

.... ... ....
CODE
... ... ... ...

END of MAIN.C

FILE DEFINITIONS.H:
#include "structs.h"
#include "variables.h"
... ... ... ... ...
END of DEFINITIONS.H

In this case with cascade includes normally memberlist doesn't work.

But anyway Pelle it is very functional now (and sufficient for my uses  :wink: ).
So I think it's OK  :mrgreen: .
F.
Title: Substructure member list
Post by: Pelle on August 31, 2005, 08:03:33 PM
Quote from: "frankie"
Pelle I mean **not directly included** not not included at all...

Ah! OK.

Quote from: "frankie"

In this case with cascade includes normally memberlist doesn't work.

No, probably not.

Quote from: "frankie"

But anyway Pelle it is very functional now (and sufficient for my uses  :wink: ).
So I think it's OK  :mrgreen: .
F.

It should work OK now - especially with recent changes.

This will however not work perfectly anymore:
Code: [Select]

union __tst3
{
   float val;
   struct ___llf
   {
      unsigned mantissa;
      unsigned exponent;
      unsigned sign;
   };
};

With an existing tag ('___llf') I can't assign it's members to tag '__tst3' - so they will not show up in the list. No way to solve this, but I'm not sure it's a big problem in real world code.

Pelle
Title: Substructure member list
Post by: frankie on September 01, 2005, 09:57:40 AM
Pelle,
just for sake of curiosity, you wrote:
Quote
With an existing tag ('___llf') I can't assign it's members to tag '__tst3' - so they will not show up in the list.

this seems something like a down-top approach, but could eventually be more functional a top-down approach where you store in main structure record the reference to the included structures? So when you have a symbol that is a structure you have also, in the symbol's record, the tags of all other symbols and structures accessed. This means that, becouse of recursion, you have to modify the main struct record as many times as many symbols it includes. Not easy, but not a complete nightmare.
Anyway you made a great job.
Title: Substructure member list
Post by: Pelle on September 01, 2005, 09:06:20 PM
It might help in this special case, but otherwise not very useful I think.

More redundant info in the database, making it bigger. Not much help during lookup either - I still have to resolve typedef's, since this info might not be available when building the browse info (not in the current file).

Pelle
Title: Substructure member list
Post by: frankie on September 01, 2005, 10:06:52 PM
I see.
Anyway I think that the occourrence of a tag to an unnamed substructure inside a structure is more unique than rare  :mrgreen: . And this kind of definition is not a good practice, for me it's martian code  :lol: .
Thank you for the answer.
Title: Substructure member list
Post by: Pelle on September 04, 2005, 02:56:25 PM
Call it what you like - we seem to agree here... ;-)

Pelle