Zopfli is written in C for portability... wait what? [closed] - c

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
So I am not a C programmer so pardon this question.
I was reading this blog entry Google Zopfli Compression and I was a little dumbfounded by the following sentence : "Zopfli is written in C for portability".
How exactly is C a portable language? Or does he not mean portable in a compile-to-machine-code sense, but some other context? I guess C is more portable than writing assembly code. But is that really the comparison he is trying to make? I hope someone can enlighten me as to what he means and how exactly C is a portable language.
Thanks a lot!

Portable in this context means something like "Anybody can take this source code and compile it on their own computer and have this program." Very nearly all computers drawing power somewhere today have a C compiler available for them (it may not be installed on that machine, but it's either available to be installed or is available as a cross-compiler (eg embedded systems)), so that same source code is portable virtually everywhere. (EDIT: I'm assuming based on context that the source code doesn't have system-specific things in it, as system-specific things would limit your portability.)

"Portability" has multiple meanings, depending on the context:
The C language is "portable" in the sense that C compilers have been written for a wide variety of platforms, from mainframes to microcontrollers;
The language is also "portable" in the sense that there is an agreed-upon standard that implementations conform to (to greater or lesser degree), so you don't have subtly different versions of the language depending on the vendor - the behavior of a conforming program should be the same on any conforming implementation;
C programs that don't make any assumptions about the system they're running on (type sizes, alignment, endianess) or use system-specific libraries are often "trivially" portable; they only need to be recompiled for the target platform, without needing to edit the source code.
Compared to the majority of its contemporaries (Pascal, Fortran, etc.), C is highly portable, and I spent the bulk of the '90s writing C code that had to run on multiple platforms concurrently (one project required the same code to run on Windows NT, Solaris, and Classic MacOS).
C's portability can be summed up as "write once1, build and run everywhere", where Java and C#'s portability can be summed up as "write and build once, run everywhere."
1. Subject to the caveats in the third bullet

For a piece of software to be considered cross-platform, it must be able to function on more than one computer architecture or operating system.
Developing such program can be a time-consuming task because different operating systems have different application programming interfaces (API).
For example, Linux uses a different API for application software than Windows does.
C is a language you can use in most of the API.

C code can be directly called in C++, and easily used in C# and I believe Objective-C. That and the wide availability of c compilers, it does make sense.
Of course, the argument can also be made that Java is more portable as far as running it directly on other machines. But Java can't be moved from language to language as easily.

Related

What are the differences between the various C standard library implementations [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 months ago.
Improve this question
While I was researching how fopen and moreover the structure FILE are built I found out it wasn't all just GNU libc. I began to look closer at the various implementations such as Google's Bionic, Musl, Newlib and several others. Having only been aware of Musl and up until now my understanding was that it was just a more optimized version of gnu libc. I hadn't given much thought about how, or if, they are allowed to differ and how they are possibly similar with the same respect.
Specifically how does the Posix and ANSI C standard dictate the various implementations? Meaning are all fopen and FILE (all libc functions/structures) determined to be built more or less the same? Or is it that they are opaque and just held to the "standard" of operating the same (return values and interfaces exposed)?
Intuitively, I would think its as I have described but maybe Musl is literally built more efficiently and optimized from compilation/linkage.
Any insight is greatly appreciated.
Specifically how does the Posix and ANSI C standard dictate the various implementations?
They don't, they only dictate the expected behavior of calling each of the library's functions.
What are the differences between the various C standard library implementations
You can split this into 2 categories:
implementations for different operating systems. E.g. a standard C library designed for Windows must use the Windows' kernel API and/or depend on other Windows specific dynamically linked libraries, a standard C library designed for Linux must use the Linux kernel API, etc. For operating systems that use micro-kernels or exo-kernels the standard C library could be radically different (e.g. maybe "open()" sends a message to a different process).
implementations for the same OS. In this case most differences are likely minor. E.g. if you asked 5 different programmers to implement their own version of strlen() you might get 2 simple versions that are almost identical, 1 almost as simple version that is slightly different, and 2 complex versions that are very different (and contain highly optimized inline assembly). However; it's convenient to shove things that aren't part of the standard C library into the same library (e.g. OS specific extensions, and extensions like POSIX) so different implementations of the C standard library can have different extensions and/or different versions of extensions.
Of course an implementation of the standard C library can attempt to be portable and support multiple environments (e.g. 32-bit and 64-bit code) and multiple operating systems (e.g. with lots of #ifdef ...); so there's also differences in which targets the source code of a standard C library tries to support.

Is C a single threaded language [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I was recently reading "The C Programming language" by Ritchie, I noticed that C is a single threaded language. Well I want to know what actually is the difference between Single threaded language and multi threaded language. If C is a single threaded, then is it asynchronous or synchronous?
The C programming language is now a standard, so read the C11 specification, that is n1570. Remember that a programming language is a specification (so is defined in some technical report) not a software. Ritchie's book is about an older version of C (written at a time -the 1980s- where multicore computers and multithreading did not exist or where very unusual, and Ritchie himself did not have any such computer or system). The C standard defines (loosely) the behavior of C implementations (and undefined behavior is a very important and tricky notion in it).
There is some thread support in C11.
You could also use C99 (or even C11) with some external libraries, such as pthreads on POSIX, providing threads.
You could view threads (and processes, and files) as some features or abstractions provided by operating systems. A language specification usually don't tell much about them (for example, most OSes have directories, but the C standard don't tell anything about these).
Actually, if you read the C11 standard carefully, you'll probably notice that a computer hardware is not even required (just implicitly subsumed) by it. In principle a C implementation could be a team of humans (and "running a C program on a classroom, considered as a computer" is a nice way of teaching C). In practice, using human slaves as the C implementation is unethical and inefficient, and you should prefer some computer (but what is a computer is not defined by the C11 standard).
It does not depend on the language that it is single or multi-threaded. You can implement threading using libraries. Like in C you have pthread library on POSIX in C99 standards. In python also, you can also create the threads. It is basically related to operating system and usually used where you have some input-output operations.
In computer science, a thread of execution is the smallest sequence of
programmed instructions that can be managed independently by a
scheduler, which is typically a part of the operating system.
Threads in OS

What data structures and algorithms are not implementable in C? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
This may sound naive, but are there any data structures / algorithms that cannot be constructed in C, given enough code? I understand the argument of being Turing complete. I also know it's beneficial to have an elegant solution and that time complexity is important (i.e. more expressive or succinct when implemented in Ruby / Java / C# / Haskell / Lisp). All the languages I've researched or used all seem to have been created or subsequently refactored into C based compilers, interpreters, and/or virtual machines. Are some complex data structures only implementable with an interpreter and/or virtual machine? If that virtual machine or interpreter is C based, isn't that just another data structure abstraction of the underlying C code? i.e. C has a simple type system but serves as the foundation for a dynamic type system. I was surprised to learn metaprogramming seems possible in C using the preprocessor (ioccc.org Immanuel Herrmann). I've also seen some intriguing C algorithms that mimic the concurrency model of Erlang, but don't recall the source.
What inspired this question was the StackOverflow post (Lesser Known Useful Data Structures) and the Patrick Dussud interview on channel9 (Garbage Collection - Past, Present and Future) - explaining how they wrote the the first CLR garbage collector (written in Lisp targeting the JVM, compiled from Lisp to C++ for the CLR).
So, at the end of the day, after I finish punching my cards, I'm wondering if this question is probably more about C programming language design than convenience of programming and time complexity. For example, I could implement a highly complex algorithm in Prolog that is very elegant and quite difficult to understand expressed any other way, but I'm still limited by the assembly instructions and the computer architecture (on/off) at the other end of the stick, so I'd be here all night.
Shor's algorithm for factorizing integers in O((log n)^3) polynomial time cannot be implemented in C, because the computers that it can run on do not yet officially exist. Maybe someday there will be a quantum circuit complete version of C and I'll have to revise my answer.
Joking aside, I don't think anybody can give you a satisfying answer to this. I will try to cover some aspects:
Vanilla, standard C might not be able to make use of the whole feature set of your processor. For example, you are not able to use the TSX feature of recent Intel processors explicitly. You can of course resort to OS primitives, inline assembly, language extensions or third-party libraries to circumvent that.
C by itself is not very good at parallel/asynchronous/concurrent/distributed programming. Some examples of languages that probably make a lot of tasks infinitely easier in this area are Haskell (maybe Data Parallel Haskell soon?), Erlang, etc. that provide very fast and lightweight threads/processes and async I/O. Working with green threads and heavily asynchronous I/O in C is probably less pleasant, although I'm sure it can be done.
In the end, on the user level side of things, of course you can emulate every Turing complete language with any other, as you pointed out so correctly.
Any Turing-complete machine or language can implement any other Turing-complete language, which means it can implement any program in any other Turing-complete language by interpretation if no other way. So the question you're asking is ill-formed; the issue is not whether tasks can be accomplished but how hard you have to work to accomplish them.
C in particular functions almost as a "high-level assembler language", since it will let you get away with many things that more recent languages won't, and thus may allow solutions that would be harder to implement in a more strongly-checked language.
That doesn't mean C is the best language for all those purposes. It forces you to pay much more attention to detail in many areas ranging from memory management to bounds checking to object-orientation (you CAN write OO code in C, but you have to implement it from the ground up). You have to explicitly load and invoke libraries for things that may be built into other languages. C datatypes can be incredibly convoluted (though typedefs and macros can hide much of that complexity). And so on.
The best tool for any given task is the one that (a) you are, or can become, comfortable with; (b) that's a good fit for the task at hand, and (c) that you have available.
Take a look at Turing completeness: Turing Completeness
Basically, any language which is Turing complete can execute all Turing-computable functions. C is a Turing complete language, so in theory you can implement any known solvable algorithm in C (albeit it may be terribly inefficient).

What language to learn for microcontroller programming? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
I'm getting into microcontroller programming and have been hearing contrasting views. What language is most used in the industry for microcontroller programming? Is this what you use in your own work? If not, why not?
P.S.: I'm hoping the answer is not assembly language.
In my experience, you absolutely must know C, and assembly language helps too.
Unless you are dealing with very bare-bones microcontrollers (like the RS08 series), C is by far the language of choice. Get to know C, understand functionality like volatile and const. Also understand the architecture - what is efficient, what isn't, what can the CPU do. These will differ wildly from a "desktop" environment. Learn to love stdint.h.
You will encounter C++ (or a restricted subset) as projects scale up.
However, you need to understand the CPU and how to read basic assembly as a debugging tool. You can't become an excellent embedded developer without this skillset.
What 'contrasting' views have you heard? To some extent it will depend on the microcontroller and the application. However C is available for almost all architectures (I hesitate to say all, but probably all that you will ever encounter); so on that point alone, learning C would give you the greatest coverage.
For all architectures, the availability of an assembler and a C compiler are pretty much a given. For 32-bit and most 16-bit architectures C++ will also be available. Notable exceptions I have encountered are Microchip's PIC24/dsPIC parts for which C++ is not supported by Microchip's own GNU based compiler (although 3rd party compilers may do so).
While there are C++ compilers for 8 bit microcontroller's C++ is not ubiquitous on such platforms, and often the compilers are subsets of the full language. For the types (or more specifically the size) of application for which 8-bit is usually employed, C++ may be useful but not to the extent that it is on much larger applications, so C is generally adequate.
There are lot of myths about C++ in embedded systems; while the language is larger than C and has constructs that may compromise the performance or capacity of your system, you only pay for what you use with C++. But of course if what you use is just the C subset, the C would be adequate in any case.
The point about C (and C++) is that it is a systems level language; it will run on your microprocessor with no additional support save a very simple runtime start-up to initialise the processor (and possibly external SDRAM), initialise static data, establish a stack, and in the case of C++ invoke static constructors. This is why along with target specific assembler, it is used to build operating systems and kernels - it needs no operating system or kernel itself to run.
One of the reasons I suggested that it may depend on the microcontroller is that if for example it is an ARM9 with a few Mb of external SDRAM, and at least say 4Mb Flash (also usually external - memory takes up a lot of die space), then you could run a 'heavyweight' OS on it such as Linux, WinCE, or Symbian, or even a large RTOS such as QNX or VxWorks. Then your choice of language (once you got the OS working), would be influenced by the OS, though for real-time applications C and C++ would still dominate, (or often Ada in military, avionics, and some transport applications).
For mid-size applications - a few hundred KBytes of code and data space - C# running on the .NET-Micro platform is possible; However I sat in a presentation of this at the Embedded Systems Show in the UK a few years ago, just after it was when it was launched; when I asked the question "but is it real-time", and was told, "no you need WinCE for that", there was a gasp and a groan from much of the audience, and some stopped wasting their time an left the presentation there and then (including me).
So I am still interested in the 'contrasting' opinions you have heard; because although it is possible to use other languages; the answer to your question:
What language is most used in the
industry for microcontoller
programming?
then the definitive answer is C; for the reasons I have given. For anyone who might choose to contest this assertion here are the statistics (note the different survey method after 2004 explained in the text). However just to add to the collection of alternatives, I once spent two years programming in Forth on embedded systems, and I know of people still using it, but it is a bit of a niche.
I've successfully used both C and C++ but in almost any microcontroller project you will need to be familiar with the assembly language of the target micro. If only for debugging low level hardware issues assembly will be indispensable, even if it is a cursory familiarity.
I think the hardest thing for me when moving from a desktop environment to a micro was that almost everything needs to be allocated statically. You won't often use malloc/new in a micro unless maybe it has external RAM.
I notice that you also tagged your question with FPGA and Verilog, take a look at Altium, they have a C to Hardware compiler that works really well with their integrated environment.
Regarding assembler:
Prefer C/C++ over assembler as much as possible. You'll get better productivity by writing as much as possible in C or C++. That includes being able to run some of your code on a PC, which can help developing the higher-level code (application-layer functions).
On many embedded platforms, it's good to have someone on the project who is comfortable with a little assembler. Mostly to get start-up code and interrupts going nicely, and perhaps functions for interrupt enable/disable. That's not the same as knowing it really thoroughly--just a basic working knowledge will be sufficient.
If you're porting an RTOS (e.g. µC/OS-II) to a new platform, then you'll have to know your assembler more. But hopefully your RTOS supports your platform well already.
If you're pushing up against CPU performance limits, you probably need to know assembler more thoroughly. But hopefully you're not pushing performance limits much, because that can be a drag on a project's viability.
If you're writing for a DSP, you probably need to know the DSP's assembler fairly thoroughly.
Microcontrollers were originally programmed only in assembly language, but various high-level programming languages are now also in common use to target microcontrollers. These languages are either designed specially for the purpose, or versions of general purpose languages such as the C programming language. Compilers for general purpose languages will typically have some restrictions as well as enhancements to better support the unique characteristics of microcontrollers. Some microcontrollers have environments to aid developing certain types of applications. Microcontroller vendors often make tools freely available to make it easier to adopt their hardware.
Many microcontrollers are so quirky that they effectively require their own non-standard dialects of C, such as SDCC for the 8051, which prevent using standard tools (such as code libraries or static analysis tools) even for code unrelated to hardware features. Interpreters are often used to hide such low level quirks.
Interpreter firmware is also available for some microcontrollers. For example, BASIC on the early microcontrollers Intel 8052[4]; BASIC and FORTH on the Zilog Z8[5] as well as some modern devices. Typically these interpreters support interactive programming.
Simulators are available for some microcontrollers, such as in Microchip's MPLAB environment. These allow a developer to analyze what the behavior of the microcontroller and their program should be if they were using the actual part. A simulator will show the internal processor state and also that of the outputs, as well as allowing input signals to be generated. While on the one hand most simulators will be limited from being unable to simulate much other hardware in a system, they can exercise conditions that may otherwise be hard to reproduce at will in the physical implementation, and can be the quickest way to debug and analyze problems.
You need to know assembly language programming.You need to have good knowledge in C and also C++ too.so work hard on thse things to get better expertize on micro controller programming.
And don't forget about VHDL.
For microcontrollers assembler comes before C. Before the ARMs started pushing into this market the compilers were horrible and the memory and ROM really tiny. There are not enough resources or commonality to port your code so writing in C for portability makes no sense.
Some microcontroller's assembler is less than desirable, and ARM is taking over that market. For less money, less power, and less footprint you can have a 32-bit processor with more resources. It just makes sense. Much if your code will still not port, but you can probably get by with C.
Bottom line, assembler and C. If they advertise BASIC or Java or something like that, mark that company on your blacklist and move on. Been there, done that, have the scars to prove it.
First Assembly. After C.
I think that who knows Assembly and C are better than who knows only C.

Why is C used for writing drivers and OS codes? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Why is C used for writing drivers and OS codes?
Is there a size problem?
Are there any drivers written in other languages?
Which language were XP, Vista, and Solaris written in?
C compiles down to machine code and doesn't require any runtime support for the language itself. This means that it's possible to write code that can run before things like filesystems, virtual memory, processes, and anything else but registers and RAM exist.
In safety-critical environments (think avionics, spacecraft, medical devices, transportation, control software for process control), systems (as well as drivers) are often written using Ada or even SPARK/Ada.
To clarify: C is usually understood to be fairly low level, and pretty much like a "macro language" for assembly itself, that's also where its power is coming from (speed, size, portability).
Ada, on the other, hand has been specifically designed for safety-critical applications with verifiability in mind, to quote Ada 2005 for Mission-Critical Systems:
Ada [9] is the language of choice for many critical systems due to its careful design and the existence of clear guidelines for building high integrity systems [10]
That's also where Ada's support for strong typing comes in, as well as a number of other important features (quoting design for safety):
Programming languages differ wildly in
their appropriateness for use in
safetyrelated systems. Carré et al.
identified six factors that influence
the suitability of a language for
high-integrity applications [Carré
1990]. These are:
Logical soundness
Complexity of definition
Expressive power
Security
Verifiability
Bounded time and space constraints
No standard programming language performs
well in all these areas although some
(such as Pascal and Ada) perform much
better than languages such as C or
C++. In highly critical applications
‘verifiability’ is of great
importance. Certain languages allow
powerful software verification tools
to be used to perform a wide range of
static tests on the code to detect a
range of programming errors.
[...] An
important issue in the selection of a
programming language is the quality of
the available compilers and other
tools. For certain languages validated
compilers are available. While not
guaranteeing perfection, validation
greatly increasing our confidence in a
tool. Unfortunately, validated
compilers are only available for a
limited number of languages, such as
Ada and Pascal. In addition to
compilers, developers of critical
systems will make use of a range of
other tools such as static code
analysis packages. The static tests
that can be performed on a piece of
code vary greatly depending on the
language used. To aid this process it
is common to restrict the features
that are used within certain languages
to a ‘safe subset’ of the language.
Well structured and defined languages
such as subsets of Ada, Pascal and
Modula-2 allow a great many tests to
be performed such as data flow
analysis, data use analysis,
information flow analysis and range
checking. Unfortunately many of these
tests cannot be performed on languages
such as C and C++ .
It would be really beyond the scope of this question to go into even more detail, but you may want to check out some of the following pointers:
Ada compared to C and C++
Ada vs. C
Quantifying the Debate: Ada vs. C++
Why choosing Ada as a teaching language? (Ada vs. C in University)
Comparing Development Costs of C and Ada (summary)
C / C++ / Java Pitfalls
& Ada Benefits
Is Ada a better C?
Ada, C, C++, and Java vs. The Steelman
Ada: Dispelling the Myths
Real-time programming safety in Java and Ada
If anyone wants to look into Ada some more, check out this: Ada Programming (wikibooks)
There are even programming languages that are specifically developed for highly critical applications, such as JOVIAL or HAL/S, the latter of which is used by the space shuttle program.
Is there any drivers written in any other languages?
I have seen some Linux drivers for special hardware being written in Ada, don't know about other operating systems though. However, such drivers usually end up wrapping the the C API.
Because C has the best combination of speed, low memory use, low-level access to the hardware, and popularity.
Most operating systems have a kernel written in C, and applications on top of that written in either C, C++, C# or Obj-C
C is by far the easiest language(other than assembly) to "get going" on bare bones hardware. With C, (assuming you have a 32bit bootloader such as GRUB to do the hard mode switching) all you must do is make a little crt0.asm file that sets up the stack and that's it(you get the language, not including libc). With C++ you must worry about dynamic casts, exceptions, global constructors, overriding new, etc etc.. With C# you must port the .Net runtime(which on it's own basically requires a kernel) and I'm not sure about Obj-C, but Im sure it has some requirements also...
C is simply the easiest language to use for drivers. Not only is it easy to get started with, but also it's easy to know exactly what happens at the machine level. Their is no operator overloading to confuse you and such. Sure it's handy in a "good" environment, but in Ring 0 where a bad pointer not only crashes your application, but usually results in a triple fault(reboot), blue screen, or kernel panic. You really like knowing what goes on in your machine..
"why we are using C language for writing drivers and OS codes.?"
So that programmers won't have to learn new syntax of each new assembly language for each new kind of machine.
"Is there any drivers written in any other languages?"
Historically, assembly languages. I don't remember if PL/S or BLISS could be used for drivers. Maybe B. In modern times, a few brave people use C++ but they have to be very careful. C++ can be used a bit more easily in user mode drivers in some situations.
Lisp machines had their operating systems written in Lisp, which shows that you don't have to use C or assembly. The Lisp machine business was destroyed by the availability of cheap PCs, whose operating systems were of course written in C and assembly.
C was one of the very first languages (that wasn't assembly) that was suitable for writing operating systems, so it caught on early. While other languages have appeared since that are also suitable for writing operating systems in, C has remained popular perhaps due to its long history and the familiarity programmers have with its structure and syntax.
C is also a language that teaches a lot about memory management and is low-level enough to show the barrier between hardware and software. This is something that is rare among many methodologies today, that have grown more towards abstraction way above anything at the hardware level. I find C is a great way to learn these things, while being able to write speedy code at the same time.
Remember that C was originally developed for writing operating systems (in this case - Unix) and similar low-level stuff. It is wery close to the system architecture and does not contain any extra features that we want to control, how they exactly work. However, please note that the rest of the operating system, including the programming libraries, does not have to be written in the same language, as the kernel. The kernel functions are provided through a system of interrupts and in fact such programming libraries can be written in any language that supports assembler snippets.
The most popular operating system nowadays are written in C: Windows, Linux and many other Unix clones, however this is not the rule. There are some object-oriented operating systems, where both the kernel and the programming interface are written in an objective language, such as:
NeXTSTEP - Objective-C
BeOS - C++
Syllable - C++
See: Object-oriented operating system on Wikipedia
Note that in Linux, it is possible to write kernel drivers in the languages other than C (however, it is not recommended). Anyway, everything becomes a machine code when it comes to running it.
"C compiles down to machine code and doesn't require any runtime support for the language itself."
This is the best feature of C
It's my belief that languages like Python, Java, and others are popular mainly because they offer extensive standard libraries that allow the programmer to code a solution in less lines. Literally a ruby programmer can open and read a file in one line where in C it takes multiple lines. However beneath this abstraction are multiple lines. Therefore the same abstraction be done in C and it's recommended. Oddly it seems the C philosophy is not to reduce the total lines of code so there is no organized effort to do so. C seems to be viewed as a language for all processor chips and naturally this means that it's hard to create any 'standard' abstracted one line solutions. But C does allow you to use #ifdef preprocessor commands so in theory you can have multiple variations of an implementation for multiple processors and platforms all on one header file. This can't be the case for python, or java. So while C does not have a fancy standard library it's useful for portability. If your company wants to offer programs that run on computers, embedded, and portable devices then C is your choice language. It's hard to replace C's usefulness in the world.
As another note for machines that have drivers in other languages, there is the SunSpot robotics platform. Drivers for devices that are connected (sensors, motors, and everything else that can communicate via the I/O pins) are written in Java by the user.

Resources