1.1 --- a/test/harness/testcase.c Fri Jan 27 21:40:35 2012 +0000
1.2 +++ b/test/harness/testcase.c Fri Jan 27 23:59:51 2012 +0000
1.3 @@ -3,10 +3,6 @@
1.4 #include <string.h>
1.5 #include <unistd.h>
1.6 #include <errno.h>
1.7 -#ifdef WIN32
1.8 -#include <io.h>
1.9 -#endif
1.10 -#include <fcntl.h>
1.11 #include <bl/bl.h>
1.12 #include "testcase.h"
1.13
1.14 @@ -15,86 +11,12 @@
1.15 return g_quark_from_static_string("testcase-error-quark");
1.16 }
1.17
1.18 -#if !HAVE_MKSTEMP
1.19 /*
1.20 - * An insecure implementation of mkstemp(), for those platforms that
1.21 - * don't support it.
1.22 + * As write(), but with error handling.
1.23 */
1.24 -int mkstemp(char *template)
1.25 +static size_t write_file(int fd,const char *buf,size_t count,GError **error)
1.26 {
1.27 - int fd;
1.28 - char *s;
1.29 - for(;;)
1.30 - {
1.31 - s=g_strdup(template);
1.32 - mktemp(s);
1.33 - if (!*s)
1.34 - {
1.35 - errno=EEXIST;
1.36 - g_free(s);
1.37 - return -1;
1.38 - }
1.39 - fd=open(s,O_RDWR|O_CREAT|O_EXCL,0600);
1.40 - if (fd>0)
1.41 - {
1.42 - strcpy(template,s);
1.43 - g_free(s);
1.44 - return fd;
1.45 - }
1.46 - else
1.47 - g_free(s);
1.48 - }
1.49 -}
1.50 -#endif /* !HAVE_MKSTEMP */
1.51 -
1.52 -/*
1.53 - * As write(), but always convert NL to CR NL.
1.54 - */
1.55 -static size_t write_text(int fd,const char *buf,size_t count,GError **error)
1.56 -{
1.57 - size_t i;
1.58 - FILE *fp;
1.59 - fd=dup(fd);
1.60 - if (fd<0)
1.61 - return -1;
1.62 -#ifdef WIN32
1.63 - if (_setmode(fd,_O_BINARY)<0)
1.64 - {
1.65 - close(fd);
1.66 - g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.67 - "Failed to set mode of bookloupe input file to binary: %s",
1.68 - g_strerror(errno));
1.69 - return -1;
1.70 - }
1.71 -#endif
1.72 - fp=fdopen(fd,"wb");
1.73 - if (!fp)
1.74 - {
1.75 - close(fd);
1.76 - g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.77 - "Failed to open stream to bookloupe input file: %s",
1.78 - g_strerror(errno));
1.79 - return -1;
1.80 - }
1.81 - for(i=0;i<count;i++)
1.82 - {
1.83 - if (buf[i]=='\n')
1.84 - if (putc('\r',fp)==EOF)
1.85 - {
1.86 - g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.87 - "Error writing bookloupe input file: %s",g_strerror(errno));
1.88 - (void)fclose(fp);
1.89 - return -1;
1.90 - }
1.91 - if (putc(buf[i],fp)==EOF)
1.92 - {
1.93 - g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.94 - "Error writing bookloupe input file: %s",g_strerror(errno));
1.95 - (void)fclose(fp);
1.96 - return -1;
1.97 - }
1.98 - }
1.99 - if (fclose(fp))
1.100 + if (write(fd,buf,count)<count)
1.101 {
1.102 g_set_error(error,G_FILE_ERROR,g_file_error_from_errno(errno),
1.103 "Error writing bookloupe input file: %s",g_strerror(errno));
1.104 @@ -104,20 +26,30 @@
1.105 }
1.106
1.107 /*
1.108 - * Return the length (in bytes) or any common prefix between s1 and s2.
1.109 + * Return the length (in bytes) of any common prefix between s1 and s2.
1.110 + * The returned length will always represent an exact number of characters.
1.111 */
1.112 size_t common_prefix_length(const char *s1,const char *s2)
1.113 {
1.114 - size_t i;
1.115 - for(i=0;s1[i] && s2[i] && s1[i]==s2[i];i++)
1.116 - ;
1.117 - return i;
1.118 + gunichar c1,c2;
1.119 + const char *s=s1;
1.120 + while(*s1 && *s2)
1.121 + {
1.122 + c1=g_utf8_get_char(s1);
1.123 + c2=g_utf8_get_char(s2);
1.124 + if (c1!=c2)
1.125 + break;
1.126 + s1=g_utf8_next_char(s1);
1.127 + s2=g_utf8_next_char(s2);
1.128 + }
1.129 + return s1-s;
1.130 }
1.131
1.132 void print_unexpected(const char *unexpected,gsize differs_at)
1.133 {
1.134 int col;
1.135 - const char *endp,*bol;
1.136 + gunichar c;
1.137 + const char *endp,*bol,*s;
1.138 GString *string;
1.139 endp=strchr(unexpected+differs_at,'\n');
1.140 if (!endp)
1.141 @@ -128,27 +60,64 @@
1.142 bol++;
1.143 else
1.144 bol=string->str;
1.145 - col=differs_at-(bol-string->str);
1.146 + col=0;
1.147 + s=bol;
1.148 + endp=string->str+differs_at;
1.149 + while(s<endp)
1.150 + {
1.151 + c=g_utf8_get_char(s);
1.152 + s=g_utf8_next_char(s);
1.153 + if (c=='\t')
1.154 + col=(col&~7)+8;
1.155 + else if (g_unichar_iswide(c))
1.156 + col+=2;
1.157 + else if (!g_unichar_iszerowidth(c))
1.158 + col++;
1.159 + }
1.160 fprintf(stderr,"%s\n%*s^\n",string->str,col,"");
1.161 g_string_free(string,TRUE);
1.162 }
1.163
1.164 +/*
1.165 + * Replace \n with \r\n and U+240A (visible symbol for LF) with \n
1.166 + */
1.167 +char *unix2dos(const char *text)
1.168 +{
1.169 + gunichar c;
1.170 + const gunichar visible_lf=0x240A;
1.171 + GString *string;
1.172 + string=g_string_new(NULL);
1.173 + while(*text)
1.174 + {
1.175 + c=g_utf8_get_char(text);
1.176 + text=g_utf8_next_char(text);
1.177 + if (c=='\n')
1.178 + g_string_append(string,"\r\n");
1.179 + else if (c==visible_lf)
1.180 + g_string_append_c(string,'\n');
1.181 + else
1.182 + g_string_append_unichar(string,c);
1.183 + }
1.184 + return g_string_free(string,FALSE);
1.185 +}
1.186 +
1.187 gboolean spawn_bootloupe(const char *encoding,const char *standard_input,
1.188 char **standard_output,char **filename,GError **error)
1.189 {
1.190 gboolean r;
1.191 int fd,exit_status;
1.192 size_t n,pos,offset;
1.193 - FILE *fp;
1.194 char input[]="TEST-XXXXXX";
1.195 char *command[3];
1.196 - char *output,*s;
1.197 + char *output,*s,*t;
1.198 GError *tmp_err=NULL;
1.199 if (standard_input)
1.200 {
1.201 if (encoding)
1.202 {
1.203 - s=g_convert(standard_input,-1,encoding,"UTF-8",NULL,&n,&tmp_err);
1.204 + t=unix2dos(standard_input);
1.205 + s=g_convert(t,-1,encoding,"UTF-8",NULL,&n,&tmp_err);
1.206 + g_free(t);
1.207 if (!s)
1.208 {
1.209 g_propagate_prefixed_error(error,tmp_err,
1.210 @@ -158,7 +127,7 @@
1.211 }
1.212 else
1.213 {
1.214 - s=g_strdup(standard_input);
1.215 + s=unix2dos(standard_input);
1.216 n=strlen(s);
1.217 }
1.218 }
1.219 @@ -167,8 +136,8 @@
1.220 n=0;
1.221 s=NULL;
1.222 }
1.223 - fd=mkstemp(input);
1.224 - if (n && write_text(fd,s,n,error)!=n)
1.225 + fd=g_mkstemp(input);
1.226 + if (n && write_file(fd,s,n,error)!=n)
1.227 {
1.228 g_free(s);
1.229 close(fd);