3 MPSL - Minimum Profit Scripting Language
4 Copyright (C) 2003/2010 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
39 #define F_ARGS mpdm_t a, mpdm_t l
41 #define A(n) mpdm_aget(a, n)
45 #define IA(n) mpdm_ival(A(n))
50 #define RA(n) mpdm_rval(A(n))
57 * size - Returns the size of a 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).
66 /** integer = size(v); */
68 static mpdm_t
F_size(F_ARGS
)
70 return MPDM_I(mpdm_size(A0
));
74 * clone - Creates a clone of a 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.
83 static mpdm_t
F_clone(F_ARGS
)
85 return mpdm_clone(A0
);
89 * dump - Dumps a value to stdin.
92 * Dumps a value to stdin. The value can be complex. This function
93 * is for debugging purposes only.
98 static mpdm_t
F_dump(F_ARGS
)
105 * dumper - Returns a visual representation of a complex value.
108 * Returns a visual representation of a complex value.
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
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.
145 * Returns non-zero if @v is an array.
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.
159 * Returns non-zero if @v is a hash.
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.
173 * Returns non-zero if @v is a executable.
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
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
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.
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.
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.
227 * @offset: deletion offset
228 * @num: number of elements to collapse
230 * Collapses an array value, deleting @num elements at
231 * the specified @offset.
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.
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.
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.
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).
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.
280 * Extracts the first element of the array. The array
281 * is shrinked by one.
283 * Returns the deleted element.
287 static mpdm_t
F_shift(F_ARGS
)
289 return mpdm_shift(A0
);
293 * push - Pushes a value into an array.
297 * Pushes a value into an array (i.e. inserts at the end).
300 /** e = push(a, e); */
301 static mpdm_t
F_push(F_ARGS
)
303 return mpdm_push(A0
, A1
);
307 * pop - Pops a value from an array.
310 * Pops a value from the array (i.e. deletes from the end
315 static mpdm_t
F_pop(F_ARGS
)
321 * queue - Implements a queue in an array.
323 * @e: the element to be pushed
324 * @size: maximum size of array
326 * Pushes the @e element into the @a array. If the array already has
327 * @size elements, the first (oldest) element is deleted from the
328 * queue and returned.
330 * Returns the deleted element, or NULL if the array doesn't have
331 * @size elements yet.
334 /** v = queue(a, e, size); */
335 static mpdm_t
F_queue(F_ARGS
)
337 return mpdm_queue(A0
, A1
, IA2
);
341 * seek - Seeks a value in an array (sequential).
344 * @step: number of elements to step
346 * Seeks sequentially the value @k in the @a array in
347 * increments of @step. A complete search should use a step of 1.
348 * Returns the offset of the element if found, or -1 otherwise.
351 /** integer = seek(a, k, step); */
352 static mpdm_t
F_seek(F_ARGS
)
354 return MPDM_I(mpdm_seek(A0
, A1
, IA2
));
358 * sort - Sorts an array.
360 * @sorting_func: sorting function
362 * Sorts the array. For each pair of elements being sorted, the
363 * @sorting_func is called with the two elements to be sorted as
364 * arguments. This function must return a signed integer value indicating
367 * If no function is supplied, the sorting is done using cmp().
369 * Returns the sorted array (the original one is left untouched).
372 /** array = sort(a); */
373 /** array = sort(a, sorting_func); */
374 static mpdm_t
F_sort(F_ARGS
)
379 r
= mpdm_sort_cb(mpdm_clone(v
), 1, A1
);
386 * split - Separates a string into an array of pieces.
387 * @v: the value to be separated
390 * Separates the @v string value into an array of pieces, using @s
393 * If the separator is NULL, the string is splitted by characters.
395 * If the string does not contain the separator, an array holding
396 * the complete string as its unique argument is returned.
400 /** array = split(v, s); */
401 static mpdm_t
F_split(F_ARGS
)
403 return mpdm_split(A0
, A1
);
407 * join - Joins all elements of an array into one.
408 * @a: array to be joined
411 * Joins all elements from @a into one string, using @s as a glue.
415 /** string = join(a, s); */
416 static mpdm_t
F_join(F_ARGS
)
418 return mpdm_join(A0
, A1
);
422 * hsize - Returns the number of pairs of a hash.
425 * Returns the number of key-value pairs of a hash.
428 /** integer = hsize(h); */
429 static mpdm_t
F_hsize(F_ARGS
)
431 return MPDM_I(mpdm_hsize(A0
));
435 * exists - Tests if a key exists.
439 * Returns 1 if @k is defined in @h, or 0 othersize.
442 /** bool = exists(h, k); */
443 static mpdm_t
F_exists(F_ARGS
)
445 return mpsl_boolean(mpdm_exists(A0
, A1
));
449 * hdel - Deletes a key from a hash.
453 * Deletes the key @k from the hash @h. Returns the previous
454 * value, or NULL if the key was not defined.
457 /** v = hdel(h, k); */
458 static mpdm_t
F_hdel(F_ARGS
)
460 return mpdm_hdel(A0
, A1
);
464 * keys - Returns the keys of a hash.
467 * Returns an array containing all the keys of the @h hash.
471 /** array = keys(h); */
472 static mpdm_t
F_keys(F_ARGS
)
474 return mpdm_keys(A0
);
478 * open - Opens a file.
479 * @filename: the file name
480 * @mode: an fopen-like mode string
482 * Opens a file. If @filename can be open in the specified @mode, a
483 * value will be returned containing the file descriptor, or NULL
486 * If the file is open for reading, some charset detection methods are
487 * used. If any of them is successful, its name is stored in the
488 * `DETECTED_ENCODING' global variable. This value is
489 * suitable to be copied over `ENCODING' or `TEMP_ENCODING'.
491 * If the file is open for writing, the encoding to be used is read from
492 * the `ENCODING' global variable and, if not set, from the
493 * `TEMP_ENCODING' one. The latter will always be deleted afterwards.
495 * [Character Set Conversion]
497 /** fd = open(filename, mode); */
498 static mpdm_t
F_open(F_ARGS
)
500 return mpdm_open(A0
, A1
);
504 * close - Closes a file descriptor.
505 * @fd: the file descriptor
507 * Closes the file descriptor.
511 static mpdm_t
F_close(F_ARGS
)
513 return mpdm_close(A0
);
517 * read - Reads a line from a file descriptor.
518 * @fd: the file descriptor
520 * Reads a line from @fd. Returns the line, or NULL on EOF.
522 * [Character Set Conversion]
524 /** string = read(fd); */
525 static mpdm_t
F_read(F_ARGS
)
527 return mpdm_read(A0
);
531 * getchar - Reads a character from a file descriptor.
532 * @fd: the file descriptor
534 * Returns a character read from @fd, or NULL on EOF. No
535 * charset conversion is done.
538 /** string = getchar(fd); */
539 static mpdm_t
F_getchar(F_ARGS
)
541 return mpdm_getchar(A0
);
545 * putchar - Writes a character to a file descriptor.
546 * @fd: the file descriptor
549 * Writes the first character in @s into @fd. No charset
550 * conversion is done.
552 * Returns the number of chars written (0 or 1).
555 /** s = putchar(fd, s); */
556 static mpdm_t
F_putchar(F_ARGS
)
558 return MPDM_I(mpdm_putchar(A0
, A1
));
562 * fseek - Sets a file pointer.
563 * @fd: the file descriptor
564 * @offset: the offset
565 * @whence: the position
567 * Sets the file pointer position of @fd to @offset. @whence can
568 * be: 0 for SEEK_SET, 1 for SEEK_CUR and 2 for SEEK_END.
570 * Returns the value from the fseek() C function call.
573 /** integer = fseek(fd, offset, whence); */
574 static mpdm_t
F_fseek(F_ARGS
)
576 return MPDM_I(mpdm_fseek(A0
, IA1
, IA2
));
580 * ftell - Returns the current file pointer.
581 * @fd: the file descriptor
583 * Returns the position of the file pointer in @fd.
586 /** integer = ftell(fd); */
587 static mpdm_t
F_ftell(F_ARGS
)
589 return MPDM_I(mpdm_ftell(A0
));
593 * unlink - Deletes a file.
594 * @filename: file name to be deleted
599 /** bool = unlink(filename); */
600 static mpdm_t
F_unlink(F_ARGS
)
602 return mpsl_boolean(mpdm_unlink(A0
));
606 * stat - Gives status from a file.
607 * @filename: file name to get the status from
609 * Returns a 14 element array of the status (permissions, onwer, etc.)
610 * from the desired @filename, or NULL if the file cannot be accessed.
613 * The values are: 0, device number of filesystem; 1, inode number;
614 * 2, file mode; 3, number of hard links to the file; 4, uid; 5, gid;
615 * 6, device identifier; 7, total size of file in bytes; 8, atime;
616 * 9, mtime; 10, ctime; 11, preferred block size for system I/O;
617 * 12, number of blocks allocated and 13, canonicalized file name.
618 * Not all elements have necesarily meaningful values, as most are
622 /** array = stat(filename); */
623 static mpdm_t
F_stat(F_ARGS
)
625 return mpdm_stat(A0
);
629 * chmod - Changes a file's permissions.
630 * @filename: the file name
631 * @perms: permissions (element 2 from stat())
633 * Changes the permissions for a file.
636 /** integer = chmod(filename, perms); */
637 static mpdm_t
F_chmod(F_ARGS
)
639 return MPDM_I(mpdm_chmod(A0
, A1
));
643 * chown - Changes a file's owner.
644 * @filename: the file name
645 * @uid: user id (element 4 from stat())
646 * @gid: group id (element 5 from stat())
648 * Changes the owner and group id's for a file.
651 /** integer = chown(filename, uid, gid); */
652 static mpdm_t
F_chown(F_ARGS
)
654 return MPDM_I(mpdm_chown(A0
, A1
, A2
));
658 * glob - Executes a file globbing.
659 * @spec: Globbing spec
660 * @base: Optional base directory
662 * Executes a file globbing. @spec is system-dependent, but usually
663 * the * and ? metacharacters work everywhere. @base can contain a
664 * directory; if that's the case, the output strings will include it.
665 * In any case, each returned value will be suitable for a call to
668 * Returns an array of files that match the globbing (can be an empty
669 * array if no file matches), or NULL if globbing is unsupported.
670 * Directories are returned first and their names end with a slash.
673 /** array = glob(spec, base); */
674 static mpdm_t
F_glob(F_ARGS
)
676 return mpdm_glob(A0
, A1
);
680 * encoding - Sets the current charset encoding for files.
681 * @charset: the charset name.
683 * Sets the current charset encoding for files. Future opened
684 * files will be assumed to be encoded with @charset, which can
685 * be any of the supported charset names (utf-8, iso-8859-1, etc.),
686 * and converted on each read / write. If charset is NULL, it
687 * is reverted to default charset conversion (i.e. the one defined
690 * This function stores the @charset value into the `ENCODING' global
693 * Returns a negative number if @charset is unsupported, or zero
694 * if no errors were found.
696 * [Character Set Conversion]
698 /** integer = encoding(charset); */
699 static mpdm_t
F_encoding(F_ARGS
)
701 return MPDM_I(mpdm_encoding(A0
));
705 * popen - Opens a pipe.
706 * @prg: the program to pipe
707 * @mode: an fopen-like mode string
709 * Opens a pipe to a program. If @prg can be open in the specified @mode,
710 * return file descriptor, or NULL otherwise.
712 * The @mode can be `r' (for reading), `w' (for writing), or `r+' or `w+'
713 * for a special double pipe reading-writing mode.
716 /** fd = popen(prg, mode); */
717 static mpdm_t
F_popen(F_ARGS
)
719 return mpdm_popen(A0
, A1
);
723 * popen2 - Opens a pipe and returns an array of two pipes.
724 * @prg: the program to pipe
726 * Opens a read-write pipe and returns an array of two descriptors,
727 * one for reading and one for writing. If @prg could not be piped to,
731 /** array = popen2(prg); */
732 static mpdm_t
F_popen2(F_ARGS
)
734 return mpdm_popen2(A0
);
738 * pclose - Closes a pipe.
739 * @fd: the value containing the file descriptor
745 static mpdm_t
F_pclose(F_ARGS
)
747 return mpdm_pclose(A0
);
751 * regex - Matches a regular expression.
752 * @v: the value to be matched
753 * @r: the regular expression
754 * @ra: an array of regular expressions
755 * @offset: offset from the start of the value
757 * Matches a regular expression against a value. Valid flags are `i',
758 * for case-insensitive matching, `m', to treat the string as a
759 * multiline string (i.e., one containing newline characters), so
760 * that ^ and $ match the boundaries of each line instead of the
761 * whole string, `l', to return the last matching instead of the
762 * first one, or `g', to match globally; in that last case, an array
763 * containing all matches is returned instead of a string scalar.
765 * If @r is a string, an ordinary regular expression matching is tried
766 * over the @v string. If the matching is possible, the match result
767 * is returned, or NULL otherwise.
769 * If @r is an array (of strings), each element is tried sequentially
770 * as an individual regular expression over the @v string, each one using
771 * the offset returned by the previous match. All regular expressions
772 * must match to be successful. If this is the case, an array (with
773 * the same number of arguments) is returned containing the matched
774 * strings, or NULL otherwise.
776 * If @r is NULL, the result of the previous regex matching
777 * is returned as a two element array. The first element will contain
778 * the character offset of the matching and the second the number of
779 * characters matched. If the previous regex was unsuccessful, NULL
781 * [Regular Expressions]
783 /** string = regex(v, r); */
784 /** string = regex(v, r, offset); */
785 /** array = regex(v, ra); */
786 /** array = regex(); */
787 static mpdm_t
F_regex(F_ARGS
)
789 return mpdm_regex(A0
, A1
, IA2
);
793 * sregex - Matches and substitutes a regular expression.
794 * @v: the value to be matched
795 * @r: the regular expression
796 * @s: the substitution string, hash or code
797 * @offset: offset from the start of v
799 * Matches a regular expression against a value, and substitutes the
800 * found substring with @s. Valid flags are `i', for case-insensitive
801 * matching, and `g', for global replacements (all ocurrences in @v
802 * will be replaced, instead of just the first found one).
804 * If @s is executable, it's executed with the matched part as
805 * the only argument and its return value is used as the
806 * substitution string.
808 * If @s is a hash, the matched string is used as a key to it and
809 * its value used as the substitution. If this value itself is
810 * executable, it's executed with the matched string as its only
811 * argument and its return value used as the substitution.
813 * If @r is NULL, returns the number of substitutions made in the
814 * previous call to sregex() (can be zero if none was done).
816 * Returns the modified string, or the original one if no substitutions
818 * [Regular Expressions]
820 /** string = sregex(v, r, s); */
821 /** string = sregex(v, r, s, offset); */
822 /** integer = sregex(); */
823 static mpdm_t
F_sregex(F_ARGS
)
825 return mpdm_sregex(A0
, A1
, A2
, IA3
);
829 * gettext - Translates a string to the current language.
832 * Translates the @str string to the current language.
834 * This function can still be used even if there is no real gettext
835 * support by manually filling the __I18N__ hash.
837 * If the string is found in the current table, the translation is
838 * returned; otherwise, the same @str value is returned.
842 /** string = gettext(str); */
843 static mpdm_t
F_gettext(F_ARGS
)
845 return mpdm_gettext(A0
);
849 * gettext_domain - Sets domain and data directory for translations.
850 * @dom: the domain (application name)
851 * @data: directory contaning the .mo files
853 * Sets the domain (application name) and translation data for translating
854 * strings that will be returned by gettext(). @data must point to a
855 * directory containing the .mo (compiled .po) files.
857 * If there is no gettext support, returns 0, or 1 otherwise.
861 /** bool = gettext_domain(dom, data); */
862 static mpdm_t
F_gettext_domain(F_ARGS
)
864 return MPDM_I(mpdm_gettext_domain(A0
, A1
));
868 * load - Loads an MPSL source code file.
869 * @source_file: the source code file
871 * Loads and executes an MPSL source code file and returns
875 /** load(source_file); */
876 static mpdm_t
F_load(F_ARGS
)
878 return mpdm_exec(mpsl_compile_file(A0
,
879 mpsl_get_symbol(MPDM_LS(L
"INC"),
884 * compile - Compiles a string of MSPL source code file.
885 * @source: the source code string
887 * Compiles a string of MPSL source code and returns an
891 /** func = compile(source); */
892 static mpdm_t
F_compile(F_ARGS
)
894 return mpsl_compile(A0
);
898 * error - Simulates an error.
899 * @err: the error message
901 * Simulates an error. The @err error message is stored in the `ERROR'
902 * global variable and an internal abort global flag is set, so no further
903 * MPSL code can be executed until reset.
906 static mpdm_t
F_error(F_ARGS
)
908 return mpsl_error(A0
);
912 * uc - Converts a string to uppercase.
913 * @str: the string to be converted
915 * Returns @str converted to uppercase.
918 /** string = uc(str); */
919 static mpdm_t
F_uc(F_ARGS
)
921 return mpdm_ulc(A0
, 1);
925 * lc - Converts a string to lowercase.
926 * @str: the string to be converted
928 * Returns @str converted to lowercase.
931 /** string = uc(str); */
932 static mpdm_t
F_lc(F_ARGS
)
934 return mpdm_ulc(A0
, 0);
938 * time - Returns the current time.
940 * Returns the current time from the epoch (C library time()).
943 /** integer = time(); */
944 static mpdm_t
F_time(F_ARGS
)
946 return MPDM_I(time(NULL
));
950 * chdir - Changes the working directory
953 * Changes the working directory
956 /** integer = chdir(dir); */
957 static mpdm_t
F_chdir(F_ARGS
)
959 return MPDM_I(mpdm_chdir(A0
));
963 * sscanf - Extracts data like sscanf().
964 * @str: the string to be parsed
965 * @fmt: the string format
966 * @offset: the character offset to start scanning
968 * Extracts data from a string using a special format pattern, very
969 * much like the scanf() series of functions in the C library. Apart
970 * from the standard percent-sign-commands (s, u, d, i, f, x,
971 * n, [, with optional size and * to ignore), it implements S,
972 * to match a string of characters upto what follows in the format
973 * string. Also, the [ set of characters can include other % formats.
975 * Returns an array with the extracted values. If %n is used, the
976 * position in the scanned string is returned as the value.
979 /** array = sscanf(str, fmt); */
980 /** array = sscanf(str, fmt, offset); */
981 static mpdm_t
F_sscanf(F_ARGS
)
983 return mpdm_sscanf(A0
, A1
, IA2
);
987 * eval - Evaluates MSPL code.
988 * @code: A value containing a string of MPSL code, or executable code
989 * @args: optional arguments for @code
991 * Evaluates a piece of code. The @code can be a string containing MPSL
992 * source code (that will be compiled) or a direct executable value. If
993 * the compilation or the execution gives an error, the `ERROR' variable
994 * will be set to a printable value and NULL returned. Otherwise, the
995 * exit value from the code is returned and `ERROR' set to NULL. The
996 * internal abort flag is reset on exit.
1000 /** v = eval(code, args); */
1001 static mpdm_t
F_eval(F_ARGS
)
1005 a
= mpdm_ref(mpdm_clone(a
));
1008 r
= mpsl_eval(c
, a
, l
);
1017 * sprintf - Formats a sprintf()-like string.
1018 * @fmt: the string format
1019 * @arg1: first argument
1020 * @arg2: second argument
1021 * @argn: nth argument
1023 * Formats a string using the sprintf() format taking the values from
1024 * the variable arguments.
1027 /** string = sprintf(fmt, arg1 [,arg2 ... argn]); */
1028 static mpdm_t
F_sprintf(F_ARGS
)
1032 a
= mpdm_ref(mpdm_clone(a
));
1035 /* if the first argument is an array, take it as the arguments */
1036 if ((v
= mpdm_aget(a
, 0)) != NULL
&& MPDM_IS_ARRAY(v
))
1039 r
= mpdm_sprintf(f
, a
);
1048 * print - Writes values to stdout.
1049 * @arg1: first argument
1050 * @arg2: second argument
1051 * @argn: nth argument
1053 * Writes the variable arguments to stdout.
1056 /** print(arg1 [,arg2 ... argn]); */
1057 static mpdm_t
F_print(F_ARGS
)
1061 for (n
= 0; n
< mpdm_size(a
); n
++)
1062 mpdm_write_wcs(stdout
, mpdm_string(A(n
)));
1068 * write - Writes values to a file descriptor.
1069 * @fd: the file descriptor
1070 * @arg1: first argument
1071 * @arg2: second argument
1072 * @argn: nth argument
1074 * Writes the variable arguments to the file descriptor, doing
1075 * charset conversion in the process.
1077 * Returns the total size written to @fd.
1079 * [Character Set Conversion]
1081 /** integer = write(fd, arg1 [,arg2 ... argn]); */
1082 static mpdm_t
F_write(F_ARGS
)
1086 for (n
= 1; n
< mpdm_size(a
); n
++)
1087 r
+= mpdm_write(A0
, A(n
));
1094 * chr - Returns the Unicode character represented by the codepoint.
1095 * @c: the codepoint as an integer value
1097 * Returns a 1 character string containing the character which
1098 * Unicode codepoint is @c.
1101 /** string = chr(c); */
1102 static mpdm_t
F_chr(F_ARGS
)
1106 tmp
[0] = (wchar_t) mpdm_ival(mpdm_aget(a
, 0));
1114 * ord - Returns the Unicode codepoint of a character.
1117 * Returns the Unicode codepoint for the first character in
1121 /** integer = ord(str); */
1122 static mpdm_t
F_ord(F_ARGS
)
1125 mpdm_t v
= mpdm_aget(a
, 0);
1128 wchar_t *ptr
= mpdm_string(v
);
1137 * map - Maps an array into another.
1139 * @filter: the filter
1141 * Returns a new array built by applying the @filter to all the
1142 * elements of the array @a. The filter can be an executable function
1143 * accepting one argument, in which case the return value of the function
1144 * will be used as the output element; @filt can also be a hash, in which
1145 * case the original element will be used as a key to the hash and the
1146 * associated value used as the output element.
1150 /** array = map(a, filter); */
1151 static mpdm_t
F_map(F_ARGS
)
1153 mpdm_t set
= mpdm_aget(a
, 0);
1154 mpdm_t key
= mpdm_aget(a
, 1);
1157 /* map NULL to NULL */
1161 out
= mpdm_ref(MPDM_A(mpdm_size(set
)));
1163 if (MPDM_IS_EXEC(key
)) {
1166 /* executes the code using the element as argument
1167 and stores the result in the output array */
1168 for (n
= 0; n
< mpdm_size(set
); n
++)
1169 mpdm_aset(out
, mpdm_exec_1(key
, mpdm_aget(set
, n
), l
), n
);
1171 else if (MPDM_IS_HASH(key
)) {
1174 /* maps each value using the element as key */
1175 for (n
= 0; n
< mpdm_size(set
); n
++)
1176 mpdm_aset(out
, mpdm_hget(key
, mpdm_aget(set
, n
)), n
);
1179 return mpdm_unrefnd(out
);
1184 * grep - Greps inside an array.
1186 * @filter: the filter
1188 * Greps inside an array and returns another one containing only the
1189 * elements that passed the filter. If @filter is a string, it's accepted
1190 * as a regular expression, which will be applied to each element.
1191 * If @filter is executable, it will be called with the element as its
1192 * only argument and its return value used as validation.
1194 * The new array will contain all elements that passed the filter.
1196 * [Regular Expressions]
1198 /** array = grep(filter, a); */
1199 static mpdm_t
F_grep(F_ARGS
)
1201 mpdm_t set
= mpdm_aget(a
, 0);
1202 mpdm_t key
= mpdm_aget(a
, 1);
1203 mpdm_t out
= mpdm_ref(MPDM_A(0));
1205 if (MPDM_IS_EXEC(key
)) {
1208 /* it's executable */
1209 for (n
= 0; n
< mpdm_size(set
); n
++) {
1210 mpdm_t v
= mpdm_aget(set
, n
);
1211 mpdm_t w
= mpdm_ref(mpdm_exec_1(key
, v
, l
));
1213 if (mpsl_is_true(w
))
1219 else if (key
->flags
& MPDM_STRING
) {
1222 /* it's a string; use it as a regular expression */
1223 for (n
= 0; n
< mpdm_size(set
); n
++) {
1224 mpdm_t v
= mpdm_aget(set
, n
);
1225 mpdm_t w
= mpdm_ref(mpdm_regex(v
, key
, 0));
1234 return mpdm_size(mpdm_unrefnd(out
)) == 0 ? NULL
: out
;
1237 static mpdm_t
F_getenv(F_ARGS
)
1239 mpdm_t e
= mpdm_hget_s(mpdm_root(), L
"ENV");
1241 return mpdm_hget(e
, mpdm_aget(a
, 0));
1244 static mpdm_t
F_bincall(F_ARGS
)
1246 return MPDM_X(mpdm_ival(mpdm_aget(a
, 0)));
1250 * random - Returns a random value.
1252 * Returns a random number from 0 to value - 1.
1255 /** integer = random(value); */
1256 static mpdm_t
F_random(F_ARGS
)
1258 static unsigned int seed
= 0;
1260 int range
= mpdm_ival(mpdm_aget(a
, 0));
1262 if (range
== 0 || seed
== 0)
1265 seed
= (seed
* 58321) + 11113;
1266 r
= (seed
>> 16) % range
;
1274 * sleep - Sleeps a number of milliseconds.
1276 * Sleeps a number of milliseconds.
1279 /** sleep(msecs); */
1280 static mpdm_t
F_sleep(F_ARGS
)
1282 mpdm_sleep(mpdm_ival(mpdm_aget(a
, 0)));
1289 * mutex - Returns a new mutex.
1291 * Returns a new mutex.
1294 /** var = mutex(); */
1295 static mpdm_t
F_mutex(F_ARGS
)
1297 return mpdm_new_mutex();
1302 * mutex_lock - Locks a mutex (possibly waiting).
1305 * Locks a mutex. If the mutex is already locked by
1306 * another process, it waits until it's unlocked.
1309 /** mutex_lock(mtx); */
1310 static mpdm_t
F_mutex_lock(F_ARGS
)
1312 mpdm_mutex_lock(A0
);
1318 * mutex_unlock - Unlocks a mutex.
1324 /** mutex_unlock(mtx); */
1325 static mpdm_t
F_mutex_unlock(F_ARGS
)
1327 mpdm_mutex_unlock(A0
);
1333 * semaphore - Returns a new semaphore.
1334 * cnt: the initial count of the semaphore.
1336 * Returns a new semaphore.
1339 /** var = semaphore(cnt); */
1340 static mpdm_t
F_semaphore(F_ARGS
)
1342 return mpdm_new_semaphore(IA0
);
1347 * semaphore_wait - Waits for a semaphore to be ready.
1348 * @sem: the semaphore to wait onto
1350 * Waits for the value of a semaphore to be > 0. If it's
1351 * not, the thread waits until it is.
1354 /** semaphore_wait(sem); */
1355 static mpdm_t
F_semaphore_wait(F_ARGS
)
1357 mpdm_semaphore_wait(A0
);
1363 * semaphore_post - Increments the value of a semaphore.
1364 * @sem: the semaphore to increment
1366 * Increments by 1 the value of a semaphore.
1369 /** semaphore_post(mtx); */
1370 static mpdm_t
F_semaphore_post(F_ARGS
)
1372 mpdm_semaphore_post(A0
);
1379 mpdm_t(*func
) (mpdm_t
, mpdm_t
);
1381 { L
"size", F_size
},
1382 { L
"clone", F_clone
},
1383 { L
"dump", F_dump
},
1384 { L
"dumper", F_dumper
},
1386 { L
"is_array", F_is_array
},
1387 { L
"is_hash", F_is_hash
},
1388 { L
"is_exec", F_is_exec
},
1389 { L
"splice", F_splice
},
1390 { L
"expand", F_expand
},
1391 { L
"collapse", F_collapse
},
1393 { L
"adel", F_adel
},
1394 { L
"shift", F_shift
},
1395 { L
"push", F_push
},
1397 { L
"queue", F_queue
},
1398 { L
"seek", F_seek
},
1399 { L
"sort", F_sort
},
1400 { L
"split", F_split
},
1401 { L
"join", F_join
},
1402 { L
"hsize", F_hsize
},
1403 { L
"exists", F_exists
},
1404 { L
"hdel", F_hdel
},
1405 { L
"keys", F_keys
},
1406 { L
"open", F_open
},
1407 { L
"close", F_close
},
1408 { L
"read", F_read
},
1409 { L
"write", F_write
},
1410 { L
"getchar", F_getchar
},
1411 { L
"putchar", F_putchar
},
1412 { L
"fseek", F_fseek
},
1413 { L
"ftell", F_ftell
},
1414 { L
"unlink", F_unlink
},
1415 { L
"stat", F_stat
},
1416 { L
"chmod", F_chmod
},
1417 { L
"chown", F_chown
},
1418 { L
"glob", F_glob
},
1419 { L
"encoding", F_encoding
},
1420 { L
"popen", F_popen
},
1421 { L
"popen2", F_popen2
},
1422 { L
"pclose", F_pclose
},
1423 { L
"regex", F_regex
},
1424 { L
"sregex", F_sregex
},
1425 { L
"load", F_load
},
1426 { L
"compile", F_compile
},
1427 { L
"error", F_error
},
1428 { L
"eval", F_eval
},
1429 { L
"print", F_print
},
1430 { L
"gettext", F_gettext
},
1431 { L
"gettext_domain", F_gettext_domain
},
1432 { L
"sprintf", F_sprintf
},
1436 { L
"grep", F_grep
},
1437 { L
"getenv", F_getenv
},
1440 { L
"time", F_time
},
1441 { L
"chdir", F_chdir
},
1442 { L
"sscanf", F_sscanf
},
1443 { L
"bincall", F_bincall
},
1444 { L
"random", F_random
},
1445 { L
"sleep", F_sleep
},
1446 { L
"mutex", F_mutex
},
1447 { L
"mutex_lock", F_mutex_lock
},
1448 { L
"mutex_unlock", F_mutex_unlock
},
1449 { L
"semaphore", F_semaphore
},
1450 { L
"semaphore_wait", F_semaphore_wait
},
1451 { L
"semaphore_post", F_semaphore_post
},
1456 mpdm_t
mpsl_build_funcs(void)
1457 /* build all functions */
1462 /* creates all the symbols in the CORE library */
1467 for (n
= 0; mpsl_funcs
[n
].name
!= NULL
; n
++) {
1468 mpdm_t f
= MPDM_S(mpsl_funcs
[n
].name
);
1469 mpdm_t x
= MPDM_X(mpsl_funcs
[n
].func
);
1471 mpdm_hset(mpdm_root(), f
, x
);