Como eu implementaria algo semelhante à Diretiva Objective-C @Encode () Compiler no ANSI C?

StackOverflow https://stackoverflow.com/questions/2255637

Pergunta

A Diretiva @Encode retorna um const Char *, que é um descritor de tipo codificado dos vários elementos do tipo de dados que foi passado. Exemplo segue:

struct test
{ int ti ;
  char tc ;
} ;

printf( "%s", @encode(struct test) ) ;
// returns "{test=ic}"

Eu podia ver usando o sizeof () para determinar os tipos primitivos - e se fosse um objeto completo, eu poderia usar os métodos de classe para fazer introspecção.

No entanto, como determina cada elemento de uma estrutura opaca?

Foi útil?

Solução

@Lothars Answer pode ser "cínica", mas está bem perto da marca, infelizmente. Para implementar algo como @encode(), você precisa de um analisador completo para extrair as informações do tipo. Bem, pelo menos para qualquer coisa que não seja "trivial" @encode() declarações (ou seja, @encode(char *)). Os compiladores modernos geralmente têm dois ou três componentes principais:

  • A extremidade frontal.
  • A extremidade intermediária (para alguns compiladores).
  • O back -end.

O front -end deve analisar todo o código -fonte e basicamente converter o texto do código -fonte em um formulário interno "utilizável da máquina".

O back -end traduz o formulário interno "utilizável da máquina" para o código executável.

Os compiladores que possuem uma "extremidade intermediária" normalmente o fazem por causa de alguma necessidade: eles suportam vários "front finais", possivelmente compostos de idiomas completamente diferentes. Outro motivo é simplificar a otimização: toda a otimização passa funciona na mesma representação intermediária. o gcc O Compiler Suite é um exemplo de compilador de "três estágios". llvm Pode ser considerado um compilador de estágio "intermediário e back -end": a máquina virtual de baixo nível é a representação intermediária e toda a otimização ocorre nesta forma. llvm Também capaz de mantê-lo nessa representação intermediária até o último segundo- isso permite "otimização do tempo de link". o clang O compilador é realmente um "front end" que (efetivamente) saídas llvm Representação intermediária.

Então, se você quiser adicionar @encode() Funcionalidade para um compilador 'existente', você provavelmente precisaria fazê -lo como uma "fonte de origem" 'compilador / pré -processador'. Foi assim que os compiladores originais Objective-C e C ++ foram escritos- eles analisaram o texto da fonte de entrada e o converteram em "Plain C", que foi então alimentado com o compilador C padrão. Há algumas maneiras de fazer isso:

Role o seu próprio

  • Usar yacc e lex para montar um analisador ANSI-C. Você precisará de uma gramática ANSI C Gramática (YACC) é um bom começo. Na verdade, para ficar claro, quando digo yacc, Eu realmente quero dizer búfalo e flex. E também, vagamente, os outros vários yacc e lex como ferramentas baseadas em C: limão, DPARSER, etc ...
  • Usar perl com Yapp ou Eyapp, que são pseudo-yacc clones em perl. Provavelmente melhor para prototipando rapidamente uma ideia em comparação com a base de C yacc e lex- Está perl Afinal: expressões regulares, matrizes associativas, nenhum gerenciamento de memória etc.
  • Construa seu analisador com Antlr. Não tenho nenhuma experiência com essa cadeia de ferramentas, mas é outra ferramenta "compilador compilador" que (parece) ser mais voltado para os desenvolvedores de Java. Parece haver gramáticas C e Objective-C disponíveis gratuitamente.

Hackear outra ferramenta

Observação: Não tenho experiência pessoal usando nenhuma dessas ferramentas para fazer algo como adicionar @encode(), mas eu suspeito que eles seriam uma grande ajuda.

  • CIL - Não há experiência pessoal com esta ferramenta, mas projetada para analisar o código -fonte C e depois "fazer coisas" com ela. Pelo que posso recolher dos documentos, essa ferramenta deve permitir extrair as informações de tipo que você precisa.
  • Escasso - Vale a pena olhar, mas não tenho certeza.
  • Clang - Não o usei para esse fim, mas supostamente um dos objetivos era torná -lo "facilmente hackeável" para esse tipo de coisa. Particularmente (e novamente, sem experiência pessoal) em fazer o "levantamento pesado" de toda a análise, permitindo que você se concentre na parte "interessante", que neste caso seria extrair contexto e sintaxe informações sensíveis ao tipo e depois converteria isso em para uma string c simples.
  • Plugins GCC - Os plugins são um recurso GCC 4.5 (que é o recurso atual alfa/beta do compilador) e "pode" permitir que você conecte facilmente ao compilador para extrair as informações de tipo que você precisaria. Não faço ideia se a arquitetura do plug -in permite esse tipo de coisa.

Outros

  • Coccinelle - Marcado recentemente para "olhar mais tarde". Isso "pode" ser capaz de fazer o que você deseja e "pode" ser capaz de fazê -lo sem muito esforço.
  • Metac - Marcado este recentemente marcado recentemente. Não faço ideia de quão útil isso seria.
  • mygcc - "pode" fazer o que você quiser. É uma ideia interessante, mas não é diretamente aplicável ao que você deseja. Na página da web: "O MYGCC permite que os programadores adicionem suas próprias verificações que levam em consideração a sintaxe, o fluxo de controle e as informações do fluxo de dados".

Links.

Editar #1, os links de bônus.

@Lothar faz um bom ponto em seu comentário. Eu realmente pretendia incluir lcc, mas parece que se perdeu ao longo do caminho.

  • LCC - O lcc C compilador. Este é um compilador C que é particularmente pequeno, pelo menos em termos de tamanho do código -fonte. Isso também tem um livro, o que eu recomendo.
  • TCC - O tcc C compilador. Não tão pedagógico quanto lcc, mas definitivamente ainda vale a pena olhar.
  • poc - O poc Objective-C compilador. Esta é um compilador Objective-C "fonte para fonte". Ele analisa o código-fonte Objective-C e emite o código-fonte C, que ele passa para gcc (bem, geralmente gcc). Tem várias extensões / recursos objetivas-C que não estão disponíveis em gcc. Definitivamente vale a pena olhar.

Outras dicas

Você implementaria isso implementando o compilador ANSI C primeiro e depois adicionaria alguns Pragmas e funções específicos de implementação a ele.

Sim, eu sei que essa é uma resposta cínica e aceito os votos.

Uma maneira de fazer isso seria escrever um pré -processador, que lê o código -fonte para as definições de tipo e também substitui @encode... com a corda correspondente literal.

Outra abordagem, se o seu programa for compilado com -g, seria escrever uma função que lê a definição de tipo das informações de depuração do programa em tempo de execução ou use gdb ou outro programa para lê -lo para você e depois reformate -o conforme desejado. o gdb ptype O comando pode ser usado para imprimir a definição de um tipo específico (ou se isso é insuficiente, também existe maint print type, que certamente imprimirá muito mais informações do que você poderia desejar).

Se você estiver usando um compilador que suporta plugins (por exemplo, GCC 4.5), também pode ser possível escrever um plug -in do compilador para isso. Seu plug -in pode então tirar proveito das informações de tipo que o compilador já analisou. Obviamente, essa abordagem seria muito específica do compilador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top