DEV Community

Cover image for ConfigLang: A Lightweight Configuration Language for Modern Applications
Muhammed Shafin P
Muhammed Shafin P

Posted on

ConfigLang: A Lightweight Configuration Language for Modern Applications

Configuration files are the backbone of modern software development. Whether you're deploying a web server, configuring a database, or setting up environment-specific variables, you need a way to store and manage settings that's both human-readable and programmatically accessible. Enter ConfigLang—a pure C99 embedded configuration language that brings simplicity and type safety to your configuration workflow.

Why Another Configuration Language?

The configuration landscape is crowded with options like JSON, YAML, TOML, and INI files. So why ConfigLang? The answer lies in its unique combination of features: it's written in pure C99 with zero external dependencies, offers a clean C API for easy integration, and includes programming constructs like conditionals and immutable variables that traditional configuration formats lack.

ConfigLang occupies a sweet spot between static configuration files and full programming languages. It gives you just enough logic to handle environment-specific settings without the complexity of a scripting language.

Core Features at a Glance

ConfigLang's syntax is refreshingly simple. Variables are declared with the set keyword, and you can make them immutable using const set. The language supports two fundamental types: integers and strings.

set port = 8080
set host = "localhost"
const set max_connections = 100
Enter fullscreen mode Exit fullscreen mode

What sets ConfigLang apart is its support for conditional logic. You can apply different configurations based on runtime conditions using if statements with standard comparison operators.

Important syntax rules:

  • Variables must be defined before they are referenced in conditional expressions
  • If blocks allow only one set statement
  • The closing brace } must appear on the same line as the statement
set debug = 0
set log_level = "info"

if debug == 0 { set log_level = "error" }
if debug == 1 { set log_level = "debug" }
Enter fullscreen mode Exit fullscreen mode

This feature makes ConfigLang powerful for managing development, staging, and production environments within a single configuration file.

Supported Comparison Operators

ConfigLang supports the following comparison operators in if statements:

  • == - Equal to
  • != - Not equal to
  • > - Greater than
  • < - Less than
  • >= - Greater than or equal to
  • <= - Less than or equal to

All comparisons work with both integers and strings (string comparison is lexicographic).

Syntax Rules and Constraints

ConfigLang enforces several key syntax rules:

Variable Declaration Order

Variables must be declared with set before they can be used in conditional expressions.

# Correct - variable defined first
set mode = "prod"
if mode == "prod" { set port = 80 }

# Incorrect - would cause an error
if mode == "prod" { set port = 80 }
set mode = "prod"
Enter fullscreen mode Exit fullscreen mode

Single Statement Per If Block

Each if block can contain exactly one set statement. This keeps conditional logic simple and prevents complex nested logic.

# Correct
if debug == 1 { set verbose = 1 }

# Incorrect - multiple statements not allowed
if debug == 1 { 
    set verbose = 1
    set trace = 1
}
Enter fullscreen mode Exit fullscreen mode

Inline Closing Braces

The closing brace } must appear on the same line as the set statement within the if block.

# Correct
if production == 0 { set ssl = 0 }

# Incorrect - brace on separate line
if production == 0 { set ssl = 0
}
Enter fullscreen mode Exit fullscreen mode

Chained Conditionals

You can chain multiple if statements without else clauses:

set environment = "production"
set timeout = 30

if environment == "development" { set timeout = 300 }
if environment == "staging" { set timeout = 100 }
if environment == "production" { set timeout = 30 }
Enter fullscreen mode Exit fullscreen mode

Type Safety and Immutability

ConfigLang enforces type safety at runtime. Attempting to retrieve an integer variable as a string—or vice versa—results in a clear type mismatch error. The const keyword prevents accidental modification of critical configuration values, catching bugs before they reach production.

Error codes:

  • ERR_CFG_OK (0) - Success
  • ERR_CFG_PARSE_ERROR (1) - Syntax error during parsing
  • ERR_CFG_FILE_ERROR (2) - File I/O error
  • ERR_CFG_VARIABLE_NOT_FOUND (3) - Variable doesn't exist
  • ERR_CFG_CONST_VIOLATION (4) - Attempted to modify const variable
  • ERR_CFG_TYPE_MISMATCH (5) - Type mismatch (int vs string)
  • ERR_CFG_NULL_POINTER (6) - NULL pointer passed to API
  • ERR_CFG_OUT_OF_MEMORY (7) - Memory allocation failed

C API Reference

The C API is straightforward and minimal:

#include "configlang.h"

// Create and destroy
ConfigLang* cfg_create(void);
void cfg_destroy(ConfigLang* cfg);

// Load configuration
int cfg_load_string(ConfigLang* cfg, const char* code);
int cfg_load_file(ConfigLang* cfg, const char* path);

// Get values (type-safe)
int cfg_get_int(ConfigLang* cfg, const char* name, int* out);
int cfg_get_string(ConfigLang* cfg, const char* name, const char** out);

// Set values (runtime modification)
int cfg_set_int(ConfigLang* cfg, const char* name, int value);

// Save configuration
int cfg_save_file(ConfigLang* cfg, const char* path);

// Error handling
const char* cfg_get_error(ConfigLang* cfg);
Enter fullscreen mode Exit fullscreen mode

Basic Usage Example

ConfigLang* cfg = cfg_create();

// Load from string
const char* config = 
    "set port = 8080\n"
    "set host = \"localhost\"\n"
    "const set max_connections = 100\n";

if (cfg_load_string(cfg, config) != ERR_CFG_OK) {
    fprintf(stderr, "Error: %s\n", cfg_get_error(cfg));
    cfg_destroy(cfg);
    return 1;
}

// Retrieve values
int port;
const char* host;
int max_conn;

cfg_get_int(cfg, "port", &port);
cfg_get_string(cfg, "host", &host);
cfg_get_int(cfg, "max_connections", &max_conn);

printf("Server: %s:%d (max connections: %d)\n", host, port, max_conn);

// Modify non-const value
cfg_set_int(cfg, "port", 9000);

// Save to file
cfg_save_file(cfg, "server.cfg");

cfg_destroy(cfg);
Enter fullscreen mode Exit fullscreen mode

Advanced Features

Variable References

Copy values between variables:

set base_port = 8080
set app_port = base_port
Enter fullscreen mode Exit fullscreen mode

Multiline Strings

Support complex text content using the #%%% delimiter:

set welcome_message = #%%%
Welcome to our application!
This is a multiline message.
%%%#
Enter fullscreen mode Exit fullscreen mode

Comments

Use # for single-line comments:

# This is a comment
set port = 8080  # inline comments not supported
Enter fullscreen mode Exit fullscreen mode

Practical Configuration Example

# Application Configuration
const set app_name = "WebService"
const set version = "1.0.0"

# Environment settings (must be defined before use)
set environment = "production"
set debug = 0

# Port configuration based on environment
set port = 8080
if environment == "production" { set port = 80 }
if environment == "development" { set port = 3000 }

# Debug-dependent settings
set log_level = "info"
if debug == 1 { set log_level = "debug" }

# Connection settings
set max_connections = 100
if environment == "development" { set max_connections = 10 }

# Host configuration
set host = "0.0.0.0"
if debug == 1 { set host = "localhost" }

# Multiline configuration
set startup_banner = #%%%
=================================
  WebService v1.0.0
  Starting on port 80
=================================
%%%#
Enter fullscreen mode Exit fullscreen mode

When to Use ConfigLang

ConfigLang shines in scenarios where traditional configuration formats fall short:

  • Application configuration files with environment-specific settings
  • Build systems managing compiler flags across platforms
  • Feature flags and toggles with type safety
  • Embedded systems (zero-dependency C99 implementation)
  • Game settings requiring runtime validation
  • Simple automation needing configuration with basic logic

Understanding the Limitations

ConfigLang is deliberately constrained to keep it focused on configuration:

  • No floating-point numbers - only integers
  • No arithmetic operations - do calculations in application code
  • No loops - configuration is declarative
  • No arrays or complex data structures - use multiple variables
  • Limited string operations - assignment only
  • Single statement per if block - keeps logic simple
  • No else clauses - use chained if statements instead

These aren't oversights—they're design decisions. ConfigLang isn't trying to replace scripting languages. It's a configuration language that's more powerful than JSON but simpler than a full programming language.

Building and Installation

Compile the Library

gcc -std=c99 -fPIC -shared -o libconfiglang.so configlang.c
Enter fullscreen mode Exit fullscreen mode

Link to Your Application

gcc -o myapp myapp.c -L. -lconfiglang
Enter fullscreen mode Exit fullscreen mode

Or compile directly:

gcc -std=c99 -o myapp myapp.c configlang.c
Enter fullscreen mode Exit fullscreen mode

Configuration Limits

The implementation defines the following limits (configurable in source):

  • MAX_VARIABLES - 128 variables maximum
  • MAX_VAR_NAME - 32 characters for variable names
  • MAX_STRING_VALUE - 1024 characters for string values
  • MAX_LINE_LENGTH - 2048 characters per line
  • MAX_ERROR_MSG - 256 characters for error messages

The Bigger Picture

ConfigLang represents a philosophy: configuration should be simple, safe, and just powerful enough. By combining type safety, immutability, and conditional logic in a minimal syntax with strict constraints, it addresses real pain points in configuration management without introducing unnecessary complexity.

For developers tired of wrestling with YAML indentation errors, JSON's lack of comments, or the complexity of embedding a full scripting language for simple configuration needs, ConfigLang offers a refreshing alternative. It's a tool that does one thing well—managing configuration with just enough logic to be useful and just enough constraints to stay maintainable.

Whether you're building a web service, an embedded system, or a desktop application, ConfigLang gives you the configuration power you need without the complexity you don't.

License

MIT License - suitable for both open-source and commercial projects.

Learn More

Top comments (0)