|
今天阅读了GMP的代码,发现许多有趣的东西,看到了一种在一个文件中混合多种语言的技巧。这里的混合语言编程不是指C中嵌入汇编语言的那种,C中嵌入汇编语言还是符合某种C编译器语言语法的。这里的混合语言具有这样的特点,文件类型是A语言源代码,但在文件中A嵌入B语言源代码。比如
1. 批处理中嵌入perl代码,下面的例子是我的一个老大(美国人)写的。这里的关键是"#!Perl/bin/perl -w" 和 "%perl% -x %0 %*" 这2句. 第2句使用参数 -x 调用自己,按照perl命令行参数的规则,则#!Perl前的代码将忽略。
-----------------------------------
@rem = '--*-Perl-*--
@echo off
rem is perl on path?
perl -v > nul 2>&1
if %errorlevel% equ 0 (
set perl=perl
) ELSE (
set perl=c:\svg_cygwin_db\bin\perl.exe
)
if "%OS%" == "Windows_NT" goto WinNT
echo PERL=%perl%
%perl% -x "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9
goto endofperl
:WinNT
%perl% -x %0 %*
if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl
if %errorlevel% == 9009 echo You do not have Perl in your PATH.
if errorlevel 1 goto script_failed_so_exit_with_non_zero_val 2>nul
goto endofperl
@rem ';
#!Perl/bin/perl -w
#line 22
use FindBin qw(\$RealDir);
use lib "\$RealDir/lib";
use RTH;
RTH::run();
__END__
:endofperl
------------------------------------------------
2.shell脚本中嵌入c语言源代码。
这是在GMP源码包中的config.guess中看到了。这个文件的类型是shell脚本,从第一句"#! /bin/sh" 可以看出。但在这个文件文件中混入许多c代码。例如:"cat >\$dummy.c <<\EOF" 下面的行就是标准的c代码,直到EOF为止,在EOF下面的代码则是将这段c代码编译并运行编译好的程序。
---------------------------------------------------------------
dummy=my_test
cat >\$dummy.c <<\EOF
#include <stdio.h>
struct {
int n; /* force 4-byte alignment */
char a[8];
} getpvr = {
0,
{
0x7c, 0x7f, 0x42, 0xa6, /* mfpvr r3 */
0x4e, 0x80, 0x00, 0x20, /* blr */
}
};
int
main ()
{
unsigned (*fun)();
unsigned pvr;
/* a separate "fun" variable is necessary for gcc 2.95.2 on MacOS,
it gets a compiler error on a combined cast and call */
fun = (unsigned (*)()) getpvr.a;
pvr = (*fun) ();
switch (pvr >> 16) {
case 0x0001: puts ("powerpc601"); break;
case 0x0003: puts ("powerpc603"); break;
case 0x0004: puts ("powerpc604"); break;
case 0x0006: puts ("powerpc603e"); break;
case 0x0007: puts ("powerpc603e"); break; /* 603ev */
case 0x0008: puts ("powerpc750"); break;
case 0x0009: puts ("powerpc604e"); break;
case 0x000a: puts ("powerpc604e"); break; /* 604ev5 */
case 0x000c: puts ("powerpc7400"); break;
case 0x0041: puts ("powerpc630"); break;
case 0x0050: puts ("powerpc860"); break;
case 0x8000: puts ("powerpc7450"); break;
case 0x8001: puts ("powerpc7455"); break;
case 0x8002: puts ("powerpc7457"); break;
case 0x8003: puts ("powerpc7447"); break; /* really 7447A */
case 0x800c: puts ("powerpc7410"); break;
}
return 0;
}
EOF
if (\$CC_FOR_BUILD \$dummy.c -o \$dummy) >/dev/null 2>&1; then
# This style construct is needed on AIX 4.3 to suppress the SIGILL error
# from (*fun)(). Using \$SHELL -c ./\$dummy 2>/dev/null doesn't work.
{ x=`./\$dummy`; } 2>/dev/null
if test -n "\$x"; then
exact_cpu=\$x
fi
fi
-----------------------------------------------------------------------------------------------------------------------------
注意:由于本论坛会对美元符号解释为公式,故文中所有的美元符号都写成斜杠加美元符号。 |
|