Revert bs-a and bs-b patch.
[mpsl.git] / mpsl_f.c
blobb198ca2427955d6e5eaf9e311f079efc0e522a63
1 /*
3 MPSL - Minimum Profit Scripting Language
4 Copyright (C) 2003/2012 Angel Ortega <angel@triptico.com>
6 mpsl_f.c - Minimum Profit Scripting Language Function Library
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
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.
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
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
26 #include "config.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <wchar.h>
32 #include <time.h>
34 #include "mpdm.h"
35 #include "mpsl.h"
37 /** code **/
39 #define F_ARGS mpdm_t a, mpdm_t l
41 #define A(n) mpdm_aget(a, n)
42 #define A0 A(0)
43 #define A1 A(1)
44 #define A2 A(2)
45 #define IA(n) mpdm_ival(A(n))
46 #define IA0 IA(0)
47 #define IA1 IA(1)
48 #define IA2 IA(2)
49 #define IA3 IA(3)
50 #define RA(n) mpdm_rval(A(n))
51 #define RA0 RA(0)
52 #define RA1 RA(1)
53 #define RA2 RA(2)
54 #define RA3 RA(3)
56 /**
57 * size - Returns the size of a value.
58 * @v: the value
60 * Returns the size of a value. For scalars, the size is the
61 * string length; for arrays, the number of elements, and
62 * for hashes, the number of buckets in the hash (which is
63 * probably not useful, see hsize() instead).
64 * [Value Management]
66 /** integer = size(v); */
67 /* ; */
68 static mpdm_t F_size(F_ARGS)
70 return MPDM_I(mpdm_size(A0));
73 /**
74 * clone - Creates a clone of a value.
75 * @v: the value
77 * Creates a clone of a value. If the value is multiple, a new value will
78 * be created containing clones of all its elements; otherwise,
79 * the same unchanged value is returned.
80 * [Value Management]
82 /** v2 = clone(v); */
83 static mpdm_t F_clone(F_ARGS)
85 return mpdm_clone(A0);
88 /**
89 * dump - Dumps a value to stdin.
90 * @v: The value
92 * Dumps a value to stdin. The value can be complex. This function
93 * is for debugging purposes only.
94 * [Debugging]
95 * [Input-Output]
97 /** dump(v); */
98 static mpdm_t F_dump(F_ARGS)
100 mpdm_dump(A0);
101 return NULL;
105 * dumper - Returns a visual representation of a complex value.
106 * @v: The value
108 * Returns a visual representation of a complex value.
109 * [Debugging]
110 * [Strings]
112 /** string = dumper(v); */
113 static mpdm_t F_dumper(F_ARGS)
115 return mpdm_dumper(A0);
119 * cmp - Compares two values.
120 * @v1: the first value
121 * @v2: the second value
123 * Compares two values. If both are strings, a standard string
124 * comparison (using wcscmp()) is returned; if both are arrays,
125 * the size is compared first and, if they have the same number
126 * elements, each one is compared; otherwise, a simple pointer
127 * comparison is done.
129 * In either case, an integer is returned, which is < 0 if @v1
130 * is lesser than @v2, > 0 on the contrary or 0 if both are
131 * equal.
132 * [Strings]
133 * [Arrays]
135 /** integer = cmp(v); */
136 static mpdm_t F_cmp(F_ARGS)
138 return MPDM_I(mpdm_cmp(A0, A1));
142 * is_array - Tests if a value is an array.
143 * @v: the value
145 * Returns non-zero if @v is an array.
146 * [Value Management]
147 * [Arrays]
149 /** bool = is_array(v); */
150 static mpdm_t F_is_array(F_ARGS)
152 return mpsl_boolean(MPDM_IS_ARRAY(A0));
156 * is_hash - Tests if a value is a hash.
157 * @v: the value
159 * Returns non-zero if @v is a hash.
160 * [Value Management]
161 * [Hashes]
163 /** bool = is_hash(v); */
164 static mpdm_t F_is_hash(F_ARGS)
166 return mpsl_boolean(MPDM_IS_HASH(A0));
170 * is_exec - Tests if a value is executable.
171 * @v: the value
173 * Returns non-zero if @v is a executable.
174 * [Value Management]
176 /** bool = is_exec(v); */
177 static mpdm_t F_is_exec(F_ARGS)
179 return mpsl_boolean(MPDM_IS_EXEC(A0));
183 * splice - Creates a new string value from another.
184 * @v: the original value
185 * @i: the value to be inserted
186 * @offset: offset where the substring is to be inserted
187 * @del: number of characters to delete
189 * Creates a new string value from @v, deleting @del chars at @offset
190 * and substituting them by @i. If @del is 0, no deletion is done.
191 * both @offset and @del can be negative; if this is the case, it's
192 * assumed as counting from the end of @v. If @v is NULL, @i will become
193 * the new string, and both @offset and @del will be ignored. If @v is
194 * not NULL and @i is, no insertion process is done (only deletion, if
195 * applicable).
197 * Returns a two element array, with the new string in the first
198 * element and the deleted string in the second (with a NULL value
199 * if @del is 0).
200 * [Strings]
202 /** array = splice(v, i, offset, del); */
203 static mpdm_t F_splice(F_ARGS)
205 return mpdm_splice(A0, A1, IA2, IA3);
209 * expand - Expands an array.
210 * @a: the array
211 * @offset: insertion offset
212 * @num: number of elements to insert
214 * Expands an array value, inserting @num elements (initialized
215 * to NULL) at the specified @offset.
216 * [Arrays]
218 /** expand(a, offset, num); */
219 static mpdm_t F_expand(F_ARGS)
221 return mpdm_expand(A0, IA1, IA2);
225 * collapse - Collapses an array.
226 * @a: the array
227 * @offset: deletion offset
228 * @num: number of elements to collapse
230 * Collapses an array value, deleting @num elements at
231 * the specified @offset.
232 * [Arrays]
234 /** collapse(a, offset, num); */
235 static mpdm_t F_collapse(F_ARGS)
237 return mpdm_collapse(A0, IA1, IA2);
241 * ins - Insert an element in an array.
242 * @a: the array
243 * @e: the element to be inserted
244 * @offset: subscript where the element is going to be inserted
246 * Inserts the @e value in the @a array at @offset.
247 * Further elements are pushed up, so the array increases its size
248 * by one. Returns the inserted element.
249 * [Arrays]
251 /** e = ins(a, e, offset); */
252 static mpdm_t F_ins(F_ARGS)
254 return mpdm_ins(A0, A1, IA2);
258 * adel - Deletes an element of an array.
259 * @a: the array
260 * @offset: subscript of the element to be deleted
262 * Deletes the element at @offset of the @a array. The array
263 * is shrinked by one. If @offset is negative, is counted from
264 * the end of the array (so a value of -1 means delete the
265 * last element of the array).
267 * Returns NULL (previous versions returned the deleted element).
268 * [Arrays]
270 /** v = adel(a, offset); */
271 static mpdm_t F_adel(F_ARGS)
273 return mpdm_adel(A0, IA1);
277 * shift - Extracts the first element of an array.
278 * @a: the array
280 * Extracts the first element of the array. The array
281 * is shrinked by one.
283 * Returns the deleted element.
284 * [Arrays]
286 /** v = shift(a); */
287 static mpdm_t F_shift(F_ARGS)
289 return mpdm_shift(A0);
293 * push - Pushes a value into an array.
294 * @a: the array
295 * @arg1: first value
296 * @arg2: second value
297 * @argn: nth value
299 * Pushes values into an array (i.e. inserts at the end).
300 * Returns the last element pushed.
301 * [Arrays]
303 /** argn = push(a, arg1 [, arg2, ... argn]); */
304 static mpdm_t F_push(F_ARGS)
306 int n;
307 mpdm_t r = NULL;
309 for (n = 1; n < mpdm_size(a); n++) {
310 mpdm_unref(r);
311 r = mpdm_push(A0, A(n));
312 mpdm_ref(r);
315 return mpdm_unrefnd(r);
319 * pop - Pops a value from an array.
320 * @a: the array
322 * Pops a value from the array (i.e. deletes from the end
323 * and returns it).
324 * [Arrays]
326 /** v = pop(a); */
327 static mpdm_t F_pop(F_ARGS)
329 return mpdm_pop(A0);
333 * queue - Implements a queue in an array.
334 * @a: the array
335 * @e: the element to be pushed
336 * @size: maximum size of array
338 * Pushes the @e element into the @a array. If the array already has
339 * @size elements, the first (oldest) element is deleted from the
340 * queue and returned.
342 * Returns the deleted element, or NULL if the array doesn't have
343 * @size elements yet.
344 * [Arrays]
346 /** v = queue(a, e, size); */
347 static mpdm_t F_queue(F_ARGS)
349 return mpdm_queue(A0, A1, IA2);
353 * seek - Seeks a value in an array (sequential).
354 * @a: the array
355 * @k: the key
356 * @step: number of elements to step
358 * Seeks sequentially the value @k in the @a array in
359 * increments of @step. A complete search should use a step of 1.
360 * Returns the offset of the element if found, or -1 otherwise.
361 * [Arrays]
363 /** integer = seek(a, k, step); */
364 static mpdm_t F_seek(F_ARGS)
366 return MPDM_I(mpdm_seek(A0, A1, IA2));
370 * sort - Sorts an array.
371 * @a: the array
372 * @sorting_func: sorting function
374 * Sorts the array. For each pair of elements being sorted, the
375 * @sorting_func is called with the two elements to be sorted as
376 * arguments. This function must return a signed integer value indicating
377 * the sorting order.
379 * If no function is supplied, the sorting is done using cmp().
381 * Returns the sorted array (the original one is left untouched).
382 * [Arrays]
384 /** array = sort(a); */
385 /** array = sort(a, sorting_func); */
386 static mpdm_t F_sort(F_ARGS)
388 mpdm_t r, v;
390 v = mpdm_ref(A0);
391 r = mpdm_sort_cb(mpdm_clone(v), 1, A1);
392 mpdm_unref(v);
394 return r;
398 * split - Separates a string into an array of pieces.
399 * @v: the value to be separated
400 * @s: the separator
402 * Separates the @v string value into an array of pieces, using @s
403 * as a separator.
405 * If the separator is NULL, the string is splitted by characters.
407 * If the string does not contain the separator, an array holding
408 * the complete string as its unique argument is returned.
409 * [Arrays]
410 * [Strings]
412 /** array = split(v, s); */
413 static mpdm_t F_split(F_ARGS)
415 return mpdm_split(A0, A1);
419 * join - Joins all elements of an array into one.
420 * @a: array to be joined
421 * @s: joiner string
423 * Joins all elements from @a into one string, using @s as a glue.
424 * [Arrays]
425 * [Strings]
427 /** string = join(a, s); */
428 static mpdm_t F_join(F_ARGS)
430 return mpdm_join(A0, A1);
434 * hsize - Returns the number of pairs of a hash.
435 * @h: the hash
437 * Returns the number of key-value pairs of a hash.
438 * [Hashes]
440 /** integer = hsize(h); */
441 static mpdm_t F_hsize(F_ARGS)
443 return MPDM_I(mpdm_hsize(A0));
447 * exists - Tests if a key exists.
448 * @h: the hash
449 * @k: the key
451 * Returns 1 if @k is defined in @h, or 0 othersize.
452 * [Hashes]
454 /** bool = exists(h, k); */
455 static mpdm_t F_exists(F_ARGS)
457 return mpsl_boolean(mpdm_exists(A0, A1));
461 * hdel - Deletes a key from a hash.
462 * @h: the hash
463 * @k: the key
465 * Deletes the key @k from the hash @h. Returns the previous
466 * value, or NULL if the key was not defined.
467 * [Hashes]
469 /** v = hdel(h, k); */
470 static mpdm_t F_hdel(F_ARGS)
472 return mpdm_hdel(A0, A1);
476 * keys - Returns the keys of a hash.
477 * @h: the hash
479 * Returns an array containing all the keys of the @h hash.
480 * [Hashes]
481 * [Arrays]
483 /** array = keys(h); */
484 static mpdm_t F_keys(F_ARGS)
486 return mpdm_keys(A0);
490 * open - Opens a file.
491 * @filename: the file name
492 * @mode: an fopen-like mode string
494 * Opens a file. If @filename can be open in the specified @mode, a
495 * value will be returned containing the file descriptor, or NULL
496 * otherwise.
498 * If the file is open for reading, some charset detection methods are
499 * used. If any of them is successful, its name is stored in the
500 * `DETECTED_ENCODING' global variable. This value is
501 * suitable to be copied over `ENCODING' or `TEMP_ENCODING'.
503 * If the file is open for writing, the encoding to be used is read from
504 * the `ENCODING' global variable and, if not set, from the
505 * `TEMP_ENCODING' one. The latter will always be deleted afterwards.
506 * [Input-Output]
507 * [Character Set Conversion]
509 /** fd = open(filename, mode); */
510 static mpdm_t F_open(F_ARGS)
512 return mpdm_open(A0, A1);
516 * close - Closes a file descriptor.
517 * @fd: the file descriptor
519 * Closes the file descriptor.
520 * [Input-Output]
522 /** close(fd); */
523 static mpdm_t F_close(F_ARGS)
525 return mpdm_close(A0);
529 * read - Reads a line from a file descriptor.
530 * @fd: the file descriptor
532 * Reads a line from @fd. Returns the line, or NULL on EOF.
533 * [Input-Output]
534 * [Character Set Conversion]
536 /** string = read(fd); */
537 static mpdm_t F_read(F_ARGS)
539 return mpdm_read(A0);
543 * getchar - Reads a character from a file descriptor.
544 * @fd: the file descriptor
546 * Returns a character read from @fd, or NULL on EOF. No
547 * charset conversion is done.
548 * [Input-Output]
550 /** string = getchar(fd); */
551 static mpdm_t F_getchar(F_ARGS)
553 return mpdm_getchar(A0);
557 * putchar - Writes a character to a file descriptor.
558 * @fd: the file descriptor
559 * @s: the string
561 * Writes the first character in @s into @fd. No charset
562 * conversion is done.
564 * Returns the number of chars written (0 or 1).
565 * [Input-Output]
567 /** s = putchar(fd, s); */
568 static mpdm_t F_putchar(F_ARGS)
570 return MPDM_I(mpdm_putchar(A0, A1));
574 * fseek - Sets a file pointer.
575 * @fd: the file descriptor
576 * @offset: the offset
577 * @whence: the position
579 * Sets the file pointer position of @fd to @offset. @whence can
580 * be: 0 for SEEK_SET, 1 for SEEK_CUR and 2 for SEEK_END.
582 * Returns the value from the fseek() C function call.
583 * [Input-Output]
585 /** integer = fseek(fd, offset, whence); */
586 static mpdm_t F_fseek(F_ARGS)
588 return MPDM_I(mpdm_fseek(A0, IA1, IA2));
592 * ftell - Returns the current file pointer.
593 * @fd: the file descriptor
595 * Returns the position of the file pointer in @fd.
596 * [Input-Output]
598 /** integer = ftell(fd); */
599 static mpdm_t F_ftell(F_ARGS)
601 return MPDM_I(mpdm_ftell(A0));
605 * unlink - Deletes a file.
606 * @filename: file name to be deleted
608 * Deletes a file.
609 * [Input-Output]
611 /** bool = unlink(filename); */
612 static mpdm_t F_unlink(F_ARGS)
614 return mpsl_boolean(mpdm_unlink(A0));
618 * stat - Gives status from a file.
619 * @filename: file name to get the status from
621 * Returns a 14 element array of the status (permissions, onwer, etc.)
622 * from the desired @filename, or NULL if the file cannot be accessed.
623 * (man 2 stat).
625 * The values are: 0, device number of filesystem; 1, inode number;
626 * 2, file mode; 3, number of hard links to the file; 4, uid; 5, gid;
627 * 6, device identifier; 7, total size of file in bytes; 8, atime;
628 * 9, mtime; 10, ctime; 11, preferred block size for system I/O;
629 * 12, number of blocks allocated and 13, canonicalized file name.
630 * Not all elements have necesarily meaningful values, as most are
631 * system-dependent.
632 * [Input-Output]
634 /** array = stat(filename); */
635 static mpdm_t F_stat(F_ARGS)
637 return mpdm_stat(A0);
641 * chmod - Changes a file's permissions.
642 * @filename: the file name
643 * @perms: permissions (element 2 from stat())
645 * Changes the permissions for a file.
646 * [Input-Output]
648 /** integer = chmod(filename, perms); */
649 static mpdm_t F_chmod(F_ARGS)
651 return MPDM_I(mpdm_chmod(A0, A1));
655 * chown - Changes a file's owner.
656 * @filename: the file name
657 * @uid: user id (element 4 from stat())
658 * @gid: group id (element 5 from stat())
660 * Changes the owner and group id's for a file.
661 * [Input-Output]
663 /** integer = chown(filename, uid, gid); */
664 static mpdm_t F_chown(F_ARGS)
666 return MPDM_I(mpdm_chown(A0, A1, A2));
670 * glob - Executes a file globbing.
671 * @spec: Globbing spec
672 * @base: Optional base directory
674 * Executes a file globbing. @spec is system-dependent, but usually
675 * the * and ? metacharacters work everywhere. @base can contain a
676 * directory; if that's the case, the output strings will include it.
677 * In any case, each returned value will be suitable for a call to
678 * open().
680 * Returns an array of files that match the globbing (can be an empty
681 * array if no file matches), or NULL if globbing is unsupported.
682 * Directories are returned first and their names end with a slash.
683 * [Input-Output]
685 /** array = glob(spec, base); */
686 static mpdm_t F_glob(F_ARGS)
688 return mpdm_glob(A0, A1);
692 * encoding - Sets the current charset encoding for files.
693 * @charset: the charset name.
695 * Sets the current charset encoding for files. Future opened
696 * files will be assumed to be encoded with @charset, which can
697 * be any of the supported charset names (utf-8, iso-8859-1, etc.),
698 * and converted on each read / write. If charset is NULL, it
699 * is reverted to default charset conversion (i.e. the one defined
700 * in the locale).
702 * This function stores the @charset value into the `ENCODING' global
703 * variable.
705 * Returns a negative number if @charset is unsupported, or zero
706 * if no errors were found.
707 * [Input-Output]
708 * [Character Set Conversion]
710 /** integer = encoding(charset); */
711 static mpdm_t F_encoding(F_ARGS)
713 return MPDM_I(mpdm_encoding(A0));
717 * popen - Opens a pipe.
718 * @prg: the program to pipe
719 * @mode: an fopen-like mode string
721 * Opens a pipe to a program. If @prg can be open in the specified @mode,
722 * return file descriptor, or NULL otherwise.
724 * The @mode can be `r' (for reading), `w' (for writing), or `r+' or `w+'
725 * for a special double pipe reading-writing mode.
726 * [Input-Output]
728 /** fd = popen(prg, mode); */
729 static mpdm_t F_popen(F_ARGS)
731 return mpdm_popen(A0, A1);
735 * popen2 - Opens a pipe and returns an array of two pipes.
736 * @prg: the program to pipe
738 * Opens a read-write pipe and returns an array of two descriptors,
739 * one for reading and one for writing. If @prg could not be piped to,
740 * returns NULL.
741 * [Input-Output]
743 /** array = popen2(prg); */
744 static mpdm_t F_popen2(F_ARGS)
746 return mpdm_popen2(A0);
750 * pclose - Closes a pipe.
751 * @fd: the value containing the file descriptor
753 * Closes a pipe.
754 * [Input-Output]
756 /** pclose(fd); */
757 static mpdm_t F_pclose(F_ARGS)
759 return mpdm_pclose(A0);
763 * regex - Matches a regular expression.
764 * @v: the value to be matched
765 * @r: the regular expression
766 * @ra: an array of regular expressions
767 * @offset: offset from the start of the value
769 * Matches a regular expression against a value. Valid flags are `i',
770 * for case-insensitive matching, `m', to treat the string as a
771 * multiline string (i.e., one containing newline characters), so
772 * that ^ and $ match the boundaries of each line instead of the
773 * whole string, `l', to return the last matching instead of the
774 * first one, or `g', to match globally; in that last case, an array
775 * containing all matches is returned instead of a string scalar.
777 * If @r is a string, an ordinary regular expression matching is tried
778 * over the @v string. If the matching is possible, the match result
779 * is returned, or NULL otherwise.
781 * If @r is an array (of strings), each element is tried sequentially
782 * as an individual regular expression over the @v string, each one using
783 * the offset returned by the previous match. All regular expressions
784 * must match to be successful. If this is the case, an array (with
785 * the same number of arguments) is returned containing the matched
786 * strings, or NULL otherwise.
788 * If @r is NULL, the result of the previous regex matching
789 * is returned as a two element array. The first element will contain
790 * the character offset of the matching and the second the number of
791 * characters matched. If the previous regex was unsuccessful, NULL
792 * is returned.
793 * [Regular Expressions]
795 /** string = regex(v, r); */
796 /** string = regex(v, r, offset); */
797 /** array = regex(v, ra); */
798 /** array = regex(); */
799 static mpdm_t F_regex(F_ARGS)
801 return mpdm_regex(A0, A1, IA2);
805 * sregex - Matches and substitutes a regular expression.
806 * @v: the value to be matched
807 * @r: the regular expression
808 * @s: the substitution string, hash or code
809 * @offset: offset from the start of v
811 * Matches a regular expression against a value, and substitutes the
812 * found substring with @s. Valid flags are `i', for case-insensitive
813 * matching, and `g', for global replacements (all ocurrences in @v
814 * will be replaced, instead of just the first found one).
816 * If @s is executable, it's executed with the matched part as
817 * the only argument and its return value is used as the
818 * substitution string.
820 * If @s is a hash, the matched string is used as a key to it and
821 * its value used as the substitution. If this value itself is
822 * executable, it's executed with the matched string as its only
823 * argument and its return value used as the substitution.
825 * If @r is NULL, returns the number of substitutions made in the
826 * previous call to sregex() (can be zero if none was done).
828 * Returns the modified string, or the original one if no substitutions
829 * were done.
830 * [Regular Expressions]
832 /** string = sregex(v, r, s); */
833 /** string = sregex(v, r, s, offset); */
834 /** integer = sregex(); */
835 static mpdm_t F_sregex(F_ARGS)
837 return mpdm_sregex(A0, A1, A2, IA3);
841 * gettext - Translates a string to the current language.
842 * @str: the string
844 * Translates the @str string to the current language.
846 * This function can still be used even if there is no real gettext
847 * support by manually filling the __I18N__ hash.
849 * If the string is found in the current table, the translation is
850 * returned; otherwise, the same @str value is returned.
851 * [Strings]
852 * [Localization]
854 /** string = gettext(str); */
855 static mpdm_t F_gettext(F_ARGS)
857 return mpdm_gettext(A0);
861 * gettext_domain - Sets domain and data directory for translations.
862 * @dom: the domain (application name)
863 * @data: directory contaning the .mo files
865 * Sets the domain (application name) and translation data for translating
866 * strings that will be returned by gettext(). @data must point to a
867 * directory containing the .mo (compiled .po) files.
869 * If there is no gettext support, returns 0, or 1 otherwise.
870 * [Strings]
871 * [Localization]
873 /** bool = gettext_domain(dom, data); */
874 static mpdm_t F_gettext_domain(F_ARGS)
876 return MPDM_I(mpdm_gettext_domain(A0, A1));
880 * load - Loads an MPSL source code file.
881 * @source_file: the source code file
883 * Loads and executes an MPSL source code file and returns
884 * its value.
885 * [Code Control]
887 /** load(source_file); */
888 static mpdm_t F_load(F_ARGS)
890 return mpdm_exec(mpsl_compile_file(A0,
891 mpsl_get_symbol(MPDM_LS(L"INC"),
892 l)), NULL, l);
896 * compile - Compiles a string of MSPL source code file.
897 * @source: the source code string
899 * Compiles a string of MPSL source code and returns an
900 * executable value.
901 * [Code Control]
903 /** func = compile(source); */
904 static mpdm_t F_compile(F_ARGS)
906 return mpsl_compile(A0);
910 * error - Simulates an error.
911 * @err: the error message
913 * Simulates an error. The @err error message is stored in the `ERROR'
914 * global variable and an internal abort global flag is set, so no further
915 * MPSL code can be executed until reset.
916 * [Code Control]
918 /** error(err); */
919 static mpdm_t F_error(F_ARGS)
921 return mpsl_error(A0);
925 * uc - Converts a string to uppercase.
926 * @str: the string to be converted
928 * Returns @str converted to uppercase.
929 * [Strings]
931 /** string = uc(str); */
932 static mpdm_t F_uc(F_ARGS)
934 return mpdm_ulc(A0, 1);
938 * lc - Converts a string to lowercase.
939 * @str: the string to be converted
941 * Returns @str converted to lowercase.
942 * [Strings]
944 /** string = uc(str); */
945 static mpdm_t F_lc(F_ARGS)
947 return mpdm_ulc(A0, 0);
951 * time - Returns the current time.
953 * Returns the current time from the epoch (C library time()).
954 * [Miscellaneous]
956 /** integer = time(); */
957 static mpdm_t F_time(F_ARGS)
959 return MPDM_I(time(NULL));
963 * chdir - Changes the working directory
964 * @dir: the new path
966 * Changes the working directory
967 * [Input-Output]
969 /** integer = chdir(dir); */
970 static mpdm_t F_chdir(F_ARGS)
972 return MPDM_I(mpdm_chdir(A0));
976 * sscanf - Extracts data like sscanf().
977 * @str: the string to be parsed
978 * @fmt: the string format
979 * @offset: the character offset to start scanning
981 * Extracts data from a string using a special format pattern, very
982 * much like the scanf() series of functions in the C library. Apart
983 * from the standard percent-sign-commands (s, u, d, i, f, x,
984 * n, [, with optional size and * to ignore), it implements S,
985 * to match a string of characters upto what follows in the format
986 * string. Also, the [ set of characters can include other % formats.
988 * Returns an array with the extracted values. If %n is used, the
989 * position in the scanned string is returned as the value.
990 * [Strings]
992 /** array = sscanf(str, fmt); */
993 /** array = sscanf(str, fmt, offset); */
994 static mpdm_t F_sscanf(F_ARGS)
996 return mpdm_sscanf(A0, A1, IA2);
1000 * eval - Evaluates MSPL code.
1001 * @code: A value containing a string of MPSL code, or executable code
1002 * @args: optional arguments for @code
1004 * Evaluates a piece of code. The @code can be a string containing MPSL
1005 * source code (that will be compiled) or a direct executable value. If
1006 * the compilation or the execution gives an error, the `ERROR' variable
1007 * will be set to a printable value and NULL returned. Otherwise, the
1008 * exit value from the code is returned and `ERROR' set to NULL. The
1009 * internal abort flag is reset on exit.
1011 * [Code Control]
1013 /** v = eval(code, args); */
1014 static mpdm_t F_eval(F_ARGS)
1016 mpdm_t r, c;
1018 a = mpdm_ref(mpdm_clone(a));
1019 c = mpdm_shift(a);
1021 r = mpsl_eval(c, a, l);
1023 mpdm_unref(a);
1025 return r;
1030 * sprintf - Formats a sprintf()-like string.
1031 * @fmt: the string format
1032 * @arg1: first argument
1033 * @arg2: second argument
1034 * @argn: nth argument
1036 * Formats a string using the sprintf() format taking the values from
1037 * the variable arguments.
1038 * [Strings]
1040 /** string = sprintf(fmt, arg1 [,arg2 ... argn]); */
1041 static mpdm_t F_sprintf(F_ARGS)
1043 mpdm_t f, v, r;
1045 a = mpdm_ref(mpdm_clone(a));
1046 f = mpdm_shift(a);
1048 /* if the first argument is an array, take it as the arguments */
1049 if ((v = mpdm_aget(a, 0)) != NULL && MPDM_IS_ARRAY(v))
1050 a = v;
1052 r = mpdm_sprintf(f, a);
1054 mpdm_unref(a);
1056 return r;
1061 * print - Writes values to stdout.
1062 * @arg1: first argument
1063 * @arg2: second argument
1064 * @argn: nth argument
1066 * Writes the variable arguments to stdout.
1067 * [Input-Output]
1069 /** print(arg1 [,arg2 ... argn]); */
1070 static mpdm_t F_print(F_ARGS)
1072 int n;
1074 for (n = 0; n < mpdm_size(a); n++)
1075 mpdm_write_wcs(stdout, mpdm_string(A(n)));
1076 return NULL;
1081 * write - Writes values to a file descriptor.
1082 * @fd: the file descriptor
1083 * @arg1: first argument
1084 * @arg2: second argument
1085 * @argn: nth argument
1087 * Writes the variable arguments to the file descriptor, doing
1088 * charset conversion in the process.
1090 * Returns the total size written to @fd.
1091 * [Input-Output]
1092 * [Character Set Conversion]
1094 /** integer = write(fd, arg1 [,arg2 ... argn]); */
1095 static mpdm_t F_write(F_ARGS)
1097 int n, r = 0;
1099 for (n = 1; n < mpdm_size(a); n++)
1100 r += mpdm_write(A0, A(n));
1102 return MPDM_I(r);
1107 * chr - Returns the Unicode character represented by the codepoint.
1108 * @c: the codepoint as an integer value
1110 * Returns a 1 character string containing the character which
1111 * Unicode codepoint is @c.
1112 * [Strings]
1114 /** string = chr(c); */
1115 static mpdm_t F_chr(F_ARGS)
1117 wchar_t tmp[2];
1119 tmp[0] = (wchar_t) mpdm_ival(mpdm_aget(a, 0));
1120 tmp[1] = L'\0';
1122 return MPDM_S(tmp);
1127 * ord - Returns the Unicode codepoint of a character.
1128 * @str: the string
1130 * Returns the Unicode codepoint for the first character in
1131 * the string.
1132 * [Strings]
1134 /** integer = ord(str); */
1135 static mpdm_t F_ord(F_ARGS)
1137 int ret = 0;
1138 mpdm_t v = mpdm_aget(a, 0);
1140 if (v != NULL) {
1141 wchar_t *ptr = mpdm_string(v);
1142 ret = (int) *ptr;
1145 return MPDM_I(ret);
1150 * map - Maps an array into another.
1151 * @a: the array
1152 * @filter: the filter
1154 * Returns a new array built by applying the @filter to all the
1155 * elements of the array @a. The filter can be an executable function
1156 * accepting one argument, in which case the return value of the function
1157 * will be used as the output element; @filt can also be a hash, in which
1158 * case the original element will be used as a key to the hash and the
1159 * associated value used as the output element.
1161 * [Arrays]
1163 /** array = map(a, filter); */
1164 static mpdm_t F_map(F_ARGS)
1166 mpdm_t set = mpdm_aget(a, 0);
1167 mpdm_t key = mpdm_aget(a, 1);
1168 mpdm_t out;
1170 /* map NULL to NULL */
1171 if (set == NULL)
1172 return NULL;
1174 out = mpdm_ref(MPDM_A(mpdm_size(set)));
1176 if (MPDM_IS_EXEC(key)) {
1177 int n;
1179 /* executes the code using the element as argument
1180 and stores the result in the output array */
1181 for (n = 0; n < mpdm_size(set); n++)
1182 mpdm_aset(out, mpdm_exec_1(key, mpdm_aget(set, n), l), n);
1184 else if (MPDM_IS_HASH(key)) {
1185 int n;
1187 /* maps each value using the element as key */
1188 for (n = 0; n < mpdm_size(set); n++)
1189 mpdm_aset(out, mpdm_hget(key, mpdm_aget(set, n)), n);
1192 return mpdm_unrefnd(out);
1197 * grep - Greps inside an array.
1198 * @a: the array
1199 * @filter: the filter
1201 * Greps inside an array and returns another one containing only the
1202 * elements that passed the filter. If @filter is a string, it's accepted
1203 * as a regular expression, which will be applied to each element.
1204 * If @filter is executable, it will be called with the element as its
1205 * only argument and its return value used as validation.
1207 * The new array will contain all elements that passed the filter.
1208 * [Arrays]
1209 * [Regular Expressions]
1211 /** array = grep(filter, a); */
1212 static mpdm_t F_grep(F_ARGS)
1214 mpdm_t set = mpdm_aget(a, 0);
1215 mpdm_t key = mpdm_aget(a, 1);
1216 mpdm_t out = mpdm_ref(MPDM_A(0));
1218 if (MPDM_IS_EXEC(key)) {
1219 int n;
1221 /* it's executable */
1222 for (n = 0; n < mpdm_size(set); n++) {
1223 mpdm_t v = mpdm_aget(set, n);
1224 mpdm_t w = mpdm_ref(mpdm_exec_1(key, v, l));
1226 if (mpsl_is_true(w))
1227 mpdm_push(out, v);
1229 mpdm_unref(w);
1232 else if (MPDM_IS_STRING(key)) {
1233 int n;
1235 /* it's a string; use it as a regular expression */
1236 for (n = 0; n < mpdm_size(set); n++) {
1237 mpdm_t v = mpdm_aget(set, n);
1238 mpdm_t w = mpdm_ref(mpdm_regex(v, key, 0));
1240 if (w)
1241 mpdm_push(out, v);
1243 mpdm_unref(w);
1247 return mpdm_size(mpdm_unrefnd(out)) == 0 ? NULL : out;
1250 static mpdm_t F_getenv(F_ARGS)
1252 mpdm_t e = mpdm_hget_s(mpdm_root(), L"ENV");
1254 return mpdm_hget(e, mpdm_aget(a, 0));
1257 static mpdm_t F_bincall(F_ARGS)
1259 return MPDM_X(mpdm_ival(mpdm_aget(a, 0)));
1263 * random - Returns a random value.
1265 * Returns a random number from 0 to value - 1.
1266 * [Miscellaneous]
1268 /** integer = random(value); */
1269 static mpdm_t F_random(F_ARGS)
1271 static unsigned int seed = 0;
1272 int r = 0;
1273 int range = mpdm_ival(mpdm_aget(a, 0));
1275 if (range == 0 || seed == 0)
1276 seed = time(NULL);
1277 else {
1278 seed = (seed * 58321) + 11113;
1279 r = (seed >> 16) % range;
1282 return MPDM_I(r);
1287 * sleep - Sleeps a number of milliseconds.
1289 * Sleeps a number of milliseconds.
1290 * [Threading]
1292 /** sleep(msecs); */
1293 static mpdm_t F_sleep(F_ARGS)
1295 mpdm_sleep(mpdm_ival(mpdm_aget(a, 0)));
1297 return NULL;
1302 * mutex - Returns a new mutex.
1304 * Returns a new mutex.
1305 * [Threading]
1307 /** var = mutex(); */
1308 static mpdm_t F_mutex(F_ARGS)
1310 return mpdm_new_mutex();
1315 * mutex_lock - Locks a mutex (possibly waiting).
1316 * @mtx: the mutex
1318 * Locks a mutex. If the mutex is already locked by
1319 * another process, it waits until it's unlocked.
1320 * [Threading]
1322 /** mutex_lock(mtx); */
1323 static mpdm_t F_mutex_lock(F_ARGS)
1325 mpdm_mutex_lock(A0);
1326 return NULL;
1331 * mutex_unlock - Unlocks a mutex.
1332 * @mtx: the mutex
1334 * Unlocks a mutex.
1335 * [Threading]
1337 /** mutex_unlock(mtx); */
1338 static mpdm_t F_mutex_unlock(F_ARGS)
1340 mpdm_mutex_unlock(A0);
1341 return NULL;
1346 * semaphore - Returns a new semaphore.
1347 * cnt: the initial count of the semaphore.
1349 * Returns a new semaphore.
1350 * [Threading]
1352 /** var = semaphore(cnt); */
1353 static mpdm_t F_semaphore(F_ARGS)
1355 return mpdm_new_semaphore(IA0);
1360 * semaphore_wait - Waits for a semaphore to be ready.
1361 * @sem: the semaphore to wait onto
1363 * Waits for the value of a semaphore to be > 0. If it's
1364 * not, the thread waits until it is.
1365 * [Threading]
1367 /** semaphore_wait(sem); */
1368 static mpdm_t F_semaphore_wait(F_ARGS)
1370 mpdm_semaphore_wait(A0);
1371 return NULL;
1376 * semaphore_post - Increments the value of a semaphore.
1377 * @sem: the semaphore to increment
1379 * Increments by 1 the value of a semaphore.
1380 * [Threading]
1382 /** semaphore_post(mtx); */
1383 static mpdm_t F_semaphore_post(F_ARGS)
1385 mpdm_semaphore_post(A0);
1386 return NULL;
1391 * tr - Transliterates a string.
1392 * @str: the string
1393 * @from: set of characters to be replaced
1394 * @to: set of characters to replace
1396 * Transliterates @str to a new string with all characters from @from
1397 * replaced by those in @to.
1398 * [Threading]
1400 /** tr(str, from, to); */
1401 static mpdm_t F_tr(F_ARGS)
1403 return mpdm_tr(A0, A1, A2);
1408 * int - Returns the integer part of a number.
1409 * @n: the number
1411 * Returns the integer part of the number @n.
1412 * [Miscellaneous]
1414 static mpdm_t F_int(F_ARGS)
1416 return MPDM_I(RA0);
1420 static struct {
1421 wchar_t *name;
1422 mpdm_t(*func) (mpdm_t, mpdm_t);
1423 } mpsl_funcs[] = {
1424 { L"size", F_size },
1425 { L"clone", F_clone },
1426 { L"dump", F_dump },
1427 { L"dumper", F_dumper },
1428 { L"cmp", F_cmp },
1429 { L"is_array", F_is_array },
1430 { L"is_hash", F_is_hash },
1431 { L"is_exec", F_is_exec },
1432 { L"splice", F_splice },
1433 { L"expand", F_expand },
1434 { L"collapse", F_collapse },
1435 { L"ins", F_ins },
1436 { L"adel", F_adel },
1437 { L"shift", F_shift },
1438 { L"push", F_push },
1439 { L"pop", F_pop },
1440 { L"queue", F_queue },
1441 { L"seek", F_seek },
1442 { L"sort", F_sort },
1443 { L"split", F_split },
1444 { L"join", F_join },
1445 { L"hsize", F_hsize },
1446 { L"exists", F_exists },
1447 { L"hdel", F_hdel },
1448 { L"keys", F_keys },
1449 { L"open", F_open },
1450 { L"close", F_close },
1451 { L"read", F_read },
1452 { L"write", F_write },
1453 { L"getchar", F_getchar },
1454 { L"putchar", F_putchar },
1455 { L"fseek", F_fseek },
1456 { L"ftell", F_ftell },
1457 { L"unlink", F_unlink },
1458 { L"stat", F_stat },
1459 { L"chmod", F_chmod },
1460 { L"chown", F_chown },
1461 { L"glob", F_glob },
1462 { L"encoding", F_encoding },
1463 { L"popen", F_popen },
1464 { L"popen2", F_popen2 },
1465 { L"pclose", F_pclose },
1466 { L"regex", F_regex },
1467 { L"sregex", F_sregex },
1468 { L"load", F_load },
1469 { L"compile", F_compile },
1470 { L"error", F_error },
1471 { L"eval", F_eval },
1472 { L"print", F_print },
1473 { L"gettext", F_gettext },
1474 { L"gettext_domain", F_gettext_domain },
1475 { L"sprintf", F_sprintf },
1476 { L"chr", F_chr },
1477 { L"ord", F_ord },
1478 { L"map", F_map },
1479 { L"grep", F_grep },
1480 { L"getenv", F_getenv },
1481 { L"uc", F_uc },
1482 { L"lc", F_lc },
1483 { L"time", F_time },
1484 { L"chdir", F_chdir },
1485 { L"sscanf", F_sscanf },
1486 { L"bincall", F_bincall },
1487 { L"random", F_random },
1488 { L"sleep", F_sleep },
1489 { L"mutex", F_mutex },
1490 { L"mutex_lock", F_mutex_lock },
1491 { L"mutex_unlock", F_mutex_unlock },
1492 { L"semaphore", F_semaphore },
1493 { L"semaphore_wait", F_semaphore_wait },
1494 { L"semaphore_post", F_semaphore_post },
1495 { L"tr", F_tr },
1496 { L"int", F_int },
1497 { NULL, NULL }
1501 mpdm_t mpsl_build_funcs(void)
1502 /* build all functions */
1504 mpdm_t c;
1505 int n;
1507 /* creates all the symbols in the CORE library */
1508 c = MPDM_H(0);
1510 mpdm_ref(c);
1512 for (n = 0; mpsl_funcs[n].name != NULL; n++) {
1513 mpdm_t f = MPDM_S(mpsl_funcs[n].name);
1514 mpdm_t x = MPDM_X(mpsl_funcs[n].func);
1516 mpdm_hset(mpdm_root(), f, x);
1517 mpdm_hset(c, f, x);
1520 mpdm_unrefnd(c);
1522 return c;