summaryrefslogtreecommitdiff
path: root/av.c
diff options
context:
space:
mode:
Diffstat (limited to 'av.c')
-rw-r--r--av.c333
1 files changed, 333 insertions, 0 deletions
diff --git a/av.c b/av.c
new file mode 100644
index 0000000000..ee7a30a061
--- /dev/null
+++ b/av.c
@@ -0,0 +1,333 @@
+/* $RCSfile: array.c,v $$Revision: 4.1 $$Date: 92/08/07 17:18:22 $
+ *
+ * Copyright (c) 1991, Larry Wall
+ *
+ * You may distribute under the terms of either the GNU General Public
+ * License or the Artistic License, as specified in the README file.
+ *
+ * $Log: array.c,v $
+ * Revision 4.1 92/08/07 17:18:22 lwall
+ * Stage 6 Snapshot
+ *
+ * Revision 4.0.1.3 92/06/08 11:45:05 lwall
+ * patch20: Perl now distinguishes overlapped copies from non-overlapped
+ *
+ * Revision 4.0.1.2 91/11/05 16:00:14 lwall
+ * patch11: random cleanup
+ * patch11: passing non-existend array elements to subrouting caused core dump
+ *
+ * Revision 4.0.1.1 91/06/07 10:19:08 lwall
+ * patch4: new copyright notice
+ *
+ * Revision 4.0 91/03/20 01:03:32 lwall
+ * 4.0 baseline.
+ *
+ */
+
+#include "EXTERN.h"
+#include "perl.h"
+
+SV**
+av_fetch(ar,key,lval)
+register AV *ar;
+I32 key;
+I32 lval;
+{
+ SV *sv;
+
+ if (key < 0 || key > AvFILL(ar)) {
+ if (lval && key >= 0) {
+ if (AvREAL(ar))
+ sv = NEWSV(5,0);
+ else
+ sv = sv_mortalcopy(&sv_undef);
+ return av_store(ar,key,sv);
+ }
+ else
+ return 0;
+ }
+ if (!AvARRAY(ar)[key]) {
+ if (lval) {
+ sv = NEWSV(6,0);
+ return av_store(ar,key,sv);
+ }
+ return 0;
+ }
+ return &AvARRAY(ar)[key];
+}
+
+SV**
+av_store(ar,key,val)
+register AV *ar;
+I32 key;
+SV *val;
+{
+ I32 tmp;
+ SV** ary;
+
+ if (key < 0)
+ return 0;
+ if (key > AvMAX(ar)) {
+ I32 newmax;
+
+ if (AvALLOC(ar) != AvARRAY(ar)) {
+ tmp = AvARRAY(ar) - AvALLOC(ar);
+ Move(AvARRAY(ar), AvALLOC(ar), AvMAX(ar)+1, SV*);
+ Zero(AvALLOC(ar)+AvMAX(ar)+1, tmp, SV*);
+ AvMAX(ar) += tmp;
+ AvARRAY(ar) -= tmp;
+ if (key > AvMAX(ar) - 10) {
+ newmax = key + AvMAX(ar);
+ goto resize;
+ }
+ }
+ else {
+ if (AvALLOC(ar)) {
+ newmax = key + AvMAX(ar) / 5;
+ resize:
+ Renew(AvALLOC(ar),newmax+1, SV*);
+ Zero(&AvALLOC(ar)[AvMAX(ar)+1], newmax - AvMAX(ar), SV*);
+ }
+ else {
+ newmax = key < 4 ? 4 : key;
+ Newz(2,AvALLOC(ar), newmax+1, SV*);
+ }
+ AvARRAY(ar) = AvALLOC(ar);
+ AvMAX(ar) = newmax;
+ }
+ }
+ ary = AvARRAY(ar);
+ if (AvREAL(ar)) {
+ if (AvFILL(ar) < key) {
+ while (++AvFILL(ar) < key) {
+ if (ary[AvFILL(ar)] != Nullsv) {
+ sv_free(ary[AvFILL(ar)]);
+ ary[AvFILL(ar)] = Nullsv;
+ }
+ }
+ }
+ if (ary[key])
+ sv_free(ary[key]);
+ }
+ ary[key] = val;
+ return &ary[key];
+}
+
+AV *
+newAV()
+{
+ register AV *ar;
+
+ Newz(1,ar,1,AV);
+ SvREFCNT(ar) = 1;
+ sv_upgrade(ar,SVt_PVAV);
+ AvREAL_on(ar);
+ AvALLOC(ar) = AvARRAY(ar) = 0;
+ AvMAX(ar) = AvFILL(ar) = -1;
+ return ar;
+}
+
+AV *
+av_make(size,strp)
+register I32 size;
+register SV **strp;
+{
+ register AV *ar;
+ register I32 i;
+ register SV** ary;
+
+ Newz(3,ar,1,AV);
+ sv_upgrade(ar,SVt_PVAV);
+ New(4,ary,size+1,SV*);
+ AvALLOC(ar) = ary;
+ Zero(ary,size,SV*);
+ AvREAL_on(ar);
+ AvARRAY(ar) = ary;
+ AvFILL(ar) = size - 1;
+ AvMAX(ar) = size - 1;
+ for (i = 0; i < size; i++) {
+ if (*strp) {
+ ary[i] = NEWSV(7,0);
+ sv_setsv(ary[i], *strp);
+ }
+ strp++;
+ }
+ return ar;
+}
+
+AV *
+av_fake(size,strp)
+register I32 size;
+register SV **strp;
+{
+ register AV *ar;
+ register SV** ary;
+
+ Newz(3,ar,1,AV);
+ SvREFCNT(ar) = 1;
+ sv_upgrade(ar,SVt_PVAV);
+ New(4,ary,size+1,SV*);
+ AvALLOC(ar) = ary;
+ Copy(strp,ary,size,SV*);
+ AvREAL_off(ar);
+ AvARRAY(ar) = ary;
+ AvFILL(ar) = size - 1;
+ AvMAX(ar) = size - 1;
+ while (size--) {
+ if (*strp)
+ SvTEMP_off(*strp);
+ strp++;
+ }
+ return ar;
+}
+
+void
+av_clear(ar)
+register AV *ar;
+{
+ register I32 key;
+
+ if (!ar || !AvREAL(ar) || AvMAX(ar) < 0)
+ return;
+ /*SUPPRESS 560*/
+ if (key = AvARRAY(ar) - AvALLOC(ar)) {
+ AvMAX(ar) += key;
+ AvARRAY(ar) -= key;
+ }
+ for (key = 0; key <= AvMAX(ar); key++)
+ sv_free(AvARRAY(ar)[key]);
+ AvFILL(ar) = -1;
+ Zero(AvARRAY(ar), AvMAX(ar)+1, SV*);
+}
+
+void
+av_undef(ar)
+register AV *ar;
+{
+ register I32 key;
+
+ if (!ar)
+ return;
+ /*SUPPRESS 560*/
+ if (key = AvARRAY(ar) - AvALLOC(ar)) {
+ AvMAX(ar) += key;
+ AvARRAY(ar) -= key;
+ }
+ if (AvREAL(ar)) {
+ for (key = 0; key <= AvMAX(ar); key++)
+ sv_free(AvARRAY(ar)[key]);
+ }
+ Safefree(AvALLOC(ar));
+ AvALLOC(ar) = AvARRAY(ar) = 0;
+ AvMAX(ar) = AvFILL(ar) = -1;
+}
+
+void
+av_free(ar)
+AV *ar;
+{
+ av_undef(ar);
+ Safefree(ar);
+}
+
+bool
+av_push(ar,val)
+register AV *ar;
+SV *val;
+{
+ return av_store(ar,++(AvFILL(ar)),val) != 0;
+}
+
+SV *
+av_pop(ar)
+register AV *ar;
+{
+ SV *retval;
+
+ if (AvFILL(ar) < 0)
+ return Nullsv;
+ retval = AvARRAY(ar)[AvFILL(ar)];
+ AvARRAY(ar)[AvFILL(ar)--] = Nullsv;
+ return retval;
+}
+
+void
+av_popnulls(ar)
+register AV *ar;
+{
+ register I32 fill = AvFILL(ar);
+
+ while (fill >= 0 && !AvARRAY(ar)[fill])
+ fill--;
+ AvFILL(ar) = fill;
+}
+
+void
+av_unshift(ar,num)
+register AV *ar;
+register I32 num;
+{
+ register I32 i;
+ register SV **sstr,**dstr;
+
+ if (num <= 0)
+ return;
+ if (AvARRAY(ar) - AvALLOC(ar) >= num) {
+ AvMAX(ar) += num;
+ AvFILL(ar) += num;
+ while (num--)
+ *--AvARRAY(ar) = Nullsv;
+ }
+ else {
+ (void)av_store(ar,AvFILL(ar)+num,(SV*)0); /* maybe extend array */
+ dstr = AvARRAY(ar) + AvFILL(ar);
+ sstr = dstr - num;
+#ifdef BUGGY_MSC5
+ # pragma loop_opt(off) /* don't loop-optimize the following code */
+#endif /* BUGGY_MSC5 */
+ for (i = AvFILL(ar) - num; i >= 0; i--) {
+ *dstr-- = *sstr--;
+#ifdef BUGGY_MSC5
+ # pragma loop_opt() /* loop-optimization back to command-line setting */
+#endif /* BUGGY_MSC5 */
+ }
+ Zero(AvARRAY(ar), num, SV*);
+ }
+}
+
+SV *
+av_shift(ar)
+register AV *ar;
+{
+ SV *retval;
+
+ if (AvFILL(ar) < 0)
+ return Nullsv;
+ retval = *AvARRAY(ar);
+ *(AvARRAY(ar)++) = Nullsv;
+ AvMAX(ar)--;
+ AvFILL(ar)--;
+ return retval;
+}
+
+I32
+av_len(ar)
+register AV *ar;
+{
+ return AvFILL(ar);
+}
+
+void
+av_fill(ar, fill)
+register AV *ar;
+I32 fill;
+{
+ if (fill < 0)
+ fill = -1;
+ if (fill <= AvMAX(ar))
+ AvFILL(ar) = fill;
+ else {
+ AvFILL(ar) = fill - 1; /* don't clobber in-between values */
+ (void)av_store(ar,fill,Nullsv);
+ }
+}