understanding C namespaces - c

Quoting from here,
In C, there are two different namespaces of types: a namespace of struct/union/enum tag names and a namespace of typedef names.
name.c
$ cat name.c
#include<stdio.h>
typedef long long long2;
int long2 () {
return 4;
}
int main() {
printf("hello, world!");
return 0;
}
$ gcc name.c -o name
name.c:4: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$
name2.c
$ cat name2.c
#include<stdio.h>
int four() {
return 4;
}
struct dummy {
int member;
};
int main() {
struct dummy four;
}
$ gcc name2.c -o name2
$
I am trying to understand C namespace conflicts.
In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?

C has four different name spaces for identifiers:
Label names (the goto type).
Tags (names of structures, unions and enumerations).
Members of structures and unions (these have a separate namespace per structure/union).
All other identifiers (function names, object names, type(def) names, enumeration constants, etc).
See also C99 6.2.3.
So your two question can be answered as:
Yes, function names and typedef names share the same name space.
No conflict, because the compiler will use scope rules (for function or object names). The identifier in main is said to shadow the global function name, something your compiler will warn you about if you set the warning levels high enough.

But the crucial point on your examples isn't about namespace, but the scope of the names.
In name.c, both long2 are "ordinary identifiers" (share the same name space), and both of them are defined in the same scope, so there is a conflict. (C99 §6.7/3)
If name2.c, the local variable four is in a scope deeper than the function four, so the variable hides the function four (C99 §6.2.1/4).

Your 2nd example does not show "no conflict". There is a conflict! Try this:
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
struct dummy four;
four.member = four();
}
And now this
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
int (*fx)(void) = four; /* "save" function */
struct dummy four; /* hide it */
four.member = fx(); /* use "hidden" fx */
}
In your 2nd example, the variable four hides the function four().

To answer your two questions quick.
Q1. In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
A1. Yes, identifiers for functions and typedef'ed types share the same namespace. So there's a conflict.
Q2. In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
A2. There's no conflict in your 2nd example even though the two identifiers named four belong to the same identifier namesapce, which is Ordinary namespace. Because the variable identifier four in the main is in a function scope, whereas the function identifier four in a file scope. So the latter one is hidden by the former one as the basic scope rule. If you move the variable four to the file scope(global) like below, you'll see an error.
...
struct dummy four; // Error! there's a previous definition
// in this file scope(global).
int main() {
// struct dummy four; // Commented out.
}
Actually, there are four different identifier namespaces: Label, Tag, Member, and Ordinary. You can find details about them at https://en.cppreference.com/w/c/language/name_space

Related

Why can a typedef not share a name with an object but a tag can? [duplicate]

Quoting from here,
In C, there are two different namespaces of types: a namespace of struct/union/enum tag names and a namespace of typedef names.
name.c
$ cat name.c
#include<stdio.h>
typedef long long long2;
int long2 () {
return 4;
}
int main() {
printf("hello, world!");
return 0;
}
$ gcc name.c -o name
name.c:4: error: 'long2' redeclared as different kind of symbol
name.c:3: error: previous declaration of 'long2' was here
$
name2.c
$ cat name2.c
#include<stdio.h>
int four() {
return 4;
}
struct dummy {
int member;
};
int main() {
struct dummy four;
}
$ gcc name2.c -o name2
$
I am trying to understand C namespace conflicts.
In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
C has four different name spaces for identifiers:
Label names (the goto type).
Tags (names of structures, unions and enumerations).
Members of structures and unions (these have a separate namespace per structure/union).
All other identifiers (function names, object names, type(def) names, enumeration constants, etc).
See also C99 6.2.3.
So your two question can be answered as:
Yes, function names and typedef names share the same name space.
No conflict, because the compiler will use scope rules (for function or object names). The identifier in main is said to shadow the global function name, something your compiler will warn you about if you set the warning levels high enough.
But the crucial point on your examples isn't about namespace, but the scope of the names.
In name.c, both long2 are "ordinary identifiers" (share the same name space), and both of them are defined in the same scope, so there is a conflict. (C99 §6.7/3)
If name2.c, the local variable four is in a scope deeper than the function four, so the variable hides the function four (C99 §6.2.1/4).
Your 2nd example does not show "no conflict". There is a conflict! Try this:
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
struct dummy four;
four.member = four();
}
And now this
#include <stdio.h>
int four(void) { return 4; }
struct dummy { int member; };
int main(void) {
int (*fx)(void) = four; /* "save" function */
struct dummy four; /* hide it */
four.member = fx(); /* use "hidden" fx */
}
In your 2nd example, the variable four hides the function four().
To answer your two questions quick.
Q1. In the first case, why is there a conflict? Do functions also belong to the typedef namespace?
A1. Yes, identifiers for functions and typedef'ed types share the same namespace. So there's a conflict.
Q2. In the second case, why is there no conflict at all? The function and the variable both are named four. Why does the compiler allow that? How is &four supposed to be resolved?
A2. There's no conflict in your 2nd example even though the two identifiers named four belong to the same identifier namesapce, which is Ordinary namespace. Because the variable identifier four in the main is in a function scope, whereas the function identifier four in a file scope. So the latter one is hidden by the former one as the basic scope rule. If you move the variable four to the file scope(global) like below, you'll see an error.
...
struct dummy four; // Error! there's a previous definition
// in this file scope(global).
int main() {
// struct dummy four; // Commented out.
}
Actually, there are four different identifier namespaces: Label, Tag, Member, and Ordinary. You can find details about them at https://en.cppreference.com/w/c/language/name_space

Why is GCC make throwing errors and uneccesary warnings only when using the struct name instead of typedef?

I have a program consisting of two source files (farm.c, init.c) and two corresponding header files (farm.h, init.h) Both source files contain header guards and each other, because they both require functions/variables from each other.
init.h:
#ifndef INIT_H
#define INIT_H
#include<stdio.h>
#include<stdlib.h>
#include"farm.h"
#define PIG_SOUND "oink"
#define CALF_SOUND "baa"
enum types {PIG, CALF};
typedef struct resources {
size_t pork;
size_t veal;
size_t lamb;
size_t milk;
size_t eggs;
} resources;
typedef struct animal {
size_t legs;
char* sound;
int efficiency;
void (*exclaim)(struct animal*);
void (*work)(struct animal*, struct resources*);
} animal;
/* I have tried various ways of declaring structs in addition to
the typedef such as this */
//animal stock;
//animal farm;
void make_pig(struct animal* a, int perf);
void make_calf(struct animal* a, int perf);
#endif
farm.h:
#ifndef FARM_H
#define FARM_H
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include"init.h"
/* GCC does not recognise the typedef or struct identifier
until these forward declarations have been made in
addition to the included init.h header file */
//typedef struct animal animal;
//typedef struct resources resources;
void exclaim(animal* b);
void work(struct animal* b, struct resources* s);
#endif
init.c:
#include"init.h"
void make_pig(animal* a, int perf) {
a->legs = 4;
a->sound = PIG_SOUND;
a->efficiency = perf;
a->exclaim = exclaim;
a->work = work;
}
void make_calf(animal* a, int perf) {
a->legs = 4;
a->sound = CALF_SOUND;
a->efficiency = perf;
a->exclaim = exclaim;
a->work = work;
}
farm.c:
#include"farm.h"
int main() {
return 0;
}
void exclaim(animal* a) {
for (int i = 0; i < 3; i++) {
printf("%s ", a->sound);
}
printf("\n");
}
void work(animal* a, struct resources* r) {
if (!strcmp(a->sound, PIG_SOUND)) {
r->pork += a->efficiency;
}
if (!strcmp(a->sound, CALF_SOUND)) {
r->veal += a->efficiency;
}
}
Using both types of names (i.e.,struct ani and animal) normally works perfectly fine on my Linux system with the C99 standard. However when I use struct ani instead of animal here, I get the below warnings for every instance of the type usage for struct ani and struct resources.
lib/farm.h:10:21: warning: ‘struct ani’ declared inside parameter list will not be visible outside of this definition or declaration
10 | void exclaim(struct ani* a);
| ^~~
lib/farm.h:11:33: warning: ‘struct resources’ declared inside parameter list will not be visible outside of this definition or declaration
11 | void work(struct ani* a, struct resources* r);
And 10 warnings in total for every usage of function pointers of the form:
src/init.c:17:16: warning: assignment to ‘void (*)(struct ani *)’ from incompatible pointer type ‘void (*)(struct ani *)’ [-Wincompatible-pointer-types]
17 | a->exclaim = exclaim;
| ^
src/init.c:18:13: warning: assignment to ‘void (*)(struct ani *, struct resources *)’ from incompatible pointer type ‘void (*)(struct ani *, struct resources *)’ [-Wincompatible-pointer-types]
18 | a->work = work;
Can someone please explain why such behaviour occurs and how I can avoid problems? It typically takes me an unfeasible amount of time to solve these errors and I still don't truly understand my mistake in the first place.
You've hit one of the odd corner cases of C scoping rules.
Informally, a tagged struct (or union, but I'm not going to repeat that over and over) springs into existence when it is named if no declaration for it is visible. "Springs into existence" means that it is considered declared in the current scope. Also, if a tagged struct was previously named in a scope and you then declare a struct with the same tag, the two structs are considered the same. Until a declaration for the struct is completed, the struct is considered an incomplete type, but a pointer to an incomplete type is a complete type, so you can declare a pointer to a tagged struct before you actually complete the definition of the struct.
Most of the time, that just works with minimal thought. But function prototypes are a bit special, because a function prototype is a scope, all by itself. (The scope lasts only until the end of the function declaration.)
When you put that together, you end up with the issue you're facing. You cannot use a pointer to a tagged struct in a function prototype unless the tagged struct was known before the function prototype appears. If it had been mentioned before, even in an outer scope, the tag is visible and therefore will be considered to be the same struct (even if it is still incomplete). But if the tag was not previously visible, a new struct type will be created within the prototype scope, which will not be visible after that scope ends (which is almost immediately).
Concretely, if you write the following:
extern struct animal * barnyard;
void exclaim(struct animal*);
then the two uses of struct animal refer to the same struct type, which will presumably be completed later (or in another translation unit).
But without the extern struct animal * barnyard; declaration, the struct animal named in the exclaim prototype is not previously visible, so thus is declared only in the prototype scope, so it is not the same type as some subsequent use of struct animal. Had you put the declarations in the opposite order, you would have seen a compiler warning (assuming you'd asked for compile warnings):
void exclaim(struct animal*);
extern struct animal * barnyard;
(On godbolt, bless it's heart)
A typedef declaration performs the same way as the extern declaration above; the fact that it is a type alias is not relevant. What's important is that the use of struct animal in the declaration causes the type to spring into existence, and you can subsequently use it freely in a prototype. That's the same reason that the function pointers inside your struct definitions are OK; the start of the struct definition was sufficient to cause the tag to be declared, so the prototype sees it.
In fact, any syntactic construction which contains a tagged struct (struct whatever) will serve the same purpose, because what matters is the effect of mentioning a tagged struct with no visible declaration. Above, I used extern global declarations as examples because they are lines which might appear in a header, but there are many other possibilities, including even the declaration of a function which returns a pointer to a struct (because the return type of a function declaration is not in the prototype scope).
See below for some additional comments about the edited question.
My personal preference is to always use typedefs as forward declarations of tags, and never use struct foo anywhere in my code other than the typedef and the subsequent definition:
typedef struct Animal Animal;
void exclaim(Animal*);
// ...
// Later or in a different header
struct Animal {
Animal* next;
void (*exclaim)(Animal *);
// etc.
};
Note that I always use the same identifier for the tag and the typedef. Why not? There's no confusion and tags have not been in the same namespace as other identifiers since C was premordial.
For me, a big advantage of this style is that it lets me separate implementation details; the public header only contains the typedef declarations (and prototypes which use that type) and only the implementation needs to contain the actual definitions (after first having included the public header).
Note: since this answer was written, the question was edited to add a more detailed code sample. For now, I'll just leave these additional notes here:
On the whole, you get better answers when you provide better information. Since I couldn't see your actual code, I did the best I could, which was to try to explain what is going on, leaving you to apply that to your actual code.
In the code you have now added to the question, there is a circular header dependency. These should be avoided; it's almost impossible to get them right. The circular dependency means that you don't control the order of inclusion, so a declaration in one header might not come before the use in another header. You no longer have a forward declaration, because, depending on the inclusion order, it might be a backward declaration.
To resolve the circular dependency, abstract out the shared components and put them in a new header file. Here, forward declarations of structs (using, for example, typedefs) are highly useful because they don't depend on anything used in the definition of the struct. A shared header might include only typedefs, or it might also include prototypes which don't require additional dependencies.
Also, avoid putting long lists of library includes in your header files; include only those headers actually necessary to define types actually used in the header.

How to define a struct in a struct and reuse the same name twice?

I have a simple C code example using a struct in a struct.
I need for documentation (doxygen) a named struct, in my example HermannS.
In doxygen I can refer to age with \ref ottoS::HermannS::age.
In doxygen I can not use \ref ottoS.name.age etc
For logic the name HermannS have to be the same.
Problem: But now the code create an redefinition-error
struct ottoS {
struct HermannS {
int age;
} name;
};
struct otherS {
struct HermannS {
int size;
} name;
};
int main ()
{
return 0;
}
I get the following error-message:
main.c:16:10: error: redefinition of ‘struct HermannS’
struct HermannS {
^~~~~~~~
main.c:10:10: note: originally defined here
struct HermannS {
^~~~~~~~
Question: how to define a struct in a struct and reuse the name HermannS ?
better Question: is there a gcc extension (prefix) to hide this error?
→ but this would be a very high price to pay for a simple doxygen documentation issue.
A struct declaration does not create a new namespace in C the way it does in C++, so you can't create type names that are "local" to a struct type. The tag name HermannS can only be used for one struct type definition.
C has four name spaces:
all labels (disambiguated by : or goto);
all tag names (disambiguated by struct, union, or enum)
member names (disambiguated by . or ->)
all other names (typedef names, enumeration constants, variable names, function names, etc.)
Unfortunately, what you're trying to do won't work in C - you'll have to use a different tag name for each inner struct definition.
You can't, as the compiler is telling you, and you really do not need to either. If you're not using that structure anywhere else, just don't name it:
struct ottoS {
struct {
int age;
} name;
};
struct otherS {
struct {
int size;
} name;
};
The only other (obvious) solution is to name the two inner structs differently.
If your logic/code/documentation is based on the fact that you need those two different structures to have the same name, then I would advise revisiting the logic, because it looks flawed.
is there a gcc extension (prefix) to hide this error?
No there is not. This is not a simple error, it's invalid C code: you are effectively defining two different types under the same name. The compiler will not be able to compile your code unless you avoid this.
C standard say in section 6.7.2.1 para 8
The presence of a struct-declaration-list in a
struct-or-union-specifier declares a new type, within a translation
unit.
So all structs within the same translation unit share the same namespace.
HermannS is redefined thus code is ill-formed.
Some workaround would be adding a prefix with the parent structure name:
struct ottoS {
struct ottoS_HermannS {
int age;
} name;
};
struct otherS {
struct otherS_HermannS {
int size;
} name;
};
Latest C standards allow the implementation to accept characters from the extended set like $. It will help avoid collisions with more conventional names. It works with gcc. However, the code will no longer be portable.
struct ottoS {
struct ottoS$HermannS {
int age;
} name;
};
struct otherS {
struct otherS$HermannS {
int size;
} name;
};
It mimics :: operator form C++ a bit. You could use some other unicode character and use it to postprocess your Doxygen documentation with sed-like tool. I mean replacing magic character with ::.
As the program is ill-formed it will not compile. However if struct HermannS is never used except the declaration then you could use the following trick.
If HermannS is removed then ottoS.name and otherS.name would become anonymous structs and the code would compile. All anonymous structs are independent types. Just pass -DHermannS= to the GCC's command.
gcc prog.c -DHermannS=
It will add a macro HermannS that expands to an empty token.
Do not pass this option to doxygen to let it generate a proper documentation.

Namespace lookup order in C

Is there an order of lookup in the namespaces namely, tag namespace and ordinary name space ? Consider the following code :
#include <stdio.h>
int main (void){
typedef struct{ //This belongs to ordinary name space
int min;
} st;
st myst;
myst.min=6;
struct myst{ // This belongs to tag name space
int min;
};
myst.min=7;
printf("%d\n%d\n",myst.min,myst.min);
return 0;
}
Output
7
7
The compiler looks for the variable to print in the tag namespace first , I guess. I don't know if the lookup is even done for the same identifier in the ordinary namespace and if it is done I am clueless why it doesn't print it.
There is no namespace lookup order in C. Only one namespace is ever considered for any particular identifier; it is determined by what kind of identifier is being looked up. Structure tags are one kind, with their own namespace; variable names are in the broader category of "ordinary identifiers", which have a separate namespace. There are other name spaces, too, but the compiler can always tell from context which one is relevant to any given identifier.
Thus, in your program, both uses of myst.min refer to the variable declared as st myst; and there isn't any second variable in the "tag" namespace (as you seem to have thought there would be).
You can see this for yourself by commenting out everything within main above myst.min = 7:
#include <stdio.h>
int main (void){
#if 0
typedef struct{ //This belongs to ordinary name space
int min;
} st;
st myst;
myst.min=6;
#endif
struct myst{ // This belongs to tag name space
int min;
};
myst.min=7;
printf("%d\n%d\n",myst.min,myst.min);
return 0;
}
Attempting to compile this will produce a hard error:
test.c: In function ‘main’:
test.c:14:3: error: ‘myst’ undeclared (first use in this function)
What the struct myst declaration does is declare another type, which you can then use to declare variables. But it's not used for anything unless you actually do that. For instance
#include <stdio.h>
typedef struct { int min; } st;
struct myst { int min };
int main(void)
{
// uses the typedef name 'st', in the ordinary namespace,
// to declare the variable 'myst', also in the ordinary namespace
st myst = { 6 };
// uses the struct name 'myst', in the tag namespace,
// to declare the variable 'myst2', in the ordinary namespace
struct myst myst2 = { 7 };
printf("%d %d\n", myst.min, myst2.min);
return 0;
}
will print 6 7. This program also illustrates how myst, the variable, and myst, the struct tag, are indeed in two different namespaces and can be referred to independently.
(Thanks to John Bollinger for the new first paragraph. —ed)
C namespaces are completely disjoint. Each identifier is searches ony in one namespace. For example:
Identifiers that follow structand union keywords are searched in the tag namespace
Identifiers that follow the goto keyword are searched in the label namespace
Identifiers that follow . or -> symbols are searched in their structure or union member namespace (each structure and union has its own member namespace; type of the preceding expression determines which one to search)
Other identifiers are searched in the ordinary namespace.
There is no lookup order. The (unique) namespace to search is completely determined by the context.

How can I return an anonymous struct in C?

Trying some code, I realized that the following code compiles:
struct { int x, y; } foo(void) {
}
It seems as if we are defining a function named foo which returns an anonymous struct.
Does it only happen to compile with my compiler or is this legal C(99)?
If so, what is the correct syntax for a return statement and how can I correctly assign the returned value to a variable?
The struct you're returning is not an anonymous struct. The C standard defines an anonymous struct as a member of another struct that doesn't use a tag. What you're returning is a struct without a tag, but since it isn't a member, it is not anonymous. GCC uses the name < anonymous > to indicate a struct without a tag.
Let's say you try to declare an identical struct in the function.
struct { int x, y; } foo( void )
{
return ( struct { int x, y; } ){ 0 } ;
}
GCC complains about it: incompatible types when returning type 'struct < anonymous>', but 'struct <anonymous>' was expected.
Apparently the types are not compatible. Looking in the standard we see that:
6.2.7 Compatible type and composite type
1: Two types have compatible type if their types are the same. Additional rules for determining whether two types are compatible are described in 6.7.2 for type specifiers, in 6.7.3 for type qualifiers, and in 6.7.6 for declarators. Moreover, two structure, union, or enumerated types declared in separate translation units are compatible if their tags and members satisfy the following requirements: If one is declared with a tag, the other shall be declared with the same tag. If both are completed anywhere within their respective translation units, then the following additional requirements apply: there shall be a one-to-one correspondence between their members such that each pair of corresponding members are declared with compatible types; if one member of the pair is declared with an alignment specifier, the other is declared with an equivalent alignment specifier; and if one member of the pair is declared with a name, the other is declared with the same name. For two structures, corresponding members shall be declared in the same order. For two structures or unions, corresponding bit-fields shall have the same widths. For two enumerations, corresponding members shall have the same values.
The second bold part, explains that if both struct are without the tag, such as in this example, they have to follow additional requirements listed following that part, which they do. But if you notice the first bold part, they have to be in separate translation units, and structs in the example aren't. So they are not compatible and the code is not valid.
It is impossible to make the code correct since if you declare a struct and use it in this function. You have to use a tag, which violates the rule that both have structs have to have the same tag:
struct t { int x, y; } ;
struct { int x, y; } foo( void )
{
struct t var = { 0 } ;
return var ;
}
Again GCC complains: incompatible types when returning type 'struct t' but 'struct <anonymous>' was expected
This works in my version of GCC, but seems like a total hack. It is perhaps useful in auto-generated code where you don't want to deal with the additional complexity of generating unique structure tags, but I'm sort of stretching to come up with even that rationalization.
struct { int x,y; }
foo(void) {
typeof(foo()) ret;
ret.x = 1;
ret.y = 10;
return ret;
}
main()
{
typeof(foo()) A;
A = foo();
printf("%d %d\n", A.x, A.y);
}
Also, it's dependent on typeof() being present in the compiler -- GCC and LLVM seem to support it, but I'm sure many compilers do not.
You probably cannot explicitly return some aggregate value from your function (unless you use a typeof extension to get the type of the result).
The moral of the story is that even if you can declare a function returning an anonymous struct, you should practically never do that.
Instead, name the struct and code:
struct twoints_st { int x; int y; };
struct twoints_st foo (void) {
return ((struct twoints_st) {2, 3});
};
Notice that it is syntactically ok, but it is generally undefined behavior at execution to have a function without return (e.g., you could call exit inside it). But why would you want to code the following (probably legal)?
struct { int xx; int yy; } bizarrefoo(void) { exit(EXIT_FAILURE); }
Here's a way to return anonymous structs in C++14 without any hacks I just discovered.
(C++ 11 should be sufficient, I suppose)
In my case a function intersect() returns std::pair<bool, Point> which is not very descriptive so I decided to make a custom type for the result.
I could have made a separate struct but it wasn't worth since I would need it only for this special case; that's why I used an anonymous struct.
auto intersect(...params...) {
struct
{
Point point;
bool intersects = false;
} result;
// do stuff...
return result;
}
And now, instead of the ugly
if (intersection_result.first) {
Point p = intersection_result.second
I can use the much better looking:
if (intersection_result.intersects) {
Point p = intersection_result.point;
You could define a structure in specification of the return argument. Moreover you can use compound literals introduced in C99 for brevity:
#include<stdio.h>
struct foo { int x, y; }
foo( void )
{
return (struct foo){ 1, 2 } ;
}
int main()
{
struct foo res = foo();
printf("%d %d\n", res.x, res.y);
}
prints:
1 2
The code compiles in pedantic mode for C99 with no warnings. Note that the tag name is the same as function. This works because namespaces for structs and global objects are separated. This way you minimize the chances for accidental conflict of names. You can use something like foo_result if you consider it more suitable.
Or you could create infinite recursion:
struct { int x, y; } foo(void) {
return foo();
}
Which I think is completely legal.
This works up to the newest version of GCC. It is particularly useful for creating dynamic arrays with macros. For instance:
#define ARRAY_DECL(name, type) struct { int count; type *array; } name
Then you can make the array with realloc, etc. This is useful because then you can create a dynamic array with any type, and there is one way to make all of them. Otherwise, you would end up using a lot of void *'s and then writing functions to actually get the values back out with casts and such. You can shortcut all of this with macros; that is their beauty.

Resources