Skip to main content

Embedded configuration and automation language library

Project description

ConfigLang

An embedded configuration and automation language library written in pure C99 with Python bindings. ConfigLang provides a simple, readable syntax for configuration files with support for variables, conditionals, and type safety.

Features

  • Pure C99 - No external dependencies
  • Python Bindings - Easy integration with Python projects
  • Type System - Integer and string types with type checking
  • Const Variables - Immutable configuration values
  • Conditionals - If logic for dynamic configuration
  • Variable References - Copy values between variables
  • Multiline Strings - Support for complex text values
  • Comments - Single-line comments with #
  • Save/Load - Persist configuration state to files

Language Syntax

Critical Syntax Rules

Important constraints to remember:

  1. Variables must be defined before use - You cannot reference a variable in a conditional before it has been declared with set
  2. Single statement per if block - Each if block can contain only ONE set statement
  3. Closing brace on same line - The } must appear on the same line as the statement inside the if block
  4. No else clause - Use chained if statements instead of if-else

Variables

Set integer or string variables:

set x = 10
set name = "Hello World"
set count = 42

Const Variables

Create immutable variables:

const set max_users = 100
const set app_name = "MyApp"

Attempting to modify a const variable will raise an error.

Variable References

Copy values from one variable to another:

set original = 42
set copy = original

set name = "Config"
set backup = name

Conditionals

CORRECT: Basic if statement with closing brace on same line:

set value = 60
if value > 50 { set value = 50 }

CORRECT: Variable must be defined before use in condition:

set debug = 0
set log_level = "info"
if debug == 1 { set log_level = "debug" }

CORRECT: Chained if statements for multiple conditions:

set environment = "production"
set timeout = 30

if environment == "development" { set timeout = 300 }
if environment == "staging" { set timeout = 100 }
if environment == "production" { set timeout = 30 }

CORRECT: Chained if statements (if-if pattern):

set x = 55
if x > 50 { set x = 50 } if x < 10 { set x = 10 }

INCORRECT: Closing brace on separate line:

# This will fail to parse!
if value > 50 { 
    set value = 50
}

INCORRECT: Multiple statements in if block:

# This will fail - only ONE set per if block!
if debug == 1 {
    set verbose = 1
    set trace = 1
}

INCORRECT: Variable used before definition:

# This will fail - x is not defined yet!
if x > 50 { set x = 50 }
set x = 55

Comparison Operators

All standard comparison operators are supported:

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

Example:

set x = 10
if x >= 10 { set ready = 1 }
if x != 0 { set active = 1 }

Multiline Strings

For complex text content, use multiline delimiters:

set config = #%%%
line 1
line 2
line 3
%%%#

Comments

Single-line comments start with #:

# This is a comment
set x = 10  # Inline comment

Installation

C Library

Compile the C library:

# Linux/macOS
gcc -shared -fPIC -std=c99 -o libconfiglang.so configlang.c

# macOS (alternative)
gcc -shared -fPIC -std=c99 -o libconfiglang.dylib configlang.c

# Windows
gcc -shared -o configlang.dll configlang.c

Compile the test program:

gcc -std=c99 -o test test.c configlang.c
./test

Python Package

Install from source:

pip install .

Or install in development mode:

pip install -e .

Usage Examples

C API

#include "configlang.h"
#include <stdio.h>

int main(void) {
    // Create instance
    ConfigLang* cfg = cfg_create();
    
    // Load configuration
    const char* code = 
        "set port = 8080\n"
        "set host = \"localhost\"\n"
        "const set max_connections = 100\n"
        "if port < 1024 { set port = 8080 }\n";
    
    int result = cfg_load_string(cfg, code);
    if (result != ERR_CFG_OK) {
        fprintf(stderr, "Error: %s\n", cfg_get_error(cfg));
        cfg_destroy(cfg);
        return 1;
    }
    
    // Get values
    int port;
    const char* host;
    
    cfg_get_int(cfg, "port", &port);
    cfg_get_string(cfg, "host", &host);
    
    printf("Server: %s:%d\n", host, port);
    
    // Modify value
    cfg_set_int(cfg, "port", 9000);
    
    // Save configuration
    cfg_save_file(cfg, "server.cfg");
    
    // Cleanup
    cfg_destroy(cfg);
    
    return 0;
}

Python API

from configlang import ConfigLang

# Create instance
cfg = ConfigLang()

# Load configuration
code = """
set debug = 0
set port = 8080
set host = "localhost"
const set max_connections = 100
if debug == 1 { set port = 3000 }
"""

cfg.load_string(code)

# Get values
print(f"Port: {cfg.get_int('port')}")
print(f"Host: {cfg.get_string('host')}")

# Modify value
cfg.set_int('port', 9000)

# Dictionary-style access
cfg['port'] = 3000
print(f"Port: {cfg['port']}")

# Save configuration
cfg.save_file('server.cfg')

Context Manager (Python)

with ConfigLang() as cfg:
    cfg.load_string('set x = 10\nset name = "Test"')
    print(cfg.get_int('x'))
    # Automatically cleaned up

API Reference

C Functions

Function Description
cfg_create() Create a new ConfigLang instance
cfg_destroy(cfg) Destroy instance and free resources
cfg_load_file(cfg, path) Load configuration from file
cfg_load_string(cfg, code) Load configuration from string
cfg_get_int(cfg, name, out) Get integer variable value
cfg_get_string(cfg, name, out) Get string variable value
cfg_set_int(cfg, name, value) Set integer variable value
cfg_save_file(cfg, path) Save configuration to file
cfg_get_error(cfg) Get last error message

Python Methods

Method Description
ConfigLang() Create new instance
load_file(path) Load configuration from file
load_string(code) Load configuration from string
get_int(name) Get integer variable value
get_string(name) Get string variable value
set_int(name, value) Set integer variable value
save_file(path) Save configuration to file
get_error() Get last error message
get(name) Auto-detect type and get value

Error Codes

Code Constant Description
0 ERR_CFG_OK Success
1 ERR_CFG_PARSE_ERROR Syntax error in configuration
2 ERR_CFG_FILE_ERROR File I/O error
3 ERR_CFG_VARIABLE_NOT_FOUND Variable doesn't exist
4 ERR_CFG_CONST_VIOLATION Attempted to modify const variable
5 ERR_CFG_TYPE_MISMATCH Variable type mismatch
6 ERR_CFG_NULL_POINTER NULL pointer passed
7 ERR_CFG_OUT_OF_MEMORY Memory allocation failed

Python Exceptions

  • ConfigLangError - Base exception class
  • ParseError - Syntax error in configuration
  • VariableNotFoundError - Variable doesn't exist
  • ConstViolationError - Attempted to modify const variable
  • TypeMismatchError - Variable type mismatch

Example Configuration File

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

# Server Settings
set debug = 0
set host = "0.0.0.0"
set port = 8080

# Apply production settings
if debug == 0 { set port = 80 }
if debug == 0 { set workers = 4 }

# Apply development settings
if debug == 1 { set port = 8080 }
if debug == 1 { set workers = 1 }

# Database Configuration
set db_host = "localhost"
set db_port = 5432
set db_name = "myapp"

# Limits
const set max_connections = 100
const set timeout = 30

# Multiline description
set description = #%%%
This is a multi-line
application description
that spans several lines.
%%%#

Complete Working Example

This example demonstrates all features with correct syntax:

# ============================================
# Complete ConfigLang Example
# ============================================

# Constants (immutable)
const set APP_NAME = "WebServer"
const set VERSION = "2.0.0"
const set MAX_USERS = 1000

# Environment variable
set environment = "production"

# Default values
set port = 8080
set host = "localhost"
set workers = 2
set timeout = 30
set log_level = "info"

# Production configuration
if environment == "production" { set port = 80 }
if environment == "production" { set host = "0.0.0.0" }
if environment == "production" { set workers = 8 }
if environment == "production" { set log_level = "warning" }

# Development configuration  
if environment == "development" { set port = 3000 }
if environment == "development" { set host = "127.0.0.1" }
if environment == "development" { set workers = 1 }
if environment == "development" { set log_level = "debug" }

# Staging configuration
if environment == "staging" { set port = 8080 }
if environment == "staging" { set workers = 4 }

# Database settings
set db_enabled = 1
set db_host = "localhost"
set db_port = 5432

if db_enabled == 1 { set db_name = "production_db" }
if db_enabled == 0 { set db_name = "test_db" }

# Feature flags
set feature_cache = 1
set feature_logging = 1

if feature_cache == 1 { set cache_size = 1024 }
if feature_logging == 1 { set log_size = 100 }

# Variable references
set backup_host = host
set backup_port = port

# Multiline content
set welcome = #%%%
=========================================
  Welcome to WebServer v2.0.0
  Environment: production
  Running on: 0.0.0.0:80
=========================================
%%%#

Language Grammar

program      → statement*
statement    → comment | set_stmt | if_stmt
comment      → '#' text '\n'
set_stmt     → 'const'? 'set' identifier '=' value
if_stmt      → 'if' condition '{' set_stmt '}' if_stmt?
condition    → identifier operator value
operator     → '>' | '<' | '>=' | '<=' | '==' | '!='
value        → integer | string | identifier | multiline
integer      → '-'? [0-9]+
string       → '"' [^"]* '"'
multiline    → '#%%%' .* '%%%#'
identifier   → [a-zA-Z_][a-zA-Z0-9_]*

Key Grammar Notes:

  • if_stmt can only contain ONE set_stmt inside the braces
  • The closing } must be on the same line as the set_stmt
  • Chaining is done by following one if_stmt with another if_stmt
  • There is no separate else keyword - use chained if statements

Type System

ConfigLang has a simple type system with two types:

  1. Integer - Signed integers (e.g., 42, -10, 0)
  2. String - Text values (e.g., "Hello", "Config")

Types are checked at runtime. Attempting to get or set a variable with the wrong type will result in a TYPE_MISMATCH error.

Implementation Limits

The C implementation defines these 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

Limitations

  • No floating-point numbers (integers only)
  • No arithmetic operations (use for configuration, not computation)
  • No loops (conditionals only)
  • No functions or procedures
  • No arrays or complex data structures
  • String operations are limited to assignment
  • Only one set statement per if block
  • No else keyword - use chained if statements instead
  • Closing brace must be on same line as the statement
  • Variables must be declared before use in conditionals

Use Cases

ConfigLang is designed for:

  • Application configuration files
  • Build system configuration
  • Environment-specific settings
  • Feature flags and toggles
  • Embedded system configuration
  • Game settings and preferences
  • Simple automation scripts

Best Practices

  1. Define variables before conditionals: Always declare variables with set before using them in if conditions
  2. Use chained if statements: Instead of if-else, use multiple if statements
  3. Keep conditionals simple: Each if block should modify only one variable
  4. Use const for fixed values: Mark configuration values that shouldn't change as const
  5. Group related settings: Use comments to organize your configuration into logical sections
  6. One line per if block: Keep the syntax compact with if condition { set var = value }

Common Patterns

Environment-Based Configuration

set env = "production"
set port = 80

if env == "development" { set port = 3000 }
if env == "staging" { set port = 8080 }
if env == "production" { set port = 80 }

Feature Flags

set feature_x = 1
set feature_y = 0

set module_x_enabled = 0
set module_y_enabled = 0

if feature_x == 1 { set module_x_enabled = 1 }
if feature_y == 1 { set module_y_enabled = 1 }

Conditional Defaults

set mode = 1
set timeout = 30

if mode == 0 { set timeout = 10 }
if mode == 1 { set timeout = 30 }
if mode == 2 { set timeout = 60 }

License

MIT License - See LICENSE file for details

Author

hejhdiss

Links

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.

Changelog

Version 1.0.0

  • Initial release
  • C library implementation
  • Python bindings
  • Full test suite
  • Documentation

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

configlang-1.0.2.tar.gz (115.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

configlang-1.0.2-py3-none-any.whl (110.5 kB view details)

Uploaded Python 3

File details

Details for the file configlang-1.0.2.tar.gz.

File metadata

  • Download URL: configlang-1.0.2.tar.gz
  • Upload date:
  • Size: 115.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.0

File hashes

Hashes for configlang-1.0.2.tar.gz
Algorithm Hash digest
SHA256 192d0c13d760bab1eaf6fb6bfaae39a7027c47a7d7fde50491c46a945d06cb36
MD5 9b4967043dd456a49d6a39e421b7fa8a
BLAKE2b-256 5fb97f4cc2c1b1b5ddb2bb90e6f103e2520f0e1a6660bf7b4aac4e5460bee9f8

See more details on using hashes here.

File details

Details for the file configlang-1.0.2-py3-none-any.whl.

File metadata

  • Download URL: configlang-1.0.2-py3-none-any.whl
  • Upload date:
  • Size: 110.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.0

File hashes

Hashes for configlang-1.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 fd2f309da8ebf70d9f1fb32414b40101bdbc35b2dd48ea88b88e27c6ddbaf840
MD5 b472d87592c026835b7c268fe15b872e
BLAKE2b-256 22ae013255437c3494dbde3ddc31062d67232bc79f1e97d9582d5aa744a0fde3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page