* strports.c (st_end_input): avoid dubious pointer arithmetic.
[bpt/guile.git] / libguile / gh_data.c
CommitLineData
0acef67a 1/* Copyright (C) 1995,1996,1997,1998, 1999 Free Software Foundation, Inc.
ee2a8b9b
JB
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2, or (at your option)
5 * any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this software; see the file COPYING. If not, write to
82892bed
JB
14 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15 * Boston, MA 02111-1307 USA
ee2a8b9b
JB
16 *
17 * As a special exception, the Free Software Foundation gives permission
18 * for additional uses of the text contained in its release of GUILE.
19 *
20 * The exception is that, if you link the GUILE library with other files
21 * to produce an executable, this does not by itself cause the
22 * resulting executable to be covered by the GNU General Public License.
23 * Your use of that executable is in no way restricted on account of
24 * linking the GUILE library code into it.
25 *
26 * This exception does not however invalidate any other reasons why
27 * the executable file might be covered by the GNU General Public License.
28 *
29 * This exception applies only to the code released by the
30 * Free Software Foundation under the name GUILE. If you copy
31 * code from other Free Software Foundation releases into a copy of
32 * GUILE, as the General Public License permits, the exception does
33 * not apply to the code that you add in this way. To avoid misleading
34 * anyone as to the status of such modified files, you must delete
35 * this exception notice from them.
36 *
37 * If you write modifications of your own for GUILE, it is your choice
38 * whether to permit this exception to apply to your modifications.
82892bed 39 * If you do not wish that, delete this exception notice. */
ee2a8b9b
JB
40\f
41
42/* data initialization and C<->Scheme data conversion */
43
44#include <stdio.h>
45
46#include <gh.h>
47
48/* data conversion C->scheme */
49SCM
dbb3005d
MG
50gh_int2scmb (int x) /* this is being phased out */
51{
52 return (x ? SCM_BOOL_T : SCM_BOOL_F);
53}
54SCM
55gh_bool2scm (int x)
ee2a8b9b
JB
56{
57 return (x ? SCM_BOOL_T : SCM_BOOL_F);
58}
59SCM
60gh_int2scm (int x)
61{
62 return scm_long2num ((long) x);
63}
64SCM
65gh_ulong2scm (unsigned long x)
66{
67 return scm_ulong2num (x);
68}
69SCM
70gh_long2scm (long x)
71{
72 return scm_long2num (x);
73}
74SCM
75gh_double2scm (double x)
76{
77 return scm_makdbl (x, 0.0);
78}
79SCM
80gh_char2scm (char c)
81{
2c92112b 82 return SCM_MAKICHR (c);
ee2a8b9b
JB
83}
84SCM
85gh_str2scm (char *s, int len)
86{
87 return scm_makfromstr (s, len, 0);
88}
89SCM
90gh_str02scm (char *s)
91{
92 return scm_makfrom0str (s);
93}
94/* Copy LEN characters at SRC into the *existing* Scheme string DST,
95 starting at START. START is an index into DST; zero means the
96 beginning of the string.
97
98 If START + LEN is off the end of DST, signal an out-of-range
99 error. */
100void
101gh_set_substr (char *src, SCM dst, int start, int len)
102{
2c92112b 103 char *dst_ptr;
fd88bd7c
JB
104 unsigned long dst_len;
105 unsigned long effective_length;
ee2a8b9b
JB
106
107 SCM_ASSERT (SCM_NIMP (dst) && SCM_STRINGP (dst), dst, SCM_ARG3,
108 "gh_set_substr");
fd88bd7c 109
ee2a8b9b
JB
110 dst_ptr = SCM_CHARS (dst);
111 dst_len = SCM_LENGTH (dst);
fd88bd7c
JB
112 SCM_ASSERT (len >= 0 && (unsigned) len <= dst_len,
113 dst, SCM_ARG4, "gh_set_substr");
114
115 scm_protect_object (dst);
116 effective_length = ((unsigned) len < dst_len) ? len : dst_len;
117 memmove (dst_ptr + start, src, effective_length);
ee2a8b9b
JB
118 scm_unprotect_object (dst);
119}
120
121/* Return the symbol named SYMBOL_STR. */
122SCM
123gh_symbol2scm (char *symbol_str)
124{
125 return SCM_CAR (scm_intern (symbol_str, strlen (symbol_str)));
126}
127
b774ee1f
MD
128SCM
129gh_ints2scm (int *d, int n)
130{
b774ee1f 131 int i;
0acef67a
JB
132 SCM v = scm_make_vector(SCM_MAKINUM(n), SCM_UNSPECIFIED);
133 SCM *velts = SCM_VELTS(v);
134
b774ee1f 135 for (i = 0; i < n; ++i)
0acef67a
JB
136 velts[i] = (d[i] >= SCM_MOST_NEGATIVE_FIXNUM
137 && d[i] <= SCM_MOST_POSITIVE_FIXNUM
138 ? SCM_MAKINUM (d[i])
139 : scm_long2big (d[i]));
140 return v;
3ffc7a36
MD
141}
142
143SCM
144gh_doubles2scm (double *d, int n)
145{
3ffc7a36 146 int i;
0acef67a
JB
147 SCM v = scm_make_vector(SCM_MAKINUM(n), SCM_UNSPECIFIED);
148 SCM *velts = SCM_VELTS(v);
149
150 for(i = 0; i < n; i++)
151 velts[i] = scm_makdbl(d[i], 0.0);
152 return v;
153}
154
155/* Do not use this function for building normal Scheme vectors, unless
156 you arrange for the elements to be protected from GC while you
157 initialize the vector. */
158static SCM
159makvect (char* m, int len, int type)
160{
161 SCM ans;
162 SCM_NEWCELL (ans);
163 SCM_DEFER_INTS;
164 SCM_SETCHARS (ans, m);
165 SCM_SETLENGTH (ans, len, type);
166 SCM_ALLOW_INTS;
167 return ans;
b774ee1f
MD
168}
169
3ffc7a36
MD
170SCM
171gh_chars2byvect (char *d, int n)
172{
173 char *m = scm_must_malloc (n * sizeof (char), "vector");
174 memcpy (m, d, n * sizeof (char));
175 return makvect (m, n, scm_tc7_byvect);
176}
177
178SCM
179gh_shorts2svect (short *d, int n)
180{
181 char *m = scm_must_malloc (n * sizeof (short), "vector");
182 memcpy (m, d, n * sizeof (short));
183 return makvect (m, n, scm_tc7_svect);
184}
185
b774ee1f
MD
186SCM
187gh_longs2ivect (long *d, int n)
188{
189 char *m = scm_must_malloc (n * sizeof (long), "vector");
190 memcpy (m, d, n * sizeof (long));
191 return makvect (m, n, scm_tc7_ivect);
192}
193
194SCM
195gh_ulongs2uvect (unsigned long *d, int n)
196{
197 char *m = scm_must_malloc (n * sizeof (unsigned long), "vector");
198 memcpy (m, d, n * sizeof (unsigned long));
199 return makvect (m, n, scm_tc7_uvect);
200}
201
3ffc7a36
MD
202#ifdef SCM_FLOATS
203#ifdef SCM_SINGLES
b774ee1f 204SCM
3ffc7a36 205gh_floats2fvect (float *d, int n)
b774ee1f 206{
3ffc7a36
MD
207 char *m = scm_must_malloc (n * sizeof (float), "vector");
208 memcpy (m, d, n * sizeof (float));
209 return makvect (m, n, scm_tc7_fvect);
b774ee1f 210}
3ffc7a36 211#endif
b774ee1f 212
f3a2c4cf
MD
213SCM
214gh_doubles2dvect (double *d, int n)
215{
f3a2c4cf
MD
216 char *m = scm_must_malloc (n * sizeof (double), "vector");
217 memcpy (m, d, n * sizeof (double));
b774ee1f 218 return makvect (m, n, scm_tc7_dvect);
f3a2c4cf
MD
219}
220#endif
ee2a8b9b
JB
221
222/* data conversion scheme->C */
223int
224gh_scm2bool (SCM obj)
225{
226 return ((obj) == SCM_BOOL_F) ? 0 : 1;
227}
228unsigned long
229gh_scm2ulong (SCM obj)
230{
231 return scm_num2ulong (obj, (char *) SCM_ARG1, "gh_scm2ulong");
232}
233long
234gh_scm2long (SCM obj)
235{
236 return scm_num2long (obj, (char *) SCM_ARG1, "gh_scm2long");
237}
238int
239gh_scm2int (SCM obj)
240{
241 /* NOTE: possible loss of precision here */
242 return (int) scm_num2long (obj, (char *) SCM_ARG1, "gh_scm2int");
243}
244double
245gh_scm2double (SCM obj)
246{
247 return scm_num2dbl (obj, "gh_scm2double");
248}
249char
250gh_scm2char (SCM obj)
251{
252 return SCM_ICHR (obj);
253}
254
3ffc7a36
MD
255/* Convert a vector, weak vector, string, substring or uniform vector
256 into an array of chars. If result array in arg 2 is NULL, malloc a
257 new one. */
258char *
259gh_scm2chars (SCM obj, char *m)
f3a2c4cf
MD
260{
261 int i, n;
3ffc7a36 262 long v;
f3a2c4cf
MD
263 SCM val;
264 if (!SCM_NIMP (obj))
265 scm_wrong_type_arg (0, 0, obj);
266 switch (SCM_TYP7 (obj))
267 {
268 case scm_tc7_vector:
269 case scm_tc7_wvect:
270 n = SCM_LENGTH (obj);
f3a2c4cf
MD
271 for (i = 0; i < n; ++i)
272 {
273 val = SCM_VELTS (obj)[i];
274 if (SCM_INUMP (val))
3ffc7a36
MD
275 {
276 v = SCM_INUM (val);
277 if (v < -128 || v > 255)
278 scm_out_of_range (0, obj);
279 }
f3a2c4cf 280 else
3ffc7a36
MD
281 scm_wrong_type_arg (0, 0, obj);
282 }
283 if (m == 0)
284 m = (char *) malloc (n * sizeof (char));
285 for (i = 0; i < n; ++i)
286 m[i] = SCM_INUM (SCM_VELTS (obj)[i]);
287 break;
288 case scm_tc7_byvect:
289 case scm_tc7_string:
290 case scm_tc7_substring:
291 n = SCM_LENGTH (obj);
292 if (m == 0)
293 m = (char *) malloc (n * sizeof (char));
294 memcpy (m, SCM_VELTS (obj), n * sizeof (char));
295 break;
296 default:
297 scm_wrong_type_arg (0, 0, obj);
298 }
299 return m;
300}
301
302/* Convert a vector, weak vector or uniform vector into an array of
303 shorts. If result array in arg 2 is NULL, malloc a new one. */
304short *
305gh_scm2shorts (SCM obj, short *m)
306{
307 int i, n;
308 long v;
309 SCM val;
310 if (!SCM_NIMP (obj))
311 scm_wrong_type_arg (0, 0, obj);
312 switch (SCM_TYP7 (obj))
313 {
314 case scm_tc7_vector:
315 case scm_tc7_wvect:
316 n = SCM_LENGTH (obj);
317 for (i = 0; i < n; ++i)
318 {
319 val = SCM_VELTS (obj)[i];
320 if (SCM_INUMP (val))
f3a2c4cf 321 {
3ffc7a36
MD
322 v = SCM_INUM (val);
323 if (v < -32768 || v > 65535)
324 scm_out_of_range (0, obj);
f3a2c4cf 325 }
3ffc7a36
MD
326 else
327 scm_wrong_type_arg (0, 0, obj);
328 }
329 if (m == 0)
330 m = (short *) malloc (n * sizeof (short));
331 for (i = 0; i < n; ++i)
332 m[i] = SCM_INUM (SCM_VELTS (obj)[i]);
333 break;
334 case scm_tc7_svect:
335 n = SCM_LENGTH (obj);
336 if (m == 0)
337 m = (short *) malloc (n * sizeof (short));
338 memcpy (m, SCM_VELTS (obj), n * sizeof (short));
339 break;
340 default:
341 scm_wrong_type_arg (0, 0, obj);
342 }
343 return m;
344}
345
346/* Convert a vector, weak vector or uniform vector into an array of
347 longs. If result array in arg 2 is NULL, malloc a new one. */
348long *
349gh_scm2longs (SCM obj, long *m)
350{
351 int i, n;
352 SCM val;
353 if (!SCM_NIMP (obj))
354 scm_wrong_type_arg (0, 0, obj);
355 switch (SCM_TYP7 (obj))
356 {
357 case scm_tc7_vector:
358 case scm_tc7_wvect:
359 n = SCM_LENGTH (obj);
360 for (i = 0; i < n; ++i)
361 {
362 val = SCM_VELTS (obj)[i];
363 if (!SCM_INUMP (val) && !(SCM_NIMP (val) && SCM_BIGP (val)))
364 scm_wrong_type_arg (0, 0, obj);
365 }
366 if (m == 0)
367 m = (long *) malloc (n * sizeof (long));
368 for (i = 0; i < n; ++i)
369 {
370 val = SCM_VELTS (obj)[i];
371 m[i] = SCM_INUMP (val) ? SCM_INUM (val) : scm_num2long (val, 0, 0);
372 }
373 break;
374 case scm_tc7_ivect:
375 case scm_tc7_uvect:
376 n = SCM_LENGTH (obj);
377 if (m == 0)
378 m = (long *) malloc (n * sizeof (long));
379 memcpy (m, SCM_VELTS (obj), n * sizeof (long));
380 break;
381 default:
382 scm_wrong_type_arg (0, 0, obj);
383 }
384 return m;
385}
386
387/* Convert a vector, weak vector or uniform vector into an array of
388 floats. If result array in arg 2 is NULL, malloc a new one. */
389float *
390gh_scm2floats (SCM obj, float *m)
391{
392 int i, n;
393 SCM val;
394 if (!SCM_NIMP (obj))
395 scm_wrong_type_arg (0, 0, obj);
396 switch (SCM_TYP7 (obj))
397 {
398 case scm_tc7_vector:
399 case scm_tc7_wvect:
400 n = SCM_LENGTH (obj);
401 for (i = 0; i < n; ++i)
402 {
403 val = SCM_VELTS (obj)[i];
404 if (!SCM_INUMP (val)
405 && !(SCM_NIMP (val) && (SCM_BIGP (val) || SCM_REALP (val))))
406 scm_wrong_type_arg (0, 0, val);
407 }
408 if (m == 0)
409 m = (float *) malloc (n * sizeof (float));
410 for (i = 0; i < n; ++i)
411 {
412 val = SCM_VELTS (obj)[i];
413 if (SCM_INUMP (val))
414 m[i] = SCM_INUM (val);
415 else if (SCM_BIGP (val))
416 m[i] = scm_num2long (val, 0, 0);
417 else
418 m[i] = SCM_REALPART (val);
f3a2c4cf
MD
419 }
420 break;
421#ifdef SCM_FLOATS
422#ifdef SCM_SINGLES
423 case scm_tc7_fvect:
424 n = SCM_LENGTH (obj);
3ffc7a36
MD
425 if (m == 0)
426 m = (float *) malloc (n * sizeof (float));
427 memcpy (m, (float *) SCM_VELTS (obj), n * sizeof (float));
f3a2c4cf
MD
428 break;
429#endif
430 case scm_tc7_dvect:
431 n = SCM_LENGTH (obj);
3ffc7a36
MD
432 if (m == 0)
433 m = (float*) malloc (n * sizeof (float));
f3a2c4cf 434 for (i = 0; i < n; ++i)
3ffc7a36
MD
435 m[i] = ((double *) SCM_VELTS (obj))[i];
436 break;
437#endif
438 default:
439 scm_wrong_type_arg (0, 0, obj);
440 }
441 return m;
442}
443
444/* Convert a vector, weak vector or uniform vector into an array of
445 doubles. If result array in arg 2 is NULL, malloc a new one. */
446double *
447gh_scm2doubles (SCM obj, double *m)
448{
449 int i, n;
450 SCM val;
451 if (!SCM_NIMP (obj))
452 scm_wrong_type_arg (0, 0, obj);
453 switch (SCM_TYP7 (obj))
454 {
455 case scm_tc7_vector:
456 case scm_tc7_wvect:
457 n = SCM_LENGTH (obj);
458 for (i = 0; i < n; ++i)
459 {
460 val = SCM_VELTS (obj)[i];
461 if (!SCM_INUMP (val)
462 && !(SCM_NIMP (val) && (SCM_BIGP (val) || SCM_REALP (val))))
463 scm_wrong_type_arg (0, 0, val);
464 }
465 if (m == 0)
466 m = (double *) malloc (n * sizeof (double));
467 for (i = 0; i < n; ++i)
468 {
469 val = SCM_VELTS (obj)[i];
470 if (SCM_INUMP (val))
471 m[i] = SCM_INUM (val);
472 else if (SCM_BIGP (val))
473 m[i] = scm_num2long (val, 0, 0);
474 else
475 m[i] = SCM_REALPART (val);
476 }
477 break;
478#ifdef SCM_FLOATS
479#ifdef SCM_SINGLES
480 case scm_tc7_fvect:
481 n = SCM_LENGTH (obj);
482 if (m == 0)
483 m = (double *) malloc (n * sizeof (double));
484 for (i = 0; i < n; ++i)
485 m[i] = ((float *) SCM_VELTS (obj))[i];
486 break;
487#endif
488 case scm_tc7_dvect:
489 n = SCM_LENGTH (obj);
490 if (m == 0)
491 m = (double*) malloc (n * sizeof (double));
492 memcpy (m, SCM_VELTS (obj), n * sizeof (double));
f3a2c4cf
MD
493 break;
494#endif
495 default:
496 scm_wrong_type_arg (0, 0, obj);
497 }
498 return m;
499}
500
ee2a8b9b
JB
501/* string conversions between C and Scheme */
502
503/* gh_scm2newstr() -- Given a Scheme string STR, return a pointer to a
504 new copy of its contents, followed by a null byte. If lenp is
505 non-null, set *lenp to the string's length.
506
507 This function uses malloc to obtain storage for the copy; the
508 caller is responsible for freeing it.
509
510 Note that Scheme strings may contain arbitrary data, including null
511 characters. This means that null termination is not a reliable way
512 to determine the length of the returned value. However, the
513 function always copies the complete contents of STR, and sets
514 *LEN_P to the true length of the string (when LEN_P is non-null). */
515char *
516gh_scm2newstr (SCM str, int *lenp)
517{
518 char *ret_str;
519 int len;
520
66d1e129 521 SCM_ASSERT (SCM_NIMP (str) && SCM_ROSTRINGP (str), str, SCM_ARG3,
ee2a8b9b
JB
522 "gh_scm2newstr");
523
524 /* protect str from GC while we copy off its data */
525 scm_protect_object (str);
526
527 len = SCM_LENGTH (str);
528
9b1b00fe
JB
529 ret_str = (char *) scm_must_malloc ((len + 1) * sizeof (char),
530 "gh_scm2newstr");
ee2a8b9b 531 /* so we copy tmp_str to ret_str, which is what we will allocate */
66d1e129 532 memcpy (ret_str, SCM_ROCHARS (str), len); /* test ROCHARS here -twp */
ee2a8b9b
JB
533 /* now make sure we null-terminate it */
534 ret_str[len] = '\0';
535
536 scm_unprotect_object (str);
537
538 if (lenp != NULL)
539 {
540 *lenp = len;
541 }
542
543 return ret_str;
544}
545
546
547/* Copy LEN characters at START from the Scheme string SRC to memory
548 at DST. START is an index into SRC; zero means the beginning of
549 the string. DST has already been allocated by the caller.
550
551 If START + LEN is off the end of SRC, silently truncate the source
552 region to fit the string. If truncation occurs, the corresponding
553 area of DST is left unchanged. */
554void
555gh_get_substr (SCM src, char *dst, int start, int len)
556{
557 int src_len, effective_length;
66d1e129 558 SCM_ASSERT (SCM_NIMP (src) && SCM_ROSTRINGP (src), src, SCM_ARG3,
ee2a8b9b
JB
559 "gh_get_substr");
560
561 scm_protect_object (src);
562 src_len = SCM_LENGTH (src);
563 effective_length = (len < src_len) ? len : src_len;
66d1e129 564 memcpy (dst + start, SCM_ROCHARS (src), effective_length * sizeof (char));
ee2a8b9b
JB
565 /* FIXME: must signal an error if len > src_len */
566 scm_unprotect_object (src);
567}
568
569
570/* gh_scm2newsymbol() -- Given a Scheme symbol 'identifier, return a
571 pointer to a string with the symbol characters "identifier",
572 followed by a null byte. If lenp is non-null, set *lenp to the
573 string's length.
574
575 This function uses malloc to obtain storage for the copy; the
576 caller is responsible for freeing it. */
577char *
578gh_symbol2newstr (SCM sym, int *lenp)
579{
580 char *ret_str;
581 int len;
582
583 SCM_ASSERT (SCM_NIMP (sym) && SCM_SYMBOLP (sym), sym, SCM_ARG3,
584 "gh_scm2newsymbol");
585
586 /* protect str from GC while we copy off its data */
587 scm_protect_object (sym);
588
589 len = SCM_LENGTH (sym);
590
9b1b00fe
JB
591 ret_str = (char *) scm_must_malloc ((len + 1) * sizeof (char),
592 "gh_symbol2newstr");
ee2a8b9b
JB
593 /* so we copy tmp_str to ret_str, which is what we will allocate */
594 memcpy (ret_str, SCM_CHARS (sym), len);
595 /* now make sure we null-terminate it */
596 ret_str[len] = '\0';
597
598 scm_unprotect_object (sym);
599
600 if (lenp != NULL)
601 {
602 *lenp = len;
603 }
604
605 return ret_str;
606}
607
608
609/* create a new vector of the given length, all initialized to the
610 given value */
e5eece74
MG
611SCM
612gh_make_vector (SCM len, SCM fill)
ee2a8b9b 613{
a8741caa 614 return scm_make_vector (len, fill);
ee2a8b9b
JB
615}
616
617/* set the given element of the given vector to the given value */
618SCM
956328d2 619gh_vector_set_x (SCM vec, SCM pos, SCM val)
ee2a8b9b
JB
620{
621 return scm_vector_set_x (vec, pos, val);
622}
623
624/* retrieve the given element of the given vector */
625SCM
e5eece74 626gh_vector_ref (SCM vec, SCM pos)
ee2a8b9b
JB
627{
628 return scm_vector_ref (vec, pos);
629}
630
631/* returns the length of the given vector */
632unsigned long
633gh_vector_length (SCM v)
634{
635 return gh_scm2ulong (scm_vector_length (v));
636}
35379308 637
ef5d3ae1
MG
638
639/* uniform vector support */
640
641/* returns the length as a C unsigned long integer */
642unsigned long
643gh_uniform_vector_length (SCM v)
644{
645 return gh_scm2ulong (scm_uniform_vector_length (v));
646}
647
648/* gets the given element from a uniform vector; ilist is a list (or
649 possibly a single integer) of indices, and its length is the
650 dimension of the uniform vector */
651SCM
652gh_uniform_vector_ref (SCM v, SCM ilist)
653{
654 return scm_uniform_vector_ref (v, ilist);
655}
656
657/* sets an individual element in a uniform vector */
658/* SCM */
659/* gh_list_to_uniform_array ( */
660
661
35379308
JB
662/* Data lookups between C and Scheme
663
664 Look up a symbol with a given name, and return the object to which
665 it is bound. gh_lookup examines the Guile top level, and
666 gh_module_lookup checks the module namespace specified by the
667 `vec' argument.
668
669 The return value is the Scheme object to which SNAME is bound, or
670 SCM_UNDEFINED if SNAME is not bound in the given context. [FIXME:
671 should this be SCM_UNSPECIFIED? Can a symbol ever legitimately be
672 bound to SCM_UNDEFINED or SCM_UNSPECIFIED? What is the difference?
673 -twp] */
674
675SCM
676gh_lookup (char *sname)
677{
678 return gh_module_lookup (SCM_BOOL_F, sname);
679}
680
681SCM
682gh_module_lookup (SCM vec, char *sname)
683{
684 SCM sym = gh_symbol2scm (sname);
685 if ((scm_symbol_bound_p (vec, sym)) == SCM_BOOL_T)
686 return scm_symbol_binding (vec, sym);
687 else
688 return SCM_UNDEFINED;
689}