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:
- Variables must be defined before use - You cannot reference a variable in a conditional before it has been declared with
set - Single statement per if block - Each if block can contain only ONE
setstatement - Closing brace on same line - The
}must appear on the same line as the statement inside the if block - 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 classParseError- Syntax error in configurationVariableNotFoundError- Variable doesn't existConstViolationError- Attempted to modify const variableTypeMismatchError- 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_stmtcan only contain ONEset_stmtinside the braces- The closing
}must be on the same line as theset_stmt - Chaining is done by following one
if_stmtwith anotherif_stmt - There is no separate
elsekeyword - use chainedifstatements
Type System
ConfigLang has a simple type system with two types:
- Integer - Signed integers (e.g.,
42,-10,0) - 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 maximumMAX_VAR_NAME- 32 characters for variable namesMAX_STRING_VALUE- 1024 characters for string valuesMAX_LINE_LENGTH- 2048 characters per lineMAX_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
setstatement perifblock - No
elsekeyword - use chainedifstatements 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
- Define variables before conditionals: Always declare variables with
setbefore using them inifconditions - Use chained if statements: Instead of if-else, use multiple if statements
- Keep conditionals simple: Each if block should modify only one variable
- Use const for fixed values: Mark configuration values that shouldn't change as
const - Group related settings: Use comments to organize your configuration into logical sections
- 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
- GitHub: https://github.com/hejhdiss/configlang
- Issues: https://github.com/hejhdiss/configlang/issues
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
192d0c13d760bab1eaf6fb6bfaae39a7027c47a7d7fde50491c46a945d06cb36
|
|
| MD5 |
9b4967043dd456a49d6a39e421b7fa8a
|
|
| BLAKE2b-256 |
5fb97f4cc2c1b1b5ddb2bb90e6f103e2520f0e1a6660bf7b4aac4e5460bee9f8
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd2f309da8ebf70d9f1fb32414b40101bdbc35b2dd48ea88b88e27c6ddbaf840
|
|
| MD5 |
b472d87592c026835b7c268fe15b872e
|
|
| BLAKE2b-256 |
22ae013255437c3494dbde3ddc31062d67232bc79f1e97d9582d5aa744a0fde3
|