A implementação do GCC de colchetes angulares inclui. Por que tem que ser como descrito abaixo?

11

Este documento em sua seção 2.6 Inclui computados possui o seguinte parágrafo:

Se a linha se expandir para um fluxo de token começando com um token <e incluindo um>, os tokens entre o <e o primeiro> serão combinados para formar o nome do arquivo a ser incluído. Qualquer espaço em branco entre os tokens é reduzido para um único espaço; qualquer espaço após o inicial <é retido, mas um espaço à direita antes do fechamento> é ignorado . O CPP procura o arquivo de acordo com as regras para colchetes angulares.

Eu sei que isso é uma implementação definida, mas por que tem que ser assim para o GCC? Estou me referindo especificamente à frase destacada acima.

EDITAR

Acabei de notar que o terceiro parágrafo anterior ao citado acima diz o seguinte:

Você deve ter cuidado ao definir a macro. #definesalva tokens, não texto. O pré-processador não tem como saber que a macro será usada como argumento de #include, portanto, gera tokens comuns, não um nome de cabeçalho. É improvável que cause problemas se você incluir aspas duplas, que são próximas o suficiente para constantes de seqüência de caracteres. Se você usar colchetes angulares, no entanto, poderá ter problemas .

Alguém sabe que tipo de problema está sendo apontado aqui?

Ayrosa
fonte
6
O melhor palpite é que os desenvolvedores do GCC acham que ter espaços no final de um nome de arquivo é uma abominação.
user3386109
11
Os nomes de arquivos com espaços iniciais e / ou finais são muito complicados, especialmente no Windows.
Remy Lebeau
11
Só porque foi definido assim, não significa necessariamente que deve ser definido assim. Não é obrigatório pelo padrão.
eerorika 24/04
O Visual Studio remove o espaço inicial e o final, se comportando de maneira diferente. O HP aCC se comporta como o gcc (talvez por motivos de compatibilidade).
Slimak 25/04
Às vezes, a documentação simplesmente descreve o que o código faz, e não o contrário, especialmente nos casos que não importam (você pode usar qualquer espaço em qualquer lugar se usar aspas duplas).
rustyx 25/04

Respostas:

9

Eu acho que o implementador escolheu a maneira mais simples quando implementou essa funcionalidade, sem pensar muito.

Parece que a implementação inicial chegou em 2000-07-03 (duas décadas atrás!). A parte relevante se parece com ( fonte ):

  for (;;)
    {
      t = cpp_get_token (pfile);
      if (t->type == CPP_GREATER || t->type == CPP_EOF)
        break;

      CPP_RESERVE (pfile, TOKEN_LEN (t));
      if (t->flags & PREV_WHITE)
        CPP_PUTC_Q (pfile, ' ');
      pfile->limit = spell_token (pfile, t, pfile->limit);
    }

Notavelmente, ele ocorre quando vê o CPP_GREATERtoken (ou seja >), antes de reservar memória para o token. Isso faz sentido, pois não há necessidade de alocar memória quando o token não será gravado no buffer.

Então, somente após a memória ser reservada, o pré-processador verifica se o token possui espaço em branco anterior ( t->flags & PREV_WHITE) e, quando possui, grava um caractere de espaço em branco no buffer.

Como resultado, em < foo / bar >, somente os espaços em branco antes foo(ou seja, após a inicial <) /, e barsão mantidos.

cpplearner
fonte
Brilhante, ótima resposta. É a primeira vez que tenho a oportunidade de ver um código no GCC. Obrigado por isso.
Ayrosa 26/04
Mas não é o caso de a condição if (t->flags & PREV_WHITE) CPP_PUTC_Q (pfile, ' ');contradizer o que está sendo dito no documento: "Qualquer espaço em branco entre os tokens é reduzido a um único espaço; ..."?
Ayrosa 26/04