• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
4 
5                         All Rights Reserved
6 
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
14 
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 
23 ******************************************************************/
24 
25 /* Macintosh OS-specific interface */
26 
27 #include "Python.h"
28 #include "pymactoolbox.h"
29 
30 #include <Carbon/Carbon.h>
31 #include <ApplicationServices/ApplicationServices.h>
32 
33 #include <arpa/inet.h>  /* for ntohl, htonl */
34 
35 
36 #ifndef HAVE_OSX105_SDK
37 typedef SInt16  FSIORefNum;
38 #endif
39 
40 static PyObject *MacOS_Error; /* Exception MacOS.Error */
41 
42 #define PATHNAMELEN 1024
43 
44 /* ----------------------------------------------------- */
45 
46 /* Declarations for objects of type Resource fork */
47 
48 typedef struct {
49     PyObject_HEAD
50     FSIORefNum fRefNum;
51     int isclosed;
52 } rfobject;
53 
54 static PyTypeObject Rftype;
55 
56 
57 
58 /* ---------------------------------------------------------------- */
59 
60 static void
do_close(rfobject * self)61 do_close(rfobject *self)
62 {
63     if (self->isclosed ) return;
64     (void)FSCloseFork(self->fRefNum);
65     self->isclosed = 1;
66 }
67 
68 static char rf_read__doc__[] =
69 "Read data from resource fork"
70 ;
71 
72 static PyObject *
rf_read(rfobject * self,PyObject * args)73 rf_read(rfobject *self, PyObject *args)
74 {
75     long n;
76     PyObject *v;
77     OSErr err;
78     ByteCount n2;
79 
80     if (self->isclosed) {
81         PyErr_SetString(PyExc_ValueError, "Operation on closed file");
82         return NULL;
83     }
84 
85     if (!PyArg_ParseTuple(args, "l", &n))
86         return NULL;
87 
88     v = PyBytes_FromStringAndSize((char *)NULL, n);
89     if (v == NULL)
90         return NULL;
91 
92     err = FSReadFork(self->fRefNum, fsAtMark, 0, n, PyString_AsString(v), &n2);
93     if (err && err != eofErr) {
94         PyMac_Error(err);
95         Py_DECREF(v);
96         return NULL;
97     }
98     _PyString_Resize(&v, n2);
99     return v;
100 }
101 
102 
103 static char rf_write__doc__[] =
104 "Write to resource fork"
105 ;
106 
107 static PyObject *
rf_write(rfobject * self,PyObject * args)108 rf_write(rfobject *self, PyObject *args)
109 {
110     char *buffer;
111     long size;
112     OSErr err;
113 
114     if (self->isclosed) {
115         PyErr_SetString(PyExc_ValueError, "Operation on closed file");
116         return NULL;
117     }
118     if (!PyArg_ParseTuple(args, "s#", &buffer, &size))
119         return NULL;
120     err = FSWriteFork(self->fRefNum, fsAtMark, 0, size, buffer, NULL);
121     if (err) {
122         PyMac_Error(err);
123         return NULL;
124     }
125     Py_INCREF(Py_None);
126     return Py_None;
127 }
128 
129 
130 static char rf_seek__doc__[] =
131 "Set file position"
132 ;
133 
134 static PyObject *
rf_seek(rfobject * self,PyObject * args)135 rf_seek(rfobject *self, PyObject *args)
136 {
137     long amount;
138     int whence = SEEK_SET;
139     int mode;
140     OSErr err;
141 
142     if (self->isclosed) {
143         PyErr_SetString(PyExc_ValueError, "Operation on closed file");
144         return NULL;
145     }
146     if (!PyArg_ParseTuple(args, "l|i", &amount, &whence)) {
147         return NULL;
148     }
149 
150     switch (whence) {
151     case SEEK_CUR:
152         mode = fsFromMark;
153         break;
154     case SEEK_END:
155         mode = fsFromLEOF;
156         break;
157     case SEEK_SET:
158         mode = fsFromStart;
159         break;
160     default:
161         PyErr_BadArgument();
162         return NULL;
163     }
164 
165     err = FSSetForkPosition(self->fRefNum, mode, amount);
166     if (err != noErr) {
167         PyMac_Error(err);
168         return NULL;
169     }
170     Py_INCREF(Py_None);
171     return Py_None;
172 }
173 
174 
175 static char rf_tell__doc__[] =
176 "Get file position"
177 ;
178 
179 static PyObject *
rf_tell(rfobject * self,PyObject * args)180 rf_tell(rfobject *self, PyObject *args)
181 {
182     long long where;
183     OSErr err;
184 
185     if (self->isclosed) {
186         PyErr_SetString(PyExc_ValueError, "Operation on closed file");
187         return NULL;
188     }
189     if (!PyArg_ParseTuple(args, ""))
190         return NULL;
191 
192     err = FSGetForkPosition(self->fRefNum, &where);
193     if (err != noErr) {
194         PyMac_Error(err);
195         return NULL;
196     }
197     return PyLong_FromLongLong(where);
198 }
199 
200 static char rf_close__doc__[] =
201 "Close resource fork"
202 ;
203 
204 static PyObject *
rf_close(rfobject * self,PyObject * args)205 rf_close(rfobject *self, PyObject *args)
206 {
207     if (!PyArg_ParseTuple(args, ""))
208         return NULL;
209     do_close(self);
210     Py_INCREF(Py_None);
211     return Py_None;
212 }
213 
214 
215 static struct PyMethodDef rf_methods[] = {
216  {"read",       (PyCFunction)rf_read,   1,      rf_read__doc__},
217  {"write",      (PyCFunction)rf_write,  1,      rf_write__doc__},
218  {"seek",       (PyCFunction)rf_seek,   1,      rf_seek__doc__},
219  {"tell",       (PyCFunction)rf_tell,   1,      rf_tell__doc__},
220  {"close",      (PyCFunction)rf_close,  1,      rf_close__doc__},
221 
222     {NULL,              NULL}           /* sentinel */
223 };
224 
225 /* ---------- */
226 
227 
228 static rfobject *
newrfobject(void)229 newrfobject(void)
230 {
231     rfobject *self;
232 
233     self = PyObject_NEW(rfobject, &Rftype);
234     if (self == NULL)
235         return NULL;
236     self->isclosed = 1;
237     return self;
238 }
239 
240 
241 static void
rf_dealloc(rfobject * self)242 rf_dealloc(rfobject *self)
243 {
244     do_close(self);
245     PyObject_DEL(self);
246 }
247 
248 static PyObject *
rf_getattr(rfobject * self,char * name)249 rf_getattr(rfobject *self, char *name)
250 {
251     return Py_FindMethod(rf_methods, (PyObject *)self, name);
252 }
253 
254 static char Rftype__doc__[] =
255 "Resource fork file object"
256 ;
257 
258 static PyTypeObject Rftype = {
259     PyObject_HEAD_INIT(&PyType_Type)
260     0,                                  /*ob_size*/
261     "MacOS.ResourceFork",               /*tp_name*/
262     sizeof(rfobject),                   /*tp_basicsize*/
263     0,                                  /*tp_itemsize*/
264     /* methods */
265     (destructor)rf_dealloc,     /*tp_dealloc*/
266     (printfunc)0,               /*tp_print*/
267     (getattrfunc)rf_getattr,            /*tp_getattr*/
268     (setattrfunc)0,     /*tp_setattr*/
269     (cmpfunc)0,                 /*tp_compare*/
270     (reprfunc)0,                /*tp_repr*/
271     0,                          /*tp_as_number*/
272     0,                  /*tp_as_sequence*/
273     0,                  /*tp_as_mapping*/
274     (hashfunc)0,                /*tp_hash*/
275     (ternaryfunc)0,             /*tp_call*/
276     (reprfunc)0,                /*tp_str*/
277 
278     /* Space for future expansion */
279     0L,0L,0L,0L,
280     Rftype__doc__ /* Documentation string */
281 };
282 
283 
284 /* End of code for Resource fork objects */
285 /* -------------------------------------------------------- */
286 
287 /*----------------------------------------------------------------------*/
288 /* Miscellaneous File System Operations */
289 
290 static char getcrtp_doc[] = "Get MacOS 4-char creator and type for a file";
291 
292 static PyObject *
MacOS_GetCreatorAndType(PyObject * self,PyObject * args)293 MacOS_GetCreatorAndType(PyObject *self, PyObject *args)
294 {
295     PyObject *creator, *type, *res;
296     OSErr err;
297     FSRef ref;
298     FSCatalogInfo       cataloginfo;
299     FileInfo* finfo;
300 
301     if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSRef, &ref)) {
302 #if APPLE_SUPPORTS_QUICKTIME
303         /* This function is documented to take an FSSpec as well,
304          * which only works in 32-bit mode.
305          */
306         PyErr_Clear();
307         FSSpec fss;
308         FInfo info;
309 
310         if (!PyArg_ParseTuple(args, "O&", PyMac_GetFSSpec, &fss))
311             return NULL;
312 
313         if ((err = FSpGetFInfo(&fss, &info)) != noErr) {
314             return PyErr_Mac(MacOS_Error, err);
315         }
316 
317         info.fdCreator = ntohl(info.fdCreator);
318         info.fdType = ntohl(info.fdType);
319 
320         creator = PyString_FromStringAndSize(
321                         (char *)&info.fdCreator, 4);
322         type = PyString_FromStringAndSize((char *)&info.fdType, 4);
323         res = Py_BuildValue("OO", creator, type);
324         Py_DECREF(creator);
325         Py_DECREF(type);
326         return res;
327 #else   /* APPLE_SUPPORTS_QUICKTIME */
328         return NULL;
329 #endif  /* APPLE_SUPPORTS_QUICKTIME */
330     }
331 
332     err = FSGetCatalogInfo(&ref,
333                     kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
334                     NULL, NULL, NULL);
335     if (err != noErr) {
336         PyErr_Mac(MacOS_Error, err);
337         return NULL;
338     }
339 
340     if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
341         /* Directory: doesn't have type/creator info.
342          *
343          * The specific error code is for backward compatibility with
344          * earlier versions.
345          */
346         PyErr_Mac(MacOS_Error, fnfErr);
347         return NULL;
348 
349     }
350     finfo = (FileInfo*)&(cataloginfo.finderInfo);
351     finfo->fileCreator = ntohl(finfo->fileCreator);
352     finfo->fileType = ntohl(finfo->fileType);
353     creator = PyString_FromStringAndSize((char*)&(finfo->fileCreator), 4);
354     type = PyString_FromStringAndSize((char*)&(finfo->fileType), 4);
355 
356     res = Py_BuildValue("OO", creator, type);
357     Py_DECREF(creator);
358     Py_DECREF(type);
359     return res;
360 }
361 
362 static char setcrtp_doc[] = "Set MacOS 4-char creator and type for a file";
363 
364 static PyObject *
MacOS_SetCreatorAndType(PyObject * self,PyObject * args)365 MacOS_SetCreatorAndType(PyObject *self, PyObject *args)
366 {
367     ResType creator, type;
368     FSRef ref;
369     FileInfo* finfo;
370     OSErr err;
371     FSCatalogInfo       cataloginfo;
372 
373     if (!PyArg_ParseTuple(args, "O&O&O&",
374                     PyMac_GetFSRef, &ref, PyMac_GetOSType, &creator, PyMac_GetOSType, &type)) {
375 #if APPLE_SUPPORTS_QUICKTIME
376         /* Try to handle FSSpec arguments, for backward compatibility */
377         FSSpec fss;
378         FInfo info;
379 
380         if (!PyArg_ParseTuple(args, "O&O&O&",
381             PyMac_GetFSSpec, &fss, PyMac_GetOSType, &creator, PyMac_GetOSType, &type))
382             return NULL;
383 
384         if ((err = FSpGetFInfo(&fss, &info)) != noErr)
385             return PyErr_Mac(MacOS_Error, err);
386 
387         info.fdCreator = creator;
388         info.fdType = type;
389 
390         if ((err = FSpSetFInfo(&fss, &info)) != noErr)
391             return PyErr_Mac(MacOS_Error, err);
392         Py_INCREF(Py_None);
393         return Py_None;
394 #else /* APPLE_SUPPORTS_QUICKTIME */
395         return NULL;
396 #endif /* APPLE_SUPPORTS_QUICKTIME */
397     }
398 
399     err = FSGetCatalogInfo(&ref,
400                     kFSCatInfoFinderInfo|kFSCatInfoNodeFlags, &cataloginfo,
401                     NULL, NULL, NULL);
402     if (err != noErr) {
403         PyErr_Mac(MacOS_Error, err);
404         return NULL;
405     }
406 
407     if ((cataloginfo.nodeFlags & kFSNodeIsDirectoryMask) != 0) {
408         /* Directory: doesn't have type/creator info.
409          *
410          * The specific error code is for backward compatibility with
411          * earlier versions.
412          */
413         PyErr_Mac(MacOS_Error, fnfErr);
414         return NULL;
415 
416     }
417     finfo = (FileInfo*)&(cataloginfo.finderInfo);
418     finfo->fileCreator = creator;
419     finfo->fileType = type;
420 
421     err = FSSetCatalogInfo(&ref, kFSCatInfoFinderInfo, &cataloginfo);
422     if (err != noErr) {
423         PyErr_Mac(MacOS_Error, fnfErr);
424         return NULL;
425     }
426 
427     Py_INCREF(Py_None);
428     return Py_None;
429 }
430 
431 
432 static char geterr_doc[] = "Convert OSErr number to string";
433 
434 static PyObject *
MacOS_GetErrorString(PyObject * self,PyObject * args)435 MacOS_GetErrorString(PyObject *self, PyObject *args)
436 {
437     int err;
438     char buf[256];
439     Handle h;
440     char *str;
441     static int errors_loaded;
442 
443     if (!PyArg_ParseTuple(args, "i", &err))
444         return NULL;
445 
446     h = GetResource('Estr', err);
447     if (!h && !errors_loaded) {
448         /*
449         ** Attempt to open the resource file containing the
450         ** Estr resources. We ignore all errors. We also try
451         ** this only once.
452         */
453         PyObject *m, *rv;
454         errors_loaded = 1;
455 
456         m = PyImport_ImportModuleNoBlock("macresource");
457         if (!m) {
458             if (Py_VerboseFlag)
459                 PyErr_Print();
460             PyErr_Clear();
461         }
462         else {
463             rv = PyObject_CallMethod(m, "open_error_resource", "");
464             if (!rv) {
465                 if (Py_VerboseFlag)
466                     PyErr_Print();
467                 PyErr_Clear();
468             }
469             else {
470                 Py_DECREF(rv);
471                 /* And try again... */
472                 h = GetResource('Estr', err);
473             }
474             Py_DECREF(m);
475         }
476     }
477     /*
478     ** Whether the code above succeeded or not, we won't try
479     ** again.
480     */
481     errors_loaded = 1;
482 
483     if (h) {
484         HLock(h);
485         str = (char *)*h;
486         memcpy(buf, str+1, (unsigned char)str[0]);
487         buf[(unsigned char)str[0]] = '\0';
488         HUnlock(h);
489         ReleaseResource(h);
490     }
491     else {
492         PyOS_snprintf(buf, sizeof(buf), "Mac OS error code %d", err);
493     }
494 
495     return Py_BuildValue("s", buf);
496 }
497 
498 
499 #ifndef __LP64__
500 
501 static char splash_doc[] = "Open a splash-screen dialog by resource-id (0=close)";
502 
503 static PyObject *
MacOS_splash(PyObject * self,PyObject * args)504 MacOS_splash(PyObject *self, PyObject *args)
505 {
506     int resid = -1;
507     static DialogPtr curdialog = NULL;
508     DialogPtr olddialog;
509     WindowRef theWindow;
510     CGrafPtr thePort;
511 #if 0
512     short xpos, ypos, width, height, swidth, sheight;
513 #endif
514 
515     if (!PyArg_ParseTuple(args, "|i", &resid))
516         return NULL;
517     olddialog = curdialog;
518     curdialog = NULL;
519 
520     if ( resid != -1 ) {
521         curdialog = GetNewDialog(resid, NULL, (WindowPtr)-1);
522         if ( curdialog ) {
523             theWindow = GetDialogWindow(curdialog);
524             thePort = GetWindowPort(theWindow);
525 #if 0
526             width = thePort->portRect.right - thePort->portRect.left;
527             height = thePort->portRect.bottom - thePort->portRect.top;
528             swidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
529             sheight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top - LMGetMBarHeight();
530             xpos = (swidth-width)/2;
531             ypos = (sheight-height)/5 + LMGetMBarHeight();
532             MoveWindow(theWindow, xpos, ypos, 0);
533             ShowWindow(theWindow);
534 #endif
535             DrawDialog(curdialog);
536         }
537     }
538     if (olddialog)
539         DisposeDialog(olddialog);
540     Py_INCREF(Py_None);
541     return Py_None;
542 }
543 
544 static char DebugStr_doc[] = "Switch to low-level debugger with a message";
545 
546 static PyObject *
MacOS_DebugStr(PyObject * self,PyObject * args)547 MacOS_DebugStr(PyObject *self, PyObject *args)
548 {
549     Str255 message;
550     PyObject *object = 0;
551 
552     if (!PyArg_ParseTuple(args, "O&|O", PyMac_GetStr255, message, &object))
553         return NULL;
554 
555     DebugStr(message);
556     Py_INCREF(Py_None);
557     return Py_None;
558 }
559 
560 
561 static char SysBeep_doc[] = "BEEEEEP!!!";
562 
563 static PyObject *
MacOS_SysBeep(PyObject * self,PyObject * args)564 MacOS_SysBeep(PyObject *self, PyObject *args)
565 {
566     int duration = 6;
567 
568     if (!PyArg_ParseTuple(args, "|i", &duration))
569         return NULL;
570     SysBeep(duration);
571     Py_INCREF(Py_None);
572     return Py_None;
573 }
574 
575 #endif /* __LP64__ */
576 
577 static char WMAvailable_doc[] =
578     "True if this process can interact with the display."
579     "Will foreground the application on the first call as a side-effect."
580     ;
581 
582 static PyObject *
MacOS_WMAvailable(PyObject * self,PyObject * args)583 MacOS_WMAvailable(PyObject *self, PyObject *args)
584 {
585     static PyObject *rv = NULL;
586 
587     if (!PyArg_ParseTuple(args, ""))
588         return NULL;
589     if (!rv) {
590         ProcessSerialNumber psn;
591 
592         /*
593         ** This is a fairly innocuous call to make if we don't have a window
594         ** manager, or if we have no permission to talk to it. It will print
595         ** a message on stderr, but at least it won't abort the process.
596         ** It appears the function caches the result itself, and it's cheap, so
597         ** no need for us to cache.
598         */
599 #ifdef kCGNullDirectDisplay
600         /* On 10.1 CGMainDisplayID() isn't available, and
601         ** kCGNullDirectDisplay isn't defined.
602         */
603         if (CGMainDisplayID() == 0) {
604             rv = Py_False;
605         } else {
606 #else
607         {
608 #endif
609             if (GetCurrentProcess(&psn) < 0 ||
610                 SetFrontProcess(&psn) < 0) {
611                 rv = Py_False;
612             } else {
613                 rv = Py_True;
614             }
615         }
616     }
617     Py_INCREF(rv);
618     return rv;
619 }
620 
621 static char GetTicks_doc[] = "Return number of ticks since bootup";
622 
623 static PyObject *
624 MacOS_GetTicks(PyObject *self, PyObject *args)
625 {
626     return Py_BuildValue("i", (int)TickCount());
627 }
628 
629 static char openrf_doc[] = "Open resource fork of a file";
630 
631 static PyObject *
632 MacOS_openrf(PyObject *self, PyObject *args)
633 {
634     OSErr err;
635     char *mode = "r";
636     FSRef ref;
637     SInt8 permission = fsRdPerm;
638     rfobject *fp;
639     HFSUniStr255 name;
640 
641     if (!PyArg_ParseTuple(args, "O&|s", PyMac_GetFSRef, &ref, &mode))
642         return NULL;
643     while (*mode) {
644         switch (*mode++) {
645         case '*': break;
646         case 'r': permission = fsRdPerm; break;
647         case 'w': permission = fsWrPerm; break;
648         case 'b': break;
649         default:
650             PyErr_BadArgument();
651             return NULL;
652         }
653     }
654 
655     err = FSGetResourceForkName(&name);
656     if (err != noErr) {
657         PyMac_Error(err);
658         return NULL;
659     }
660 
661     if ( (fp = newrfobject()) == NULL )
662         return NULL;
663 
664 
665     err = FSOpenFork(&ref, name.length, name.unicode, permission, &fp->fRefNum);
666     if (err != noErr) {
667         Py_DECREF(fp);
668         PyMac_Error(err);
669         return NULL;
670     }
671     fp->isclosed = 0;
672     return (PyObject *)fp;
673 }
674 
675 
676 
677 static PyMethodDef MacOS_Methods[] = {
678     {"GetCreatorAndType",               MacOS_GetCreatorAndType, 1,     getcrtp_doc},
679     {"SetCreatorAndType",               MacOS_SetCreatorAndType, 1,     setcrtp_doc},
680     {"GetErrorString",                  MacOS_GetErrorString,   1,      geterr_doc},
681     {"openrf",                          MacOS_openrf,           1,      openrf_doc},
682 #ifndef __LP64__
683     {"splash",                          MacOS_splash,           1,      splash_doc},
684     {"DebugStr",                        MacOS_DebugStr,         1,      DebugStr_doc},
685     {"SysBeep",                         MacOS_SysBeep,          1,      SysBeep_doc},
686 #endif /* __LP64__ */
687     {"GetTicks",                        MacOS_GetTicks,         1,      GetTicks_doc},
688     {"WMAvailable",                     MacOS_WMAvailable,              1,      WMAvailable_doc},
689     {NULL,                              NULL}            /* Sentinel */
690 };
691 
692 
693 void
694 initMacOS(void)
695 {
696     PyObject *m, *d;
697 
698     if (PyErr_WarnPy3k("In 3.x, the MacOS module is removed.", 1))
699         return;
700 
701     m = Py_InitModule("MacOS", MacOS_Methods);
702     d = PyModule_GetDict(m);
703 
704     /* Initialize MacOS.Error exception */
705     MacOS_Error = PyMac_GetOSErrException();
706     if (MacOS_Error == NULL || PyDict_SetItemString(d, "Error", MacOS_Error) != 0)
707         return;
708     Rftype.ob_type = &PyType_Type;
709     Py_INCREF(&Rftype);
710     if (PyDict_SetItemString(d, "ResourceForkType", (PyObject *)&Rftype) != 0)
711         return;
712     /*
713     ** This is a hack: the following constant added to the id() of a string
714     ** object gives you the address of the data. Unfortunately, it is needed for
715     ** some of the image and sound processing interfaces on the mac:-(
716     */
717     {
718         PyStringObject *p = 0;
719         long off = (long)&(p->ob_sval[0]);
720 
721         if( PyDict_SetItemString(d, "string_id_to_buffer", Py_BuildValue("i", off)) != 0)
722             return;
723     }
724 #define PY_RUNTIMEMODEL "macho"
725     if (PyDict_SetItemString(d, "runtimemodel",
726                             Py_BuildValue("s", PY_RUNTIMEMODEL)) != 0)
727         return;
728 #if defined(WITH_NEXT_FRAMEWORK)
729 #define PY_LINKMODEL "framework"
730 #elif defined(Py_ENABLE_SHARED)
731 #define PY_LINKMODEL "shared"
732 #else
733 #define PY_LINKMODEL "static"
734 #endif
735     if (PyDict_SetItemString(d, "linkmodel",
736                             Py_BuildValue("s", PY_LINKMODEL)) != 0)
737         return;
738 
739 }
740