File:
[gforth] /
gforth /
Attic /
primitives
Revision
1.12:
download - view:
text,
annotated -
select for diffs
Wed Jul 13 19:21:05 1994 UTC (29 years, 9 months ago) by
pazsan
Branches:
MAIN
CVS tags:
HEAD
Moved setjmp from engine to go_forth, because the socalled "globbered"
variables where saved in memory (and this slows down everything).
Added global up0 for security (up is globbered).
Added restrict's functionalitz to cross.fs
removed all occurency of cell+ name>, because the bug in name> is
fixed.
Added a dusty workaround at the end of prims2x.fs, because of
strange exceptions.
1: \ Copyright 1992 by the ANSI figForth Development Group
2: \
3: \ WARNING: This file is processed by m4. Make sure your identifiers
4: \ don't collide with m4's (e.g. by undefining them).
5: \
6: \ This file contains instructions in the following format:
7: \
8: \ forth name stack effect category [pronounciation]
9: \ [""glossary entry""]
10: \ C code
11: \ [:
12: \ Forth code]
13: \
14: \ The pronounciataion is also used for forming C names.
15: \
16: \ These informations are automagically translated into C-code for the
17: \ interpreter and into some other files. The forth name of a word is
18: \ automatically turned into upper case. I hope that your C compiler has
19: \ decent optimization, otherwise the automatically generated code will
20: \ be somewhat slow. The Forth version of the code is included for manual
21: \ compilers, so they will need to compile only the important words.
22: \
23: \ Note that stack pointer adjustment is performed according to stack
24: \ effect by automatically generated code and NEXT is automatically
25: \ appended to the C code. Also, you can use the names in the stack
26: \ effect in the C code. Stack access is automatic. One exception: if
27: \ your code does not fall through, the results are not stored into the
28: \ stack. Use different names on both sides of the '--', if you change a
29: \ value (some stores to the stack are optimized away).
30: \
31: \ The stack variables have the following types:
32: \ name matches type
33: \ f.* Bool
34: \ c.* Char
35: \ [nw].* Cell
36: \ u.* UCell
37: \ d.* DCell
38: \ ud.* UDCell
39: \ r.* Float
40: \ a_.* Cell *
41: \ c_.* Char *
42: \ f_.* Float *
43: \ df_.* DFloat *
44: \ sf_.* SFloat *
45: \ xt.* XT
46: \ wid.* WID
47: \ f83name.* F83Name *
48: \
49: \ In addition the following names can be used:
50: \ ip the instruction pointer
51: \ sp the data stack pointer
52: \ rp the parameter stack pointer
53: \ NEXT executes NEXT
54: \ cfa
55: \ NEXT1 executes NEXT1
56: \ FLAG(x) makes a Forth flag from a C flag
57: \
58: \ Percentages in comments are from Koopmans book: average/maximum use
59: \ (taken from four, not very representattive benchmarks)
60: \
61: \ To do:
62: \ make sensible error returns for file words
63: \
64: \ throw execute, cfa and NEXT1 out?
65: \ macroize *ip, ip++, *ip++ (pipelining)?
66:
67: \ these m4 macros would collide with identifiers
68: undefine(`index')
69: undefine(`shift')
70:
71: noop -- fig
72: ;
73:
74: lit -- w fig
75: w = (Cell)*ip++;
76:
77: execute xt -- core,fig
78: cfa = xt;
79: IF_TOS(TOS = sp[0]);
80: NEXT1;
81:
82: branch-lp+!# -- new branch_lp_plus_store_number
83: /* this will probably not be used */
84: branch_adjust_lp:
85: lp += (int)(ip[1]);
86: goto branch;
87:
88: branch -- fig
89: branch:
90: ip = (Xt *)(((int)ip)+(int)*ip);
91:
92: \ condbranch(forthname,restline,code)
93: \ this is non-syntactical: code must open a brace that is close by the macro
94: define(condbranch,
95: $1 $2
96: $3 goto branch;
97: }
98: else
99: ip++;
100:
101: $1-lp+!# $2_lp_plus_store_number
102: $3 goto branch_adjust_lp;
103: }
104: else
105: ip+=2;
106:
107: )
108:
109: condbranch(?branch,f -- f83 question_branch,
110: if (f==0) {
111: IF_TOS(TOS = sp[0]);
112: )
113:
114: condbranch((next),-- cmFORTH paren_next,
115: if ((*rp)--) {
116: )
117:
118: condbranch((loop),-- fig paren_loop,
119: int index = *rp+1;
120: int limit = rp[1];
121: if (index != limit) {
122: *rp = index;
123: )
124:
125: condbranch((+loop),n -- fig paren_plus_loop,
126: /* !! check this thoroughly */
127: int index = *rp;
128: int olddiff = index-rp[1];
129: /* sign bit manipulation and test: (x^y)<0 is equivalent to (x<0) != (y<0) */
130: /* dependent upon two's complement arithmetic */
131: if ((olddiff^(olddiff+n))>=0 /* the limit is not crossed */
132: || (olddiff^n)>=0 /* it is a wrap-around effect */) {
133: *rp = index+n;
134: IF_TOS(TOS = sp[0]);
135: )
136:
137: condbranch((s+loop),n -- new paren_symmetric_plus_loop,
138: ""The run-time procedure compiled by S+LOOP. It loops until the index
139: crosses the boundary between limit and limit-sign(n). I.e. a symmetric
140: version of (+LOOP).""
141: /* !! check this thoroughly */
142: int oldindex = *rp;
143: int diff = oldindex-rp[1];
144: int newdiff = diff+n;
145: if (n<0) {
146: diff = -diff;
147: newdiff = - newdiff;
148: }
149: if (diff>=0 || newdiff<0) {
150: *rp = oldindex+n;
151: IF_TOS(TOS = sp[0]);
152: )
153:
154: unloop -- core
155: rp += 2;
156:
157: (for) ncount -- cmFORTH paren_for
158: /* or (for) = >r -- collides with unloop! */
159: *--rp = 0;
160: *--rp = ncount;
161:
162: (do) nlimit nstart -- fig paren_do
163: /* or do it in high-level? 0.09/0.23% */
164: *--rp = nlimit;
165: *--rp = nstart;
166: :
167: swap >r >r ;
168:
169: (?do) nlimit nstart -- core-ext paren_question_do
170: *--rp = nlimit;
171: *--rp = nstart;
172: if (nstart == nlimit) {
173: IF_TOS(TOS = sp[0]);
174: goto branch;
175: }
176: else {
177: ip++;
178: }
179:
180: i -- n core,fig
181: n = *rp;
182:
183: j -- n core
184: n = rp[2];
185:
186: \ digit is high-level: 0/0%
187:
188: (emit) c -- fig paren_emit
189: putchar(c);
190: emitcounter++;
191:
192: (type) c_addr n -- fig paren_type
193: fwrite(c_addr,sizeof(Char),n,stdout);
194: emitcounter += n;
195:
196: key -- n fig
197: fflush(stdout);
198: /* !! noecho */
199: n = key();
200:
201: key? -- n fig key_q
202: fflush(stdout);
203: n = key_query;
204:
205: cr -- fig
206: puts("");
207:
208: move c_from c_to ucount -- core
209: memmove(c_to,c_from,ucount);
210: /* make an Ifdef for bsd and others? */
211:
212: cmove c_from c_to u -- string
213: while (u-- > 0)
214: *c_to++ = *c_from++;
215:
216: cmove> c_from c_to u -- string c_move_up
217: while (u-- > 0)
218: c_to[u] = c_from[u];
219:
220: fill c_addr u c -- core
221: memset(c_addr,c,u);
222:
223: compare c_addr1 u1 c_addr2 u2 -- n string
224: n = memcmp(c_addr1, c_addr2, u1<u2 ? u1 : u2);
225: if (n==0)
226: n = u1-u2;
227: if (n<0)
228: n = -1;
229: else if (n>0)
230: n = 1;
231:
232: -text c_addr1 u c_addr2 -- n new dash_text
233: n = memcmp(c_addr1, c_addr2, u);
234: if (n<0)
235: n = -1;
236: else if (n>0)
237: n = 1;
238:
239: capscomp c_addr1 u c_addr2 -- n new
240: Char c1, c2;
241: for (;; u--, c_addr1++, c_addr2++) {
242: if (u == 0) {
243: n = 0;
244: break;
245: }
246: c1 = toupper(*c_addr1);
247: c2 = toupper(*c_addr2);
248: if (c1 != c2) {
249: if (c1 < c2)
250: n = -1;
251: else
252: n = 1;
253: break;
254: }
255: }
256:
257: -trailing c_addr u1 -- c_addr u2 string dash_trailing
258: u2 = u1;
259: while (c_addr[u2-1] == ' ')
260: u2--;
261:
262: /string c_addr1 u1 n -- c_addr2 u2 string slash_string
263: c_addr2 = c_addr1+n;
264: u2 = u1-n;
265:
266: + n1 n2 -- n core,fig plus
267: n = n1+n2;
268:
269: - n1 n2 -- n core,fig minus
270: n = n1-n2;
271:
272: negate n1 -- n2 core,fig
273: /* use minus as alias */
274: n2 = -n1;
275:
276: 1+ n1 -- n2 core one_plus
277: n2 = n1+1;
278:
279: 1- n1 -- n2 core one_minus
280: n2 = n1-1;
281:
282: max n1 n2 -- n core
283: if (n1<n2)
284: n = n2;
285: else
286: n = n1;
287: :
288: 2dup < if
289: swap drop
290: else
291: drop
292: endif ;
293:
294: min n1 n2 -- n core
295: if (n1<n2)
296: n = n1;
297: else
298: n = n2;
299:
300: abs n1 -- n2 core
301: if (n1<0)
302: n2 = -n1;
303: else
304: n2 = n1;
305:
306: * n1 n2 -- n core,fig star
307: n = n1*n2;
308:
309: / n1 n2 -- n core,fig slash
310: n = n1/n2;
311:
312: mod n1 n2 -- n core
313: n = n1%n2;
314:
315: /mod n1 n2 -- n3 n4 core slash_mod
316: n4 = n1/n2;
317: n3 = n1%n2; /* !! is this correct? look into C standard! */
318:
319: 2* n1 -- n2 core two_star
320: n2 = 2*n1;
321:
322: 2/ n1 -- n2 core two_slash
323: /* !! is this still correct? */
324: n2 = n1>>1;
325:
326: fm/mod d1 n1 -- n2 n3 core f_m_slash_mod
327: ""floored division: d1 = n3*n1+n2, n1>n2>=0 or 0>=n2>n1""
328: /* assumes that the processor uses either floored or symmetric division */
329: n3 = d1/n1;
330: n2 = d1%n1;
331: /* note that this 1%-3>0 is optimized by the compiler */
332: if (1%-3>0 && (d1<0) != (n1<0) && n2!=0) {
333: n3--;
334: n2+=n1;
335: }
336:
337: sm/rem d1 n1 -- n2 n3 core s_m_slash_rem
338: ""symmetric division: d1 = n3*n1+n2, sign(n2)=sign(d1) or 0""
339: /* assumes that the processor uses either floored or symmetric division */
340: n3 = d1/n1;
341: n2 = d1%n1;
342: /* note that this 1%-3<0 is optimized by the compiler */
343: if (1%-3<0 && (d1<0) != (n1<0) && n2!=0) {
344: n3++;
345: n2-=n1;
346: }
347:
348: m* n1 n2 -- d core m_star
349: d = (DCell)n1 * (DCell)n2;
350:
351: um* u1 u2 -- ud core u_m_star
352: /* use u* as alias */
353: ud = (UDCell)u1 * (UDCell)u2;
354:
355: um/mod ud u1 -- u2 u3 core u_m_slash_mod
356: u3 = ud/u1;
357: u2 = ud%u1;
358:
359: m+ d1 n -- d2 double m_plus
360: d2 = d1+n;
361:
362: d+ d1 d2 -- d double,fig d_plus
363: d = d1+d2;
364:
365: d- d1 d2 -- d double d_minus
366: d = d1-d2;
367:
368: dnegate d1 -- d2 double
369: /* use dminus as alias */
370: d2 = -d1;
371:
372: dmax d1 d2 -- d double
373: if (d1<d2)
374: d = d2;
375: else
376: d = d1;
377:
378: dmin d1 d2 -- d double
379: if (d1<d2)
380: d = d1;
381: else
382: d = d2;
383:
384: dabs d1 -- d2 double
385: if (d1<0)
386: d2 = -d1;
387: else
388: d2 = d1;
389:
390: d2* d1 -- d2 double d_two_star
391: d2 = 2*d1;
392:
393: d2/ d1 -- d2 double d_two_slash
394: /* !! is this still correct? */
395: d2 = d1/2;
396:
397: d>s d -- n double d_to_s
398: /* make this an alias for drop? */
399: n = d;
400:
401: and w1 w2 -- w core,fig
402: w = w1&w2;
403:
404: or w1 w2 -- w core,fig
405: w = w1|w2;
406:
407: xor w1 w2 -- w core,fig
408: w = w1^w2;
409:
410: invert w1 -- w2 core
411: w2 = ~w1;
412:
413: rshift u1 n -- u2 core
414: u2 = u1>>n;
415:
416: lshift u1 n -- u2 core
417: u2 = u1<<n;
418:
419: \ comparisons(prefix, args, prefix, arg1, arg2, wordsets...)
420: define(comparisons,
421: $1= $2 -- f $6 $3equals
422: f = FLAG($4==$5);
423:
424: $1<> $2 -- f $7 $3different
425: /* use != as alias ? */
426: f = FLAG($4!=$5);
427:
428: $1< $2 -- f $8 $3less
429: f = FLAG($4<$5);
430:
431: $1> $2 -- f $9 $3greater
432: f = FLAG($4>$5);
433:
434: $1<= $2 -- f new $3less_or_equal
435: f = FLAG($4<=$5);
436:
437: $1>= $2 -- f new $3greater_or_equal
438: f = FLAG($4>=$5);
439:
440: )
441:
442: comparisons(0, n, zero_, n, 0, core, core-ext, core, core-ext)
443: comparisons(, n1 n2, , n1, n2, core, core-ext, core, core)
444: comparisons(u, u1 u2, u_, u1, u2, new, new, core, core-ext)
445: comparisons(d, d1 d2, d_, d1, d2, double, new, double, new)
446: comparisons(d0, d, d_zero_, d, 0, double, new, double, new)
447: comparisons(du, ud1 ud2, d_u_, ud1, ud2, new, new, double-ext, new)
448:
449: within u1 u2 u3 -- f core-ext
450: f = FLAG(u1-u2 < u3-u2);
451:
452: sp@ -- a_addr fig spat
453: a_addr = sp;
454:
455: sp! a_addr -- fig spstore
456: sp = a_addr+1;
457: /* works with and without TOS caching */
458:
459: rp@ -- a_addr fig rpat
460: a_addr = rp;
461:
462: rp! a_addr -- fig rpstore
463: rp = a_addr;
464:
465: fp@ -- f_addr new fp_fetch
466: f_addr = fp;
467:
468: fp! f_addr -- new fp_store
469: fp = f_addr;
470:
471: ;s -- core exit
472: ip = (Xt *)(*rp++);
473:
474: >r w -- core,fig to_r
475: *--rp = w;
476:
477: r> -- w core,fig r_from
478: w = *rp++;
479:
480: r@ -- w core,fig r_fetch
481: /* use r as alias */
482: /* make r@ an alias for i */
483: w = *rp;
484:
485: rdrop -- fig
486: rp++;
487:
488: i' -- w fig i_tick
489: w=rp[1];
490:
491: over w1 w2 -- w1 w2 w1 core,fig
492:
493: drop w -- core,fig
494:
495: swap w1 w2 -- w2 w1 core,fig
496:
497: dup w -- w w core,fig
498:
499: rot w1 w2 w3 -- w2 w3 w1 core rote
500:
501: -rot w1 w2 w3 -- w3 w1 w2 fig not_rote
502:
503: nip w1 w2 -- w2 core-ext
504:
505: tuck w1 w2 -- w2 w1 w2 core-ext
506:
507: ?dup w -- w core question_dupe
508: if (w!=0) {
509: IF_TOS(*sp-- = w;)
510: #ifndef USE_TOS
511: *--sp = w;
512: #endif
513: }
514:
515: pick u -- w core-ext
516: w = sp[u+1];
517:
518: 2drop w1 w2 -- core two_drop
519:
520: 2dup w1 w2 -- w1 w2 w1 w2 core two_dupe
521:
522: 2over w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2 core two_over
523:
524: 2swap w1 w2 w3 w4 -- w3 w4 w1 w2 core two_swap
525:
526: 2rot w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2 double two_rote
527:
528: \ toggle is high-level: 0.11/0.42%
529:
530: @ a_addr -- w fig fetch
531: w = *a_addr;
532:
533: ! w a_addr -- core,fig store
534: *a_addr = w;
535:
536: +! n a_addr -- core,fig plus_store
537: *a_addr += n;
538:
539: c@ c_addr -- c fig cfetch
540: c = *c_addr;
541:
542: c! c c_addr -- fig cstore
543: *c_addr = c;
544:
545: 2! w1 w2 a_addr -- core two_store
546: a_addr[0] = w2;
547: a_addr[1] = w1;
548:
549: 2@ a_addr -- w1 w2 core two_fetch
550: w2 = a_addr[0];
551: w1 = a_addr[1];
552:
553: d! d a_addr -- double d_store
554: /* !! alignment problems on some machines */
555: *(DCell *)a_addr = d;
556:
557: d@ a_addr -- d double d_fetch
558: d = *(DCell *)a_addr;
559:
560: cell+ a_addr1 -- a_addr2 core cell_plus
561: a_addr2 = a_addr1+1;
562:
563: cells n1 -- n2 core
564: n2 = n1 * sizeof(Cell);
565:
566: char+ c_addr1 -- c_addr2 core care_plus
567: c_addr2 = c_addr1+1;
568:
569: chars n1 -- n2 core cares
570: n2 = n1 * sizeof(Char);
571:
572: count c_addr1 -- c_addr2 u core
573: u = *c_addr1;
574: c_addr2 = c_addr1+1;
575:
576: (bye) n -- toolkit-ext paren_bye
577: deprep_terminal();
578: exit(n);
579:
580: system c_addr u -- n own
581: char pname[u+1];
582: cstr(pname,c_addr,u);
583: n=system(pname);
584:
585: popen c_addr u n -- wfileid own
586: char pname[u+1];
587: static char* mode[2]={"r","w"};
588: cstr(pname,c_addr,u);
589: wfileid=(Cell)popen(pname,mode[n]);
590:
591: pclose wfileid -- wior own
592: wior=pclose((FILE *)wfileid);
593:
594: time&date -- nyear nmonth nday nhour nmin nsec ansi time_and_date
595: struct timeval time1;
596: struct timezone zone1;
597: struct tm *ltime;
598: gettimeofday(&time1,&zone1);
599: ltime=localtime(&time1.tv_sec);
600: nyear =ltime->tm_year+1900;
601: nmonth=ltime->tm_mon;
602: nday =ltime->tm_mday;
603: nhour =ltime->tm_hour;
604: nmin =ltime->tm_min;
605: nsec =ltime->tm_sec;
606:
607: ms n -- ansi
608: struct timeval timeout;
609: timeout.tv_sec=n/1000;
610: timeout.tv_usec=1000*(n%1000);
611: (void)select(0,0,0,0,&timeout);
612:
613: allocate u -- a_addr wior memory
614: a_addr = (Cell *)malloc(u);
615: wior = a_addr==NULL; /* !! Define a return code */
616:
617: free a_addr -- wior memory
618: free(a_addr);
619: wior = 0;
620:
621: resize a_addr1 u -- a_addr2 wior memory
622: a_addr2 = realloc(a_addr1, u);
623: wior = a_addr2==NULL; /* !! Define a return code */
624:
625: (f83find) c_addr u f83name1 -- f83name2 new paren_f83find
626: for (; f83name1 != NULL; f83name1 = f83name1->next)
627: if (F83NAME_COUNT(f83name1)==u &&
628: strncmp(c_addr, f83name1->name, u)== 0 /* or inline? */)
629: break;
630: f83name2=f83name1;
631:
632: (f83casefind) c_addr u f83name1 -- f83name2 new paren_f83casefind
633: for (; f83name1 != NULL; f83name1 = f83name1->next)
634: if (F83NAME_COUNT(f83name1)==u &&
635: strncasecmp(c_addr, f83name1->name, u)== 0 /* or inline? */)
636: break;
637: f83name2=f83name1;
638:
639: (parse-white) c_addr1 u1 -- c_addr2 u2 new paren_parse_white
640: /* use !isgraph instead of isspace? */
641: Char *endp = c_addr1+u1;
642: while (c_addr1<endp && isspace(*c_addr1))
643: c_addr1++;
644: if (c_addr1<endp) {
645: for (c_addr2 = c_addr1; c_addr1<endp && !isspace(*c_addr1); c_addr1++)
646: ;
647: u2 = c_addr1-c_addr2;
648: }
649: else {
650: c_addr2 = c_addr1;
651: u2 = 0;
652: }
653:
654: close-file wfileid -- wior file close_file
655: wior = FILEIO(fclose((FILE *)wfileid)==EOF);
656:
657: open-file c_addr u ntype -- w2 wior file open_file
658: char fname[u+1];
659: cstr(fname, c_addr, u);
660: w2 = (Cell)fopen(fname, fileattr[ntype]);
661: wior = FILEEXIST(w2 == NULL);
662:
663: create-file c_addr u ntype -- w2 wior file create_file
664: int fd;
665: char fname[u+1];
666: cstr(fname, c_addr, u);
667: fd = creat(fname, 0666);
668: if (fd > -1) {
669: w2 = (Cell)fdopen(fd, fileattr[ntype]);
670: assert(w2 != NULL);
671: wior = 0;
672: } else {
673: assert(fd == -1);
674: wior = FILEIO(fd);
675: w2 = 0;
676: }
677:
678: delete-file c_addr u -- wior file delete_file
679: char fname[u+1];
680: cstr(fname, c_addr, u);
681: wior = FILEEXIST(unlink(fname));
682:
683: rename-file c_addr1 u1 c_addr2 u2 -- wior file-ext rename_file
684: char fname1[u1+1];
685: char fname2[u2+1];
686: cstr(fname1, c_addr1, u1);
687: cstr(fname2, c_addr2, u2);
688: wior = FILEEXIST(rename(fname1, fname2));
689:
690: file-position wfileid -- ud wior file file_position
691: /* !! use tell and lseek? */
692: ud = ftell((FILE *)wfileid);
693: wior = 0; /* !! or wior = FLAG(ud<0) */
694:
695: reposition-file ud wfileid -- wior file reposition_file
696: wior = FILEIO(fseek((FILE *)wfileid, (long)ud, SEEK_SET));
697:
698: file-size wfileid -- ud wior file file_size
699: struct stat buf;
700: wior = FILEEXIST(fstat(fileno((FILE *)wfileid), &buf));
701: ud = buf.st_size;
702:
703: resize-file ud wfileid -- wior file resize_file
704: wior = FILEIO(ftruncate(fileno((FILE *)wfileid), (int)ud));
705:
706: read-file c_addr u1 wfileid -- u2 wior file read_file
707: /* !! fread does not guarantee enough */
708: u2 = fread(c_addr, sizeof(Char), u1, (FILE *)wfileid);
709: wior = FILEIO(u2<u1 && ferror((FILE *)wfileid));
710: /* !! who performs clearerr((FILE *)wfileid); ? */
711:
712: read-line c_addr u1 wfileid -- u2 flag wior file read_line
713: if ((flag=FLAG(!feof((FILE *)wfileid)))) {
714: char *s = fgets(c_addr,u1+1,(FILE *)wfileid);
715: wior=FILEIO(ferror((FILE *)wfileid));
716: u2=strlen(c_addr);
717: u2-=((u2>0) && (c_addr[u2-1]==NEWLINE));
718: }
719: else {
720: wior=0;
721: u2=0;
722: }
723:
724: write-file c_addr u1 wfileid -- wior file write_file
725: /* !! fwrite does not guarantee enough */
726: {
727: int u2 = fwrite(c_addr, sizeof(Char), u1, (FILE *)wfileid);
728: wior = FILEIO(u2<u1 && ferror((FILE *)wfileid));
729: }
730:
731: flush-file wfileid -- wior file-ext flush_file
732: wior = FILEIO(fflush((FILE *) wfileid));
733:
734: comparisons(f, r1 r2, f_, r1, r2, new, new, float, new)
735: comparisons(f0, r, f_zero_, r, 0., float, new, float, new)
736:
737: d>f d -- r float d_to_f
738: r = d;
739:
740: f>d r -- d float f_to_d
741: /* !! basis 15 is not very specific */
742: d = r;
743:
744: f! r f_addr -- float f_store
745: *f_addr = r;
746:
747: f@ f_addr -- r float f_fetch
748: r = *f_addr;
749:
750: df@ df_addr -- r float-ext d_f_fetch
751: #ifdef IEEE_FP
752: r = *df_addr;
753: #else
754: !! df@
755: #endif
756:
757: df! r df_addr -- float-ext d_f_store
758: #ifdef IEEE_FP
759: *df_addr = r;
760: #else
761: !! df!
762: #endif
763:
764: sf@ sf_addr -- r float-ext s_f_fetch
765: #ifdef IEEE_FP
766: r = *sf_addr;
767: #else
768: !! sf@
769: #endif
770:
771: sf! r sf_addr -- float-ext s_f_store
772: #ifdef IEEE_FP
773: *sf_addr = r;
774: #else
775: !! sf!
776: #endif
777:
778: f+ r1 r2 -- r3 float f_plus
779: r3 = r1+r2;
780:
781: f- r1 r2 -- r3 float f_minus
782: r3 = r1-r2;
783:
784: f* r1 r2 -- r3 float f_star
785: r3 = r1*r2;
786:
787: f/ r1 r2 -- r3 float f_slash
788: r3 = r1/r2;
789:
790: f** r1 r2 -- r3 float-ext f_star_star
791: r3 = pow(r1,r2);
792:
793: fnegate r1 -- r2 float
794: r2 = - r1;
795:
796: fdrop r -- float
797:
798: fdup r -- r r float
799:
800: fswap r1 r2 -- r2 r1 float
801:
802: fover r1 r2 -- r1 r2 r1 float
803:
804: frot r1 r2 r3 -- r2 r3 r1 float
805:
806: float+ f_addr1 -- f_addr2 float float_plus
807: f_addr2 = f_addr1+1;
808:
809: floats n1 -- n2 float
810: n2 = n1*sizeof(Float);
811:
812: floor r1 -- r2 float
813: /* !! unclear wording */
814: r2 = floor(r1);
815:
816: fround r1 -- r2 float
817: /* !! unclear wording */
818: r2 = rint(r1);
819:
820: fmax r1 r2 -- r3 float
821: if (r1<r2)
822: r3 = r2;
823: else
824: r3 = r1;
825:
826: fmin r1 r2 -- r3 float
827: if (r1<r2)
828: r3 = r1;
829: else
830: r3 = r2;
831:
832: represent r c_addr u -- n f1 f2 float
833: char *sig;
834: int flag;
835: int decpt;
836: sig=ecvt(r, u, &decpt, &flag);
837: n=decpt;
838: f1=FLAG(flag!=0);
839: f2=FLAG(isdigit(sig[0])!=0);
840: memmove(c_addr,sig,u);
841:
842: >float c_addr u -- flag float to_float
843: /* real signature: c_addr u -- r t / f */
844: Float r;
845: char number[u+1];
846: char *endconv;
847: cstr(number, c_addr, u);
848: r=strtod(number,&endconv);
849: if((flag=FLAG(!(int)*endconv)))
850: {
851: IF_FTOS(fp[0] = FTOS);
852: fp += -1;
853: FTOS = r;
854: }
855: else if(*endconv=='d' || *endconv=='D')
856: {
857: *endconv='E';
858: r=strtod(number,&endconv);
859: if((flag=FLAG(!(int)*endconv)))
860: {
861: IF_FTOS(fp[0] = FTOS);
862: fp += -1;
863: FTOS = r;
864: }
865: }
866:
867: fabs r1 -- r2 float-ext
868: r2 = fabs(r1);
869:
870: facos r1 -- r2 float-ext
871: r2 = acos(r1);
872:
873: fasin r1 -- r2 float-ext
874: r2 = asin(r1);
875:
876: fatan r1 -- r2 float-ext
877: r2 = atan(r1);
878:
879: fatan2 r1 r2 -- r3 float-ext
880: r3 = atan2(r1,r2);
881:
882: fcos r1 -- r2 float-ext
883: r2 = cos(r1);
884:
885: fexp r1 -- r2 float-ext
886: r2 = exp(r1);
887:
888: fexpm1 r1 -- r2 float-ext
889: r2 =
890: #ifdef expm1
891: expm1(r1);
892: #else
893: exp(r1)-1;
894: #endif
895:
896: fln r1 -- r2 float-ext
897: r2 = log(r1);
898:
899: flnp1 r1 -- r2 float-ext
900: r2 =
901: #ifdef log1p
902: log1p(r1);
903: #else
904: log(r1+1);
905: #endif
906:
907: flog r1 -- r2 float-ext
908: r2 = log10(r1);
909:
910: fsin r1 -- r2 float-ext
911: r2 = sin(r1);
912:
913: fsincos r1 -- r2 r3 float-ext
914: r2 = sin(r1);
915: r3 = cos(r1);
916:
917: fsqrt r1 -- r2 float-ext
918: r2 = sqrt(r1);
919:
920: ftan r1 -- r2 float-ext
921: r2 = tan(r1);
922:
923: \ The following words access machine/OS/installation-dependent ANSI
924: \ figForth internals
925: \ !! how about environmental queries DIRECT-THREADED,
926: \ INDIRECT-THREADED, TOS-CACHED, FTOS-CACHED, CODEFIELD-DOES */
927:
928: >body xt -- a_addr core to_body
929: a_addr = PFA(xt);
930:
931: >code-address xt -- c_addr new to_code_address
932: ""c_addr is the code address of the word xt""
933: /* !! This behaves installation-dependently for DOES-words */
934: c_addr = CODE_ADDRESS(xt);
935:
936: >does-code xt -- a_addr new to_does_code
937: ""If xt ist the execution token of a defining-word-defined word,
938: a_addr is the start of the Forth code after the DOES>; Otherwise the
939: behaviour is uundefined""
940: /* !! there is currently no way to determine whether a word is
941: defining-word-defined */
942: a_addr = DOES_CODE(xt);
943:
944: code-address! n xt -- new code_address_store
945: ""Creates a code field with code address c_addr at xt""
946: MAKE_CF(xt, symbols[CF(n)]);
947: CACHE_FLUSH(xt,PFA(0));
948:
949: does-code! a_addr xt -- new does_code_store
950: ""creates a code field at xt for a defining-word-defined word; a_addr
951: is the start of the Forth code after DOES>""
952: MAKE_DOES_CF(xt, a_addr);
953: CACHE_FLUSH(xt,PFA(0));
954:
955: does-handler! a_addr -- new does_jump_store
956: ""creates a DOES>-handler at address a_addr. a_addr usually points
957: just behind a DOES>.""
958: MAKE_DOES_HANDLER(a_addr);
959: CACHE_FLUSH(a_addr,DOES_HANDLER_SIZE);
960:
961: /does-handler -- n new slash_does_handler
962: ""the size of a does-handler (includes possible padding)""
963: /* !! a constant or environmental query might be better */
964: n = DOES_HANDLER_SIZE;
965:
966: toupper c1 -- c2 new
967: c2 = toupper(c1);
968:
969: \ local variable implementation primitives
970: @local# -- w new fetch_local_number
971: w = *(Cell *)(lp+(int)(*ip++));
972:
973: @local0 -- w new fetch_local_zero
974: w = *(Cell *)(lp+0);
975:
976: @local4 -- w new fetch_local_four
977: w = *(Cell *)(lp+4);
978:
979: @local8 -- w new fetch_local_eight
980: w = *(Cell *)(lp+8);
981:
982: @local12 -- w new fetch_local_twelve
983: w = *(Cell *)(lp+12);
984:
985: f@local# -- r new f_fetch_local_number
986: r = *(Float *)(lp+(int)(*ip++));
987:
988: f@local0 -- r new f_fetch_local_zero
989: r = *(Float *)(lp+0);
990:
991: f@local8 -- r new f_fetch_local_eight
992: r = *(Float *)(lp+8);
993:
994: laddr# -- c_addr new laddr_number
995: /* this can also be used to implement lp@ */
996: c_addr = (Char *)(lp+(int)(*ip++));
997:
998: lp+!# -- new lp_plus_store_number
999: ""used with negative immediate values it allocates memory on the
1000: local stack, a positive immediate argument drops memory from the local
1001: stack""
1002: lp += (int)(*ip++);
1003:
1004: -4lp+! -- new minus_four_lp_plus_store
1005: lp += -4;
1006:
1007: 8lp+! -- new eight_lp_plus_store
1008: lp += 8;
1009:
1010: 16lp+! -- new sixteen_lp_plus_store
1011: lp += 16;
1012:
1013: lp! c_addr -- new lp_store
1014: lp = (Address)c_addr;
1015:
1016: >l w -- new to_l
1017: lp -= sizeof(Cell);
1018: *(Cell *)lp = w;
1019:
1020: f>l r -- new f_to_l
1021: lp -= sizeof(Float);
1022: *(Float *)lp = r;
1023:
1024: up! a_addr -- new up_store
1025: up=(char *)a_addr;
1026: up0=(char *)a_addr;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>