Transformando argumentos posicionais de um script de shell

1

Estou tentando escrever um script de shell que irá transformar a posição argumentos que são passados para ele da seguinte forma.

O shell script passa esses argumentos para um executável binário ( ffigen ) que é derivado do frontend gcc 4.0 , então o comando os argumentos de linha que seguem também são gcc argumentos e significam o mesmo coisa como eles fazem para gcc .

Considere a seguinte linha de comando

./htest.sh -I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include \
/usr/include/gtk-2.0/gtk/gtk.h -include/usr/include/bar.h /usr/include/myheader.h

Existem essencialmente duas opções diferentes aqui, a opção -I , que passa um diretório para gcc para procurar arquivos de inclusão e -include , que processa um arquivo de cabeçalho como se #include "file" aparecesse como primeira linha do arquivo de origem principal.

As duas versões diferentes dadas aqui diferem em saber se existe espaço entre o flag de opção e o argumento. Parece que ambos são admissível.

Atualmente, as únicas versões que aparecem no upstream são

-I/usr/include/gtk-2.0 and -include /usr/include/gtk-2.0/gtk/gtk.h

mas não parece uma má ideia tentar testar este código no futuro no caso de alguém adicionar esses outros formulários mais tarde.

O que o script do upstream faz é, na maioria das vezes, adicionar os argumentos para CFLAGS e, em seguida, passar o argumento final para ffigen . O que ffigen faz não é importante aqui - minha pergunta é sobre o valor de retorno de %código%. Aqui está o script do upstream.

while [ $# -gt 1 ]
do
    echo $CFLAGS
    case ${1} in
      -pthread*)
        CFLAGS="${CFLAGS} -D_REENTRANT"
        shift
        ;;
      -x)
        shift
        shift
        ;;
      *)
        CFLAGS="${CFLAGS} ${1}"
        shift
        ;;
   esac
done

echo $CFLAGS

O que eu quero fazer é onde os nomes dos arquivos de cabeçalho são especificados no acima da linha, é transformá-los em nomes de caminhos relativos, relativos a o diretório include. Então, o que eu gostaria de ver como o retorno valor para CFLAGS , é

-I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include gtk-2.0/gtk/gtk.h -includebar.h

O que o upstream produz são apenas os argumentos inalterados.

-I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include \
/usr/include/gtk-2.0/gtk/gtk.h -include/usr/include/bar.h

Justificativa: Como o Debian mudou para multilib, os arquivos de cabeçalho não são mais em seus locais tradicionais. Agora, CFLAGS , como seu pai ffigen , pode procurar por caminhos para arquivos de cabeçalho, fornecidos que apenas os caminhos relativos são especificados. Se os caminhos absolutos são especificado, então é claro que não.

O ideal seria usar uma ferramenta projetada para funcionar com multiarch, mas uma solução rápida e suja é simplesmente tira o encabeçam caminhos absolutos do arquivo para baixo aos nomes relativos do trajeto, e forneceram ffigen é fornecido os caminhos de inclusão corretos, ele irá procurar e descubra os arquivos de cabeçalho.

A versão que tenho atualmente está abaixo. Produz

-I/usr/include/gtk-2.0 -I glib-2.0 -include gtk-2.0/gtk/gtk.h bar.h

que é terrível, mas lida corretamente com os dois casos que realmente ocorrem no upstream. Uma versão que lida com todos os quatro casos corretamente seria bem-vindo. Sim, sou preguiçosa. Eu também chupo a concha scripting.

while [ $# -gt 1 ]
do
    echo $CFLAGS
    case ${1} in
      -pthread*)
        CFLAGS="${CFLAGS} -D_REENTRANT"
        shift
        ;;
      -x)
        shift
        shift
        ;;
      -I*)
        CFLAGS="${CFLAGS} ${1}"
        shift
        ;;
      *)
        RELPATH_AFTER_INCLUDE="${1##*include/}"
        CFLAGS="${CFLAGS} ${RELPATH_AFTER_INCLUDE}"
        shift
        ;;
   esac
done

echo $CFLAGS

Aqui está um pequeno script que estou usando para testar isso

#!/bin/sh

PROGRAM=htest.sh
#PROGRAM=upstream.sh

./${PROGRAM} -I/usr/include/gtk-2.0 -I /usr/include/glib-2.0 -include \     
/usr/include/gtk-2.0/gtk/gtk.h -include/usr/include/bar.h /usr/include/myheader.h

Uma nota final sobre portabilidade. Os scripts acima são executados em traço e parece que eles são portáteis para mim. Então, uma versão que é portátil seria seja legal, mas não é essencial. Eu não vejo esse código indo para o upstream então ... Se não for portável, então bash seria Ok.

###################################################################

Para quem está interessado no pano de fundo isso, isso é no contexto de empacotamento Clozure Common Lisp para o Debian.

Veja Pacote Debian e em particular o arquivo README.source .

Veja os patches upstream link e link , que se combinam para tornar o script upstream gcc , dos quais eu discutir uma parte aqui.

Para o problema específico que estou tentando resolver aqui, consulte o tópico problemas na criação de bancos de dados de interface no multiarch do Debian .

Uma discussão do meu raciocínio acima está na terceira mensagem em que fio, de mim, para o fundo.

    
por Faheem Mitha 13.08.2012 / 06:53

2 respostas

1

As obras a seguir, mas são meio verbosas. Sugestões de melhorias bem-vindas.

while [ $# -gt 1 ]
do
    echo $CFLAGS
    case ${1} in
      -pthread*)
        CFLAGS="${CFLAGS} -D_REENTRANT"
        shift
        ;;
      -x)
        shift
        shift
        ;;
      -I)
        CFLAGS="${CFLAGS} ${1}"
        shift
        CFLAGS="${CFLAGS} ${1}"
        shift
        ;;
      -include)
        CFLAGS="${CFLAGS} ${1}"
        shift
        RELPATH_AFTER_INCLUDE="${1##*include/}"
        CFLAGS="${CFLAGS} ${RELPATH_AFTER_INCLUDE}"
        shift
        ;;
      -I*)
        CFLAGS="${CFLAGS} ${1}"
        shift
        ;;
      -include*)
        # strip off leading -include                                                                                                                              
        REMOVE_LEADING_INCLUDE="${1##-include}"
        echo "REMOVE-LEADING-INCLUDE" ${REMOVE_LEADING_INCLUDE}
        RELPATH_AFTER_INCLUDE="${REMOVE_LEADING_INCLUDE##*include/}"
        CFLAGS="${CFLAGS} -include${RELPATH_AFTER_INCLUDE}"
        shift
        ;;
      *)
       CFLAGS="${CFLAGS} ${1}"
        shift
        ;;
   esac
done

echo $CFLAGS
    
por 13.08.2012 / 08:38
2

Como às vezes você tem um espaço depois de -I ou -include e às vezes não, você não pode contar com $1 mantendo a opção e o valor.

Eu ficaria com a versão original, com as opções de maiúsculas e minúsculas "-pthread *", "-x" e "*". Então, depois de ter acumulado a variável CFLAGS, chame para sed para remover parte do caminho apenas para a opção -include:

CFLAGS=$(echo "$CFLAGS" | sed 's#\(-include \?\)/usr/include/##g')
    
por 13.08.2012 / 08:07