home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * Prototypes.
- */
-
- hidden int expand_wildcard Params((dptr, dptr));
- extern char *dirscan Params((const char *));
-
- #include "kernel.h"
- #include "swis.h"
-
- /*
- * Swi(swi,r0,r1,...)
- */
- FncDclV(Swi)
- {
- unsigned int swi_num;
- word nslots;
- int i;
- char sbuf[MaxCvtLen];
-
- struct b_list *hp;
- struct b_lelem *bp;
-
- _kernel_swi_regs regs;
-
- if (nargs < 1)
- RunErr(-101, NULL);
-
- /*
- * Get the SWI number from Arg1.
- */
- if (Qual(Arg1))
- {
- qtos(&Arg1,sbuf);
-
- regs.r[1] = (int)StrLoc(Arg1);
- if (_kernel_swi(OS_SWINumberFromString,®s,®s) != NULL)
- RunErr(-216, NULL);
-
- swi_num = regs.r[0];
- }
- else switch(Type(Arg1))
- {
- case T_Integer:
- swi_num = (int)IntVal(Arg1);
- break;
- default:
- RunErr(123,&Arg1);
- }
-
- /*
- * Pick up the register values from the following arguments
- */
- for (i = 2; i <= nargs; ++i)
- {
- if (cvint(&Arg(i)) == CvtFail)
- RunErr(101,&Arg(i));
-
- regs.r[i-2] = (int)IntVal(Arg(i));
- }
-
- for (i = nargs-1; i < 10; ++i)
- regs.r[i] = 0;
-
- if (_kernel_swi(swi_num,®s,®s) != NULL)
- Fail;
-
- /*
- * Return the values.
- */
- nslots = Max(MinListSlots,10);
- if (blkreq((word)sizeof(struct b_list) + sizeof(struct b_lelem) +
- (nslots - 1) * sizeof(struct descrip)) == Error)
- {
- RunErr(0, NULL);
- }
-
- hp = alclist((word)10);
- bp = alclstb(nslots,(word)0,(word)10);
- hp->listhead = hp->listtail = (union block *) bp;
-
- /* returns [r0,r1,r2,r3,r4,r5,r6,r7,r8,r9] */
-
- MakeInt((uword)regs.r[0],&(bp->lslots[0]));
- MakeInt((uword)regs.r[1],&(bp->lslots[1]));
- MakeInt((uword)regs.r[2],&(bp->lslots[2]));
- MakeInt((uword)regs.r[3],&(bp->lslots[3]));
- MakeInt((uword)regs.r[4],&(bp->lslots[4]));
- MakeInt((uword)regs.r[5],&(bp->lslots[5]));
- MakeInt((uword)regs.r[6],&(bp->lslots[6]));
- MakeInt((uword)regs.r[7],&(bp->lslots[7]));
- MakeInt((uword)regs.r[8],&(bp->lslots[8]));
- MakeInt((uword)regs.r[9],&(bp->lslots[9]));
-
- ArgType(0) = D_List;
- Arg(0).vword.bptr = (union block *) hp;
- Return;
- }
-
- /*
- * peek(addr,len)
- */
-
- FncDcl(Peek,2)
- {
- if (defshort(&Arg2,1) == Error) {
- RunErr(0, NULL);
- }
-
- switch (Type(Arg1)) {
- case T_Integer:
- StrLoc(Arg0) = (char *)(Arg1.vword.integr);
- break;
- default:
- RunErr(101,&Arg1);
- }
-
- switch (Type(Arg2)) {
- case T_Integer:
- StrLen(Arg0) = Arg2.vword.integr;
- break;
- default:
- RunErr(101, &Arg2);
- }
-
- Return;
- }
-
- /*
- * poke(addr,s)
- */
-
- FncDcl(Poke,2)
- {
- register char *s1,*s2;
- register word l;
- char *addr;
-
- switch (Type(Arg1)) {
- case T_Integer:
- addr = (char *)(Arg1.vword.integr);
- break;
- default:
- RunErr(101,&Arg1);
- }
-
- if (!Qual(Arg2)) {
- RunErr(103, &Arg2);
- }
-
- l = StrLen(Arg2);
- s1 = StrLoc(Arg2);
- s2 = addr;
-
- memcopy(s2,s1,l); /* Copy... */
-
- Return;
- }
-
- /*
- * Getspace(i)
- */
-
- FncDcl(GetSpace,1)
- {
- char *addr;
- uword u;
- int size;
-
- if (cvint(&Arg1) == CvtFail) {
- RunErr(101, &Arg1);
- }
-
- size = (int)IntVal(Arg1);
- addr = (char *)calloc(size,sizeof(char));
- if (addr == NULL)
- Fail;
-
- u = (uword)addr;
- MakeInt(u,&Arg0);
- Return;
- }
-
- /*
- * FreeSpace(a)
- */
-
- FncDcl(FreeSpace,1)
- {
- uword u;
- char *addr;
-
- switch (Type(Arg1)) {
- case T_Integer:
- u = Arg1.vword.integr;
- break;
- default:
- RunErr(101, &Arg1);
- }
- addr = (char *)u;
- free((pointer)addr);
- Return;
- }
-
- /*
- * Wildcard(l)
- */
-
- FncDcl(Wildcard,1)
- {
- word nslots;
-
- register struct b_list *hp;
- register struct b_lelem *bp;
- register dptr dp;
- register union block *pb;
- int i, j;
-
- /*
- * Create an initially empty list. This list will be used to
- * build the final result.
- */
- nslots = MinListSlots;
-
- if (blkreq((word)sizeof(struct b_list) + sizeof(struct b_lelem) +
- (nslots - 1) * sizeof(struct descrip)) == Error)
- {
- RunErr(0, NULL);
- }
-
- hp = alclist((word)0);
- bp = alclstb(nslots,(word)0,(word)0);
- hp->listhead = hp->listtail = (union block *) bp;
-
- /*
- * Put the new empty list into Arg0, for safe keeping if a
- * garbage collection occurs
- */
- ArgType(0) = D_List;
- Arg(0).vword.bptr = (union block *) hp;
-
- /*
- * Now, we are ready to start adding in the file names. If Arg1
- * is a list, we must handle each element in turn. Otherwise,
- * we convert Arg1 to a string, and handle it once. We use the
- * auxiliary function expand_wildcard to expand each value in
- * turn.
- */
- if (ArgType(1) == D_List)
- {
- pb = BlkLoc(Arg1);
- for (pb = pb->list.listhead; pb != NULL; pb = pb->lelem.listnext)
- {
- for (i = 0; i < pb->lelem.nused; ++i)
- {
- j = pb->lelem.first + i;
- if (j >= pb->lelem.nslots)
- j -= pb->lelem.nslots;
-
- dp = &pb->lelem.lslots[j];
- BlkLoc(Arg1) = pb; /* save in Arg1 as pb is untended */
-
- if (expand_wildcard(&Arg0, dp) == Error)
- RunErr(0, NULL);
-
- pb = BlkLoc(Arg1); /* pb is untended, so must reset */
- }
- }
- }
- else
- {
- if (expand_wildcard(&Arg0, &Arg1) == Error)
- RunErr(0, NULL);
- }
-
- Return;
- }
-
- hidden int expand_wildcard (arg, dp)
- dptr arg;
- dptr dp;
- {
- register word i;
- register struct b_list *hp;
- register struct b_lelem *bp;
-
- int len;
- char *name;
- char sbuf[MaxCvtLen];
-
- /*
- * Convert the filename pattern to a string
- */
- switch (cvstr(dp,sbuf))
- {
- case Cvt:
- break; /* Already null-terminated */
-
- case NoCvt:
- qtos(dp,sbuf);
- break;
-
- default:
- RetError(103, *dp);
- }
-
- for (name = dirscan(StrLoc(*dp)); name; name = dirscan(0))
- {
- /*
- * Request space for the new string now, to avoid the need
- * for setting up hp and bp repeatedly later
- */
- len = strlen(name);
- if (strreq(len) == Error)
- return Error;
-
- /*
- * Point hp at the list-header block and bp at the
- * last list-element block.
- */
- hp = (struct b_list *) BlkLoc(*arg);
- bp = (struct b_lelem *) hp->listtail;
-
- /*
- * If the last list-element block is full, allocate a new
- * list-element block, make it the last list-element block,
- * and make it the next block of the former last list-element
- * block.
- */
- if (bp->nused >= bp->nslots)
- {
- /*
- * Set i to the size of block to allocate.
- */
- i = hp->size / 2;
- if (i < MinListSlots)
- i = MinListSlots;
-
- /*
- * Ensure space for a new list element block. If the block
- * can't be allocated, try smaller blocks.
- */
- while (blkreq((word)sizeof(struct b_lelem) +
- i * sizeof(struct descrip)) == Error)
- {
- i /= 4;
- if (i < MinListSlots)
- return Error;
- }
-
- /*
- * Reset hp in case there was a garbage collection.
- */
- hp = (struct b_list *) BlkLoc(*arg);
-
- bp = alclstb(i, (word)0, (word)0);
- hp->listtail->lelem.listnext = (union block *) bp;
- bp->listprev = hp->listtail;
- hp->listtail = (union block *) bp;
- }
-
- /*
- * Set i to position of new last element
- */
- i = bp->first + bp->nused;
- if (i >= bp->nslots)
- i -= bp->nslots;
-
- /*
- * Now create a new string descriptor, and add it to the list
- */
- StrLen(bp->lslots[i]) = len;
- StrLoc(bp->lslots[i]) = alcstr(name, len);
-
- /*
- * Adjust block usage count and current list size.
- */
- bp->nused++;
- hp->size++;
- }
-
- return Success;
- }
-