Re: Компиляция Refal6 для Linu


Subject: Re: Компиляция Refal6 для Linu
From: Andrey Slepuhin (pooh@msu.ru)
Date: Mon Oct 29 2001 - 13:13:00 MSK


Прошу прощения за несколько запоздалое письмо, просто я хотел бы немного
прояснить ситуацию относительно ошибок.

On Sun, Oct 28, 2001 at 12:26:37AM +0400, dmsidorov@mtu-net.ru wrote:
> On Fri, Oct 26, 2001 at 08:28:50PM +0400, Arkady Klimov wrote:
> > Здравствуйте, Дмитрий,
> > с указанной Вами ошибкой я в некоторой растерянности. (На С
> > я уже более 5 лет не работаю). Почему-то до сих пор ни один
> > компилятор в этом месте не брыкался. Что сие означает? Верно
> > ли, что по стандарту языка правая часть инициализатора обязана
> > быть константой? И почему stderr - не константа?
>
> Здравствуйте, Аркадий.
>
> Мои познания в C++ весьма невелики, как инженер всегда старался
> использовать Паскаль или что-нибудь скриптовое, но вот что написано
> в FAQ к gcc2.95:
>
> Why can't I initialize a static variable with stdin?
> This has nothing to do with gcc, but people ask us about it a lot.
> Code like this:
>
> #include <stdio.h>
> FILE *yyin = stdin;
>
> will not compile with GNU libc (Linux libc6), because stdin is not a
> constant. This was done deliberately, in order for there to be no
> limit on the number of open FILE objects. It is surprising for people
> used to traditional Unix C libraries, but it is permitted by the C
> standard.
>
> Так что, получается, под Linux это будет считаться ошибкой как минимум
> до выхода новой glibc, а может, и дальше.
> Кроме того, glibc теперь включает в себя определения myulong и myushort
> (заголовок <sys/types.h>, включаемый через <stdlib.h>), полностью
> идентичные тем, что в исходниках Рефала, поэтому ошибки не возникает,
> но выдаются предупреждения об их переопределении. Чтобы избежать
> двойного определения, возможно, следует использовать препроцессорную
> директиву вроде
>
> #if __GLIBC__ >= 2
>
> но я пока не смотрел, начиная с какой версии это появилось.
>
> > В принципе, можно, наверно, поступить и так:
> >
> > 1.удалить эту строку 43 rfstor.h
> >
> > 2.заменить строку 40 rfstor.h на строку:
> > EXT FILE * stdtrc; /* File for debug information */
> > (было:
> > extern FILE * stdtrc; /* File for debug information */
> > )
> >
> > 3. Вставить инициализацию
> > stdtrc = stderr;
> > первым оператором в функцию initstor (файл rfstor.c, строка 256)
> > (эта функция вызывается первой в функции main).

С предопределенными потоками ввода-вывода все достаточно просто -
в описании стандартной библиотеки языка C нигде не указывается, что
три предопределенных потока ввода-вывода (stdin, stdout и stderr) должны
являться константными объектами, поэтому имплементация имеет право
определять их по своему усмотрению, и, следовательно, использование
их в качестве константных инициализаторов является некорректным. Поэтому
исправление, предложенное Аркадием, является единственно правильным.
Кстати, я на эти грабли в свое время наступил со старой реализацией
Рефала+.

>
> Этот способ сработал, после исправлений rfstor.c скомпилировался
> нормально. Теперь остались нескомпилированы rfarm.c и rbarm.c.
> В rbarm.c строка 252 содержит определение matherr, конфликтующее с
> аналогичным в <math.h>:
>
> # ifdef __cplusplus
> extern int matherr __P ((struct __exception *__exc));
> # else
> extern int matherr __P ((struct exception *__exc));
> # endif

Здесь несколько хуже: функция matherr() не является частью стандартной
библиотеки языка C, ее корни растут из интерфейсов Unix System V,
однако в текущем стандарте Unix98 она отсутствует. В частности, в
руководстве по glibc явно сказано:

   In the System V math library, the user-defined function `matherr' is
called when certain exceptions occur inside math library functions.
However, the Unix98 standard deprecates this interface. We support it
for historical compatibility, but recommend that you do not use it in
new programs.

То есть использовать эту функцию не рекомендуется. Вместо этого
предлагается использовать стандартные механизмы обработки сигналов -
при исключительных ситуациях во время операций с плавающей точкой
вырабатывается сигнал SIGFPE.

>
> Сообщение об ошибке в rfarm.c совершенно непонятно:
>
> rfarm.c: In function `rf_cgetnumb':
> rfarm.c:289: Unable to generate reloads for:
> (insn 45 43 47 (parallel[
> (set (reg:SI 0 %eax)
> (fix:SI (fix:SF (reg/v:SF 0 %eax))))
> (clobber (mem:HI (plus:SI (reg:SI 6 %ebp)
> (const_int -2 [0xfffffffe])) 0))
> (clobber (mem:HI (plus:SI (reg:SI 6 %ebp)
> (const_int -4 [0xfffffffc])) 0))
> (clobber (mem:SI (plus:SI (reg:SI 6 %ebp)
> (const_int -8 [0xfffffff8])) 0))
> (clobber (scratch:HI))
> ] ) 145 {fix_truncsfsi2+1} (insn_list 92 (nil))
> (expr_list:REG_EQUIV (mem:SI (reg/v:SI 3 %ebx) 0)
> (expr_list:REG_DEAD (reg/v:SF 0 %eax)
> (expr_list:REG_UNUSED (scratch:HI)
> (nil)))))
> make: *** [rfarm.o] Error 1
>
> Что делать с определением matherr в rbarm.c, я еще мог бы попробовать
> докопаться, но насчет rfarm.c никаких идей нет. Я еще не подписан, поэтому,
> если есть что подсказать, пишите не только в рассылку, но и на мой адрес.

Здесь однозначно ошибка компилятора, который не смог справиться с перегрузкой
значений регистров (в силу малого их количества в x86 архитектуре). В качестве
воркэраунда вокруг таких ситуаций обычно достаточно немного потасовать код
функции, не меняя ее смысл. Хотя лично я посоветовал бы переходить на
gcc-3.0.2. По крайней мере многие вещи там сделаны идеологически намного более
правильно.

Всего доброго,
Андрей.

-- 
A right thing should be simple (tm)



This archive was generated by hypermail 2b25 : Mon Oct 25 2004 - 21:24:59 MSD