| Vasili Burdo on Thu, 17 Dec 2009 18:07:55 +0100 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| A patch for native PARI/GP build on Windows (Mingw+Msys) |
It includes: - Configuration changes to recognize Mingw build. - Native hires plotting for Windows. - Native support of Windows console including terminal size and colors.- All tests are passed for gp-syn. For gp-sta, tests involving install() fail.
This patch is based on current PARI SVN. Comments and suggestions are VERY welcome. Vasili.
Index: config/arch-osname
===================================================================
--- config/arch-osname (revision 12034)
+++ config/arch-osname (working copy)
@@ -29,6 +29,9 @@
cygwin*) arch=`uname -m`
if test -z "$arch"; then arch=ix86; fi
osname=cygwin;;
+ mingw*) arch=`uname -m`
+ if test -z "$arch"; then arch=ix86; fi
+ osname=mingw;;
ultrix) arch=mips;;
nextstep) arch=`file /bin/sh | sed 's/.*(for architecture \(.*\))/\1/'`;;
darwin*) arch=`uname -p`
Index: config/get_dlld
===================================================================
--- config/get_dlld (revision 12034)
+++ config/get_dlld (working copy)
@@ -18,7 +18,7 @@
soname=$sodest;;
hpux) soname= ; sodest= ; DLSUFFIX=sl;;
irix) soname= ; sodest= ;;
- os2|cygwin)soname= ; sodest= ; DLSUFFIX=dll ;;
+ os2|cygwin|mingw)soname= ; sodest= ; DLSUFFIX=dll ;;
darwin)soname= ; sodest= ; DLSUFFIX=dylib;;
*) do_dll=no ;;
esac
@@ -27,6 +27,7 @@
# On FreeBSD 2.2.5 (Y. Uchikawa) and Cygwin, this does not work.
case "$osname" in
freebsd|cygwin) DL_DFLT_NAME="\\\"\$(LIBPARI_DYN)\\\"" ;;
+ mingw) DL_DFLT_NAME="\\\"\$(LIBPARI_SO)\\\"" ;;
*) DL_DFLT_NAME=NULL ;;
esac
@@ -84,6 +85,7 @@
case "$osname" in
os2) DLLDFLAGS="$CFLAGS -Zdll" ;; # assume DLLD = gcc
cygwin) DLLDFLAGS="-Wl,--out-implib=\$(LIBPARI_SO)\$(_A),--export-all-symbols";;
+ mingw) DLLDFLAGS="-Wl,--out-implib=\$(LIBPARI_SO)\$(_A)";;
esac
if test -n "$DLLDisGCC"; then
case "$arch" in
Index: config/get_graphic_lib
===================================================================
--- config/get_graphic_lib (revision 12034)
+++ config/get_graphic_lib (working copy)
@@ -29,4 +29,9 @@
. ./get_Qt # QTDIR, QTLIB
fi
+if test "$which_graphic_lib" == none; then
+ if test "$osname" == "mingw"; then
+ which_graphic_lib=win32
+ fi
+fi
echo "Hi-Res Graphics: $which_graphic_lib"
Index: config/Makefile.SH
===================================================================
--- config/Makefile.SH (revision 12034)
+++ config/Makefile.SH (working copy)
@@ -48,6 +48,10 @@
export_file=pari.def; export_create="emxexp -u"
# Actually, the build will fail until the switch to -Zomf
dlld_ignore=- ;;
+ mingw)
+ CFLAGS="$CFLAGS -fno-omit-frame-pointer"
+ export_file='$(LIBPARI).def'
+ ;;
esac
PLOTCFLAGS=
@@ -65,6 +69,9 @@
PLOTLIBS="-L\$(FLTKDIR)/lib -lfltk $FLTK_LIBS"
postconfig='-fltk-config --post '
graph=plotfltk;;
+win32)
+ PLOTLIBS="-lgdi32"
+ graph=plotWin32;;
esac
graph="plotport $graph"
@@ -489,6 +496,8 @@
EOT
else
if test -n "$export_file"; then
+ case "$osname" in
+ os2)
cat >> $file << EOT
EXPORT_FILE_BASE = $src/systems/os2/pari.def.base
@@ -502,6 +511,19 @@
\$(EXPORT_LIB_CREATE) -o \$@ \$(EXPORT_FILE)
EOT
+ ;;
+ mingw)
+ cat >> $file << EOT
+
+\$(EXPORT_FILE): \$(OBJS)
+ echo LIBRARY \$(LIBPARI) > \$@
+ echo EXPORTS >> \$@
+ nm --defined-only \$(OBJS) | grep -E '[0-9a-f]+ [A-Z] [^.]' | cut -d ' ' -f 3 | cut -c '2-' >> \$@
+ nm --defined-only \$(OBJS) | grep -E '[0-9a-f]+ [BCDGRS] [^.]' | cut -d ' ' -f 3 | cut -c '2-' | sed -e 's/\(.*\)/\1 DATA/'>> \$@
+
+EOT
+ ;;
+ esac
fi
cat >> $file << EOT
Index: config/paricfg.h.SH
===================================================================
--- config/paricfg.h.SH (revision 12034)
+++ config/paricfg.h.SH (working copy)
@@ -10,7 +10,7 @@
if test -n "$perl"; then
case "$osname" in
- os2) gphelp="perl -S gphelp -detex" ;;
+ os2|mingw) gphelp="perl -S gphelp -detex" ;;
*) gphelp="$bindir/gphelp" ;;
esac
fi
@@ -73,6 +73,19 @@
fi
fi
+if test "$osname" = "mingw"; then
+cat >> $file << EOT
+
+#undef UNIX
+#undef GPDATADIR
+#define GPDATADIR win32_GPDATADIR()
+#define GNUZCAT
+#undef ZCAT
+#define ZCAT "gzip.exe -dc"
+
+EOT
+fi
+
if test -n "$readline"; then
cat >> $file <<EOT
/* Use GNU readline library */
Index: Configure
===================================================================
--- Configure (revision 12034)
+++ Configure (working copy)
@@ -125,7 +125,7 @@
EOT
case "$osname" in
- os2) shell_q='"'; echo "shell_q='\"'" >> $dflt_conf_file;;
+ os2|mingw) shell_q='"'; echo "shell_q='\"'" >> $dflt_conf_file;;
*) shell_q="'"; echo "shell_q=\"'\"" >> $dflt_conf_file;;
esac
Index: src/graph/plotWin32.c
===================================================================
--- src/graph/plotWin32.c (revision 0)
+++ src/graph/plotWin32.c (revision 0)
@@ -0,0 +1,125 @@
+/* $Id: plotnull.c 7522 2005-12-09 18:14:24Z kb $
+
+Copyright (C) 2000 The PARI group.
+
+This file is part of the PARI/GP package.
+
+PARI/GP is free software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation. It is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY WHATSOEVER.
+
+Check the License for details. You should have received a copy of it, along
+with the package; see the file 'COPYING'. If not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "pari.h"
+#include "paripriv.h"
+#include "rect.h"
+#include <windows.h>
+
+static void SetForeground(void *data, long col)
+{
+ int r,g,b;
+ color_to_rgb(gel(pari_colormap,col), &r, &g, &b);
+
+ HPEN hOldPen = SelectObject((HDC)data, CreatePen(PS_SOLID, 2, RGB(r,g,b)));
+ if( hOldPen ) DeleteObject(hOldPen);
+}
+
+static void DrawPoint(void *data, long x, long y)
+{
+ //printf("DrawPoint\n");
+ Ellipse((HDC)data,x-1,y-1,x+1,y+1);
+}
+
+static void DrawLine(void *data, long x1, long y1, long x2, long y2)
+{
+ //printf("DrawLine %d:%d %d:%d\n", x1,y1,x2,y2);
+ MoveToEx((HDC)data, x1, y1, NULL);
+ LineTo((HDC)data,x2,y2);
+}
+
+static void DrawRectangle(void *data, long x, long y, long w, long h)
+{
+ //printf("DrawRectangle %d:%d %d:%d\n", x,y,x+w,y+h);
+ RECT rc;
+ rc.left = x; rc.right = x+w;
+ rc.top = y; rc.bottom = y+h;
+ FrameRect((HDC)data, &rc, GetStockObject(HOLLOW_BRUSH));
+}
+
+static void DrawPoints(void *data, long nb, struct plot_points *p)
+{
+ //printf("DrawPoints\n");
+ long i;
+ for(i=0; i<nb; ++i)
+ DrawPoint(data,p[i].x,p[i].y);
+}
+
+static void DrawLines(void *data, long nb, struct plot_points *p)
+{
+ //printf("DrawLines\n");
+ long i;
+ MoveToEx((HDC)data, p[0].x, p[0].y, NULL);
+ for(i=1; i<nb; ++i)
+ LineTo((HDC)data,p[i].x,p[i].y);
+}
+
+static void DrawString(void *data, long x, long y, char *text, long numtext)
+{
+ //printf("DrawString(%d:%d %s\n",x, y, text);
+ TextOut((HDC)data, x, y, text, numtext);
+}
+
+void rectdraw0(long *w, long *x, long *y, long lw)
+{
+ char tmppath[MAX_PATH], fname[MAX_PATH];
+ struct plot_eng plotWin32;
+ HDC hEmf;
+
+ GetTempPath(sizeof(tmppath), tmppath);
+ sprintf(fname, "%s\\gp-ploth-%x.emf", tmppath, time(NULL)/(24*60*60)*1000+GetTickCount());
+
+ hEmf = CreateEnhMetaFile(GetDC(NULL), fname, NULL, NULL);
+ SetMapMode(hEmf, MM_TEXT);
+ SelectObject(hEmf, GetStockObject(DEFAULT_GUI_FONT));
+ SetBkColor(hEmf, RGB(255,255,255));
+ SetBkMode(hEmf, TRANSPARENT);
+
+ plotWin32.sc=&SetForeground;
+ plotWin32.pt=&DrawPoint;
+ plotWin32.ln=&DrawLine;
+ plotWin32.bx=&DrawRectangle;
+ plotWin32.mp=&DrawPoints;
+ plotWin32.ml=&DrawLines;
+ plotWin32.st=&DrawString;
+ plotWin32.pl=&pari_plot;
+
+ gen_rectdraw0(&plotWin32, (void*)hEmf, w, x, y, lw, 1, 1);
+ DeleteEnhMetaFile(CloseEnhMetaFile(hEmf));
+
+ ShellExecute(NULL,NULL,fname,NULL,NULL,SW_SHOWDEFAULT);
+}
+
+void
+PARI_get_plot(long f)
+{
+ HDC hdc;
+ TEXTMETRIC tm;
+ if (pari_plot.init) return; // pari_plot is already set
+
+ pari_plot.init = 1;
+ pari_plot.width = GetSystemMetrics(SM_CXSCREEN)/2;
+ pari_plot.height = GetSystemMetrics(SM_CYSCREEN)/2;
+ pari_plot.hunit = pari_plot.width/100;
+ pari_plot.vunit = pari_plot.height/100;
+
+ hdc = GetDC(0);
+ SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
+ GetTextMetrics(hdc, &tm);
+ ReleaseDC(0,hdc);
+
+ pari_plot.fwidth = tm.tmAveCharWidth;
+ pari_plot.fheight = tm.tmHeight;
+}
Index: src/language/es.c
===================================================================
--- src/language/es.c (revision 12034)
+++ src/language/es.c (working copy)
@@ -21,6 +21,9 @@
#include "pari.h"
#include "paripriv.h"
#include "anal.h"
+#ifdef _WIN32
+#include <windows.h>
+#endif
typedef struct outString {
char *string; /* start of the output buffer */
@@ -376,7 +379,11 @@
static void
normalOutS(const char *s)
{
+#ifdef _WIN32
+ win32_ansi_fputs(s, pari_outfile);
+#else
fputs(s, pari_outfile);
+#endif
if (pari_logfile) { fputs(s, pari_logfile); }
}
static void
@@ -396,7 +403,11 @@
static void
normalErrS(const char *s)
{
+#ifdef _WIN32
+ win32_ansi_fputs(s, pari_errfile);
+#else
fputs(s, pari_errfile);
+#endif
if (pari_logfile) fputs(s, pari_logfile);
}
static void
@@ -1340,6 +1351,9 @@
term_width_intern(void)
{
if (GP_DATA->flags & TEST) return 0;
+#ifdef _WIN32
+ return win32_terminal_width();
+#endif
#ifdef HAS_TIOCGWINSZ
{
struct winsize s;
@@ -1364,6 +1378,9 @@
term_height_intern(void)
{
if (GP_DATA->flags & TEST) return 0;
+#ifdef _WIN32
+ return win32_terminal_height();
+#endif
#ifdef HAS_TIOCGWINSZ
{
struct winsize s;
@@ -2999,6 +3016,9 @@
# endif
# define HAVE_PIPES
#endif
+#if defined(_WIN32)
+# define HAVE_PIPES
+#endif
#ifndef O_RDONLY
# define O_RDONLY 0
#endif
@@ -3481,7 +3501,18 @@
char *
path_expand(const char *s)
{
+#ifdef _WIN32
+ char *ss, *p;
+ ss = malloc(strlen(s)+1);
+ strcpy(ss,s);
+ for(p = ss; *p != 0; ++p)
+ if( *p == '\\' ) *p = '/';
+ p = _expand_env(_path_expand(ss));
+ free(ss);
+ return p;
+#else
return _expand_env(_path_expand(s));
+#endif
}
void
@@ -3631,6 +3662,13 @@
static int
is_absolute(char *s)
{
+#ifdef _WIN32
+ if( (*s >= 'A' && *s <= 'Z') ||
+ (*s >= 'a' && *s <= 'z') )
+ {
+ return *(s+1) == ':';
+ }
+#endif
if (*s == '/') return 1;
if (*s++ != '.') return 0;
if (*s == '/') return 1;
@@ -4166,6 +4204,11 @@
}
static int
pari_dir_exists(const char *s) { return mkdir(s, 0777); }
+#elif defined(_WIN32)
+static int
+pari_file_exists(const char *s) { return GetFileAttributesA(s) != ~0; }
+static int
+pari_dir_exists(const char *s) { return mkdir(s); }
#else
static int
pari_file_exists(const char *s) { return 0; }
@@ -4239,7 +4282,7 @@
#ifdef __EMX__
if (!unix_shell())
#endif
-#if defined(__EMX__) || defined(WINCE)
+#if defined(__EMX__) || defined(WINCE) || defined(_WIN32)
{
char *t;
for (t=s; *t; t++)
Index: src/systems/mingw/mingw.c
===================================================================
--- src/systems/mingw/mingw.c (revision 0)
+++ src/systems/mingw/mingw.c (revision 0)
@@ -0,0 +1,93 @@
+#include <windows.h>
+#include <stdio.h>
+
+const char*
+win32_GPDATADIR()
+{
+ static char datadir[1024] = {0};
+ if( 0 == *datadir ) {
+ char* slash;
+ GetModuleFileNameA(0, datadir, sizeof(datadir) );
+ slash = strrchr(datadir, '\\');
+ if( slash ) *(slash+1) = 0;
+ //while( (slash = strchr(datadir, '\\')) )
+ // *slash = '/';
+ strcat(datadir, "gp-data");
+ }
+ return datadir;
+}
+
+static WORD
+win32_console_color(unsigned long c)
+{
+ int shift, intense = 0;
+ if( c >= 30 && c <= 37 ) { shift = 0; c %= 30; } else
+ if( c >= 40 && c <= 47 ) { shift = 4; c %= 40; } else
+ if( c >= 90 && c <= 97 ) { shift = 0; intense = 8; c %= 90; } else
+ if(c >= 100 && c <= 107) { shift = 4; intense = 8; c %= 100; } else
+ return 0;
+
+ WORD w = 0;
+ switch(c) {
+ case 0: w = 0; break; //black
+ case 1: w = 4; break; //red
+ case 2: w = 2; break; //green
+ case 3: w = 6; break; //yellow RG
+ case 4: w = 1; break; //blue
+ case 5: w = 5; break; //magenta RB
+ case 6: w = 3; break; //cyan GB
+ case 7: w = 7; break; //white RGB
+ }
+ return (w|intense) << shift;
+}
+
+void
+win32_ansi_fputs(const char* s, void* f)
+{
+ if( !(f == stdout || f == stderr) ) {
+ fputs(s,f);
+ return;
+ }
+
+ while(1) {
+ const char *p;
+ p = strstr(s, "\x1b[");
+ if( p > s )
+ fwrite(s,p-s,1,f);
+
+ if( p )
+ p += 2;
+ else {
+ (fputs)(s,f);
+ return;
+ }
+
+ WORD color = 7;
+ unsigned long a1=0,a2=0,a3=0;
+ a1 = strtoul(p,&p,10);
+ if( *p == ';' ) a2 = strtoul(p+1,&p,10);
+ if( *p == ';' ) a3 = strtoul(p+1,&p,10);
+ if( *p++ == 'm' ) {
+ if( a2|a3 )
+ color = win32_console_color(a2) | win32_console_color(a3);
+ }
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
+ s = p;
+ }
+}
+
+int win32_terminal_width()
+{
+ CONSOLE_SCREEN_BUFFER_INFO sbi;
+ if( !GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi) )
+ return 0;
+ return (sbi.srWindow.Right - sbi.srWindow.Left);
+}
+
+int win32_terminal_height()
+{
+ CONSOLE_SCREEN_BUFFER_INFO sbi;
+ if( !GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi) )
+ return 0;
+ return (sbi.srWindow.Bottom - sbi.srWindow.Top);
+}
Index: src/test/dotest
===================================================================
--- src/test/dotest (revision 12034)
+++ src/test/dotest (working copy)
@@ -74,7 +74,7 @@
gp=$execdir/gp-$suf;;
esac
(cat $file_in; echo 'print("Total time spent: ",gettime);') | $gp -q --test > $file_test 2>&1
- diff -c $file_out $file_test > $file_diff
+ diff -cwb $file_out $file_test > $file_diff
pat=`grep "^[-+!] " $file_diff | grep -v "Total time"`
time=`${tail}1 $file_test | sed -n 's,.*Total time spent: \(.*\),\1,p'`
if test -n "$time"; then