Skip to content

CodeShark37/Xgen

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Português | English

Made with love in Angola

GitHub release GitHub release date Language

Índice

  • O que é a Xgen?
  • Features
  • Instalação
  • Início Rápido
  • Guia de Uso
  • Modelo de Dados
  • Constraints: Dependências e Exclusões
  • Filtragem por Peso
  • Macros Auxiliares
  • Exemplos Práticos
  • API de Referência
  • Troubleshooting
  • Contribuição

O que é a Xgen?

A Xgen é uma biblioteca em C que gera, de forma exaustiva e sem repetições, todas as combinações válidas de argumentos de linha de comandos a partir de grupos de aliases semanticamente equivalentes — respeitando dependências, exclusões e limites de peso definidos pelo utilizador.

É útil sempre que é preciso gerar sistematicamente casos de teste para uma CLI: fuzzing dirigido, testes de regressão de parsers de argumentos, ou simplesmente explorar o espaço de combinações válidas de um programa com muitas flags interdependentes (como o gcc).

Compatibilidade:

  • Sistemas Operativos: Linux, Windows
  • Arquitecturas: x86, x86_64, ARM, AArch64
  • Padrão: C11+

Features

Categoria Feature Detalhes Status
Core Geração combinatória State machine explora k-combinações, permutações e aliases Completo
Constraints Dependências AND (DEP) e OR (DEP_OR) Completo
Constraints Exclusões Par-a-par (EXCL) e colectivas (EXCL_OR) Completo
Filtragem Peso cumulativo max_weight filtra combinações por custo/complexidade Completo
Performance Memoização Validação de dependências/exclusões feita ao nível do grupo, não repetida por alias/permutação Completo
Modos Geração GEN_MODE_LEXICAL e GEN_MODE_COMBINATORIAL (com permutações) Completo
Controlo Limite de emissão limit corta a geração após N combinações Completo
Robustez Validação de configuração gen_create() recusa configurações impossíveis (ciclos irresolúveis, k > group_count, etc.) Completo
Performance Zero dependências Apenas stdlib C Completo
Testes Suite de edge cases + fuzzing Ciclos, auto-referências, conflitos dep-vs-excl, pesos negativos Completo

Espaço de Combinações Explorado

# O gerador itera sobre quatro eixos:
1. Valores de k (min_args .. max_args)          — quantos grupos por combinação
2. k-combinações de grupos                       — quais grupos participam
3. Aliases dentro de cada grupo seleccionado      — qual forma do argumento usar
4. Permutações da ordem dos grupos (se activado)  — em que ordem os argumentos aparecem

# Cada combinação candidata só é emitida se satisfizer:
- Todas as Dependency (from requer pelo menos um de to[])
- Todas as Exclusion (a não pode coexistir com TODOS de b[])
- max_weight (soma dos pesos dos grupos seleccionados)

Instalação

Pré-requisitos

  • Compilador C11+ (gcc, clang)

Instalação Rápida

# Clone o repositório
git clone https://github.com/CodeShark37/xgen.git

# Entre no diretório
cd xgen

# Compile como biblioteca estática, ou inclua xgen.c/xgen.h directamente no seu projecto
gcc -c -O2 -Wall src/xgen.c -o xgen.o

Uso Básico

#include "xgen.h"

int main(void) {
    const char *help[] = { "--help", "-h" };
    ArgGroup groups[] = { { help, 2, 0 } };

    GenConfig cfg = {0};
    cfg.groups = groups;
    cfg.group_count = 1;
    cfg.min_args = 1;
    cfg.max_args = 1;

    Generator *gen = gen_create(&cfg);
    if (!gen) return 1;

    const char **args;
    size_t count;
    while (gen_next(gen, &args, &count)) {
        for (size_t i = 0; i < count; i++)
            printf("%s ", args[i]);
        printf("\n");
    }

    gen_free(gen);
    return 0;
}

Guia de Uso

Ciclo de Vida do Gerador

Passo Função Descrição
1. Criar gen_create(&cfg) Valida a configuração e devolve Generator*, ou NULL se não existir nenhuma combinação válida
2. Iterar gen_next(gen, &args, &count) Devolve a combinação actual e avança; false quando termina
3. Consultar gen_emitted(gen) / gen_done(gen) Progresso e estado da iteração
4. Libertar gen_free(gen) Liberta toda a memória interna

Opções de GenConfig

Campo Tipo Descrição
groups / group_count ArgGroup* / size_t Grupos de argumentos disponíveis
min_args / max_args size_t Intervalo de tamanho k das combinações
deps / dep_count Dependency* / size_t Regras de dependência (opcional)
excls / excl_count Exclusion* / size_t Regras de exclusão (opcional)
max_weight int Peso cumulativo máximo (0 = sem limite)
limit size_t Máximo de combinações a emitir (0 = ilimitado)
mode GenMode GEN_MODE_LEXICAL ou GEN_MODE_COMBINATORIAL

Modelo de Dados

ArgGroup — um grupo de aliases equivalentes

const char *verbose[] = { "--verbose", "-v", "--debug" };
ArgGroup g = { verbose, 3, /* weight */ 1 };

Quando um grupo é seleccionado para uma combinação, exactamente um dos seus aliases aparece no output — a Xgen gera uma variante por alias.

Índices de Grupo

Todas as regras de dependência e exclusão referenciam grupos pelo seu índice dentro do array groups[]. Usar um enum local para nomear esses índices torna as regras muito mais legíveis:

enum { G_INPUT, G_OUTPUT, G_VERBOSE };

Constraints: Dependências e Exclusões

Dependências (Dependency)

Uma dependência diz: "se from for seleccionado, pelo menos um de to[] também tem de ser".

Forma Semântica Macro
to_count == 1 AND clássico — from requer to DEP(from, to)
to_count > 1 OR — from requer pelo menos um de {...} DEP_OR(from, ...)
enum { G_OUTPUT, G_FORMAT };
Dependency deps[] = {
    DEP(G_OUTPUT, G_FORMAT),   /* --output requer --format */
};

Exclusões (Exclusion)

Uma exclusão diz: "a não pode coexistir com TODOS os elementos de b[] ao mesmo tempo".

Forma Semântica Macro
b_count == 1 Par-a-par clássico — a e b são mutuamente exclusivos EXCL(a, b)
b_count > 1 Colectiva — a só é excluído se TODOS de {...} estiverem presentes; subconjuntos parciais são permitidos EXCL_OR(a, ...)
enum { G_QUIET, G_VERBOSE };
Exclusion excls[] = {
    EXCL(G_QUIET, G_VERBOSE),  /* --quiet e --verbose são mutuamente exclusivos */
};

Nota: dependências e exclusões não são fechadas transitivamente. A requer B e B requer C não implica automaticamente A requer C — se essa relação for necessária, deve ser declarada explicitamente.

Filtragem por Peso

Cada ArgGroup tem um weight (pode ser negativo). Definindo max_weight em GenConfig, apenas combinações cuja soma de pesos não exceda o limite são emitidas. max_weight == 0 desactiva a verificação.

ArgGroup groups[] = {
    { light,  2, 1 },   /* peso 1 */
    { heavy,  2, 5 },   /* peso 5 */
};
cfg.max_weight = 4;     /* {light} passa; {heavy} e {light,heavy} são filtrados */

Macros Auxiliares

Macro Uso
DEP(from, to) Dependência AND simples
DEP_OR(from, ...) Dependência OR (variádica)
EXCL(a, b) Exclusão par-a-par
EXCL_OR(a, ...) Exclusão colectiva (variádica)
COUNT_ARGS(...) Helper interno usado por DEP_OR/EXCL_OR para contar argumentos variádicos

Exemplos Práticos

Cadeia de dependências

enum { G_FORMAT, G_OUTPUT, G_COMPRESS };
Dependency deps[] = {
    DEP(G_OUTPUT, G_FORMAT),      /* output requer format */
    DEP(G_COMPRESS, G_OUTPUT),    /* compress requer output */
};
/* Válido:   [--format], [--format --output], [--format --output --compress]
   Inválido: [--output] (falta format), [--compress --output] (falta format) */

Exclusão colectiva (não par-a-par)

enum { G_SAFE, G_OPT_SPEED, G_OPT_SIZE, G_PARALLEL };
Exclusion excls[] = {
    /* --safe-mode não pode coexistir com TODOS os três ao mesmo tempo,
       mas pode coexistir com qualquer subconjunto parcial */
    EXCL_OR(G_SAFE, G_OPT_SPEED, G_OPT_SIZE, G_PARALLEL),
};

Cenário real: flags de compilador (estilo GCC)

Um caso de uso completo — ~20 grupos de argumentos, 21 dependências e apenas 3 regras de exclusão colectiva (em vez de 25 regras par-a-par) — está implementado em examples.c, incluindo:

/* Info é sempre standalone: exclui TODOS os outros grupos numa única regra */
EXCL_OR(G_INFO, G_INPUT, G_MODE, G_OUTPUT, G_STD, G_OPT, G_DEBUG,
        G_WARN, G_WERROR, G_DEFINE, G_INCLUDE, G_ARCH, G_SANITIZE,
        G_LTO, G_PIC, G_SHARED, G_STATIC, G_LIBPATH, G_LIBLINK, G_STACK);

Consulte examples.c para os sete exemplos completos, do uso mais básico ao modelo do GCC9; tests.c para os casos extremos (ciclos, auto-referências, conflitos dependência-vs-exclusão, pesos negativos); e fuzz.c para o driver de stress-testing aleatório.

API de Referência

Função Descrição
Generator *gen_create(const GenConfig *config) Cria e valida um novo gerador; NULL se a configuração for impossível
bool gen_next(Generator *gen, const char ***out_args, size_t *out_count) Devolve a combinação actual e avança o estado
void gen_free(Generator *gen) Liberta toda a memória associada ao gerador
size_t gen_emitted(const Generator *gen) Número de combinações já emitidas
bool gen_done(const Generator *gen) Se a iteração terminou

A documentação completa de cada struct, enum e função (com exemplos individuais) está em xgen.h, escrita em Doxygen.

Troubleshooting

Sintoma Causa provável
gen_create() devolve NULL Configuração impossível: ciclo de dependências que nenhum k satisfaz, min_args > max_args, max_args > group_count, ou peso mínimo já excede max_weight
Nenhuma combinação esperada aparece Verifique se a dependência não é apenas implícita — a Xgen não fecha dependências transitivamente
Demasiadas combinações / geração lenta Reduza max_args, defina limit, ou use GEN_MODE_LEXICAL em vez de GEN_MODE_COMBINATORIAL para evitar permutações
Peso negativo com resultado inesperado Pesos negativos são somados normalmente; combinações com peso total ≤ max_weight passam, mesmo que incluam grupos "pesados" compensados por grupos de peso negativo

Contribuição

Contribuições são muito bem-vindas!

Como Contribuir

  1. Fork o repositório
  2. Crie uma branch para sua feature (git checkout -b feature/nova-funcionalidade)
  3. Commit suas mudanças (git commit -am 'Adiciona nova funcionalidade')
  4. Push para a branch (git push origin feature/nova-funcionalidade)
  5. Abra um Pull Request

Diretrizes

  • Código em C11+
  • Testes para novas funcionalidades (ver tests.c e fuzz.c)
  • Documentação Doxygen actualizada em xgen.h
  • Commits descritivos

Reportar Issues

Encontrou um bug ou tem uma sugestão? Abra uma issue!


Se este projeto te ajudou de alguma forma, deixe uma estrela!

Feito com ❤️ em Angola

Stars Forks

About

CLI Args generator - Gerador combinatório de argumentos de linha de comandos, com regras semânticas e validação de constraints

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages