libgeda

scheme_smob.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * libgeda - gEDA's library - Scheme API
00003  * Copyright (C) 2010-2012 Peter Brett <peter@peter-b.co.uk>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
00018  */
00019 
00058 #include <config.h>
00059 
00060 #include "libgeda_priv.h"
00061 #include "libgedaguile_priv.h"
00062 
00063 scm_t_bits geda_smob_tag;
00064 
00069 static void
00070 smob_weakref_notify (void *target, void *smob) {
00071   SCM s = (SCM) smob;
00072   SCM_SET_SMOB_DATA (s, NULL);
00073 }
00074 
00082 static void
00083 smob_weakref2_notify (void *target, void *smob) {
00084   SCM s = (SCM) smob;
00085   SCM_SET_SMOB_DATA_2 (s, NULL);
00086 }
00087 
00094 static size_t
00095 smob_free (SCM smob)
00096 {
00097   void *data;
00098 
00099   /* If the weak reference has already been cleared, do nothing */
00100   if (!EDASCM_SMOB_VALIDP(smob)) return 0;
00101 
00102   data = (void *) SCM_SMOB_DATA (smob);
00103 
00104   /* Otherwise, clear the weak reference */
00105   switch (EDASCM_SMOB_TYPE (smob)) {
00106   case GEDA_SMOB_TOPLEVEL:
00107     s_toplevel_weak_unref ((TOPLEVEL *) data, smob_weakref_notify, smob);
00108     break;
00109   case GEDA_SMOB_PAGE:
00110     s_page_weak_unref ((PAGE *) data, smob_weakref_notify, smob);
00111     break;
00112   case GEDA_SMOB_OBJECT:
00113     /* See edascm_from_object() for an explanation of why OBJECT
00114      * smobs store a TOPLEVEL in the second data word */
00115     s_object_weak_unref ((OBJECT *) data, smob_weakref_notify, smob);
00116     s_toplevel_weak_unref ((TOPLEVEL *) SCM_SMOB_DATA_2 (smob),
00117                            smob_weakref2_notify, smob);
00118     break;
00119   default:
00120     /* This should REALLY definitely never be run */
00121     g_critical ("%s: received bad smob flags.", __FUNCTION__);
00122   }
00123 
00124   /* If the smob is marked as garbage-collectable, destroy its
00125    * contents.
00126    *
00127    * Because PAGEs and TOPLEVELs should never be garbage collected,
00128    * emit critical warnings if the GC tries to free them.
00129    */
00130   if (EDASCM_SMOB_GCP (smob)) {
00131     switch (EDASCM_SMOB_TYPE (smob)) {
00132     case GEDA_SMOB_TOPLEVEL:
00133       g_critical ("%s: Blocked garbage-collection of TOPLEVEL %p",
00134                  __FUNCTION__, data);
00135       break;
00136     case GEDA_SMOB_PAGE:
00137       g_critical ("%s: Blocked garbage-collection of PAGE %p",
00138                  __FUNCTION__, data);
00139       break;
00140     case GEDA_SMOB_OBJECT:
00141       /* See edascm_from_object() for an explanation of why OBJECT
00142        * smobs store a TOPLEVEL in the second data word */
00143       s_delete_object ((TOPLEVEL *) SCM_SMOB_DATA_2 (smob), (OBJECT *) data);
00144       break;
00145     default:
00146       /* This should REALLY definitely never be run */
00147       g_critical ("%s: received bad smob flags.", __FUNCTION__);
00148     }
00149   }
00150   return 0;
00151 }
00152 
00161 static int
00162 smob_print (SCM smob, SCM port, scm_print_state *pstate)
00163 {
00164   gchar *hexstring;
00165 
00166   scm_puts ("#<geda-", port);
00167 
00168   switch (EDASCM_SMOB_TYPE (smob)) {
00169   case GEDA_SMOB_TOPLEVEL:
00170     scm_puts ("toplevel", port);
00171     break;
00172   case GEDA_SMOB_PAGE:
00173     scm_puts ("page", port);
00174     break;
00175   case GEDA_SMOB_OBJECT:
00176     scm_puts ("object", port);
00177     break;
00178   default:
00179     g_critical ("%s: received bad smob flags.", __FUNCTION__);
00180     scm_puts ("unknown", port);
00181   }
00182 
00183   if (SCM_SMOB_DATA (smob) != 0) {
00184     scm_dynwind_begin (0);
00185     hexstring = g_strdup_printf (" %p", (void *) SCM_SMOB_DATA (smob));
00186     scm_dynwind_unwind_handler (g_free, hexstring, SCM_F_WIND_EXPLICITLY);
00187     scm_puts (hexstring, port);
00188     scm_dynwind_end ();
00189   } else {
00190     scm_puts (" (null)", port);
00191   }
00192 
00193   scm_puts (">", port);
00194 
00195   /* Non-zero means success */
00196   return 1;
00197 }
00198 
00206 static SCM
00207 smob_equalp (SCM obj1, SCM obj2)
00208 {
00209   EDASCM_ASSERT_SMOB_VALID (obj1);
00210   EDASCM_ASSERT_SMOB_VALID (obj2);
00211 
00212   if (SCM_SMOB_DATA (obj1) == SCM_SMOB_DATA (obj2)) {
00213     return SCM_BOOL_T;
00214   } else {
00215     return SCM_BOOL_F;
00216   }
00217 }
00218 
00227 SCM
00228 edascm_from_toplevel (TOPLEVEL *toplevel)
00229 {
00230   SCM smob;
00231 
00232   SCM_NEWSMOB (smob, geda_smob_tag, toplevel);
00233   SCM_SET_SMOB_FLAGS (smob, GEDA_SMOB_TOPLEVEL);
00234 
00235   /* Set weak reference */
00236   s_toplevel_weak_ref (toplevel, smob_weakref_notify, smob);
00237 
00238   return smob;
00239 }
00240 
00249 SCM
00250 edascm_from_page (PAGE *page)
00251 {
00252   SCM smob;
00253 
00254   SCM_NEWSMOB (smob, geda_smob_tag, page);
00255   SCM_SET_SMOB_FLAGS (smob, GEDA_SMOB_PAGE);
00256 
00257   /* Set weak reference */
00258   s_page_weak_ref (page, smob_weakref_notify, smob);
00259 
00260   return smob;
00261 }
00262 
00271 PAGE *
00272 edascm_to_page (SCM smob)
00273 {
00274 #ifndef NDEBUG
00275   SCM_ASSERT (EDASCM_PAGEP (smob), smob,
00276               SCM_ARG1, "edascm_to_page");
00277 #endif
00278   EDASCM_ASSERT_SMOB_VALID (smob);
00279 
00280   return (PAGE *) SCM_SMOB_DATA (smob);
00281 }
00282 
00306 SCM
00307 edascm_from_object (OBJECT *object)
00308 {
00309   SCM smob;
00310   TOPLEVEL *toplevel = edascm_c_current_toplevel ();
00311 
00312   SCM_NEWSMOB2 (smob, geda_smob_tag, object, toplevel);
00313   SCM_SET_SMOB_FLAGS (smob, GEDA_SMOB_OBJECT);
00314 
00315   /* Set weak references */
00316   s_object_weak_ref (object, smob_weakref_notify, smob);
00317   s_toplevel_weak_ref (toplevel, smob_weakref2_notify, smob);
00318 
00319   return smob;
00320 }
00321 
00330 OBJECT *
00331 edascm_to_object (SCM smob)
00332 {
00333 #ifndef NDEBUG
00334   SCM_ASSERT (EDASCM_OBJECTP (smob), smob,
00335               SCM_ARG1, "edascm_to_object");
00336 #endif
00337   EDASCM_ASSERT_SMOB_VALID (smob);
00338 
00339   return (OBJECT *) SCM_SMOB_DATA (smob);
00340 }
00341 
00352 void
00353 edascm_c_set_gc (SCM smob, int gc)
00354 {
00355   EDASCM_ASSERT_SMOB_VALID (smob);
00356   EDASCM_SMOB_SET_GC (smob, gc);
00357 }
00358 
00369 int
00370 edascm_is_object (SCM smob)
00371 {
00372   return EDASCM_OBJECTP (smob);
00373 }
00374 
00385 int
00386 edascm_is_page (SCM smob)
00387 {
00388   return EDASCM_PAGEP (smob);
00389 }
00390 
00403 SCM_DEFINE (page_p, "%page?", 1, 0, 0,
00404             (SCM page_smob),
00405             "Test whether the value is a gEDA PAGE instance.")
00406 {
00407   return (EDASCM_PAGEP (page_smob) ? SCM_BOOL_T : SCM_BOOL_F);
00408 }
00409 
00422 SCM_DEFINE (object_p, "%object?", 1, 0, 0,
00423             (SCM object_smob),
00424             "Test whether the value is a gEDA OBJECT instance.")
00425 {
00426   return (EDASCM_OBJECTP (object_smob) ? SCM_BOOL_T : SCM_BOOL_F);
00427 }
00428 
00435 static void
00436 init_module_geda_core_smob ()
00437 {
00438   /* Register the functions. */
00439   #include "scheme_smob.x"
00440 
00441   /* Add them to the module's public definitions. */ 
00442   scm_c_export (s_page_p, s_object_p, NULL);
00443 }
00444 
00454 void
00455 edascm_init_smob ()
00456 {
00457   /* Register gEDA smob type */
00458   geda_smob_tag = scm_make_smob_type ("geda", 0);
00459   scm_set_smob_free (geda_smob_tag, smob_free);
00460   scm_set_smob_print (geda_smob_tag, smob_print);
00461   scm_set_smob_equalp (geda_smob_tag, smob_equalp);
00462 
00463   /* Define the (geda core smob) module */
00464   scm_c_define_module ("geda core smob",
00465                        init_module_geda_core_smob,
00466                        NULL);
00467 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines