libgeda
|
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 }