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