438 lines
11 KiB
C
438 lines
11 KiB
C
/******************************************************************************
|
|
Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved.
|
|
Portions of this code were written by Stephen White, aka ghond.
|
|
Use and copying of this software and preparation of derivative works based
|
|
upon this software are permitted. Any distribution of this software or
|
|
derivative works must comply with all applicable United States export
|
|
control laws. This software is made available AS IS, and Xerox Corporation
|
|
makes no warranty about the software, its performance or its conformity to
|
|
any specification. Any person obtaining a copy of this software is requested
|
|
to send their name and post office or electronic mail address to:
|
|
Pavel Curtis
|
|
Xerox PARC
|
|
3333 Coyote Hill Rd.
|
|
Palo Alto, CA 94304
|
|
Pavel@Xerox.Com
|
|
*****************************************************************************/
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
#include "pconfig.h"
|
|
#include "functions.h"
|
|
#include "list.h"
|
|
#include "streams.h"
|
|
#include "storage.h"
|
|
#include "structures.h"
|
|
#include "utils.h"
|
|
|
|
Var
|
|
new_list(int size)
|
|
{
|
|
Var new;
|
|
|
|
if (size == 0) {
|
|
static Var emptylist;
|
|
|
|
if (emptylist.v.list == 0) {
|
|
emptylist.type = TYPE_LIST;
|
|
emptylist.v.list = mymalloc(1 * sizeof(Var), M_LIST);
|
|
emptylist.v.list[0].type = TYPE_INT;
|
|
emptylist.v.list[0].v.num = 0;
|
|
}
|
|
/* give the lucky winner a reference */
|
|
addref(emptylist.v.list);
|
|
return emptylist;
|
|
}
|
|
new.type = TYPE_LIST;
|
|
new.v.list = (Var *) mymalloc((size + 1) * sizeof(Var), M_LIST);
|
|
new.v.list[0].type = TYPE_INT;
|
|
new.v.list[0].v.num = size;
|
|
return new;
|
|
}
|
|
|
|
Var
|
|
setadd(Var list, Var value)
|
|
{
|
|
if (ismember(value, list, 0)) {
|
|
free_var(value);
|
|
return list;
|
|
}
|
|
return listappend(list, value);
|
|
}
|
|
|
|
Var
|
|
setremove(Var list, Var value)
|
|
{
|
|
int i;
|
|
|
|
if ((i = ismember(value, list, 0)) != 0) {
|
|
return listdelete(list, i);
|
|
} else {
|
|
return list;
|
|
}
|
|
}
|
|
|
|
int
|
|
ismember(Var lhs, Var rhs, int case_matters)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; i <= rhs.v.list[0].v.num; i++) {
|
|
if (equality(lhs, rhs.v.list[i], case_matters)) {
|
|
return i;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Var
|
|
listset(Var list, Var value, int pos)
|
|
{
|
|
free_var(list.v.list[pos]);
|
|
list.v.list[pos] = value;
|
|
return list;
|
|
}
|
|
|
|
static Var
|
|
doinsert(Var list, Var value, int pos)
|
|
{
|
|
Var new;
|
|
int i;
|
|
int size = list.v.list[0].v.num + 1;
|
|
|
|
if (var_refcount(list) == 1 && pos == size) {
|
|
list.v.list = (Var *) myrealloc(list.v.list, (size + 1) * sizeof(Var), M_LIST);
|
|
list.v.list[0].v.num = size;
|
|
list.v.list[pos] = value;
|
|
return list;
|
|
}
|
|
new = new_list(size);
|
|
for (i = 1; i < pos; i++)
|
|
new.v.list[i] = var_ref(list.v.list[i]);
|
|
new.v.list[pos] = value;
|
|
for (i = pos; i <= list.v.list[0].v.num; i++)
|
|
new.v.list[i + 1] = var_ref(list.v.list[i]);
|
|
free_var(list);
|
|
return new;
|
|
}
|
|
|
|
Var
|
|
listinsert(Var list, Var value, int pos)
|
|
{
|
|
if (pos <= 0)
|
|
pos = 1;
|
|
else if (pos > list.v.list[0].v.num)
|
|
pos = list.v.list[0].v.num + 1;
|
|
return doinsert(list, value, pos);
|
|
}
|
|
|
|
Var
|
|
listappend(Var list, Var value)
|
|
{
|
|
return doinsert(list, value, list.v.list[0].v.num + 1);
|
|
}
|
|
|
|
Var
|
|
listdelete(Var list, int pos)
|
|
{
|
|
Var new;
|
|
int i;
|
|
|
|
new = new_list(list.v.list[0].v.num - 1);
|
|
for (i = 1; i < pos; i++) {
|
|
new.v.list[i] = var_ref(list.v.list[i]);
|
|
}
|
|
for (i = pos + 1; i <= list.v.list[0].v.num; i++)
|
|
new.v.list[i - 1] = var_ref(list.v.list[i]);
|
|
free_var(list); /* free old list */
|
|
return new;
|
|
}
|
|
|
|
Var
|
|
listconcat(Var first, Var second)
|
|
{
|
|
int lsecond = second.v.list[0].v.num;
|
|
int lfirst = first.v.list[0].v.num;
|
|
Var new;
|
|
int i;
|
|
|
|
new = new_list(lsecond + lfirst);
|
|
for (i = 1; i <= lfirst; i++)
|
|
new.v.list[i] = var_ref(first.v.list[i]);
|
|
for (i = 1; i <= lsecond; i++)
|
|
new.v.list[i + lfirst] = var_ref(second.v.list[i]);
|
|
free_var(first);
|
|
free_var(second);
|
|
|
|
return new;
|
|
}
|
|
|
|
Var
|
|
listrangeset(Var base, int from, int to, Var value)
|
|
{
|
|
/* base and value are free'd */
|
|
int index, offset = 0;
|
|
int val_len = value.v.list[0].v.num;
|
|
int base_len = base.v.list[0].v.num;
|
|
int lenleft = (from > 1) ? from - 1 : 0;
|
|
int lenmiddle = val_len;
|
|
int lenright = (base_len > to) ? base_len - to : 0;
|
|
int newsize = lenleft + lenmiddle + lenright;
|
|
Var ans;
|
|
|
|
ans = new_list(newsize);
|
|
for (index = 1; index <= lenleft; index++)
|
|
ans.v.list[++offset] = var_ref(base.v.list[index]);
|
|
for (index = 1; index <= lenmiddle; index++)
|
|
ans.v.list[++offset] = var_ref(value.v.list[index]);
|
|
for (index = 1; index <= lenright; index++)
|
|
ans.v.list[++offset] = var_ref(base.v.list[to + index]);
|
|
free_var(base);
|
|
free_var(value);
|
|
return ans;
|
|
}
|
|
|
|
Var
|
|
sublist(Var list, int lower, int upper)
|
|
{
|
|
if (lower > upper) {
|
|
free_var(list);
|
|
return new_list(0);
|
|
} else {
|
|
Var r;
|
|
int i;
|
|
|
|
r = new_list(upper - lower + 1);
|
|
for (i = lower; i <= upper; i++)
|
|
r.v.list[i - lower + 1] = var_ref(list.v.list[i]);
|
|
free_var(list);
|
|
return r;
|
|
}
|
|
}
|
|
|
|
static const char *
|
|
list2str(Var * args)
|
|
{
|
|
static Stream *str = 0;
|
|
int i;
|
|
|
|
if (!str)
|
|
str = new_stream(100);
|
|
|
|
for (i = 1; i <= args[0].v.num; i++) {
|
|
switch (args[i].type) {
|
|
case TYPE_INT:
|
|
stream_printf(str, "%d", args[i].v.num);
|
|
break;
|
|
case TYPE_OBJ:
|
|
stream_printf(str, "#%d", args[i].v.obj);
|
|
break;
|
|
case TYPE_STR:
|
|
stream_add_string(str, args[i].v.str);
|
|
break;
|
|
case TYPE_ERR:
|
|
stream_add_string(str, unparse_error(args[i].v.err));
|
|
break;
|
|
case TYPE_FLOAT:
|
|
stream_printf(str, "%g", *args[i].v.fnum);
|
|
break;
|
|
case TYPE_LIST:
|
|
stream_add_string(str, "{list}");
|
|
break;
|
|
}
|
|
}
|
|
|
|
return reset_stream(str);
|
|
}
|
|
|
|
const char *
|
|
value2str(Var value)
|
|
{
|
|
Var list;
|
|
const char *str;
|
|
|
|
list = new_list(1);
|
|
list.v.list[1] = var_ref(value);
|
|
str = list2str(list.v.list);
|
|
free_var(list);
|
|
return str;
|
|
}
|
|
|
|
Var
|
|
strrangeset(Var base, int from, int to, Var value)
|
|
{
|
|
/* base and value are free'd */
|
|
int index, offset = 0;
|
|
int val_len = strlen(value.v.str);
|
|
int base_len = strlen(base.v.str);
|
|
int lenleft = (from > 1) ? from - 1 : 0;
|
|
int lenmiddle = val_len;
|
|
int lenright = (base_len > to) ? base_len - to : 0;
|
|
int newsize = lenleft + lenmiddle + lenright;
|
|
|
|
Var ans;
|
|
char *s;
|
|
|
|
ans.type = TYPE_STR;
|
|
s = mymalloc(sizeof(char) * (newsize + 1), M_STRING);
|
|
|
|
for (index = 0; index < lenleft; index++)
|
|
s[offset++] = base.v.str[index];
|
|
for (index = 0; index < lenmiddle; index++)
|
|
s[offset++] = value.v.str[index];
|
|
for (index = 0; index < lenright; index++)
|
|
s[offset++] = base.v.str[index + to];
|
|
s[offset] = '\0';
|
|
ans.v.str = s;
|
|
free_var(base);
|
|
free_var(value);
|
|
return ans;
|
|
}
|
|
|
|
Var
|
|
substr(Var str, int lower, int upper)
|
|
{
|
|
Var r;
|
|
|
|
r.type = TYPE_STR;
|
|
if (lower > upper)
|
|
r.v.str = str_dup("");
|
|
else {
|
|
int loop, index = 0;
|
|
char *s = mymalloc(upper - lower + 2, M_STRING);
|
|
|
|
for (loop = lower - 1; loop < upper; loop++)
|
|
s[index++] = str.v.str[loop];
|
|
s[index] = '\0';
|
|
r.v.str = s;
|
|
}
|
|
free_var(str);
|
|
return r;
|
|
}
|
|
|
|
Var
|
|
strget(Var str, Var i)
|
|
{
|
|
Var r;
|
|
char *s;
|
|
|
|
r.type = TYPE_STR;
|
|
s = str_dup(" ");
|
|
s[0] = str.v.str[i.v.num - 1];
|
|
r.v.str = s;
|
|
return r;
|
|
}
|
|
|
|
char rcsid_list[] = "$Id: list.c,v 1.1.1.1 2004/02/26 13:13:56 jesse Exp $";
|
|
|
|
/*
|
|
* $Log: list.c,v $
|
|
* Revision 1.1.1.1 2004/02/26 13:13:56 jesse
|
|
* Initial import into CVS
|
|
*
|
|
* Revision 1.5 1998/12/14 13:17:57 nop
|
|
* Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims
|
|
*
|
|
* Revision 1.4 1997/07/07 03:24:54 nop
|
|
* Merge UNSAFE_OPTS (r5) after extensive testing.
|
|
*
|
|
* Revision 1.3.2.3 1997/07/03 08:04:01 bjj
|
|
* Pattern cache was not storing case_matters flag, causing many patterns to
|
|
* be impossible to find in the cache.
|
|
*
|
|
* Revision 1.3.2.2 1997/05/20 14:55:52 nop
|
|
* Include Jason's patch for bf_decode_binary losing on systems where
|
|
* char is signed.
|
|
*
|
|
* Revision 1.3.2.1 1997/03/21 15:22:56 bjj
|
|
* doinsert reallocs for appending to refcnt 1 lists. note that this wins
|
|
* because it avoids all the var_ref/free_var that's done in the general case,
|
|
* not because it avoids malloc/free. the general case could also benefit from
|
|
* using memcpy when the refcnt is 1, rather than looping with var_ref.
|
|
*
|
|
* Revision 1.3 1997/03/03 06:20:04 bjj
|
|
* new_list(0) now returns the same empty list to every caller
|
|
*
|
|
* Revision 1.2 1997/03/03 04:18:46 nop
|
|
* GNU Indent normalization
|
|
*
|
|
* Revision 1.1.1.1 1997/03/03 03:45:00 nop
|
|
* LambdaMOO 1.8.0p5
|
|
*
|
|
* Revision 2.7 1996/03/11 23:35:17 pavel
|
|
* Fixed bad use of possibly-signed characters in decode_binary().
|
|
* Release 1.8.0p1.
|
|
*
|
|
* Revision 2.6 1996/02/18 23:17:24 pavel
|
|
* Added value_hash(), string_hash(), and binary_hash(). Release 1.8.0beta3.
|
|
*
|
|
* Revision 2.5 1996/02/08 07:02:09 pavel
|
|
* Added support for floating-point numbers. Fixed registration of
|
|
* decode_binary(). Renamed err/logf() to errlog/oklog() and TYPE_NUM to
|
|
* TYPE_INT. Updated copyright notice for 1996. Release 1.8.0beta1.
|
|
*
|
|
* Revision 2.4 1996/01/16 07:26:56 pavel
|
|
* Fixed `case_matters' arguments to strsub(), index(), rindex(), match(), and
|
|
* rmatch() to allow values of any type. Release 1.8.0alpha6.
|
|
*
|
|
* Revision 2.3 1996/01/11 07:42:14 pavel
|
|
* Added support for C's crypt() function being unavailable. Fixed potential
|
|
* string overread in case of a too-short salt argument to MOO's crypt()
|
|
* function. Added built-ins encode_binary() and decode_binary(), in support
|
|
* of new binary I/O facilities. Release 1.8.0alpha5.
|
|
*
|
|
* Revision 2.2 1995/12/31 03:25:04 pavel
|
|
* Added missing #include "options.h". Release 1.8.0alpha4.
|
|
*
|
|
* Revision 2.1 1995/12/11 07:43:20 pavel
|
|
* Moved value_bytes built-in function to here.
|
|
*
|
|
* Release 1.8.0alpha2.
|
|
*
|
|
* Revision 2.0 1995/11/30 04:24:03 pavel
|
|
* New baseline version, corresponding to release 1.8.0alpha1.
|
|
*
|
|
* Revision 1.12 1992/10/23 23:03:47 pavel
|
|
* Added copyright notice.
|
|
*
|
|
* Revision 1.11 1992/10/23 19:27:07 pavel
|
|
* Removed a place where a local structure variable was initialized in its
|
|
* declaration, since some compilers can't hack that.
|
|
* Added the `%%' -> `%' transformation to substitute().
|
|
*
|
|
* Revision 1.10 1992/10/21 03:02:35 pavel
|
|
* Converted to use new automatic configuration system.
|
|
*
|
|
* Revision 1.9 1992/10/17 20:33:17 pavel
|
|
* Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and
|
|
* varref->var_ref.
|
|
* Added some (int) casts to placate over-protective compilers.
|
|
*
|
|
* Revision 1.8 1992/09/08 22:15:09 pjames
|
|
* Updated strrangeset() and listrangeset() to use correct algorithm.
|
|
*
|
|
* Revision 1.7 1992/09/08 22:03:45 pjames
|
|
* Added all code from bf_str_list.c, and some code from bf_type.c.
|
|
*
|
|
* Revision 1.6 1992/08/31 22:31:47 pjames
|
|
* Changed some `char *'s to `const char *' and fixed code accordingly.
|
|
*
|
|
* Revision 1.5 1992/08/28 23:20:22 pjames
|
|
* Added `listrangeset()' and `strrangeset()'.
|
|
*
|
|
* Revision 1.4 1992/08/28 16:29:10 pjames
|
|
* Added some varref()'s.
|
|
* Removed some free_var()'s, due to ref-counting.
|
|
* Changed some my_free()'s to free_var().
|
|
* Made `substr()' preserve the string it is passed.
|
|
*
|
|
* Revision 1.3 1992/08/10 16:53:46 pjames
|
|
* Updated #includes.
|
|
*
|
|
* Revision 1.2 1992/07/21 00:04:04 pavel
|
|
* Added rcsid_<filename-root> declaration to hold the RCS ident. string.
|
|
*
|
|
* Revision 1.1 1992/07/20 23:23:12 pavel
|
|
* Initial RCS-controlled version.
|
|
*/
|