Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Кроссплатформенный C/C++: cl/gcc/Qt/Gtk+/WxWidgets > Выделение кода после препроцессинга


Автор: Jin X 04.02.19, 13:38
Приветствую всех!

Есть прога (основной исходник и библиотека из 4-х файлов).
В библиотеке 95% – это #ifdef'ы, #define'ы и т.п. + код под неинтересующие меня платформы.
Я хочу обработать всё это дело, получив чистый исходник, без препроцессорного "мусора", под конкретную платформу.
Но include'ы хочу оставить, а не тащить их все туда же.

Проблема в том, что если написать:
gcc -E file.cpp -o file.ii

То в получаемый исходник тащатся ВСЕ include'ы.

К примеру:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    #include <iostream>
    using namespace std;
     
    #define RETURN return 0
     
    int main() {
        cout << "Hello, world!" << endl;
        RETURN;
    }

выдаёт файл на 650 Кб, т.к. туда попадает iostream и всё, что внутри него.

Как можно быстро очистить результирующий файл?

Автор: Jin X 05.02.19, 14:00
Накатал скриптик на PHP.
Может, кому пригодится ;)
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    <?php
     
    // Command line processing
     
    const UNLIMITED = 1000000000;
     
    $parse_include = true;
    $save_info = false;
    $max_empty_lines = UNLIMITED;
     
    if ($argc < 3) {
      echo "php parse_ii <infile.ii> <outfile.ii> [/x] [/l] [/0../4] <filename1> [filename2]...\n";
      echo "/x - exclude specified files (filename1, filename2...), otherwise include only them\n";
      echo "/i - save line info (numbers and filenames)\n";
      echo "/0../4 - delete more than 0 (all), 1, 2, 3 or 4 consecutive empty lines\n";
      exit(1);
    }
     
    $infile = '';
    $outfile = '';
    $filelist = [];
     
    for ($i = 1; $i < $argc; ++$i) {
      $s = trim($argv[$i]);
      switch (strtolower($s)) {
        case '/x':
          $parse_include = false;
          break;
        case '/i':
          $save_info = true;
          break;
        case '/0':
        case '/1':
        case '/2':
        case '/3':
        case '/4':
          $max_empty_lines = (int)substr($s, 1, 1);
          break;
        default:
          if (substr($s, 0, 1) == '/') {
            echo "Unknown option: $s\n";
          } else {
            if ($infile === '') { $infile = $s; }
            else if ($outfile === '') { $outfile = $s; }
            else if ($s !== '') { array_push($filelist, strtolower($s)); }
          }
      }
    }
     
    if (count($filelist) == 0) {
      echo 'No files to '.['exclude', 'include'][$parse_include]." are specified!\n";
      exit(1);
    }
     
    echo "Source filename: $infile\n";
    echo "Output filename: $outfile\n";
    echo 'Parse type: '.['exclude', 'include'][$parse_include].' ('.implode(', ', $filelist).")\n";
    echo 'Save line info: '.['no', 'yes'][$save_info]."\n";
    echo 'Max empty lines: '.($max_empty_lines < UNLIMITED ? $max_empty_lines : 'unlimited')."\n\n";
     
    // File read
     
    echo "Reading file...\n";
     
    if (!file_exists($infile)) {
      echo "Input file $infile is not found!\n";
      exit(1);
    }
     
    // File processing
     
    echo "Processing lines...\n";
     
    $output = [];
    $include = !$parse_include;
    $total_lines = 0;
    $written_lines = 0;
    $empty_count = 0;
     
    foreach (file($infile) as $s) {
      preg_match('/^#\s*\d+\s+(?:"(?:.+\\\\)?(.+)"|(?:\S+\\\\)?(\S+))/', trim($s), $result);
      if (count($result) > 1) {
        $found = in_array(strtolower(end($result)), $filelist);
        $include = ($found == $parse_include);
        if ($save_info && $include) {
          array_push($output, $s);
          ++$written_lines;
          $empty_count = 0;
        }
      } else {
        if ($include) {
          if (trim($s) === '') { ++$empty_count; } else { $empty_count = 0; }
          if ($empty_count <= $max_empty_lines) {
            array_push($output, $s);
            ++$written_lines;
          }
        }
      }
      ++$total_lines;
    }
     
    // File write
     
    echo "Writting file...\n";
     
    $file = fopen($outfile, 'w');
    fwrite($file, implode($output));
    fclose($file);
     
    echo "Successfully written $written_lines lines out of $total_lines (".((int)($written_lines/$total_lines*10000)/100)."%)\n"
     
    ?>

Автор: android90 07.02.19, 10:39
Цитата Jin X @
Накатал скриптик на PHP.
Может, кому пригодится ;)

RTFM

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    sed 's/\#include*/ /g' file.ii > file1.ii

Автор: Jin X 09.02.19, 12:20
android90, и ничего этот скрипт не делает толком...
Только заменяет #include "file" на "file" и всё.

Автор: gathering 15.02.19, 19:02
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    sed 's/\#include.*/ /g' file.ii > file1.ii


https://ideone.com/os9UBU

Автор: amk 16.02.19, 04:58
Я бы тогда лучше написал так
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    sed 's|^\s*\#\s*include\b|// \0|g' file.ii > file1.ii
просто превращая include в комментарии

Но только в первом посте требуется не это.
Jin X хочет, чтобы на выходе получился файл с исключёнными нерабочими ветками #if. Для этого всё-таки приходится заходить внутрь #include и выполнять препроцессирование.

Автор: Jin X 17.02.19, 15:08
Да ладно, можно уже не париться.
PHP-шный код выше вполне справляется с задачей :)

Добавлено
Конечно, мне надо не просто директивы #include убрать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)