Commit | Line | Data |
---|---|---|
654e6e2d JF |
1 | #include "global.h" |
2 | #include "chkrtab.h" | |
3 | ||
4 | /*=========================================== | |
5 | - | |
6 | - explode functions | |
7 | - The following function partially implement two explode functions, | |
8 | - explodec and exploden. They only work for atom arguments. | |
9 | - | |
10 | -===========================================*/ | |
11 | ||
12 | #include "chars.h" | |
13 | lispval | |
14 | Lexpldx(kind,slashify) | |
15 | int kind, slashify; /* 0=explodec 1=exploden */ | |
16 | { | |
17 | int typ, i; | |
18 | char ch, *strb, strbb[BUFSIZ]; /* temporary string buffer */ | |
19 | register lispval last, handy; | |
20 | char Idqc = Xdqc; | |
21 | snpand(4); /* kludge register save mask */ | |
22 | ||
23 | chkarg(1); | |
24 | ||
25 | handy = Vreadtable->clb; | |
26 | chkrtab(handy); | |
27 | handy = lbot->val; | |
28 | *strbuf = 0; | |
29 | typ=TYPE(handy); /* we only work for a few types */ | |
30 | ||
31 | ||
32 | /* put the characters to return in the string buffer strb */ | |
33 | ||
34 | switch(typ) { | |
35 | case STRNG: | |
36 | strb = (char *) handy; | |
37 | if(Xsdc)Idqc = Xsdc; | |
38 | goto common; | |
39 | case ATOM: | |
40 | strb = handy->pname; | |
41 | if(strb[0]==0) { | |
42 | strb = strbb; | |
43 | strbb[0] = Xdqc; | |
44 | strbb[1] = Xdqc; | |
45 | strbb[2] = 0; | |
46 | } else | |
47 | common: | |
48 | if(slashify != 0) | |
49 | { | |
50 | register char *cp, *out = strbb; | |
51 | cp = strb; | |
52 | strb = strbb; | |
53 | if(ctable[(*cp)&0177]==VNUM) | |
54 | *out++ = Xesc; | |
55 | for(; *cp; cp++) | |
56 | { | |
57 | if(ctable[*cp]& QUTMASK) | |
58 | *out++ = Xesc; | |
59 | *out++ = *cp; | |
60 | } | |
61 | *out = 0; | |
62 | } | |
63 | ||
64 | break; | |
65 | case INT: | |
66 | strb = strbb; | |
67 | sprintf(strb, "%d", lbot->val->i); | |
68 | break; | |
69 | case DOUB: | |
70 | strb = strbb; | |
71 | sprintf(strb, "%0.16G", lbot->val->r); | |
72 | break; | |
73 | case SDOT: | |
74 | { | |
75 | struct _iobuf _strbuf; | |
76 | register count; | |
77 | for((handy = lbot->val), count = 12; | |
78 | handy->CDR!=(lispval) 0; | |
79 | (handy = handy->CDR), count += 12); | |
80 | strb = (char *) alloca(count); | |
81 | ||
82 | _strbuf._flag = _IOWRT+_IOSTRG; | |
83 | _strbuf._ptr = strb; | |
84 | _strbuf._cnt = count; | |
85 | pbignum(lbot->val,&_strbuf); | |
86 | putc('.',&_strbuf); | |
87 | putc(0,&_strbuf); | |
88 | break; | |
89 | } | |
90 | default: | |
91 | errorh(Vermisc,"EXPLODE ARG MUST BE STRING, SYMBOL, FIXNUM, OR FLONUM",nil,FALSE,0,handy); | |
92 | return(nil); | |
93 | } | |
94 | ||
95 | ||
96 | if( strb[0] != NULL_CHAR ) /* if there is something to do */ | |
97 | { | |
98 | register lispval prev; | |
99 | ||
100 | protect(handy = last = newdot()); | |
101 | strbuf[1] = NULL_CHAR ; /* set up for getatom */ | |
102 | atmlen = 2; | |
103 | ||
104 | for(i=0; ch = strb[i++]; ) { | |
105 | switch(kind) { | |
106 | ||
107 | case 0: strbuf[0] = hash = ch; /* character explode */ | |
108 | hash = 177 & hash; /* cut 1st bit off if any */ | |
109 | last->car = (lispval) getatom(); /* look in oblist */ | |
110 | break; | |
111 | ||
112 | case 1: | |
113 | last->car = inewint(ch); | |
114 | break; | |
115 | } | |
116 | ||
117 | /* advance pointers */ | |
118 | prev = last; | |
119 | last->cdr = newdot(); | |
120 | last = last->cdr; | |
121 | } | |
122 | ||
123 | /* end list with a nil pointer */ | |
124 | prev->cdr = nil; | |
125 | return(handy); | |
126 | } | |
127 | else return(nil); /* return nil if no characters */ | |
128 | } | |
129 | ||
130 | /*=========================== | |
131 | - | |
132 | - (explodec 'atm) returns (a t m) | |
133 | - (explodec 234) returns (\2 \3 \4) | |
134 | -===========================*/ | |
135 | ||
136 | lispval | |
137 | Lexpldc() | |
138 | { return(Lexpldx(0,0)); } | |
139 | ||
140 | ||
141 | /*=========================== | |
142 | - | |
143 | - (exploden 'abc) returns (65 66 67) | |
144 | - (exploden 123) returns (49 50 51) | |
145 | -=============================*/ | |
146 | ||
147 | ||
148 | lispval | |
149 | Lexpldn() | |
150 | { return(Lexpldx(1,0)); } | |
151 | ||
152 | /*=========================== | |
153 | - | |
154 | - (explodea "123") returns (\\ \1 \2 \3); | |
155 | - (explodea 123) returns (\1 \2 \3); | |
156 | -=============================*/ | |
157 | ||
158 | lispval | |
159 | Lexplda() | |
160 | { return(Lexpldx(0,1)); } | |
161 | ||
162 | /* | |
163 | * (argv) returns how many arguments where on the command line which invoked | |
164 | * lisp; (argv i) returns the i'th argument made into an atom; | |
165 | */ | |
166 | ||
167 | lispval | |
168 | Largv() | |
169 | { | |
170 | register lispval handy; | |
171 | register index; | |
172 | register char c, *base; | |
173 | extern int Xargc; | |
174 | extern char **Xargv; | |
175 | ||
176 | chkarg(1); | |
177 | handy = lbot->val; | |
178 | ||
179 | if(TYPE(handy)==INT && handy->i>=0 && handy->i<Xargc) { | |
180 | strcpy(strbuf,Xargv[handy->i]); | |
181 | return(getatom()); | |
182 | } else { | |
183 | return(inewint(Xargc)); | |
184 | } | |
185 | } | |
186 | /* | |
187 | * (chdir <atom>) executes a chdir command | |
188 | * if successful, return t otherwise returns nil | |
189 | */ | |
190 | lispval Lchdir(){ | |
191 | register lispval handy; | |
192 | ||
193 | chkarg(1); | |
194 | handy=lbot->val; | |
195 | if(TYPE(handy)==ATOM && (chdir(handy->pname)>=0)) | |
196 | return(tatom); | |
197 | else | |
198 | return(nil); | |
199 | } | |
200 | ||
201 | /* ========================================================== | |
202 | - | |
203 | - ascii - convert from number to ascii character | |
204 | - | |
205 | - form:(ascii number) | |
206 | - | |
207 | - the number is checked so that it is in the range 0-255 | |
208 | - then it is made a character and returned | |
209 | - =========================================================*/ | |
210 | ||
211 | lispval | |
212 | Lascii() | |
213 | { | |
214 | register lispval handy; | |
215 | ||
216 | handy = lbot->val; /* get argument */ | |
217 | ||
218 | if(TYPE(handy) != INT) /* insure that it is an integer */ | |
219 | { error("argument not an integer",FALSE); | |
220 | return(nil); | |
221 | } | |
222 | ||
223 | if(handy->i < 0 || handy->i > 0377) /* insure that it is in range*/ | |
224 | { error("argument is out of ascii range",FALSE); | |
225 | return(nil); | |
226 | } | |
227 | ||
228 | strbuf[0] = handy->i ; /* ok value, make into a char */ | |
229 | strbuf[1] = NULL_CHAR; | |
230 | ||
231 | /* lookup and possibly intern the atom given in strbuf */ | |
232 | ||
233 | return( (lispval) getatom() ); | |
234 | } | |
235 | ||
236 | /* | |
237 | * boole - maclisp bitwise boolean function | |
238 | * (boole k x y) where k determines which of 16 possible bitwise | |
239 | * truth tables may be applied. Common values are 1 (and) 6 (xor) 7 (or) | |
240 | * the result is mapped over each pair of bits on input | |
241 | */ | |
242 | lispval | |
243 | Lboole(){ | |
244 | register x, y; | |
245 | register lispval result; | |
246 | register struct argent *mynp; | |
247 | int k; | |
248 | ||
249 | if(np - lbot < 3) | |
250 | error("Boole demands at least 3 args",FALSE); | |
251 | mynp = lbot+AD; | |
252 | k = mynp->val->i & 15; | |
253 | x = (mynp+1)->val->i; | |
254 | for(mynp += 2; mynp < np; mynp++) { | |
255 | y = mynp->val->i; | |
256 | switch(k) { | |
257 | ||
258 | case 0: x = 0; | |
259 | break; | |
260 | case 1: x = x & y; | |
261 | break; | |
262 | case 2: x = y & ~x; | |
263 | break; | |
264 | case 3: x = y; | |
265 | break; | |
266 | case 4: x = x & ~y; | |
267 | break; | |
268 | /* case 5: x = x; break; */ | |
269 | case 6: x = x ^ y; | |
270 | break; | |
271 | case 7: x = x | y; | |
272 | break; | |
273 | case 8: x = ~(x | y); | |
274 | break; | |
275 | case 9: x = ~(x ^ y); | |
276 | break; | |
277 | case 10: x = ~x; | |
278 | break; | |
279 | case 11: x = ~x | y; | |
280 | break; | |
281 | case 12: x = ~y; | |
282 | break; | |
283 | case 13: x = x | ~y; | |
284 | break; | |
285 | case 14: x = ~x | ~y; | |
286 | break; | |
287 | case 15: x = -1; | |
288 | } | |
289 | } | |
290 | return(inewint(x)); | |
291 | } | |
292 | lispval | |
293 | Lfact() | |
294 | { | |
295 | register lispval result, handy; | |
296 | register itemp; | |
297 | snpand(3); /* fixup entry mask */ | |
298 | ||
299 | result = lbot->val; | |
300 | if(TYPE(result)!=INT) error("Factorial of Non-fixnum. If you want me\ | |
301 | to calculate fact of > 2^30 We will be here till doomsday!.",FALSE); | |
302 | itemp = result->i; | |
303 | protect(result = newsdot()); | |
304 | result->CDR=(lispval)0; | |
305 | result->i = 1; | |
306 | for(; itemp > 1; itemp--) | |
307 | dmlad(result,itemp,0); | |
308 | if(result->CDR) return(result); | |
309 | (handy = newint())->i = result->i; | |
310 | return(handy); | |
311 | } | |
312 | /* | |
313 | * fix -- maclisp floating to fixnum conversion | |
314 | * for the moment, mereley convert floats to ints. | |
315 | * eventual convert to bignum if too big to fit. | |
316 | */ | |
317 | lispval Lfix() | |
318 | { | |
319 | register lispval result, handy; | |
320 | ||
321 | chkarg(1); | |
322 | handy = lbot->val; | |
323 | switch(TYPE(handy)) { | |
324 | default: | |
325 | error("innaproriate arg to fix.",FALSE); | |
326 | case INT: | |
327 | case SDOT: | |
328 | return(handy); | |
329 | case DOUB: | |
330 | if(handy->r >= 0) | |
331 | return(inewint((int)handy->r)); | |
332 | else | |
333 | return(inewint(((int)handy->r)-1)); | |
334 | } | |
335 | } | |
336 | ||
337 | lispval | |
338 | Lfloat() | |
339 | { | |
340 | register lispval handy,result; | |
341 | chkarg(1); | |
342 | handy = lbot->val; | |
343 | switch(TYPE(handy)) | |
344 | { | |
345 | case DOUB: return(handy); | |
346 | ||
347 | ||
348 | case INT: result = newdoub(); | |
349 | result->r = (double) handy->i; | |
350 | return(result); | |
351 | ||
352 | ||
353 | default: error(Vermisc,"Bad argument to float",nil,FALSE,0,handy); | |
354 | } | |
355 | } | |
356 | ||
357 | /* Lbreak ***************************************************************/ | |
358 | /* If first argument is not nil, this is evaluated and printed. Then */ | |
359 | /* error is called with the "breaking" message. */ | |
360 | lispval Lbreak() { | |
361 | register lispval hold; | |
362 | ||
363 | if (np > lbot) { | |
364 | printr(lbot->val,poport); | |
365 | dmpport(poport); | |
366 | } | |
367 | return(error("",TRUE)); | |
368 | } | |
369 | ||
370 | ||
371 | lispval LDivide() { | |
372 | register lispval result, work, temp; | |
373 | register struct argent *mynp; | |
374 | register struct argent *lbot, *np; | |
375 | int typ; | |
376 | lispval quo, rem; struct sdot dummy; | |
377 | ||
378 | chkarg(2); | |
379 | mynp = lbot; | |
380 | result = mynp->val; | |
381 | work = (mynp+1)->val; | |
382 | ||
383 | if((typ=TYPE(result))==INT) { | |
384 | protect(temp=newsdot()); | |
385 | temp->i = result->i; | |
386 | result = temp; | |
387 | } else if (typ!=SDOT) | |
388 | error("First arg to divide neither a bignum nor int.",FALSE); | |
389 | typ = TYPE(work); | |
390 | if(typ != INT && typ != SDOT) | |
391 | error("second arg to Divide neither an sdot nor an int.",FALSE); | |
392 | if(typ == INT) { | |
393 | dummy.CDR = (lispval) 0; | |
394 | dummy.I = work->i; | |
395 | work = (lispval) &dummy; | |
396 | } | |
397 | divbig(result,work, &quo, &rem); | |
398 | protect(quo); | |
399 | if(rem==((lispval) &dummy)) | |
400 | protect(rem = inewint(dummy.I)); | |
401 | protect(result = work = newdot()); | |
402 | work->car = quo; | |
403 | (work->cdr = newdot())->car = rem; | |
404 | return(result); | |
405 | } | |
406 | lispval LEmuldiv(){ | |
407 | register struct argent * mynp = lbot+AD; | |
408 | register lispval work, result; | |
409 | int quo, rem; | |
410 | snpand(3); /* fix register mask */ | |
411 | ||
412 | /* (Emuldiv mul1 mult2 add quo) => | |
413 | temp = mul1 + mul2 + sext(add); | |
414 | result = (list temp/quo temp%quo); | |
415 | to mix C and lisp a bit */ | |
416 | ||
417 | Imuldiv(mynp[0].val->i, mynp[1].val->i, mynp[2].val->i, | |
418 | mynp[3].val->i, &quo, &rem); | |
419 | protect(result=newdot()); | |
420 | (result->car=inewint(quo)); | |
421 | work = result->cdr = newdot(); | |
422 | (work->car=inewint(rem)); | |
423 | return(result); | |
424 | } | |
425 | static Imuldiv() { | |
426 | asm(" emul 4(ap),8(ap),12(ap),r0"); | |
427 | asm(" ediv 16(ap),r0,*20(ap),*24(ap)"); | |
428 | } | |
429 | ||
430 |