Это не совсем ответ на вопрос «Как заставить препроцессор сохранять вкладки»;Я слегка переосмыслил вопрос как «Как сохранить вкладки с помощью предварительной обработки».
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
или какой-либо другой редактор строк, чтобы изменить сгенерированные директивы с номерами строк.