/* * File: ocat.c * Contents: cat, lconcat */ #include "..\h\config.h" #include "..\h\rt.h" #include "rproto.h" /* * x || y - concatenate strings x and y. */ OpDcl(cater,2,"||") { char sbuf1[MaxCvtLen]; /* buffers for conversion to string */ char sbuf2[MaxCvtLen]; /* * Convert arguments to strings if necessary. */ if (cvstr(&Arg1, sbuf1) == CvtFail) RunErr(103, &Arg1); if (cvstr(&Arg2, sbuf2) == CvtFail) RunErr(103, &Arg2); if (StrLoc(Arg1) + StrLen(Arg1) == strfree) { /* * The end of Arg1 is at the end of the string space. Hence, * Arg1 was the last string allocated. Arg1 is not copied. * Instead, Arg2 is appended to the string space and the * result is pointed to the start of Arg1. * Space is only needed for the string being appended */ if (strreq(StrLen(Arg2)) == Error) RunErr(0, NULL); StrLoc(Arg0) = StrLoc(Arg1); } else { /* * Ensure space for the resulting concatenated string */ if (strreq(StrLen(Arg1) + StrLen(Arg2)) == Error) RunErr(0, NULL); /* * Otherwise, append Arg1 to the end of the string space and * point the result to the start of Arg1. */ StrLoc(Arg0) = alcstr(StrLoc(Arg1),StrLen(Arg1)); } /* * Append Arg2 to the end of the string space. */ alcstr(StrLoc(Arg2),StrLen(Arg2)); /* * Set the length of the result and return. */ StrLen(Arg0) = StrLen(Arg1) + StrLen(Arg2); Return; } /* * x ||| y - concatenate lists x and y. */ OpDcl(lconcat,2,"|||") { register struct b_list *bp1, *bp2; register struct b_lelem *lp1, *lp2; word size1, size2; /* * x and y must be lists. */ if (Arg1.dword != D_List) RunErr(108, &Arg1); if (Arg2.dword != D_List) RunErr(108, &Arg2); /* * Get the size of both lists. */ size1 = BlkLoc(Arg1)->list.size; size2 = BlkLoc(Arg2)->list.size; /* * Make a copy of both lists. */ if (cplist(&Arg1, &Arg1, (word)1, size1 + 1) == Error) RunErr(0, NULL); if (cplist(&Arg2, &Arg2, (word)1, size2 + 1) == Error) RunErr(0, NULL); /* * Get a pointer to both lists. bp1 points to the copy of Arg1 and is * the list that will be returned. */ bp1 = (struct b_list *) BlkLoc(Arg1); bp2 = (struct b_list *) BlkLoc(Arg2); /* * Perform the concatenation by hooking the lists together. */ lp1 = (struct b_lelem *) bp1->listtail; lp2 = (struct b_lelem *) bp2->listhead; lp1->listnext = (union block *) lp2; lp2->listprev = (union block *) lp1; /* * Adjust the size field to reflect the length of the concatenated lists. */ bp1->size = size1 + size2; bp1->listtail = bp2->listtail; Arg0 = Arg1; Return; }