Sun, 28 Jul 2013 23:36:59 +0530
Replaced purple_find_prpl() with purple_find_protocol_info().
* Changed its return type from PurplePlugin * to PurplePluginProtocolInfo *
* Added id to PurplePluginProtocolInfo
| 13814 | 1 | /** |
| 15884 | 2 | * @file tcl_ref.c Purple Tcl typed references API |
| 13814 | 3 | * |
| 15884 | 4 | * purple |
| 13814 | 5 | * |
| 6 | * Copyright (C) 2006 Ethan Blanton <eblanton@cs.purdue.edu> | |
|
31294
73607ab89c6f
Remove trailing whitespace
Richard Laager <rlaager@pidgin.im>
parents:
19859
diff
changeset
|
7 | * |
| 13814 | 8 | * This program is free software; you can redistribute it and/or modify |
| 9 | * it under the terms of the GNU General Public License as published by | |
| 10 | * the Free Software Foundation; either version 2 of the License, or | |
| 11 | * (at your option) any later version. | |
| 12 | * | |
| 13 | * This program is distributed in the hope that it will be useful, | |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | * GNU General Public License for more details. | |
| 17 | * | |
| 18 | * You should have received a copy of the GNU General Public License | |
| 19 | * along with this program; if not, write to the Free Software | |
|
19859
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
16877
diff
changeset
|
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
| 13814 | 21 | */ |
| 22 | ||
| 23 | #include <tcl.h> | |
| 24 | #include <glib.h> | |
| 25 | ||
| 15884 | 26 | #include "tcl_purple.h" |
| 13814 | 27 | #include "stringref.h" |
| 28 | ||
| 29 | /* Instead of all that internal representation mumbo jumbo, use these | |
| 15884 | 30 | * macros to access the internal representation of a PurpleTclRef */ |
| 13814 | 31 | #define OBJ_REF_TYPE(obj) (obj->internalRep.twoPtrValue.ptr1) |
| 32 | #define OBJ_REF_VALUE(obj) (obj->internalRep.twoPtrValue.ptr2) | |
| 33 | ||
| 15884 | 34 | static Tcl_FreeInternalRepProc purple_tcl_ref_free; |
| 35 | static Tcl_DupInternalRepProc purple_tcl_ref_dup; | |
| 36 | static Tcl_UpdateStringProc purple_tcl_ref_update; | |
| 37 | static Tcl_SetFromAnyProc purple_tcl_ref_set; | |
| 13814 | 38 | |
| 15884 | 39 | static Tcl_ObjType purple_tcl_ref = { |
| 40 | "PurpleTclRef", | |
| 41 | purple_tcl_ref_free, | |
| 42 | purple_tcl_ref_dup, | |
| 43 | purple_tcl_ref_update, | |
| 44 | purple_tcl_ref_set | |
| 13814 | 45 | }; |
| 46 | ||
| 15884 | 47 | void purple_tcl_ref_init() |
| 13814 | 48 | { |
| 15884 | 49 | Tcl_RegisterObjType(&purple_tcl_ref); |
| 13814 | 50 | } |
| 51 | ||
| 15884 | 52 | void *purple_tcl_ref_get(Tcl_Interp *interp, Tcl_Obj *obj, PurpleStringref *type) |
| 13814 | 53 | { |
| 15884 | 54 | if (obj->typePtr != &purple_tcl_ref) { |
| 55 | if (Tcl_ConvertToType(interp, obj, &purple_tcl_ref) != TCL_OK) | |
| 13814 | 56 | return NULL; |
| 57 | } | |
| 15884 | 58 | if (strcmp(purple_stringref_value(OBJ_REF_TYPE(obj)), |
| 59 | purple_stringref_value(type))) { | |
| 13814 | 60 | if (interp) { |
| 15884 | 61 | Tcl_Obj *error = Tcl_NewStringObj("Bad Purple reference type: expected ", -1); |
| 62 | Tcl_AppendToObj(error, purple_stringref_value(type), -1); | |
| 13827 | 63 | Tcl_AppendToObj(error, " but got ", -1); |
| 15884 | 64 | Tcl_AppendToObj(error, purple_stringref_value(OBJ_REF_TYPE(obj)), -1); |
| 13814 | 65 | Tcl_SetObjResult(interp, error); |
| 66 | } | |
| 67 | return NULL; | |
| 68 | } | |
| 69 | return OBJ_REF_VALUE(obj); | |
| 70 | } | |
| 71 | ||
| 15884 | 72 | Tcl_Obj *purple_tcl_ref_new(PurpleStringref *type, void *value) |
| 13814 | 73 | { |
| 74 | Tcl_Obj *obj = Tcl_NewObj(); | |
| 15884 | 75 | obj->typePtr = &purple_tcl_ref; |
| 76 | OBJ_REF_TYPE(obj) = purple_stringref_ref(type); | |
| 13814 | 77 | OBJ_REF_VALUE(obj) = value; |
| 78 | Tcl_InvalidateStringRep(obj); | |
| 79 | return obj; | |
| 80 | } | |
| 81 | ||
| 15884 | 82 | static void purple_tcl_ref_free(Tcl_Obj *obj) |
| 13814 | 83 | { |
| 15884 | 84 | purple_stringref_unref(OBJ_REF_TYPE(obj)); |
| 13814 | 85 | } |
| 86 | ||
| 15884 | 87 | static void purple_tcl_ref_dup(Tcl_Obj *obj1, Tcl_Obj *obj2) |
| 13814 | 88 | { |
| 15884 | 89 | OBJ_REF_TYPE(obj2) = purple_stringref_ref(OBJ_REF_TYPE(obj1)); |
| 13814 | 90 | OBJ_REF_VALUE(obj2) = OBJ_REF_VALUE(obj1); |
| 91 | } | |
| 92 | ||
| 15884 | 93 | static void purple_tcl_ref_update(Tcl_Obj *obj) |
| 13814 | 94 | { |
|
31956
f2b6b7f5631b
Fix up several Tcl loader string copies to use g_strlcpy().
Ethan Blanton <elb@pidgin.im>
parents:
31294
diff
changeset
|
95 | size_t len; |
| 13814 | 96 | /* This is ugly on memory, but we pretty much have to either |
| 97 | * do this or guesstimate lengths or introduce a varargs | |
| 98 | * function in here ... ugh. */ | |
| 15884 | 99 | char *bytes = g_strdup_printf("purple-%s:%p", |
| 100 | purple_stringref_value(OBJ_REF_TYPE(obj)), | |
| 13814 | 101 | OBJ_REF_VALUE(obj)); |
| 102 | ||
| 103 | obj->length = strlen(bytes); | |
|
31956
f2b6b7f5631b
Fix up several Tcl loader string copies to use g_strlcpy().
Ethan Blanton <elb@pidgin.im>
parents:
31294
diff
changeset
|
104 | len = obj->length + 1; |
|
f2b6b7f5631b
Fix up several Tcl loader string copies to use g_strlcpy().
Ethan Blanton <elb@pidgin.im>
parents:
31294
diff
changeset
|
105 | obj->bytes = ckalloc(len); |
|
f2b6b7f5631b
Fix up several Tcl loader string copies to use g_strlcpy().
Ethan Blanton <elb@pidgin.im>
parents:
31294
diff
changeset
|
106 | g_strlcpy(obj->bytes, bytes, len); |
| 13814 | 107 | g_free(bytes); |
| 108 | } | |
| 109 | ||
| 110 | /* This isn't as memory-efficient as setting could be, because we | |
| 111 | * essentially have to synthesize the Stringref here, where we would | |
| 112 | * really rather dup it. Oh, well. */ | |
| 15884 | 113 | static int purple_tcl_ref_set(Tcl_Interp *interp, Tcl_Obj *obj) |
| 13814 | 114 | { |
| 115 | char *bytes = Tcl_GetStringFromObj(obj, NULL); | |
| 116 | char *ptr; | |
| 15884 | 117 | PurpleStringref *type; |
| 13814 | 118 | void *value; |
|
16877
b2a8fef0a200
Stu pointed out that I made an error, and Josh made it clear that the
Ethan Blanton <elb@pidgin.im>
parents:
16477
diff
changeset
|
119 | static const char prefix[] = "purple-"; |
|
16477
2fe930b4dcb6
The compiler is really smart enough to catch this, but let's make it explicit.
Ethan Blanton <elb@pidgin.im>
parents:
16433
diff
changeset
|
120 | static const int prefixlen = sizeof(prefix) - 1; |
| 13814 | 121 | |
|
16477
2fe930b4dcb6
The compiler is really smart enough to catch this, but let's make it explicit.
Ethan Blanton <elb@pidgin.im>
parents:
16433
diff
changeset
|
122 | if (strlen(bytes) < prefixlen |
|
2fe930b4dcb6
The compiler is really smart enough to catch this, but let's make it explicit.
Ethan Blanton <elb@pidgin.im>
parents:
16433
diff
changeset
|
123 | || strncmp(bytes, prefix, prefixlen) |
| 13814 | 124 | || (ptr = strchr(bytes, ':')) == NULL |
|
16477
2fe930b4dcb6
The compiler is really smart enough to catch this, but let's make it explicit.
Ethan Blanton <elb@pidgin.im>
parents:
16433
diff
changeset
|
125 | || (ptr - bytes) == prefixlen) |
| 13814 | 126 | goto badobject; |
| 127 | ||
| 128 | /* Bad Ethan */ | |
| 129 | *ptr = '\0'; | |
|
16477
2fe930b4dcb6
The compiler is really smart enough to catch this, but let's make it explicit.
Ethan Blanton <elb@pidgin.im>
parents:
16433
diff
changeset
|
130 | type = purple_stringref_new(bytes + prefixlen); |
| 13814 | 131 | *ptr = ':'; |
| 132 | ptr++; | |
| 133 | ||
| 134 | if (sscanf(ptr, "%p", &value) == 0) { | |
| 15884 | 135 | purple_stringref_unref(type); |
| 13814 | 136 | goto badobject; |
| 137 | } | |
| 138 | ||
| 139 | /* At this point we know we have a good object; free the old and | |
| 140 | * install our internal representation. */ | |
| 141 | if (obj->typePtr != NULL && obj->typePtr->freeIntRepProc != NULL) | |
| 142 | obj->typePtr->freeIntRepProc(obj); | |
| 143 | ||
| 15884 | 144 | obj->typePtr = &purple_tcl_ref; |
| 13814 | 145 | OBJ_REF_TYPE(obj) = type; |
| 146 | OBJ_REF_VALUE(obj) = value; | |
| 147 | ||
| 148 | return TCL_OK; | |
| 149 | ||
| 150 | badobject: | |
| 151 | if (interp) { | |
| 152 | Tcl_SetObjResult(interp, | |
| 15884 | 153 | Tcl_NewStringObj("invalid PurpleTclRef representation", -1)); |
| 13814 | 154 | } |
| 155 | return TCL_ERROR; | |
| 156 | } |