/* Gforth support functions Copyright (C) 1995,1996,1997,1998,2000,2003 Free Software Foundation, Inc. This file is part of Gforth. Gforth is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. */ #include "config.h" #include "forth.h" #include "io.h" #include #include #include #include #include #include #include #include #include #ifdef HAS_FILE char *cstr(Char *from, UCell size, int clear) /* return a C-string corresponding to the Forth string ( FROM SIZE ). the C-string lives until the next call of cstr with CLEAR being true */ { static struct cstr_buffer { char *buffer; size_t size; } *buffers=NULL; static int nbuffers=0; static int used=0; struct cstr_buffer *b; if (buffers==NULL) buffers=malloc(0); if (clear) used=0; if (used>=nbuffers) { buffers=realloc(buffers,sizeof(struct cstr_buffer)*(used+1)); buffers[used]=(struct cstr_buffer){malloc(0),0}; nbuffers=used+1; } b=&buffers[used]; if (size+1 > b->size) { b->buffer = realloc(b->buffer,size+1); b->size = size+1; } memcpy(b->buffer,from,size); b->buffer[size]='\0'; used++; return b->buffer; } char *tilde_cstr(Char *from, UCell size, int clear) /* like cstr(), but perform tilde expansion on the string */ { char *s1,*s2; int s1_len, s2_len; struct passwd *getpwnam (), *user_entry; if (size<1 || from[0]!='~') return cstr(from, size, clear); if (size<2 || from[1]=='/') { s1 = (char *)getenv ("HOME"); if(s1 == NULL) #if defined(_WIN32) || defined (MSDOS) s1 = (char *)getenv ("TEMP"); if(s1 == NULL) s1 = (char *)getenv ("TMP"); if(s1 == NULL) #endif s1 = ""; s2 = from+1; s2_len = size-1; } else { UCell i; for (i=1; ipw_dir; s2 = from+i; s2_len = size-i; } s1_len = strlen(s1); if (s1_len>1 && s1[s1_len-1]=='/') s1_len--; { char path[s1_len+s2_len]; memcpy(path,s1,s1_len); memcpy(path+s1_len,s2,s2_len); return cstr(path,s1_len+s2_len,clear); } } #endif DCell timeval2us(struct timeval *tvp) { #ifndef BUGGY_LONG_LONG return (tvp->tv_sec*(DCell)1000000)+tvp->tv_usec; #else DCell d2; DCell d1=mmul(tvp->tv_sec,1000000); d2.lo = d1.lo+tvp->tv_usec; d2.hi = d1.hi + (d2.lo 0) *c_to++ = *c_from++; } void cmove_up(Char *c_from, Char *c_to, UCell u) { while (u-- > 0) c_to[u] = c_from[u]; } Cell compare(Char *c_addr1, UCell u1, Char *c_addr2, UCell u2) { Cell n; n = memcmp(c_addr1, c_addr2, u10) n = 1; return n; } Cell memcasecmp(const Char *s1, const Char *s2, Cell n) { Cell i; for (i=0; inext)) if ((UCell)LONGNAME_COUNT(longname1)==u && memcasecmp(c_addr, longname1->name, u)== 0 /* or inline? */) break; return longname1; } struct Longname *hashlfind(Char *c_addr, UCell u, Cell *a_addr) { struct Longname *longname1; while(a_addr != NULL) { longname1=(struct Longname *)(a_addr[1]); a_addr=(Cell *)(a_addr[0]); if ((UCell)LONGNAME_COUNT(longname1)==u && memcasecmp(c_addr, longname1->name, u)== 0 /* or inline? */) { return longname1; } } return NULL; } struct Longname *tablelfind(Char *c_addr, UCell u, Cell *a_addr) { struct Longname *longname1; while(a_addr != NULL) { longname1=(struct Longname *)(a_addr[1]); a_addr=(Cell *)(a_addr[0]); if ((UCell)LONGNAME_COUNT(longname1)==u && memcmp(c_addr, longname1->name, u)== 0 /* or inline? */) { return longname1; } } return NULL; } UCell hashkey1(Char *c_addr, UCell u, UCell ubits) /* this hash function rotates the key at every step by rot bits within ubits bits and xors it with the character. This function does ok in the chi-sqare-test. Rot should be <=7 (preferably <=5) for ASCII strings (larger if ubits is large), and should share no divisors with ubits. */ { static char rot_values[] = {5,0,1,2,3,4,5,5,5,5,3,5,5,5,5,7,5,5,5,5,7,5,5,5,5,6,5,5,5,5,7,5,5}; unsigned rot = rot_values[ubits]; Char *cp = c_addr; UCell ukey; for (ukey=0; cp>(ubits-rot))) ^ toupper(*cp)) & ((1<0) ; switch(number[u]) { case 'd': case 'D': case 'e': case 'E': break; default : u++; break; } number[u]='\0'; r=strtod(number,&endconv); if((flag=FLAG(!(Cell)*endconv))) { if (sign) r = -r; } else if(*endconv=='d' || *endconv=='D') { *endconv='E'; r=strtod(number,&endconv); if((flag=FLAG(!(Cell)*endconv))) { if (sign) r = -r; } } *rp = r; return flag; } Float v_star(Float *f_addr1, Cell nstride1, Float *f_addr2, Cell nstride2, UCell ucount) { Float r; for (r=0.; ucount>0; ucount--) { r += *f_addr1 * *f_addr2; f_addr1 = (Float *)(((Address)f_addr1)+nstride1); f_addr2 = (Float *)(((Address)f_addr2)+nstride2); } return r; } void faxpy(Float ra, Float *f_x, Cell nstridex, Float *f_y, Cell nstridey, UCell ucount) { for (; ucount>0; ucount--) { *f_y += ra * *f_x; f_x = (Float *)(((Address)f_x)+nstridex); f_y = (Float *)(((Address)f_y)+nstridey); } } UCell lshift(UCell u1, UCell n) { return u1 << n; } UCell rshift(UCell u1, UCell n) { return u1 >> n; } int gforth_system(Char *c_addr, UCell u) { int retval; char *prefix = getenv("GFORTHSYSTEMPREFIX") ? : DEFAULTSYSTEMPREFIX; size_t prefixlen = strlen(prefix); char buffer[prefixlen+u+1]; #ifndef MSDOS int old_tp=terminal_prepped; deprep_terminal(); #endif memcpy(buffer,prefix,prefixlen); memcpy(buffer+prefixlen,c_addr,u); buffer[prefixlen+u]='\0'; retval=system(buffer); /* ~ expansion on first part of string? */ #ifndef MSDOS if (old_tp) prep_terminal(); #endif return retval; }