Nuno Lucas escreveu:
> On 2/15/07, [EMAIL PROTECTED] <[EMAIL PROTECTED]> 
> wrote:
> [...]
>> 4) Map errno to [Get|Set]LastError() with preprocessor macros.
>>         #define errno GetLastError()
>>         #define __set_errno(X) SetLastError((DWORD)X)
>>         #define ENOMEM ERROR_OUTOFMEMORY
>>         (...)
> [...]
>> Conclusion:
>>
>> I like 4 the best, and I am going to give it a try.
>>
>> Any opinions/comments/requests-for-clarification/war_stories
>> would be much appreciated.
> 
> You forgot one solution:
> 
> 5) Win32 for WindowsCE doesn't have errno, just like it doesn't have
> any getcwd() and co. If the user is porting code with mingw32ce which
> uses this, either use it's own replacements or use cegcc.
> 


> I'm with 5. For me, mingw32ce is the thin wrapper around the WinCE
> Win32 API, so don't try to add functionality that doesn't exist
> already on the standard SDK.
> 

I don't see a problem in adding stuff to mingwex, as long as it
doesn't *change* what the runtime does.  Eg:  There is no fdopen
on coredll, but there is an _wfdopen.  How many implementations
of fdopen can the user pull off?  So, instead of forcing everyone
that encounters an fdopen call to port it himself, we have it in
libmingwex.a.  Notice that this is a static lib.  No dll dependency.
If the user still doesn't like our fdopen, just reimplement it, and
the linker won't even bother with our version.  This is a very
different attitude from cegcc.  On cegcc, we *reimplement* most
of the c runtime (crt).  In cegcc, when you call fopen, you are
calling the newlib version of fopen, although there is an fopen in
coredll.dll (we are ignoring it).  Another example, and I could keep
going on: in cegcc, we have our own malloc.  So allocating memory
in a cegcc app, passing the pointer into a dll build with
mingw32ce/msvc, and freeing it there, will surely crash.

So, all the extensions we have / will have on mingw32ce, will
not reimplement (minus really needed exceptions) what already
exists on coredll.  The resulting app is still a "native" WinCE
app.

I suggest everyone to take a look at wince ports of stuff like
ruby, sshd, python, <insert favorite package here>, and you will
see the same code over and over again.  If we have it on the base
package, there is only one place to have it done, and one place to
fixed if it is broken.  Having to keep local patches for a lot of
libs, and/or convincing that maintainers of those apps/libs to
accept twists into their package because WinCE is such a broken
dev env, is a worse solution IMHO.  I guess this brokenness is in my
humble opinion the reason you don't see more stuff ported to
wince, and the free developers base for wince stuff is so low.


> The possible exception may be the implementation of the minimum
> required to build a minimal C++ standard library, but I would not
> worry about iostreams and such (anyone using iostreams on WinCE,
> instead of using the lower level API is probably going in the wrong
> direction anyway).
> 

Why?  What is wrong with iostreams?

> Also, many things weren't available on earlier WinCE versions that are
> now on recent versions, so there's the risk of implementing too much
> and make the programs not compatible for the future.
> 

I don't see how.  If something we have will be added to wince proper,
we just adapt to it.  As long as the existing functions from coredll.dll
don't change their meaning, there won't be any incompatibility.  And
we all know MSFT does have a commitment to backwards compatibility.

> And, most of the missing "standard" C runtime functions are
> implemented in the MFC libraries, so a latter support for MFC
> applications compiled with mingw32ce could become messy if we do too
> much now.
> 

That doesn't case sense at all.  MFC is a c++ lib, with a very different
API from the std c functions, so how would it become messy?



> I don't mind having a separate helper library for mingw32ce but, for
> me, anyone using errno with mingw32ce will always get into trouble
> latter (there's no way to correctly map the errno errors with the
> GetLastError() results).
> 

I was until this week of the very same opinion.  If was after at porting
a bunch of packages, that I realized that 99% of the time, it does map well,
and that most ports do it the wrong way.  Look at the VLC mingw errno.h.  They
went around it by having an errno.h, and declaring a 'static int errno'.  That
is another solution I forgot adding to the list, so here goes:

6) declare an errno.h with a 'static int errno'.

This is broken, because every object (.o) will have its own instance of errno,
thus, what you get is that errno will not work across objects.

eg:
        errno.h:
        static int errno;

        file1.c:
        #include <errno.h>
        int function1()
        { errno = 1; }

        file2.c:
        #include <errno.h>
        errno = 0;
        function1();
        if (errno != 0)
        { /* will never be hit.  */}


I have another solution, that looks promising.

7) Have an int errno that maps to [Get|Set]LastError, and enables use as an 
lvalue.

This solution works across dlls,
without a shared dll, has minimum code impact, but, depends on SEH.  I tried
using the same trick as in src/newlib/newlib/libc/sys/wince/crt0.S to have SEH
with mingw32ce, but failed, so I though I would test it first in MSVC. Here is 
the
code.

#include <windows.h>

#define ERRNO_HELPER_ADDR 0xfeed

int*
_errno (void)
{
    return (int*)ERRNO_HELPER_ADDR;
}

#define errno (*_errno ())

int
_errno_handler (DWORD excp_code, struct _EXCEPTION_POINTERS *ExceptionPointers)
{
        PEXCEPTION_RECORD ExceptionRecord = ExceptionPointers->ExceptionRecord;
        PCONTEXT ContextRecord = ExceptionPointers->ContextRecord;

        if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
                return EXCEPTION_CONTINUE_SEARCH;

        DWORD Cmd = *(DWORD *)ExceptionRecord->ExceptionAddress;

        switch (Cmd&0xfff00000)
        {
        case 0xe5900000:
                {
                        DWORD DataAddr;
                        int Src, Dst, Off;
                        DWORD *Regs = (DWORD*)&ContextRecord->R0;
                        Src = (Cmd >> 16) & 0xf;
                        Dst = (Cmd >> 12) & 0xf;
                        Off = Cmd & 0xfff;
                        DataAddr = Regs[Src] + Off;
                        if (DataAddr != ERRNO_HELPER_ADDR)
                                return EXCEPTION_CONTINUE_SEARCH;
                        Regs[Dst] = GetLastError ();
                        break;
                }
        case 0xe5800000:
                {
                        DWORD DataAddr;
                        int Src, Dst, Off;
                        DWORD *Regs = (DWORD*)&ContextRecord->R0;
                        Dst = (Cmd >> 16) & 0xf;
                        Src = (Cmd >> 12) & 0xf;
                        Off = Cmd & 0xfff;
                        DataAddr = Regs[Dst] + Off;
                        if (DataAddr != ERRNO_HELPER_ADDR)
                                return EXCEPTION_CONTINUE_SEARCH;
                        SetLastError (Regs[Src]);
                        break;
                }
        default:
                {
#if 0
                        printf("Unhandled command:%x\n", Cmd);
#endif
                        return EXCEPTION_CONTINUE_SEARCH;
                }
        }
        ContextRecord->Pc += 4; // skip faulty instruction
        return EXCEPTION_CONTINUE_EXECUTION;
}

int
WINAPI WinMain2(HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPTSTR    lpCmdLine,
                int       nCmdShow)
{
        printf ("GetLastError (%d): %d\r\n", __LINE__, GetLastError ());
        errno = 1;
        printf ("GetLastError (%d): %d\r\n", __LINE__, GetLastError ());
        errno = 0;
        printf ("GetLastError (%d): %d\r\n", __LINE__, GetLastError ());
        errno = 20;
        printf ("GetLastError (%d): %d\r\n", __LINE__, GetLastError ());
        errno = 10;
        printf ("errno (%d): %d\r\n", __LINE__, errno);
        volatile int a = errno;
        SetLastError (30);
        printf ("errno (%d): %d\r\n", __LINE__, errno);
        return 0;
}

int
WINAPI WinMain (HINSTANCE hInstance,
                HINSTANCE hPrevInstance,
                LPTSTR    lpCmdLine,
                int       nCmdShow)
{
        __try
        {
                return WinMain2 (hInstance, hPrevInstance, lpCmdLine, nCmdShow);
        }
        __except (_errno_handler (GetExceptionCode (), GetExceptionInformation 
()))
        {}
        return 1;
}

I woke up on the middle of the night with this solution banging on my head,
so I could resist to test it.  It works.  Back to bed now.

Cheers,
Pedro Alves



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Cegcc-devel mailing list
Cegcc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cegcc-devel

Reply via email to