1 /*
2  * This file is part of the libsigrokdecode project.
3  *
4  * Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
5  * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 #include "libsigrokdecode-internal.h" /* First, so we avoid a _POSIX_C_SOURCE warning. */
23 
24 /**
25  * Import a Python module by name.
26  *
27  * This function is implemented in terms of PyImport_Import() rather than
28  * PyImport_ImportModule(), so that the import hooks are not bypassed.
29  *
30  * @param[in] name The name of the module to load as UTF-8 string.
31  * @return The Python module object, or NULL if an exception occurred. The
32  *  caller is responsible for evaluating and clearing the Python error state.
33  *
34  * @private
35  */
py_import_by_name(const char * name)36 SRD_PRIV PyObject *py_import_by_name(const char *name)
37 {
38 	PyObject *py_mod, *py_modname;
39 	PyGILState_STATE gstate;
40 
41 	gstate = PyGILState_Ensure();
42 
43 	py_modname = PyUnicode_FromString(name);
44 	if (!py_modname) {
45 		PyGILState_Release(gstate);
46 		return NULL;
47 	}
48 
49 	py_mod = PyImport_Import(py_modname);
50 	Py_DECREF(py_modname);
51 
52 	PyGILState_Release(gstate);
53 
54 	return py_mod;
55 }
56 
57 /**
58  * Get the value of a Python object's attribute, returned as a newly
59  * allocated char *.
60  *
61  * @param[in] py_obj The object to probe.
62  * @param[in] attr Name of the attribute to retrieve.
63  * @param[out] outstr ptr to char * storage to be filled in.
64  *
65  * @return SRD_OK upon success, a (negative) error code otherwise.
66  *         The 'outstr' argument points to a g_malloc()ed string upon success.
67  *
68  * @private
69  */
py_attr_as_str(PyObject * py_obj,const char * attr,char ** outstr)70 SRD_PRIV int py_attr_as_str(PyObject *py_obj, const char *attr, char **outstr)
71 {
72 	PyObject *py_str;
73 	int ret;
74 	PyGILState_STATE gstate;
75 
76 	gstate = PyGILState_Ensure();
77 
78 	if (!PyObject_HasAttrString(py_obj, attr)) {
79 		srd_dbg("Object has no attribute '%s'.", attr);
80 		goto err;
81 	}
82 
83 	if (!(py_str = PyObject_GetAttrString(py_obj, attr))) {
84 		srd_exception_catch("Failed to get attribute '%s'", attr);
85 		goto err;
86 	}
87 
88 	ret = py_str_as_str(py_str, outstr);
89 	Py_DECREF(py_str);
90 
91 	PyGILState_Release(gstate);
92 
93 	return ret;
94 
95 err:
96 	PyGILState_Release(gstate);
97 
98 	return SRD_ERR_PYTHON;
99 }
100 
101 /**
102  * Get the value of a Python object's attribute, returned as a newly
103  * allocated GSList of char *.
104  *
105  * @param[in] py_obj The object to probe.
106  * @param[in] attr Name of the attribute to retrieve.
107  * @param[out] outstrlist ptr to GSList of char * storage to be filled in.
108  *
109  * @return SRD_OK upon success, a (negative) error code otherwise.
110  *         The 'outstrlist' argument points to a GSList of g_malloc()ed strings
111  *         upon success.
112  *
113  * @private
114  */
py_attr_as_strlist(PyObject * py_obj,const char * attr,GSList ** outstrlist)115 SRD_PRIV int py_attr_as_strlist(PyObject *py_obj, const char *attr, GSList **outstrlist)
116 {
117 	PyObject *py_list;
118 	Py_ssize_t i;
119 	int ret;
120 	char *outstr;
121 	PyGILState_STATE gstate;
122 
123 	gstate = PyGILState_Ensure();
124 
125 	if (!PyObject_HasAttrString(py_obj, attr)) {
126 		srd_dbg("Object has no attribute '%s'.", attr);
127 		goto err;
128 	}
129 
130 	if (!(py_list = PyObject_GetAttrString(py_obj, attr))) {
131 		srd_exception_catch("Failed to get attribute '%s'", attr);
132 		goto err;
133 	}
134 
135 	if (!PyList_Check(py_list)) {
136 		srd_dbg("Object is not a list.");
137 		goto err;
138 	}
139 
140 	*outstrlist = NULL;
141 
142 	for (i = 0; i < PyList_Size(py_list); i++) {
143 		ret = py_listitem_as_str(py_list, i, &outstr);
144 		if (ret < 0) {
145 			srd_dbg("Couldn't get item %" PY_FORMAT_SIZE_T "d.", i);
146 			goto err;
147 		}
148 		*outstrlist = g_slist_append(*outstrlist, outstr);
149 	}
150 
151 	Py_DECREF(py_list);
152 
153 	PyGILState_Release(gstate);
154 
155 	return SRD_OK;
156 
157 err:
158 	PyGILState_Release(gstate);
159 
160 	return SRD_ERR_PYTHON;
161 }
162 
163 /**
164  * Get the value of a Python dictionary item, returned as a newly
165  * allocated char *.
166  *
167  * @param[in] py_obj The dictionary to probe.
168  * @param[in] key Key of the item to retrieve.
169  * @param[out] outstr Pointer to char * storage to be filled in.
170  *
171  * @return SRD_OK upon success, a (negative) error code otherwise.
172  *         The 'outstr' argument points to a g_malloc()ed string upon success.
173  *
174  * @private
175  */
py_dictitem_as_str(PyObject * py_obj,const char * key,char ** outstr)176 SRD_PRIV int py_dictitem_as_str(PyObject *py_obj, const char *key,
177 				char **outstr)
178 {
179 	PyObject *py_value;
180 	PyGILState_STATE gstate;
181 
182 	gstate = PyGILState_Ensure();
183 
184 	if (!PyDict_Check(py_obj)) {
185 		srd_dbg("Object is not a dictionary.");
186 		goto err;
187 	}
188 
189 	if (!(py_value = PyDict_GetItemString(py_obj, key))) {
190 		srd_dbg("Dictionary has no attribute '%s'.", key);
191 		goto err;
192 	}
193 
194 	PyGILState_Release(gstate);
195 
196 	return py_str_as_str(py_value, outstr);
197 
198 err:
199 	PyGILState_Release(gstate);
200 
201 	return SRD_ERR_PYTHON;
202 }
203 
204 /**
205  * Get the value of a Python list item, returned as a newly
206  * allocated char *.
207  *
208  * @param[in] py_obj The list to probe.
209  * @param[in] idx Index of the list item to retrieve.
210  * @param[out] outstr Pointer to char * storage to be filled in.
211  *
212  * @return SRD_OK upon success, a (negative) error code otherwise.
213  *         The 'outstr' argument points to a g_malloc()ed string upon success.
214  *
215  * @private
216  */
py_listitem_as_str(PyObject * py_obj,Py_ssize_t idx,char ** outstr)217 SRD_PRIV int py_listitem_as_str(PyObject *py_obj, Py_ssize_t idx,
218 				char **outstr)
219 {
220 	PyObject *py_value;
221 	PyGILState_STATE gstate;
222 
223 	gstate = PyGILState_Ensure();
224 
225 	if (!PyList_Check(py_obj)) {
226 		srd_dbg("Object is not a list.");
227 		goto err;
228 	}
229 
230 	if (!(py_value = PyList_GetItem(py_obj, idx))) {
231 		srd_dbg("Couldn't get list item %" PY_FORMAT_SIZE_T "d.", idx);
232 		goto err;
233 	}
234 
235 	PyGILState_Release(gstate);
236 
237 	return py_str_as_str(py_value, outstr);
238 
239 err:
240 	PyGILState_Release(gstate);
241 
242 	return SRD_ERR_PYTHON;
243 }
244 
245 /**
246  * Get the value of a Python dictionary item, returned as a newly
247  * allocated char *.
248  *
249  * @param py_obj The dictionary to probe.
250  * @param py_key Key of the item to retrieve.
251  * @param outstr Pointer to char * storage to be filled in.
252  *
253  * @return SRD_OK upon success, a (negative) error code otherwise.
254  *         The 'outstr' argument points to a malloc()ed string upon success.
255  *
256  * @private
257  */
py_pydictitem_as_str(PyObject * py_obj,PyObject * py_key,char ** outstr)258 SRD_PRIV int py_pydictitem_as_str(PyObject *py_obj, PyObject *py_key,
259 				char **outstr)
260 {
261 	PyObject *py_value;
262 	PyGILState_STATE gstate;
263 
264 	if (!py_obj || !py_key || !outstr)
265 		return SRD_ERR_ARG;
266 
267 	gstate = PyGILState_Ensure();
268 
269 	if (!PyDict_Check(py_obj)) {
270 		srd_dbg("Object is not a dictionary.");
271 		goto err;
272 	}
273 
274 	if (!(py_value = PyDict_GetItem(py_obj, py_key))) {
275 		srd_dbg("Dictionary has no such key.");
276 		goto err;
277 	}
278 
279 	if (!PyUnicode_Check(py_value)) {
280 		srd_dbg("Dictionary value should be a string.");
281 		goto err;
282 	}
283 
284 	PyGILState_Release(gstate);
285 
286 	return py_str_as_str(py_value, outstr);
287 
288 err:
289 	PyGILState_Release(gstate);
290 
291 	return SRD_ERR_PYTHON;
292 }
293 
294 /**
295  * Get the value of a Python dictionary item, returned as a newly
296  * allocated char *.
297  *
298  * @param py_obj The dictionary to probe.
299  * @param py_key Key of the item to retrieve.
300  * @param out TODO.
301  *
302  * @return SRD_OK upon success, a (negative) error code otherwise.
303  *
304  * @private
305  */
py_pydictitem_as_long(PyObject * py_obj,PyObject * py_key,int64_t * out)306 SRD_PRIV int py_pydictitem_as_long(PyObject *py_obj, PyObject *py_key, int64_t *out)
307 {
308 	PyObject *py_value;
309 	PyGILState_STATE gstate;
310 
311 	if (!py_obj || !py_key || !out)
312 		return SRD_ERR_ARG;
313 
314 	gstate = PyGILState_Ensure();
315 
316 	if (!PyDict_Check(py_obj)) {
317 		srd_dbg("Object is not a dictionary.");
318 		goto err;
319 	}
320 
321 	if (!(py_value = PyDict_GetItem(py_obj, py_key))) {
322 		srd_dbg("Dictionary has no such key.");
323 		goto err;
324 	}
325 
326 	if (!PyLong_Check(py_value)) {
327 		srd_dbg("Dictionary value should be a long.");
328 		goto err;
329 	}
330 
331 	*out = PyLong_AsLongLong(py_value);
332 
333 	PyGILState_Release(gstate);
334 
335 	return SRD_OK;
336 
337 err:
338 	PyGILState_Release(gstate);
339 
340 	return SRD_ERR_PYTHON;
341 }
342 
343 /**
344  * Get the value of a Python unicode string object, returned as a newly
345  * allocated char *.
346  *
347  * @param[in] py_str The unicode string object.
348  * @param[out] outstr ptr to char * storage to be filled in.
349  *
350  * @return SRD_OK upon success, a (negative) error code otherwise.
351  *         The 'outstr' argument points to a g_malloc()ed string upon success.
352  *
353  * @private
354  */
py_str_as_str(PyObject * py_str,char ** outstr)355 SRD_PRIV int py_str_as_str(PyObject *py_str, char **outstr)
356 {
357 	PyObject *py_bytes;
358 	char *str;
359 	PyGILState_STATE gstate;
360 
361 	gstate = PyGILState_Ensure();
362 
363 	if (!PyUnicode_Check(py_str)) {
364 		srd_dbg("Object is not a string object.");
365 		PyGILState_Release(gstate);
366 		return SRD_ERR_PYTHON;
367 	}
368 
369 	py_bytes = PyUnicode_AsUTF8String(py_str);
370 	if (py_bytes) {
371 		str = g_strdup(PyBytes_AsString(py_bytes));
372 		Py_DECREF(py_bytes);
373 		if (str) {
374 			*outstr = str;
375 			PyGILState_Release(gstate);
376 			return SRD_OK;
377 		}
378 	}
379 	srd_exception_catch("Failed to extract string");
380 
381 	PyGILState_Release(gstate);
382 
383 	return SRD_ERR_PYTHON;
384 }
385 
386 /**
387  * Convert a Python list of unicode strings to a C string vector.
388  * On success, a pointer to a newly allocated NUL-terminated array of
389  * allocated C strings is written to @a out_strv. The caller must g_free()
390  * each string and the array itself.
391  *
392  * @param[in] py_strseq The sequence object.
393  * @param[out] out_strv Address of string vector to be filled in.
394  *
395  * @return SRD_OK upon success, a (negative) error code otherwise.
396  *
397  * @private
398  */
py_strseq_to_char(PyObject * py_strseq,char *** out_strv)399 SRD_PRIV int py_strseq_to_char(PyObject *py_strseq, char ***out_strv)
400 {
401 	PyObject *py_item, *py_bytes;
402 	char **strv, *str;
403 	ssize_t seq_len, i;
404 	PyGILState_STATE gstate;
405 	int ret = SRD_ERR_PYTHON;
406 
407 	gstate = PyGILState_Ensure();
408 
409 	if (!PySequence_Check(py_strseq)) {
410 		srd_err("Object does not provide sequence protocol.");
411 		goto err;
412 	}
413 
414 	seq_len = PySequence_Size(py_strseq);
415 	if (seq_len < 0) {
416 		srd_exception_catch("Failed to obtain sequence size");
417 		goto err;
418 	}
419 
420 	strv = g_try_new0(char *, seq_len + 1);
421 	if (!strv) {
422 		srd_err("Failed to allocate result string vector.");
423 		ret = SRD_ERR_MALLOC;
424 		goto err;
425 	}
426 
427 	for (i = 0; i < seq_len; i++) {
428 		py_item = PySequence_GetItem(py_strseq, i);
429 		if (!py_item)
430 			goto err_out;
431 
432 		if (!PyUnicode_Check(py_item)) {
433 			Py_DECREF(py_item);
434 			goto err_out;
435 		}
436 		py_bytes = PyUnicode_AsUTF8String(py_item);
437 		Py_DECREF(py_item);
438 		if (!py_bytes)
439 			goto err_out;
440 
441 		str = g_strdup(PyBytes_AsString(py_bytes));
442 		Py_DECREF(py_bytes);
443 		if (!str)
444 			goto err_out;
445 
446 		strv[i] = str;
447 	}
448 	*out_strv = strv;
449 
450 	PyGILState_Release(gstate);
451 
452 	return SRD_OK;
453 
454 err_out:
455 	g_strfreev(strv);
456 	srd_exception_catch("Failed to obtain string item");
457 
458 err:
459 	PyGILState_Release(gstate);
460 
461 	return ret;
462 }
463 
464 /**
465  * Convert a Python scalar object to a GLib variant.
466  * Supported variant types are string, int64 and double.
467  *
468  * @param[in] py_obj The Python object. Must not be NULL.
469  * @return A floating reference to a new variant, or NULL on failure.
470  *
471  * @private
472  */
py_obj_to_variant(PyObject * py_obj)473 SRD_PRIV GVariant *py_obj_to_variant(PyObject *py_obj)
474 {
475 	GVariant *var = NULL;
476 	PyGILState_STATE gstate;
477 
478 	gstate = PyGILState_Ensure();
479 
480 	if (PyUnicode_Check(py_obj)) { /* string */
481 		PyObject *py_bytes;
482 		const char *str;
483 
484 		py_bytes = PyUnicode_AsUTF8String(py_obj);
485 		if (py_bytes) {
486 			str = PyBytes_AsString(py_bytes);
487 			if (str)
488 				var = g_variant_new_string(str);
489 			Py_DECREF(py_bytes);
490 		}
491 		if (!var)
492 			srd_exception_catch("Failed to extract string value");
493 	} else if (PyLong_Check(py_obj)) { /* integer */
494 		int64_t val;
495 
496 		val = PyLong_AsLongLong(py_obj);
497 		if (!PyErr_Occurred())
498 			var = g_variant_new_int64(val);
499 		else
500 			srd_exception_catch("Failed to extract integer value");
501 	} else if (PyFloat_Check(py_obj)) { /* float */
502 		double val;
503 
504 		val = PyFloat_AsDouble(py_obj);
505 		if (!PyErr_Occurred())
506 			var = g_variant_new_double(val);
507 		else
508 			srd_exception_catch("Failed to extract float value");
509 	} else {
510 		srd_err("Failed to extract value of unsupported type.");
511 	}
512 
513 	PyGILState_Release(gstate);
514 
515 	return var;
516 }
517