Subject: Re: BUG: Pine 4.60 errors in ../pine/osdep/mimedisp.osx

From: Matt Ackeret <[email-masked]>
Date: Tue, 1 Jun 2004 11:20:42 -0700 (PDT)

On Fri, 28 May 2004, robert delius royar wrote:
> Perhaps someone with more knowledge of Carbon than I can suggest how to write
> the conditionals so that the code is not included which is inapropriate for
> 10.2 or 10.3.  A uname -a for 10.2 will return a string which contains "6.x.x
> Darwin Kernel Version 6.x.x"

You can use Gestalt(gestaltSystemVersion) (that's just pseudo-code),
but Gestalt.h (in CarbonCore) actually recommends a better way of getting 
the info on Mac OS X.

I think that's the question you're asking -- how to get the specific system
version you're running on.  If you do that, then you could set the #defines
to be equal to the various responses to Gestalt (or the other method if you
use that one).

Otherwise, there may be stuff in CarbonCore/ConditioalMacros.h that helps you.

---

From: Jeff Franklin <[email-masked]>
Date: Fri, 11 Jun 2004 17:53:08 -0700 (PDT)

Hi Robert,

Sorry this went unanswered for so long.  Actually, someone sent us a patch 
of how it should be, which we've included in the source to be released 
with 4.61.  I've attached it.  So, does this fix the crash that you've 
been having?

Thanks,
Jeff

On Fri, 28 May 2004, robert delius royar wrote:

> In the file mimedisp.osx there are a number of #ifdefs to include code based 
> on the operating-system level.  These are incorrectly used. Those OS defines 
> are all turned on.  They are values, not simple BOOLEANS.  The system headers 
> define them this way:
> #define MAC_OS_X_VERSION_10_0 1000
> #define MAC_OS_X_VERSION_10_1 1010
> #define MAC_OS_X_VERSION_10_2 1020
> #define MAC_OS_X_VERSION_10_3 1030
>
> If you compile with new tools on a 10.2.8 system (as Dr. Clea F. Rees 
> discovered), you get a number of compilation errors.  On 10.3, you get 
> crashes when you try to open an attached html file.
>
> See also the pin-info thread "Pine 4.60 on Mac OS X: mime types and crash" 
> with the following Message-IDs:
> <[email-masked]>,
> <[email-masked]> and
> <[email-masked]>
>
> My 10.3.4 system is "7.4.0 Darwin Kernel Version 7.4.0"
>
>

--- mimedisp.osx	2004/01/08 21:02:34	1.3
+++ mimedisp.osx	2004/05/18 20:21:08	1.4
@@ -85,7 +85,7 @@
     char *file_ext, *mime_type;
     int mime_type_len;
 {
-#ifdef MAC_OS_X_VERSION_10_3
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && defined(MAC_OS_X_VERSION_10_3) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
     CFStringRef mime_ref = NULL, type_id_ref = NULL, ext_ref = NULL;
     char buf[1024];
 
@@ -130,7 +130,7 @@
     char *mime_type, *file_ext;
     int file_ext_len;
 {
-#ifdef MAC_OS_X_VERSION_10_3
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && defined(MAC_OS_X_VERSION_10_3) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3
     CFStringRef mime_ref = NULL, type_id_ref = NULL, ext_ref = NULL;
 
     if(!mime_type || !*mime_type)
@@ -172,7 +172,7 @@
     CFURLRef url_ref = NULL;
     int rv = 0;
 
-#ifdef MAC_OS_X_VERSION_10_2
+#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && defined(MAC_OS_X_VERSION_10_2) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_2
     if(&LSCopyApplicationForMIMEType == NULL)
       return 0;
     if((str_ref = CFStringCreateWithCString(NULL, mime_type,

---

From: robert delius royar <[email-masked]>
Date: Sat, 12 Jun 2004 14:28:29 -0400 (EDT)

On Fri, 11 Jun 2004 about 17:53 -0700 UTC Jeff Franklin wrote:

> Hi Robert,
> 
> Sorry this went unanswered for so long.  Actually, someone sent us a patch of
> how it should be, which we've included in the source to be released with 4.61.
> I've attached it.  So, does this fix the crash that you've been having?
> 

Jeff,

No, the problem is that the concept is wrong.  The defines in the patch are 
being used as though they were preprocessor commands, but the header where 
these macros are defined makes it clear the test must be at runtime.  I have 
the deployment_target set as per Apple's documentation, so if the macros 
were used correctly, they should have stubbed the routines not needed on a 
10.3 machine.

Unless MAC_OS_X_VERSION_MIN_REQUIRED is set at compilation so the 
preprocessor sees a value different from that needed for OSX 10.0, both bits 
of code will be included.  I have appended a copy of Apple's explanation of 
these macros to the end of this note.

If you compile the function mime_get_os_ext_from_mimetype on a 10.2 machine 
using the newest version of the compiler available from Apple for that 
machine, then you will get compile-time errors.  If you compile the program 
on a 10.3 machine with new tools, it will run on a 10.2 machine because 
osx_build_mime_type_cmd gets called before mime_get_os_ext_from_mimetype and 
its value returned makes sense on the 10.2 machine.  10.3 machines appear to 
need it to return 0 so that the fall back to mime_get_os_ext_from_mimetype 
doesn't assume that some processing has already occured.  This is the best I 
can do to figure out what is going on simply because I don't program Carbon.  
I think it's mainly reserved for OS9 compatibility.  I would have thought 
the OSX-specific sections would have used Cocoa and Darwin only.  I don't 
believe you see much Darwin mixed with Carbon development

To further complicate things, the Availability Macros were designed to be 
used in Project Builder or (later) Xcode.  The only way to import a unix 
commandline project into these is to use the configure/Makefile 
structure--not possible with Pine.  The builders assume that environment 
variables can be set (the way configure does) for unique targets.  But that 
does not seem to work with the Pine build.  I tried to use EXTRASPECIALS to 
set the values for the OS_X level, but found these were thrown away when the 
osdependent build ran--just where they were needed.

With the patch I sent earlier, the functions are included only if the 
intended target is of the correct level, but it requires hand coding if the 
build machine is running a different OS level from the target which means 
someone has to compile a 10.3 version on a 10.3 machine or 10.2 on a machine 
with the 10.2 tools (I am only supposing this latter limitation).  With the 
patch, attachments display based on their MIME type if the system knows that 
type.  (One problem the first test case I had created was that the system 
did not know the MIME type. But the error occurs whether it is known or 
not.)  If the system does not know the type, for example the Word files 
defined a APPLICATION/OCTET-STREAM, then Pine looks in its own mimerc and 
mailcaps.

The patched version, using the patch I cobbled together, will display a file 
locally if osx_build_mime_type_cmd returns 0 and the type is a form of html 
or text.  I don't believe that is what was intended.  But it suits me.  If 
the type is known, then the OS reader is launched.  However, the launch is 
such that if you exit Pine, the application closes.  That is a bad idea if 
the user launches Word to edit an attached file (for example).  I fix this 
by using my own mailcap shell scripts that call the OSX open command which 
launches the app without connecting to the parent Pine session.  This 
doesn't work for Darwin applications.  For example, I run a GTK Mazilla for 
my browser.  In that case I have to use nohup.

Frankly, I would figure most potential OSX Pine users to be familiar with 
the commandline and terminal so that they would rely on scripts and such the 
way folks on a BSD system would.  Perhaps a variant based on that concept 
using the mimedisp.bsd template would be worth developing.

robert 

---- Explanation from Apple regarding the macros.  The Tech note mentioned 
---- is more clear and points out that stub functions need to be created.
---- So the defs internal to a function do not work at all if I understand
---- the note and the explanation below.
/*
     File:       AvailabilityMacros.h
 
     Copyright:  (c) 2001-2003 by Apple Computer, Inc., all rights reserved.

     More Info:  See TechNote 2064

     Contains:   Autoconfiguration of AVAILABLE_ macros for Mac OS X

                 This header enables a developer to specify build time
                 constraints on what Mac OS X versions the resulting
                 application will be run.  There are two bounds a developer
                 can specify:
                 
                      MAC_OS_X_VERSION_MIN_REQUIRED
                      MAC_OS_X_VERSION_MAX_ALLOWED
                      
                The lower bound controls which calls to OS functions will 
                be weak-importing (allowed to be unresolved at launch time).
                The upper bound controls which OS functionality, if used,
                will result in a compiler error because that functionality is
                not available on on any OS is the specifed range.
                
                For example, suppose an application is compiled with:
                
                      MAC_OS_X_VERSION_MIN_REQUIRED = MAC_OS_X_VERSION_10_2
                      MAC_OS_X_VERSION_MAX_ALLOWED  = MAC_OS_X_VERSION_10_3
                     
                and an OS header contains:
                
                     extern void funcA(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
                     extern void funcB(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_2;
                     extern void funcC(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_3;
                     extern void funcD(void) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER;
                     extern void funcE(void) AVAILABLE_MAC_OS_X_VERSION_10_2_AND_LATER;
                     extern void funcF(void) AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
                     extern void funcG(void) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
                     
                     typedef long TypeA DEPRECATED_IN_MAC_OS_X_VERSION_10_0_AND_LATER;
                     typedef long TypeB DEPRECATED_IN_MAC_OS_X_VERSION_10_1_AND_LATER;
                     typedef long TypeC DEPRECATED_IN_MAC_OS_X_VERSION_10_2_AND_LATER;
                     typedef long TypeD DEPRECATED_IN_MAC_OS_X_VERSION_10_3_AND_LATER;
                     typedef long TypeE DEPRECATED_IN_MAC_OS_X_VERSION_10_4_AND_LATER;

                Any application code which uses these declarations will get the following:
                
                                compile         link          run 
                                -------         ------        -------
                     funcA:     normal          normal        normal
                     funcB:     warning         normal        normal
                     funcC:     normal          normal        normal
                     funcD:     normal          normal        normal
                     funcE:     normal          normal        normal
                     funcF:     normal          weak          on 10.3 normal, on 10.2 (&funcF == NULL)
                     funcG:     error           error         n/a
                     typeA:     warning
                     typeB:     warning
                     typeC:     warning
                     typeD:     normal
                     typeE:     normal

*/
 
> > are all turned on.  They are values, not simple BOOLEANS.  The system
> > headers define them this way:
> > Perhaps someone with more knowledge of Carbon than I can suggest how to
> > write the conditionals so that the code is not included which is
> > inapropriate for 10.2 or 10.3.  A uname -a for 10.2 will return a string
> > which contains "6.x.x Darwin Kernel Version 6.x.x"
> > 

-- 
Dr. Robert Delius Royar                   Associate Professor of English
Morehead State University                             Morehead, Kentucky

---

From: "Dr. Clea F. Rees" <[email-masked]>
Date: Sun, 13 Jun 2004 01:20:44 -0400 (EDT)

I patched the source code using (1) the previous osx-fix.shar; and (2)
the mimedisp.osx-diff mentioned in the message below.

Using gcc 3.3 on 10.2.8 and just "./build osx" (which isn't what I'd
normally use), I find that:
 	in case (1) the build fails with compilation errors, albeit
 	different errors than previously;
 	in case (2) compilation is successful.

I haven't tested the executables from (2) and I did get various warnings etc, but
some of these result from my using a standard command when I should make
sure it's using the /usr/local version of openssl. I didn't bother to do
that because it required a lot of mucking about last time. (I think the
osx stuff trumps the command line instruction to use /usr/local/openssl
etc. etc. in some cases, but not others. Or else I missed something
critical somewhere...)

Clea

-- 

Dr. Clea F. Rees

Department of Philosophy
Sutton Hall, Room 452
1011 South Drive
Indiana University of Pennsylvania
Indiana
PA 15705-1087
U.S.A.

Tel: +1-724-357-5614 (o)
      +1-724-357-2310 (d)

NB:  From UK, dial 00 before the appropriate number to access the
international system.

email: [email-masked]
http://users.arczip.com/rees/

---

From: robert delius royar <[email-masked]>
Date: Sun, 13 Jun 2004 10:25:03 -0400 (EDT)

> 	in case (2) compilation is successful.

I just downloaded 4.60 again and ran osx-fix.shar in the main directory.  
When I ran `./build osx', it worked without any errors.

When you run the shar archive, 
 * copy the file to the main directory of the pine distribution (i.e.
   there should be subdirectories contrib, pine, etc.),
 * if you want the separate patch files (not really needed), then
   `mkdir patch' before running the command,
 * run it with the command `sh osx-fix.shar', and
 * `chmod +x pine/osdep/osx-dep.sh'.

The shell should echo the following to you:
x - pine/makefile.osx
x - pine/osdep/osx-dep.sh
x - pine/osdep/mimedisp.osx
x - patch/osxversion.patch
x - patch/mimeosdep.patch
There will be errors if you have no patch directory, but the patches are 
already applied to the included files.

If everything ran correctly, then you should see 
cc   -g -DDEBUG -DDEBUGJOURNAL  -DENABLE_LDAP  -Dconst= -DSYSTYPE=\"OSX\" -DOSX_MAJOR_VERSION=`osdep/osx-dep.sh`   -c -o os.o os.c

The -DOSX_MAJOR_VERSION=`osdep/osx-dep.sh` is the magic that sets up the 
required versioning based on your system.

> I haven't tested the executables from (2) and I did get various warnings etc,

Because using the patch supplied from 4.61 likely creates a program which 
doesn't call the code 10.2 can't handle, it may run fine.  But I bet if 
you were to look at the code in a debugger, you would discover, as I did on 
10.3, that the code supposed to be ignored is actually compiled in.  Again, 
that is how weak binding works.  But the code in os.c is not designed to use 
weak binding correctly.  There is a discussion on unix-porting (an Apple OSX 
list) in which someone from Apple recommends Cocoa to handle calls to Aqua 
programs from Unix, not Carbon.  I think that is the real problem.  Carbon 
needs to be initialized before these calls are being made (which is why the 
command line hack works). That initialization is not being done.  I haven't 
found any documentation on this, but there is discussion on the lists about 
which C-runtime start up to use for different systems, and I suspect that 
Carbon programs built with ProjectBuilder (a.k.a. XCode) use a different 
crt.o file than do unix (Darwin) commandline compiled programs.

Cocoa uses Objective-C.  It looks as though one line of code using 
NSWorkspace could handle launching web pages in the default browser or any 
attachment that has a registered extension.  However for attachments that do 
not have an extent or a transport mechanism, Pine would be hard-pressed to 
devise one.  OSX must store its MIME types somewhere because there are 
third-party programs which can reset the defualts or add types.  But I 
haven't located that Property List.  There may be a Cocoa MIME-based command 
available also.  Unfortunate also is the fact that much of the Cocoa magic 
requires 10.2 or even 10.3.

-- 
Dr. Robert Delius Royar                   Associate Professor of English
Morehead State University                             Morehead, Kentucky
  A mathematician is a theorem's way of making another theorem.

---

From: Matt Ackeret <[email-masked]>
Date: Wed, 30 Jun 2004 12:39:37 -0700 (PDT)

>I think it's mainly reserved for OS9 compatibility.  I would have thought 

This is completely wrong.  Carbon is a peer to the Cocoa functionality.
Both are evolving as time goes on, and sometimes they both rely on shared
lower level technologies.

>believe you see much Darwin mixed with Carbon development

This is wrong.  You can call any routine, such as standard "UNIX" routines,
in any type of program.

>used in Project Builder or (later) Xcode.  The only way to import a unix 

I don't quite understand this comment.  The framework I work on,
HIToolbox (which is a subframework of the Carbon framework) does use
the same AvailabilityMacros, and for historical reasons it uses a makefile.

---

From: robert delius royar <[email-masked]>
Date: Wed, 30 Jun 2004 19:23:17 -0400 (EDT)

> lower level technologies.

OK, then there must be some set up that is handled in the standard 
Carbon init.  For example, the Carbon version of XEmacs included setup code 
to init a number of routines so that the features it used which did not rely 
on traditional C would work properly when called.  

Something must be awry or simply calling Pine using `pine -bail' would not 
prevent the http:// view crash.  (Debugging level or -d[0-9]* turned out to 
be a red hering).

> the same AvailabilityMacros, and for historical reasons it uses a makefile.

I was referring to the fact that Pine uses a somewhat non-traditional method to
build the program.  Is it possible to import the makefiles for Pine into Xcode
and build Pine?

Regarding the AvailabilityMacros comments in the AvailabilityMacros header file
and the Developer documentation which is referenced in that file both made me
believe that they were designed for a development cycle which was dependent on
features of Project Builder and XCode.  For example TN2064 explains how to use
weak linking to allow code specific to different OS versions to be linked in at
runtime using the runtime __attribute__((weak_import)) which modifies a function
definition.

TN2064 states
  The Availability Macros are a set of macros was introduced in Mac OS X version
  10.2 as a part of the July 2002 Developer Tools. They are contained in a
  header which is located at "/usr/include/AvailabilityMacros.h" on such a
  system. "AvailabilityMacros.h" helps you determine which OS versions
  introduced the APIs you are using, and tells the compiler which routines
  should be weakly linked. Over time, more and more of Apple's frameworks will
  be adopting the Availability Macros (the Carbon and Cocoa frameworks do to
  some degree today).
Then later
  There is no obvious way to setthe and settings on a per project basis, if you
  are using cpp-precomp for precompiled header processing (the default choice in
  the July 2002 Developer Tools and prior) instead of the new Persistent Front
  End (PFE) mechanism for precompiled headers (the default choice for new
  projects in the December 2002 Developer Tools). This is because there is a
  single system-wide copy of the framework precompiled headers that already
  assumes values for these defines. Redefining these settings in your project
  will break the precompiled headers, and compile times will greatly increase
  (along with lots of warnings being generated). There are two ways to fix
  this. MACOSX_DEPLOYMENT_TARGET,MAC_OS_X_VERSION_MIN_REQUIRED,MAC_OS_X_VERSION_MAX_ALLOWED
  1. Use the new Persistent Front End (PFE) mechanism for precompiled headers on
  a per project basis. You can do this using the Build Settings pane in the
  Targets tab of your project.
But there do not appear to be any modifications to the environment to accomplish
this in the current set up for 4.60.  

In fact when we compile the code on 10.3.4, the code in osx_build_mime_type_cmd
that the macro MAC_OS_X_VERSION_10_2 appears to be designed to obscure gets
linked in and runs.  It appears that the return from this function is what
causes the later crash. The MAC_OS_X_VERSION_10_3 code gets left in on 10.2 systems
and then creates compile-time errors (at least according to other reports from
people with 10.2.8 using the latest Apple dev tools for that platform).  I
believe this is the result of the macros being treated as though they were
preprocessor booleans (i.e. #ifdef is used) contrary to the documentation for
their use (cf. __attribute__((weak_import))).  If the code for 10.2 is excluded
from a 10.3 build, the crash viewing html files that I and others have seen does
not occur.  The files launch properly.

-- 
Dr. Robert Delius Royar                   Associate Professor of English
Morehead State University                             Morehead, Kentucky
  The 10,000 things have 10,000 different states, all in motion as if there
  were a True Lord to move them--but if we search for evidence of this Lord we
  fail to find any.
                                                                   -Kuo Hsiang
  17:52 up 21 days, 19:36, 1 user, load averages: 0.33 0.33 0.33