Смешивание freopen и ncurses

У меня проблемы с микшированием freopen из stdin вместе с библиотекой ncurses.

Что я делаю, это снова открываю стандартный файл в файл, анализирую его с помощью flex+bison, затем я должен вернуть его обратно и запустить ncurses.

Код для обмена является следующим:

void switchStdin(const char *newStream) {
  fflush(stdin);
  fgetpos(stdin, &pos);
  fd = dup(fileno(stdin));
  freopen(newStream, "r", stdin);
}

void revertStdin() {
  fflush(stdin);
  dup2(fd, fileno(stdin));
  close(fd);
  clearerr(stdin);
  fsetpos(stdin, &pos);
}

В моем лексере это то, что я делаю:

void parse() {
  Utils::switchStdin("./filename.ext");
  yyparse();
  Utils::revertStdin();
}

и в основном файле я просто делаю что-то вроде

parse();

initscr();
keypad(stdscr, TRUE);
noecho();
cbreak();
...

Теперь, если я не буду комментировать revertStdin он просто останавливается при запуске, если вместо этого я комментирую, синтаксический анализ работает, но графический интерфейс ncurses не отвечает и время от времени мигает.

Поскольку обе части работают независимо друг от друга, я предполагаю, что есть некоторая оговорка в их последовательном смешении, которое я пропускаю. У кого-нибудь есть ключ?

1 ответ

Там больше, чем одна проблема, но важная revertStdin не удается открыть поток:

  • switchStdin излишне называет непереносимым fflush(stdin),
  • он сохраняет дескриптор файла для stdin в fd и положение файла в pos,
  • положение файла не требуется (поскольку терминалы этого не делают)
  • revertStdin излишне называет непереносимым fflush(stdin),
  • он пытается переписать файловый дескриптор stdin используя сохраненный fd, Это не сработает.
  • в некоторых системах вы не можете присвоить новое значение stdin; бывает, что библиотека GNU C позволяет это. Если вы используете Linux, вы можете решить проблему, используя fdopen например,
    stdin = fdopen (fd, "r");
  • если нет (более переносимо) вы бы использовали newterm скорее, чем initscr, В отличие от initscr, newterm позволяет указать потоки для ввода и вывода. В этом случае вы все равно используете fdopen, но не пытаться назначить stdin, Используйте свою собственную переменную и передайте ее newterm,
Другие вопросы по тегам