diff --git a/README.md b/README.md
index 888c9b6..f485898 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,9 @@ The following are languages which have built-in support in genco.
* [🌐 JavaScript][js]
[Example][js-example]
+* [🇨 C][c]
+ [Example][c-example]
+
* [🐍 Python][python]
[Example][python-example]
**Requires a `nightly` compiler**
@@ -136,6 +139,8 @@ fn main() {
[dart-example]: https://github.com/udoprog/genco/blob/master/examples/dart.rs
[js]: https://docs.rs/genco/latest/genco/lang/js/index.html
[js-example]: https://github.com/udoprog/genco/blob/master/examples/js.rs
+[c]: https://docs.rs/genco/latest/genco/lang/c/index.html
+[c-example]: https://github.com/udoprog/genco/blob/master/examples/c.rs
[python]: https://docs.rs/genco/latest/genco/lang/python/index.html
[python-example]: https://github.com/udoprog/genco/blob/master/examples/python.rs
[solve namespace conflicts]: https://docs.rs/genco/latest/genco/lang/csharp/fn.import.html
diff --git a/examples/c.rs b/examples/c.rs
new file mode 100644
index 0000000..8eddecb
--- /dev/null
+++ b/examples/c.rs
@@ -0,0 +1,30 @@
+use genco::fmt;
+use genco::prelude::*;
+
+fn main() -> anyhow::Result<()> {
+ let printf = &c::include_system("stdio.h", "printf");
+
+ let day = "tuesday";
+ let name = "George";
+
+ let tokens = quote! {
+ const char* greet_user() {
+ return $(quoted(format!("Hello {}!", name)));
+ }
+
+ int main() {
+ const char* current_day = $(quoted(day));
+ $printf("%s\n", current_day);
+ $printf("%s\n", greet_user());
+ }
+ };
+
+ let stdout = std::io::stdout();
+ let mut w = fmt::IoWriter::new(stdout.lock());
+
+ let fmt = fmt::Config::from_lang::();
+ let config = c::Config::default();
+
+ tokens.format_file(&mut w.as_formatter(&fmt), &config)?;
+ Ok(())
+}
diff --git a/src/lang/c.rs b/src/lang/c.rs
new file mode 100644
index 0000000..be9b763
--- /dev/null
+++ b/src/lang/c.rs
@@ -0,0 +1,162 @@
+//! Specialization for C code generation.
+
+use crate as genco;
+use crate::fmt;
+use crate::quote_in;
+use crate::tokens::{quoted, ItemStr};
+use std::collections::BTreeSet;
+use std::fmt::Write as _;
+
+/// Tokens container specialization for C.
+pub type Tokens = crate::Tokens;
+
+impl_lang! {
+ /// Language specialization for C.
+ pub C {
+ type Config = Config;
+ type Format = Format;
+ type Item = Import;
+
+ fn write_quoted(out: &mut fmt::Formatter<'_>, input: &str) -> fmt::Result {
+ super::c_family_write_quoted(out, input)
+ }
+
+ fn format_file(
+ tokens: &Tokens,
+ out: &mut fmt::Formatter<'_>,
+ config: &Self::Config,
+ ) -> fmt::Result {
+ let mut header = Tokens::new();
+
+ Self::imports(&mut header, tokens);
+ let format = Format::default();
+ header.format(out, config, &format)?;
+ tokens.format(out, config, &format)?;
+ Ok(())
+ }
+ }
+
+ Import {
+ fn format(&self, out: &mut fmt::Formatter<'_>, _: &Config, _: &Format) -> fmt::Result {
+ out.write_str(&self.item)?;
+ Ok(())
+ }
+ }
+}
+
+/// The include statement for a C header file such as `#include "foo/bar.h"` or
+/// `#include `.
+///
+/// Created using the [include()] function.
+#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
+pub struct Import {
+ /// Path to included file.
+ path: ItemStr,
+ /// Item declared in the included file.
+ item: ItemStr,
+ /// True if the include is specified as a system header using `<>`, false if a local header using `""`.
+ system: bool,
+}
+
+/// Format for C.
+#[derive(Debug, Default)]
+pub struct Format {}
+
+/// Config data for C.
+#[derive(Debug, Default)]
+pub struct Config {}
+
+impl C {
+ fn imports(out: &mut Tokens, tokens: &Tokens) {
+ let mut includes = BTreeSet::new();
+
+ for include in tokens.walk_imports() {
+ includes.insert((&include.path, include.system));
+ }
+
+ if includes.is_empty() {
+ return;
+ }
+
+ for (file, system_header) in includes {
+ if system_header {
+ quote_in!(*out => #include <$(file)>);
+ } else {
+ quote_in!(*out => #include $(quoted(file)));
+ }
+ out.push();
+ }
+
+ out.line();
+ }
+}
+
+/// Include an item declared in a local C header file such as `#include "foo/bar.h"`
+///
+/// # Examples
+///
+/// ```
+/// use genco::prelude::*;
+///
+/// let fizzbuzz = c::include("foo/bar.h", "fizzbuzz");
+///
+/// let fizzbuzz_toks = quote! {
+/// $fizzbuzz
+/// };
+///
+/// assert_eq!(
+/// vec![
+/// "#include \"foo/bar.h\"",
+/// "",
+/// "fizzbuzz",
+/// ],
+/// fizzbuzz_toks.to_file_vec()?
+/// );
+/// # Ok::<_, genco::fmt::Error>(())
+/// ```
+pub fn include(path: M, item: N) -> Import
+where
+ M: Into,
+ N: Into,
+{
+ Import {
+ path: path.into(),
+ item: item.into(),
+ system: false,
+ }
+}
+
+/// Include an item declared in a C system header such as `#include `.
+///
+/// # Examples
+///
+/// ```
+/// use genco::prelude::*;
+///
+/// let printf = c::include_system("stdio.h", "printf");
+///
+/// let printf_toks = quote! {
+/// $printf
+/// };
+///
+/// assert_eq!(
+/// vec![
+/// "#include ",
+/// "",
+/// "printf",
+/// ],
+/// printf_toks.to_file_vec()?
+/// );
+/// # Ok::<_, genco::fmt::Error>(())
+/// ```
+pub fn include_system(path: M, item: N) -> Import
+where
+ M: Into,
+ N: Into,
+{
+ Import {
+ path: path.into(),
+ item: item.into(),
+ system: true,
+ }
+}
diff --git a/src/lang/mod.rs b/src/lang/mod.rs
index b98721f..a8205ea 100644
--- a/src/lang/mod.rs
+++ b/src/lang/mod.rs
@@ -17,6 +17,7 @@
//! # }
//! ```
+pub mod c;
pub mod csharp;
pub mod dart;
pub mod go;
@@ -26,6 +27,7 @@ pub mod python;
pub mod rust;
pub mod swift;
+pub use self::c::C;
pub use self::csharp::Csharp;
pub use self::dart::Dart;
pub use self::go::Go;
diff --git a/src/lib.rs b/src/lib.rs
index 0b96cb4..a0d7b6e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -74,6 +74,9 @@
//! * [🌐 JavaScript][js]
//! [Example][js-example]
//!
+//! * [🇨 C][c]
+//! [Example][c-example]
+//!
//! * [🐍 Python][python]
//! [Example][python-example]
//! **Requires a `nightly` compiler**
@@ -134,6 +137,8 @@
//! [dart-example]: https://github.com/udoprog/genco/blob/master/examples/dart.rs
//! [js]: https://docs.rs/genco/latest/genco/lang/js/index.html
//! [js-example]: https://github.com/udoprog/genco/blob/master/examples/js.rs
+//! [c]: https://docs.rs/genco/latest/genco/lang/c/index.html
+//! [c-example]: https://github.com/udoprog/genco/blob/master/examples/c.rs
//! [python]: https://docs.rs/genco/latest/genco/lang/python/index.html
//! [python-example]: https://github.com/udoprog/genco/blob/master/examples/python.rs
//! [solve namespace conflicts]: https://docs.rs/genco/latest/genco/lang/csharp/fn.import.html