Skip to content

Repository files navigation

XgenLogo

Português | English

Made with love in Angola

GitHub releaseGitHub release dateLanguage

Í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

CategoriaFeatureDetalhesStatus
CoreGeração combinatóriaState machine explora k-combinações, permutações e aliasesCompleto
ConstraintsDependênciasAND (DEP) e OR (DEP_OR)Completo
ConstraintsExclusõesPar-a-par (EXCL) e par-a-par expandida contra vários alvos (EXCL_OR)Completo
FiltragemPeso cumulativomax_weight filtra combinações por custo/complexidadeCompleto
PerformanceMemoizaçãoValidação de dependências/exclusões feita ao nível do grupo, não repetida por alias/permutaçãoCompleto
ModosGeraçãoGEN_MODE_LEXICAL e GEN_MODE_COMBINATORIAL (com permutações)Completo
ControloLimite de emissãolimit corta a geração após N combinaçõesCompleto
RobustezValidação de configuraçãogen_create() recusa configurações impossíveis (ciclos irresolúveis, k > group_count, etc.)Completo
PerformanceZero dependênciasApenas stdlib CCompleto
TestesSuite de edge cases + fuzzingCiclos, auto-referências, conflitos dep-vs-excl, pesos negativosAuxiliares

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 NENHUM elemento 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óriocd xgen
# Compile como biblioteca estática, ou inclua xgen.c/xgen.h directamente no seu projecto
gcc -c -O2 xgen.c -o xgen.o

Uso Básico

#include"xgen.h"intmain(void) {
constchar*help[] = { "--help", "-h" };
ArgGroupgroups[] = { { help, 2, 0 } };
GenConfigcfg= {0};
cfg.groups=groups;
cfg.group_count=1;
cfg.min_args=1;
cfg.max_args=1;
Generator*gen=gen_create(&cfg);
if (!gen) return1;
constchar**args;
size_tcount;
while (gen_next(gen, &args, &count)) {
for (size_ti=0; i<count; i++)
printf("%s ", args[i]);
printf("\n");
}
gen_free(gen);
return0;
}

Guia de Uso

Ciclo de Vida do Gerador

PassoFunçãoDescrição
1. Criargen_create(&cfg)Valida a configuração e devolve Generator*, ou NULL se não existir nenhuma combinação válida
2. Iterargen_next(gen, &args, &count)Devolve a combinação actual e avança; false quando termina
3. Consultargen_emitted(gen) / gen_done(gen)Progresso e estado da iteração
4. Libertargen_free(gen)Liberta toda a memória interna

Opções de GenConfig

CampoTipoDescrição
groups / group_countArgGroup* / size_tGrupos de argumentos disponíveis
min_args / max_argssize_tIntervalo de tamanho k das combinações
deps / dep_countDependency* / size_tRegras de dependência (opcional)
excls / excl_countExclusion* / size_tRegras de exclusão (opcional)
max_weightintPeso cumulativo máximo (0 = sem limite)
limitsize_tMáximo de combinações a emitir (0 = ilimitado)
modeGenModeGEN_MODE_LEXICAL ou GEN_MODE_COMBINATORIAL

Modelo de Dados

ArgGroup — um grupo de aliases equivalentes

constchar*verbose[] = { "--verbose", "-v", "--debug" };
ArgGroupg= { 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".

FormaSemânticaMacro
to_count == 1AND clássico — from requer toDEP(from, to)
to_count > 1OR — from requer pelo menos um de {...}DEP_OR(from, ...)
enum { G_OUTPUT, G_FORMAT };
Dependencydeps[] = {
DEP(G_OUTPUT, G_FORMAT), /* --output requer --format */
};

Exclusões (Exclusion)

Uma exclusão diz: "a não pode coexistir com NENHUM elemento de b[]" — basta um elemento de b[] estar presente junto de a para a combinação ser inválida.

FormaSemânticaMacro
b_count == 1Par-a-par clássico — a e b são mutuamente exclusivosEXCL(a, b)
b_count > 1Par-a-par expandida — a é inválido junto de qualquer um, individualmente, de {...}; equivale a declarar EXCL(a, b0), EXCL(a, b1), ... numa única regraEXCL_OR(a, ...)
enum { G_QUIET, G_VERBOSE };
Exclusionexcls[] = {
EXCL(G_QUIET, G_VERBOSE), /* --quiet e --verbose são mutuamente exclusivos */
};

Atenção: apesar do nome, EXCL_ORnão é uma exclusão colectiva/all-of. a junto de apenas um elemento de b[] já é suficiente para invalidar a combinação — não é necessário que todos os elementos de b[] estejam presentes ao mesmo tempo.

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.

ArgGroupgroups[] = {
{ 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

MacroUso
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 par-a-par expandida contra vários alvos (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 };
Dependencydeps[] = {
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 par-a-par expandida contra vários alvos

enum { G_SAFE, G_OPT_SPEED, G_OPT_SIZE, G_PARALLEL };
Exclusionexcls[] = {
/* --safe-mode não pode coexistir com --optimize-speed, nem com --optimize-size, nem com -Instalação cada par é excluído individualmente (não é preciso os três estarem presentes juntos) */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 par-a-par expandida (em vez de 25 regras EXCL individuais) — está implementado em examples.c, incluindo:

/* Info é sempre standalone: exclui, um a um, TODOS os outros grupos numa única regra (nenhum deles pode coexistir com Info) */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çãoDescriçã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

SintomaCausa provável
gen_create() devolve NULLConfiguraçã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 apareceVerifique se a dependência não é apenas implícita — a Xgen não fecha dependências transitivamente
Demasiadas combinações / geração lentaReduza max_args, defina limit, ou use GEN_MODE_LEXICAL em vez de GEN_MODE_COMBINATORIAL para evitar permutações
Peso negativo com resultado inesperadoPesos 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 dependência
  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

StarsForks

About

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

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages