Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/source/array.c
1069 views
1
/*
2
* IRC-II Copyright (C) 1990 Michael Sandroff and others,
3
* This file - Copyright (C) 1993,1995 Aaron Gifford
4
* This file written by Aaron Gifford and contributed to the EPIC
5
* project by Jeremy Nelson to whom it was contributed in Nov, 1993.
6
*
7
* Used with permission. See the COPYRIGHT file for copyright info.
8
*/
9
/*
10
DATE OF THIS VERSION:
11
---------------------
12
Sat Nov 27 23:00:20 MST 1993
13
14
NEW SINCE 20 NOV 1993:
15
----------------------
16
Two new functions were added: GETMATCHES() and GETRMATCHES()
17
18
BUGS:
19
-----
20
I had a script that used these functions that caused ircII to crash
21
once or twice, but I have been unable to trace the cause or reproduce
22
the crash. I would appreciate any help or info if anyone else
23
experiences similar problems. This IS my first time using writing code
24
to work with ircII code.
25
26
ARGUMENTS:
27
----------
28
array_name : A string of some sort (no spaces, case insensitive)
29
identifying an array, either an existing array, or a new array.
30
31
item_number : A number or index into the array. All array items are
32
numbered beginning at zero and continuing sequentially. The
33
item number can be an existing item of an existing array, a
34
new item in an existing array (if the previous greatest item
35
number was 5, then the new item number must be 6, maintaining
36
the sequence), or a new item (must be item zero) in a new array.
37
data_... : Basically any data you want. It is stored internally as a
38
character string, and in indexed (more to come) internally
39
using the standard C library function strcmp().
40
41
FUNCTIONS:
42
----------
43
SETITEM(array_name item_number data_to_be_stored)
44
Use SETITEM to set an existing item of an existing array to a new value,
45
to create a new value in an existing array (see note about item_number),
46
or to create a new array (see note about item_number above).
47
RETURNS: 0 (zero) if it successfully sets and existing item in the array
48
1 if it successfully creates a new array
49
2 if it successfully adds a new item to an existing array
50
-1 if it was unable to find the array specified (item_number > 0)
51
-2 if it was unable to find the item in an existing array
52
(item_number was too large)
53
54
GETITEM(array_name item_number)
55
Use this to retrieve previously stored data.
56
RETURNS: the data requested
57
OR an empty string if the array did not exist or the item did not.
58
59
NUMITEMS(array_name)
60
RETURNS: the number of items in the array
61
OR zero if the array name is invalid. Useful for auto-adding to
62
an array:
63
alias ADDDATA {
64
if (SETITEM(my-array $NUMITEMS(my-array) $*) >= 0) {
65
echo ADDED DATA
66
} {
67
echo FAILED TO ADD DATA
68
}
69
}
70
71
DELITEM(array_name item_number)
72
This deletes the item requested from the array. If it is the last item
73
(item zero), it deletes the array. If there are items numbered higher
74
than this item, they will each be moved down. So if we had a 25 item
75
array called "MY-ARRAY" and deleted item 7, items 8 through 24 (remember
76
that a 25 item array is numbered 0 to 24) would be moved down and become
77
items 7 through 23.
78
RETURNS: Zero on success,
79
-1 if unable to find the array,
80
-2 if unable find the item.
81
82
MATCHITEM(array_name pattern)
83
Searches through the items in the array for the item that best matches
84
the pattern, much like the MATCH() function does.
85
RETURNS: zero or a positive number which is the item_number of the match
86
OR -1 if unable to find the array,
87
OR -2 if no match was found in the array
88
89
RMATCHITEM(array_name data_to_look_for)
90
This treats the items in the array as patterns, searching for the
91
pattern in the array that best matches the data_to_look_for, working
92
similarly to the RMATCH() function.
93
RETURNS: zero or a positive number which is the item_number of the match
94
OR -1 if unable to find the array,
95
OR -2 if no match was found in the array
96
97
GETMATCHES(array_name pattern)
98
Seeks all array items that match the pattern.
99
RETURNS: A string containing a space-separated list of item numbers of
100
array elements that match the pattern, or a null string if no
101
matches were found, or if the array was not found.
102
103
GETRMATCHES(array_name data_to_look_for)
104
Treats all array items as patterns, and seeks to find all patterns that
105
match the data_to_look_for.
106
RETURNS: A string containing a space-separated list of item numbers of
107
array elements that match the data, or a null string if no
108
matches were found, or if the array was not found.
109
110
FINDITEM(array_name data_to_search_for)
111
This does a binary search on the items stored in the array and returns
112
the item number of the data. It is an EXACT MATCH search. It is highly
113
case sensitive, using C's strcmp() and not IRCII's caseless comparison
114
functions. I did it this way, because I needed it, so there! ;)
115
RETURNS: zero or a positive number on success -- this number IS the
116
item_number of the first match it found
117
OR -1 if unable to find the array,
118
OR -2 if the item was not found in the array.
119
120
IGETITEM(array_name index_number)
121
This is exactly like GETITEM() except it uses a index number in the same
122
range as the item_number's. It returns the item that corresponds to the
123
internal alphabetized index that these functions maintain. Thus if you
124
access items 0 to 24 of "MY-ARRAY" with this function, you would observe
125
that the items returned came in an almost alphabetized manner. They
126
would not be truly alphabetized because the ordering is done using
127
strcmp() which is case sensitive.
128
RETURNS: the data to which the index refers
129
OR an empty string on failure to find the array or index.
130
131
INDEXTOITEM(array_name index_number)
132
This converts an index_number to an item_number.
133
RETURNS: the item_number that corresponds to the index_number for
134
the array
135
OR -1 if unable to find the array,
136
OR -2 if the index_number was invalid
137
138
ITEMTOINDEX(array_name item_number)
139
This converts an item_number to an index_number.
140
RETURNS: the index_number that corresponds to the item_number for
141
the array
142
OR -1 if unable to find the array,
143
OR -2 if the item_number was invalid
144
145
DELARRAY(array_name)
146
This deletes all items in an array.
147
RETURNS: zero on success, -1 if it couldn't find the array.
148
149
NUMARRAYS()
150
RETURNS: the number of arrays that currently exist.
151
152
GETARRAYS()
153
RETURNS: a string consisting of all the names of all the arrays
154
separated by spaces.
155
156
Thanks,
157
Aaron Gifford
158
Karll on IRC
159
<[email protected]>
160
161
*/
162
/*
163
* FILE: alias.c
164
* WRITTEN BY: Aaron Gifford (Karll on IRC)
165
* DATE: Sat Nov 27 23:00:20 MST 1993
166
*/
167
168
#include "irc.h"
169
static char cvsrevision[] = "$Id: array.c 81 2009-11-24 12:06:54Z keaston $";
170
CVS_REVISION(array_c)
171
172
#include "array.h"
173
#include "ircaux.h"
174
#include "output.h"
175
#undef index
176
177
#define MAIN_SOURCE
178
#include "modval.h"
179
180
#define ARRAY_THRESHOLD 100
181
182
typedef struct an_array_struct {
183
char **item;
184
long *index;
185
long size;
186
} an_array;
187
188
static an_array array_info = {
189
NULL,
190
NULL,
191
0L
192
};
193
194
static an_array *array_array = NULL;
195
196
/*
197
* find_item() does a binary search of array.item[] using array.index[]
198
* to find an exact match of the string *find. If found, it returns the item
199
* number (array.item[item_number]) of the match. Otherwise, it returns a
200
* negative number. The negative number, if made positive again, and then
201
* having 1 subtracted from it, will be the item_number where the string *find
202
* should be inserted into the array.item[]. The function_setitem() makes use
203
* of this attribute.
204
*/
205
extern long find_item (an_array array, char *find)
206
{
207
long top, bottom, key, cmp;
208
209
top = array.size - 1;
210
bottom = 0;
211
212
while (top >= bottom)
213
{
214
key = (top - bottom) / 2 + bottom;
215
cmp = strcmp(find, array.item[array.index[key]]);
216
if (cmp == 0)
217
return key;
218
if (cmp < 0)
219
top = key - 1;
220
else
221
bottom = key + 1;
222
}
223
return -bottom - 1;
224
}
225
226
/*
227
* insert_index() takes a valid index (newIndex) and inserts it into the array
228
* **index, then increments the *size of the index array.
229
*/
230
extern void insert_index (long **index, long *size, long newIndex)
231
{
232
long cnt;
233
234
if (*size)
235
*index = (long *)RESIZE(*index, long, *size + 1);
236
else
237
{
238
*index = (long *)new_malloc(sizeof(long));
239
newIndex = 0;
240
}
241
242
for (cnt = *size; cnt > newIndex; cnt--)
243
(*index)[cnt] = (*index)[cnt - 1];
244
(*index)[newIndex] = *size;
245
(*size)++;
246
}
247
248
/*
249
* move_index() moves the array.index[] up or down to make room for new entries
250
* or to clean up so an entry can be deleted.
251
*/
252
extern void move_index (an_array *array, long oldindex, long newindex)
253
{
254
long temp;
255
256
if (newindex > oldindex)
257
newindex--;
258
if (newindex == oldindex)
259
return;
260
261
temp = array->index[oldindex];
262
263
if (oldindex < newindex)
264
for (; oldindex < newindex; oldindex++)
265
array->index[oldindex] = array->index[oldindex + 1];
266
else
267
for(; oldindex > newindex; oldindex--)
268
array->index[oldindex] = array->index[oldindex - 1];
269
270
array->index[newindex] = temp;
271
}
272
273
/*
274
* find_index() attempts to take an item and discover the index number
275
* that refers to it. find_index() assumes that find_item() WILL always return
276
* a positive or zero result (be successful) because find_index() assumes that
277
* the item is valid, and thus a find will be successful. I don't know what
278
* value ARRAY_THRESHOLD ought to be. I figured someone smarter than I am
279
* could figure it out and tell me or tell me to abandon the entire idea.
280
*/
281
extern long find_index (an_array *array, long item)
282
{
283
long i = 0;
284
285
if (array->size >= ARRAY_THRESHOLD)
286
{
287
i = find_item(*array, array->item[item]);
288
while (i >= 0 && !strcmp(array->item[array->index[i]], array->item[item]))
289
i--;
290
i++;
291
}
292
while(array->index[i] != item && i < array->size)
293
i++;
294
295
if (i == array->size)
296
say("ERROR in find_index()");
297
return i;
298
}
299
300
/*
301
* get_array() searches and finds the array referenced by *name. It returns
302
* a pointer to the array, or a null pointer on failure to find it.
303
*/
304
extern an_array * get_array (char *name)
305
{
306
long index;
307
308
if (array_info.size && *name)
309
{
310
upper(name);
311
if ((index = find_item(array_info, name)) >= 0)
312
return &array_array[array_info.index[index]];
313
}
314
return NULL;
315
}
316
317
318
/*
319
* delete_array() deletes the contents of an entire array. It assumes that
320
* find_item(array_info, name) will succeed and return a valid zero or positive
321
* value.
322
*/
323
extern void delete_array (char *name)
324
{
325
char **ptr;
326
long cnt;
327
long index;
328
long item;
329
an_array *array;
330
331
index = find_item(array_info, name);
332
item = array_info.index[index];
333
array = &array_array[item];
334
for (ptr=array->item, cnt=0; cnt < array->size; cnt++, ptr++)
335
new_free((char **)ptr);
336
new_free((char **)&array->item);
337
new_free((char **)&array->index);
338
339
if (array_info.size > 1)
340
{
341
for(cnt = 0; cnt < array_info.size; cnt++)
342
if (array_info.index[cnt] > item)
343
(array_info.index[cnt])--;
344
move_index(&array_info, index, array_info.size);
345
array_info.size--;
346
for(ptr=&array_info.item[item], cnt=item; cnt < array_info.size; cnt++, ptr++, array++)
347
{
348
*ptr = *(ptr + 1);
349
*array = *(array + 1);
350
}
351
array_info.item = (char**)RESIZE(array_info.item, char *, array_info.size);
352
array_info.index = (long *)RESIZE(array_info.index, long, array_info.size);
353
RESIZE(array_array, an_array, array_info.size);
354
}
355
else
356
{
357
new_free((char **)&array_info.item);
358
new_free((char **)&array_info.index);
359
new_free((char **)&array_array);
360
array_info.size = 0;
361
}
362
}
363
364
void delete_all_arrays(void)
365
{
366
char **ptr;
367
long index;
368
an_array *array;
369
#if 0
370
m_s3cat(&result, space, array_info.item[array_info.index[index]]);
371
#endif
372
for (index = 0; index < array_info.size; index++)
373
{
374
array = &array_array[index];
375
ptr = array->item;
376
while (array->size > 0)
377
{
378
new_free((char **)ptr);
379
ptr++;
380
array->size--;
381
}
382
new_free((char **)&array->item);
383
new_free((char **)&array->index);
384
}
385
for (index = 0; index < array_info.size; index++)
386
{
387
ptr = (char **)&array_info.item[index];
388
new_free(ptr);
389
ptr++;
390
}
391
new_free((char **)&array_info.item);
392
new_free((char **)&array_info.index);
393
new_free((char **)&array_array);
394
array_info.size = 0;
395
}
396
397
/*
398
* Now for the actual alias functions
399
* ==================================
400
*/
401
402
/*
403
* These are the same ones found in alias.c
404
*/
405
#define EMPTY empty_string
406
#define RETURN_EMPTY return m_strdup(EMPTY)
407
#define RETURN_IF_EMPTY(x) if (empty( x )) RETURN_EMPTY
408
#define GET_INT_ARG(x, y) {RETURN_IF_EMPTY(y); x = my_atol(safe_new_next_arg(y, &y));}
409
#define GET_FLOAT_ARG(x, y) {RETURN_IF_EMPTY(y); x = atof(safe_new_next_arg(y, &y));}
410
#define GET_STR_ARG(x, y) {RETURN_IF_EMPTY(y); x = new_next_arg(y, &y);RETURN_IF_EMPTY(x);}
411
#define RETURN_STR(x) return m_strdup(x ? x : EMPTY);
412
#define RETURN_INT(x) return m_strdup(ltoa(x));
413
414
/*
415
* function_matchitem() attempts to match a pattern to the contents of an array
416
* RETURNS -1 if it cannot find the array, or -2 if no matches occur
417
*/
418
BUILT_IN_FUNCTION(function_matchitem)
419
{
420
char *name;
421
long index;
422
an_array *array;
423
long current_match;
424
long best_match = 0;
425
long match = -1;
426
427
if ((name = next_arg(input, &input)) && (array = get_array(name)))
428
{
429
match = -2;
430
if (*input)
431
{
432
for (index = 0; index < array->size; index++)
433
{
434
if ((current_match = wild_match(input, array->item[index])) > best_match)
435
{
436
match = index;
437
best_match = current_match;
438
}
439
}
440
}
441
}
442
443
RETURN_INT(match);
444
}
445
446
BUILT_IN_FUNCTION(function_igetmatches)
447
{
448
char *result = NULL;
449
char *name = NULL;
450
long item;
451
an_array *array;
452
453
if ((name = next_arg(input, &input)) &&
454
(array = get_array(name)) && *input)
455
{
456
if (*input)
457
{
458
for (item = 0; item < array->size; item++)
459
{
460
if (wild_match(input, array->item[item]) > 0)
461
m_s3cat(&result, space, ltoa(find_index(array, item)));
462
}
463
}
464
}
465
466
if (!result)
467
RETURN_EMPTY;
468
469
return result;
470
}
471
472
/*
473
* function_listarray() attempts to list the contents of an array
474
* RETURNS "" if it cannot find the array
475
*/
476
BUILT_IN_FUNCTION(function_listarray)
477
{
478
char *name;
479
an_array *array;
480
long index;
481
char *result = NULL;
482
483
if ((name = next_arg(input, &input)) && (array = get_array(name)))
484
{
485
for (index = 0; index < array->size; index++)
486
m_s3cat(&result, space, array->item[index]);
487
}
488
return result ? result : m_strdup(empty_string);
489
}
490
491
/*
492
* function_getmatches() attempts to match a pattern to the contents of an
493
* array and returns a list of item_numbers of all items that match the pattern
494
* or it returns an empty string if not items matches or if the array was not
495
* found.
496
*/
497
BUILT_IN_FUNCTION(function_getmatches)
498
{
499
char *result = NULL;
500
char *name = NULL;
501
long index;
502
an_array *array;
503
504
if ((name = next_arg(input, &input)) &&
505
(array = get_array(name)) && *input)
506
{
507
if (*input)
508
{
509
for (index = 0; index < array->size; index++)
510
{
511
if (wild_match(input, array->item[index]) > 0)
512
m_s3cat(&result, space, ltoa(index));
513
}
514
}
515
}
516
if (!result)
517
RETURN_EMPTY;
518
return result;
519
}
520
521
/*
522
* function_rmatchitem() attempts to match the input text with an array of
523
* patterns, much like RMATCH()
524
* RETURNS -1 if it cannot find the array, or -2 if no matches occur
525
*/
526
BUILT_IN_FUNCTION(function_rmatchitem)
527
{
528
char *name = NULL;
529
long index;
530
an_array *array;
531
long current_match;
532
long best_match = 0;
533
long match = -1;
534
535
if ((name = next_arg(input, &input)) && (array = get_array(name)))
536
{
537
match = -2;
538
if (*input)
539
{
540
for (index = 0; index < array->size; index++)
541
{
542
if ((current_match = wild_match(array->item[index], input)) > best_match)
543
{
544
match = index;
545
best_match = current_match;
546
}
547
}
548
}
549
}
550
RETURN_INT(match)
551
}
552
553
/*
554
* function_getrmatches() attempts to match the input text with an array of
555
* patterns, and returns a list of item_numbers of all patterns that match the
556
* given text, or it returns a null string if no matches occur or if the array
557
* was not found.
558
*/
559
BUILT_IN_FUNCTION(function_getrmatches)
560
{
561
char *result = NULL;
562
char *name = NULL;
563
long index;
564
an_array *array;
565
566
if ((name = next_arg(input, &input)) && (array = get_array(name)))
567
{
568
if (*input)
569
{
570
for (index = 0; index < array->size; index++)
571
{
572
if (wild_match(array->item[index], input) > 0)
573
m_s3cat(&result, space, ltoa(index));
574
}
575
}
576
}
577
578
if (!result)
579
RETURN_EMPTY;
580
return result;
581
}
582
583
/*
584
* function_numitems() returns the number of items in an array, or -1 if unable
585
* to find the array
586
*/
587
BUILT_IN_FUNCTION(function_numitems)
588
{
589
char *name = NULL;
590
an_array *array;
591
long items = 0;
592
593
if ((name = next_arg(input, &input)) && (array = get_array(name)))
594
items = array->size;
595
596
RETURN_INT(items);
597
}
598
599
/*
600
* function_getitem() returns the value of the specified item of an array, or
601
* returns an empty string on failure to find the item or array
602
*/
603
BUILT_IN_FUNCTION(function_getitem)
604
{
605
char *name = NULL;
606
char *itemstr = NULL;
607
long item;
608
an_array *array;
609
char *found = NULL;
610
611
if ((name = next_arg(input, &input)) && (array = get_array(name)))
612
{
613
if ((itemstr = next_arg(input, &input)))
614
{
615
item = my_atol(itemstr);
616
if (item >= 0 && item < array->size)
617
found = array->item[item];
618
}
619
}
620
RETURN_STR(found);
621
}
622
623
/*
624
* function_setitem() sets an item of an array to a value, or creates a new
625
* array if the array doesn not already exist and the item number is zero, or
626
* it adds a new item to an existing array if the item number is one more than
627
* the prevously largest item number in the array.
628
* RETURNS: 0 on success
629
* 1 on success if a new item was added to an existing array
630
* 2 on success if a new array was created and item zero was set
631
* -1 if it is unable to find the array (and item number was not zero)
632
* -2 if it was unable to find the item (item < 0 or item was greater
633
* than 1 + the prevous maximum item number
634
*/
635
BUILT_IN_FUNCTION(function_setitem)
636
{
637
char *name = NULL;
638
char *itemstr = NULL;
639
long item;
640
long index = 0;
641
long oldindex;
642
an_array *array;
643
int result = -1;
644
645
if ((name = next_arg(input, &input)))
646
{
647
if (strlen(name) && (itemstr = next_arg(input, &input)))
648
{
649
item = my_atol(itemstr);
650
if (item >= 0)
651
{
652
upper(name);
653
if (array_info.size && ((index = find_item(array_info, name)) >= 0))
654
{
655
array = &array_array[array_info.index[index]];
656
result = -2;
657
if (item < array->size)
658
{
659
oldindex = find_index(array, item);
660
index = find_item(*array, input);
661
index = (index >= 0) ? index : (-index) - 1;
662
move_index(array, oldindex, index);
663
new_free(&array->item[item]);
664
malloc_strcpy(&array->item[item], input);
665
result = 0;
666
}
667
else if (item == array->size)
668
{
669
array->item = (char **)RESIZE(array->item, char *, (array->size + 1));
670
array->item[item] = NULL;
671
malloc_strcpy(&array->item[item], input);
672
index = find_item(*array, input);
673
index = (index >= 0) ? index : (-index) - 1;
674
insert_index(&array->index, &array->size, index);
675
result = 2;
676
}
677
}
678
else
679
{
680
if (item == 0)
681
{
682
if (array_info.size)
683
RESIZE(array_array, an_array, (array_info.size + 1));
684
else
685
array_array = (an_array*)new_malloc(sizeof(an_array));
686
array = &array_array[array_info.size];
687
array->size = 1;
688
array->item = (char **)new_malloc(sizeof(char *));
689
array->index = (long *)new_malloc(sizeof(long));
690
array->item[0] = (char*) 0;
691
array->index[0] = 0;
692
malloc_strcpy(&array->item[0], input);
693
if (array_info.size)
694
array_info.item = (char **)RESIZE(array_info.item, char *, (array_info.size + 1));
695
else
696
array_info.item = (char **)new_malloc(sizeof(char *));
697
array_info.item[array_info.size] = NULL;
698
malloc_strcpy(&array_info.item[array_info.size], name);
699
insert_index(&array_info.index, &array_info.size, (-index) - 1);
700
result = 1;
701
}
702
}
703
}
704
}
705
}
706
RETURN_INT(result);
707
}
708
709
/*
710
* function_getarrays() returns a string containg the names of all currently
711
* existing arrays separated by spaces
712
*/
713
BUILT_IN_FUNCTION(function_getarrays)
714
{
715
long index;
716
char *result = NULL;
717
718
for (index = 0; index < array_info.size; index++)
719
if (!input || !*input || wild_match(input, array_info.item[array_info.index[index]]))
720
m_s3cat(&result, space, array_info.item[array_info.index[index]]);
721
722
if (!result)
723
RETURN_EMPTY;
724
725
return result;
726
}
727
728
/*
729
* function_numarrays() returns the number of currently existing arrays
730
*/
731
BUILT_IN_FUNCTION(function_numarrays)
732
{
733
RETURN_INT(array_info.size)
734
}
735
736
/*
737
* function_finditem() does a binary search and returns the item number of
738
* the string that exactly matches the string searched for, or it returns
739
* -1 if unable to find the array, or -2 if unable to find the item.
740
*/
741
BUILT_IN_FUNCTION(function_finditem)
742
{
743
char *name = NULL;
744
an_array *array;
745
long item = -1;
746
747
if ((name = next_arg(input, &input)) && (array = get_array(name)))
748
{
749
if (*input)
750
{
751
item = find_item(*array, input);
752
item = (item >= 0) ? array->index[item] : -2;
753
}
754
}
755
RETURN_INT(item)
756
}
757
758
/*
759
* function_ifinditem() does a binary search and returns the index number of
760
* the string that exactly matches the string searched for, or it returns
761
* -1 if unable to find the array, or -2 if unable to find the item.
762
*/
763
BUILT_IN_FUNCTION(function_ifinditem)
764
{
765
char *name = NULL;
766
an_array *array;
767
long item = -1;
768
769
if ((name = next_arg(input, &input)) && (array = get_array(name)))
770
{
771
if (*input)
772
{
773
if ((item = find_item(*array, input)) < 0)
774
item = -2;
775
}
776
}
777
RETURN_INT(item)
778
}
779
780
/*
781
* function_igetitem() returns the item referred to by the passed-in index
782
* or returns an empty string if unable to find the array or if the index was
783
* invalid.
784
*/
785
BUILT_IN_FUNCTION(function_igetitem)
786
{
787
char *name = NULL;
788
char *itemstr = NULL;
789
long item;
790
an_array *array;
791
char *found = NULL;
792
793
if ((name = next_arg(input, &input)) && (array = get_array(name)))
794
{
795
if ((itemstr = next_arg(input, &input)))
796
{
797
item = my_atol(itemstr);
798
if (item >= 0 && item < array->size)
799
found = array->item[array->index[item]];
800
}
801
}
802
RETURN_STR(found)
803
}
804
805
/*
806
* function_indextoitem() converts an index number to an item number for the
807
* specified array. It returns a valid item number, or -1 if unable to find
808
* the array, or -2 if the index was invalid.
809
*/
810
BUILT_IN_FUNCTION(function_indextoitem)
811
{
812
char *name = NULL;
813
char *itemstr = NULL;
814
long item;
815
an_array *array;
816
long found = -1;
817
818
if ((name = next_arg(input, &input)) && (array = get_array(name)))
819
{
820
found = -2;
821
if ((itemstr = next_arg(input, &input)))
822
{
823
item = my_atol(itemstr);
824
if (item >= 0 && item < array->size)
825
found = array->index[item];
826
}
827
}
828
RETURN_INT(found)
829
}
830
831
/*
832
* function_itemtoindex() takes an item number and searches for the index that
833
* refers to the item. It returns the index number, or -1 if unable to find
834
* the array, or -2 if the item was invalid.
835
*/
836
BUILT_IN_FUNCTION(function_itemtoindex)
837
{
838
char *name;
839
char *itemstr;
840
long item;
841
an_array *array;
842
long found = -1;
843
844
if ((name = next_arg(input, &input)) && (array = get_array(name)))
845
{
846
found = -2;
847
if ((itemstr = next_arg(input, &input)))
848
{
849
item = my_atol(itemstr);
850
if (item >= 0 && item < array->size)
851
found = find_index(array, item);
852
}
853
}
854
RETURN_INT(found)
855
}
856
857
/*
858
* function_delitem() deletes an item of an array and moves the contents of the
859
* array that were stored "above" the item down by one. It returns 0 (zero)
860
* on success, -1 if unable to find the array, -2 if unable to find the item.
861
* Also, if the item is the last item in the array, it deletes the array.
862
*/
863
BUILT_IN_FUNCTION(function_delitem)
864
{
865
char *name;
866
char *itemstr;
867
char **strptr;
868
long item;
869
long cnt;
870
long oldindex;
871
an_array *array;
872
long found = -1;
873
874
if ((name = next_arg(input, &input)) && (array = get_array(name)))
875
{
876
found = -2;
877
if ((itemstr = next_arg(input, &input)))
878
{
879
item = my_atol(itemstr);
880
if (item >= 0 && item < array->size)
881
{
882
if (array->size == 1)
883
delete_array(name);
884
else
885
{
886
oldindex = find_index(array, item);
887
for(cnt = 0; cnt < array->size; cnt++)
888
if (array->index[cnt] > item)
889
(array->index[cnt])--;
890
move_index(array, oldindex, array->size);
891
new_free(&array->item[item]);
892
array->size--;
893
for(strptr=&(array->item[item]), cnt=item; cnt < array->size; cnt++, strptr++)
894
*strptr = *(strptr + 1);
895
array->item = (char**)RESIZE(array->item, char *, array->size);
896
array->index = (long*)RESIZE(array->index, long, array->size);
897
}
898
found = 0;
899
}
900
}
901
}
902
RETURN_INT(found)
903
}
904
905
/*
906
* function_delarray() deletes the entire contents of the array using the
907
* delete_array() function above. It returns 0 on success, -1 on failure.
908
*/
909
BUILT_IN_FUNCTION(function_delarray)
910
{
911
char *name;
912
long found = -1;
913
914
if ((name = next_arg(input, &input)) && (get_array(name)))
915
{
916
delete_array(name);
917
found = 0;
918
}
919
RETURN_INT(found)
920
}
921
/*
922
* function_ifindfirst() returns the first index of an exact match with the
923
* search string, or returns -2 if unable to find the array, or -1 if unable
924
* to find any matches.
925
*/
926
BUILT_IN_FUNCTION(function_ifindfirst)
927
{
928
char *name;
929
an_array *array;
930
long item = -1;
931
932
if ((name = next_arg(input, &input)) && (array = get_array(name)))
933
{
934
if (*input)
935
{
936
if ((item = find_item(*array, input)) < 0)
937
item = -2;
938
else
939
{
940
while (item >= 0 && !strcmp(array->item[array->index[item]], input))
941
item--;
942
item++;
943
}
944
}
945
}
946
RETURN_INT(item)
947
}
948
949
/*
950
* Given an array name with various strings in it, we wild_match() against
951
* the elements within the array. This allows parsing using % and *
952
* for wildcards. We return only the best match from the array, unlike
953
* getmatch() which returns ALL the matching items.
954
*/
955
956
BUILT_IN_FUNCTION(function_gettmatch)
957
{
958
char *name;
959
an_array *array;
960
char *ret = NULL;
961
#if 0
962
<shade> gettmatch(users % user@host *) would match the userhost mask in the
963
second word of the array
964
#endif
965
if ((name = next_arg(input, &input)) && (array = get_array(name)))
966
{
967
if (*input)
968
{
969
int index, current_match;
970
int best_match = 0;
971
int match = -1;
972
for (index = 0; index < array->size; index++)
973
{
974
if ((current_match = wild_match(input, array->item[index])) > best_match)
975
{
976
match = index;
977
best_match = current_match;
978
}
979
}
980
if (match != -1)
981
ret = array->item[match];
982
983
}
984
}
985
RETURN_STR(ret);
986
}
987
988
BUILT_IN_FUNCTION(function_igetrmatches)
989
{
990
char *result = (char *) 0;
991
char *name = (char *) 0;
992
long item;
993
an_array *array;
994
995
if ((name = next_arg(input, &input)) &&
996
(array = get_array(name)) && *input)
997
{
998
if (*input)
999
{
1000
for (item = 0; item < array->size; item++)
1001
{
1002
if (wild_match(array->item[item], input) > 0)
1003
m_s3cat(&result, space, ltoa(find_index(array, item)));
1004
}
1005
}
1006
}
1007
1008
if (!result)
1009
RETURN_EMPTY;
1010
1011
return result;
1012
}
1013
1014