Запретить препроцессору C менять отступ - PullRequest
0 голосов
/ 05 июля 2019

Пример (обратите внимание, в этом коде ровно один TAB, отображаемый как 8 пробелов):

int main()
{
   int x = 1;
   if (x == 1)
   {
      x = 2;
      if(x == 2)
      {
         x = 3; /* indented with TAB */
      }
   }
}

g++ -E и clang++ -E оба превращают это в:

int main()
{
   int x = 1;
   if (x == 1)
   {
      x = 2;
      if(x == 2)
      {
  x = 3;
      }
   }
}

Другой пример:

int main()
{
   int x =   ( 1 + 3);
}

->

int main()
{
   int x = ( 1 + 3);
}

Он заменял табуляцию пробелом (в первом примере) и заменял последовательные пробелы одним (во втором примере),Могу ли я заставить его не делать этого?

1 Ответ

3 голосов
/ 07 июля 2019

Это не совсем ответ на вопрос «Как заставить препроцессор сохранять вкладки»;Я слегка переосмыслил вопрос как «Как сохранить вкладки с помощью предварительной обработки».

Unix-подобные дистрибутивы должны поставляться с утилитами Posix expand и unexpand, которые, соответственно, расширяют вкладки до пробелови замените последовательности пробелов символами табуляции.Вы можете легко использовать это, чтобы сохранить ведущие вкладки при их прохождении через препроцессор:

$ # '-i' is a Gnu extension. Leave it out if you have a Posix expand.
$ expand -i tabbed.c | gcc -E - | unexpand
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"
int main()
{
   int x = 1;
   if (x == 1)
   {
      x = 2;
      if(x == 2)
      {
         x = 3;
      }
   }
}

(Примечание: в начале строки есть вкладка x = 3, хотя она не прошла черезскопируйте и вставьте в SO.)

Препроцессоры GCC (и clang) нормализуют непропускающие пробелы (включая комментарии) в один символ пробела, поэтому с этим ничего не поделаешь.По этой причине в приведенном выше примере я использовал параметр расширения -i для Gnu до expand, в результате чего он расширяет только вкладки в начальных пробелах.(unexpand просматривает только начальные пробелы, если вы не укажете опцию -a.) Это будет полезно, если вы помещаете необработанные табуляции в строки или символьные литералы вместо \t.Предположительно, вы этого не делаете.

Вывод препроцессора, показанный выше, отличается от результата предварительной обработки tabbed.c напрямую тем, что строковые директивы ссылаются на <stdin>, а не на имя файла.Добавление #line 1 "tabbed.c" 1 к входному потоку - несовершенное исправление, но оно по крайней мере пропустит директиву #line.Вы можете использовать sed или какой-либо другой редактор строк, чтобы изменить сгенерированные директивы с номерами строк.

...