From 57408873103c51aca8fa374aa9261b70f7afccf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Thu, 1 Jan 1998 17:06:47 -0800 Subject: [PATCH] lots of updates for NT, threads and new cpp Rev: src/ChangeLog:1.128 Rev: src/Makefile.in:1.49 Rev: src/backend.c:1.20 Rev: src/configure.in:1.145 Rev: src/cpp.c:1.2 Rev: src/cpp.h:1.2 Rev: src/fd_control.c:1.11 Rev: src/fdlib.c:1.1 Rev: src/fdlib.h:1.1 Rev: src/fsort.c:1.3 Rev: src/fsort_template.h:1.2 Rev: src/lex.c:1.36 Rev: src/lex.h:1.6 Rev: src/main.c:1.29 Rev: src/modules/files/file.c:1.63 Rev: src/modules/files/socket.c:1.20 Rev: src/modules/readline/readlinemod.c:1.4 Rev: src/object.c:1.30 Rev: src/object.h:1.12 Rev: src/port.c:1.13 Rev: src/program.c:1.47 Rev: src/program.h:1.23 Rev: src/stuff.c:1.4 Rev: src/stuff.h:1.4 Rev: src/threads.c:1.48 Rev: src/threads.h:1.22 Rev: src/time_stuff.h:1.5 --- src/ChangeLog | 5 + src/Makefile.in | 2 + src/backend.c | 77 +- src/configure.in | 8 +- src/cpp.c | 1952 ++++++++++++++++++++++++++++ src/cpp.h | 26 + src/fd_control.c | 10 +- src/fdlib.c | 355 +++++ src/fdlib.h | 157 +++ src/fsort.c | 2 +- src/fsort_template.h | 2 +- src/lex.c | 16 +- src/lex.h | 4 - src/main.c | 33 +- src/modules/files/file.c | 89 +- src/modules/files/socket.c | 23 +- src/modules/readline/readlinemod.c | 10 + src/object.c | 8 +- src/object.h | 3 + src/port.c | 18 + src/program.c | 18 +- src/program.h | 3 + src/stuff.c | 11 + src/stuff.h | 1 + src/threads.c | 51 +- src/threads.h | 10 +- src/time_stuff.h | 1 - 27 files changed, 2772 insertions(+), 123 deletions(-) create mode 100644 src/cpp.c create mode 100644 src/cpp.h create mode 100644 src/fdlib.c create mode 100644 src/fdlib.h diff --git a/src/ChangeLog b/src/ChangeLog index f081de6846..7bcfe69890 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +Thu Jan 1 16:56:09 1998 Fredrik Hubinette <hubbe@cytocin.hubbe.net> + + * threads.c: new methods added: wait and status + * cpp.c: new file + Mon Dec 22 09:33:59 1997 Fredrik Hubinette <hubbe@cytocin.hubbe.net> * version.c: version now includes release number diff --git a/src/Makefile.in b/src/Makefile.in index 5c0c23fe70..630257312e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -76,6 +76,8 @@ MAKE_FLAGS = $(MOST_MAKE_FLAGS) "OTHERFLAGS=$(OTHERFLAGS)" OBJ= \ language.o \ constants.o \ + cpp.o \ + fdlib.o \ cyclic.o \ array.o \ backend.o \ diff --git a/src/backend.c b/src/backend.c index 400641493a..e0d8b7ce84 100644 --- a/src/backend.c +++ b/src/backend.c @@ -4,7 +4,8 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: backend.c,v 1.19 1997/12/23 06:26:04 hubbe Exp $"); +RCSID("$Id: backend.c,v 1.20 1998/01/02 01:05:41 hubbe Exp $"); +#include "fdlib.h" #include "backend.h" #include <errno.h> #ifdef HAVE_SYS_TYPES_H @@ -21,6 +22,7 @@ RCSID("$Id: backend.c,v 1.19 1997/12/23 06:26:04 hubbe Exp $"); #include "main.h" #include "callback.h" #include "threads.h" +#include "fdlib.h" #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> @@ -62,7 +64,7 @@ struct callback *add_backend_callback(callback_func call, static void wakeup_callback(int fd, void *foo) { char buffer[1024]; - read(fd, buffer, sizeof(buffer)); /* Clear 'flag' */ + fd_read(fd, buffer, sizeof(buffer)); /* Clear 'flag' */ } /* This is used by threaded programs and signals to wake up the @@ -72,17 +74,17 @@ void wake_up_backend(void) { char foo=0; if(may_need_wakeup) - write(wakeup_pipe[1], &foo ,1); + fd_write(wakeup_pipe[1], &foo ,1); } extern int pike_make_pipe(int *); void init_backend(void) { - FD_ZERO(&selectors.read); - FD_ZERO(&selectors.write); + fd_FD_ZERO(&selectors.read); + fd_FD_ZERO(&selectors.write); if(pike_make_pipe(wakeup_pipe) < 0) - fatal("Couldn't create backend wakup pipe, errno=%d.\n",errno); + fatal("Couldn't create backend wakup pipe! errno=%d.\n",errno); set_nonblocking(wakeup_pipe[0],1); set_nonblocking(wakeup_pipe[1],1); set_read_callback(wakeup_pipe[0], wakeup_callback, 0); @@ -103,18 +105,18 @@ void set_read_callback(int fd,file_callback cb,void *data) if(cb) { - FD_SET(fd, &selectors.read); + fd_FD_SET(fd, &selectors.read); if(max_fd < fd) max_fd = fd; wake_up_backend(); }else{ if(fd <= max_fd) { - FD_CLR(fd, &selectors.read); + fd_FD_CLR(fd, &selectors.read); if(fd == max_fd) { while(max_fd >=0 && - !FD_ISSET(max_fd, &selectors.read) && - !FD_ISSET(max_fd, &selectors.write)) + !fd_FD_ISSET(max_fd, &selectors.read) && + !fd_FD_ISSET(max_fd, &selectors.write)) max_fd--; } } @@ -133,18 +135,18 @@ void set_write_callback(int fd,file_callback cb,void *data) if(cb) { - FD_SET(fd, &selectors.write); + fd_FD_SET(fd, &selectors.write); if(max_fd < fd) max_fd = fd; wake_up_backend(); }else{ if(fd <= max_fd) { - FD_CLR(fd, &selectors.write); + fd_FD_CLR(fd, &selectors.write); if(fd == max_fd) { while(max_fd >=0 && - !FD_ISSET(max_fd, &selectors.read) && - !FD_ISSET(max_fd, &selectors.write)) + !fd_FD_ISSET(max_fd, &selectors.read) && + !fd_FD_ISSET(max_fd, &selectors.write)) max_fd--; } } @@ -217,11 +219,11 @@ void do_debug(void) for(e=0;e<=max_fd;e++) { - if(FD_ISSET(e,&selectors.read) || FD_ISSET(e,&selectors.write)) + if(fd_FD_ISSET(e,&selectors.read) || fd_FD_ISSET(e,&selectors.write)) { int ret; do { - ret=fstat(e, &tmp); + ret=fd_fstat(e, &tmp); }while(ret < 0 && errno == EINTR); if(ret<0) @@ -286,7 +288,7 @@ void backend(void) } THREADS_ALLOW(); - i=select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout); + i=fd_select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout); GETTIMEOFDAY(¤t_time); THREADS_DISALLOW(); may_need_wakeup=0; @@ -295,10 +297,10 @@ void backend(void) { for(i=0; i<max_fd+1; i++) { - if(FD_ISSET(i, &sets.read) && read_callback[i]) + if(fd_FD_ISSET(i, &sets.read) && read_callback[i]) (*(read_callback[i]))(i,read_callback_data[i]); - if(FD_ISSET(i, &sets.write) && write_callback[i]) + if(fd_FD_ISSET(i, &sets.write) && write_callback[i]) (*(write_callback[i]))(i,write_callback_data[i]); } }else{ @@ -315,19 +317,19 @@ void backend(void) sets=selectors; next_timeout.tv_usec=0; next_timeout.tv_sec=0; - if(select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout) < 0 && errno == EBADF) + if(fd_select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout) < 0 && errno == EBADF) { int i; for(i=0;i<MAX_OPEN_FILEDESCRIPTORS;i++) { - if(!FD_ISSET(i, &selectors.read) && !FD_ISSET(i,&selectors.write)) + if(!fd_FD_ISSET(i, &selectors.read) && !FD_ISSET(i,&selectors.write)) continue; - FD_ZERO(& sets.read); - FD_ZERO(& sets.write); + fd_FD_ZERO(& sets.read); + fd_FD_ZERO(& sets.write); - if(FD_ISSET(i, &selectors.read)) FD_SET(i, &sets.read); - if(FD_ISSET(i, &selectors.write)) FD_SET(i, &sets.write); + if(fd_FD_ISSET(i, &selectors.read)) fd_FD_SET(i, &sets.read); + if(fd_FD_ISSET(i, &selectors.write)) fd_FD_SET(i, &sets.write); next_timeout.tv_usec=0; next_timeout.tv_sec=0; @@ -354,19 +356,36 @@ void backend(void) int write_to_stderr(char *a, INT32 len) { - int nonblock; + int nonblock=0; INT32 pos, tmp; - if((nonblock=query_nonblocking(2))) - set_nonblocking(2,0); + if(!len) return 1; for(pos=0;pos<len;pos+=tmp) { tmp=write(2,a+pos,len-pos); - if(tmp<0) break; + if(tmp<0) + { + tmp=0; + switch(errno) + { +#ifdef EWOULDBLOCK + case EWOULDBLOCK: + nonblock=1; + set_nonblocking(2,0); + continue; +#endif + + case EINTR: + continue; + } + break; + } } + if(nonblock) set_nonblocking(2,1); + return 1; } diff --git a/src/configure.in b/src/configure.in index 9cbfd81114..d5a2c84bed 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1,4 +1,4 @@ -AC_REVISION("$Id: configure.in,v 1.144 1997/12/28 09:29:08 hubbe Exp $") +AC_REVISION("$Id: configure.in,v 1.145 1998/01/02 01:05:41 hubbe Exp $") AC_INIT(interpret.c) AC_CONFIG_HEADER(machine.h) @@ -619,7 +619,7 @@ AC_CHECK_HEADERS(sys/rusage.h time.h sys/time.h sys/types.h unistd.h stdlib.h \ memory.h values.h string.h strings.h fcntl.h sys/filio.h sys/sockio.h crypt.h \ locale.h sys/resource.h sys/select.h sys/mman.h setjmp.h limits.h pthread.h \ thread.h dlfcn.h dld.h sys/times.h sched.h sys/procfs.h sys/param.h winsock.h \ -sys/ioct.h sys/socket.h malloc.h netinet/in.h sys/wait.h) +sys/ioct.h sys/socket.h malloc.h netinet/in.h sys/wait.h winbase.h) AC_CHECK_SIZEOF(char *,4) AC_CHECK_SIZEOF(long,4) @@ -900,6 +900,8 @@ AC_CHECK_FUNCS( \ setlocale \ setrlimit \ sigaction \ + sigblock \ + sigprocmask \ sigvec \ strcasecmp \ strchr \ @@ -909,6 +911,8 @@ AC_CHECK_FUNCS( \ strtod \ strtok \ strtol \ + time \ + GetSystemTimeAsFileTime \ times \ vfprintf \ vsprintf \ diff --git a/src/cpp.c b/src/cpp.c new file mode 100644 index 0000000000..55a84216ff --- /dev/null +++ b/src/cpp.c @@ -0,0 +1,1952 @@ +/*\ +||| This file a part of Pike, and is copyright by Fredrik Hubinette +||| Pike is distributed as GPL (General Public License) +||| See the files COPYING and DISCLAIMER for more information. +\*/ +#include "global.h" +#include "dynamic_buffer.h" +#include "lex.h" +#include "language.h" +#include "stralloc.h" +#include "module_support.h" +#include "interpret.h" +#include "svalue.h" +#include "pike_macros.h" +#include "hashtable.h" +#include "program.h" +#include "object.h" +#include "error.h" +#include "array.h" +#include "mapping.h" +#include "builtin_functions.h" +#include "operators.h" +#include "opcodes.h" +#include "constants.h" +#include "time.h" +#include "stuff.h" +#include <ctype.h> + +#define CPP_NO_OUTPUT 1 +#define CPP_EXPECT_ELSE 2 +#define CPP_EXPECT_ENDIF 4 +#define CPP_REALLY_NO_OUTPUT 8 +#define CPP_END_AT_NEWLINE 16 +#define CPP_DO_IF 32 + +#define OUTP() (!(flags & (CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT))) +#define PUTNL() low_my_putchar('\n', &this->buf) +#define GOBBLE(X) (data[pos]==(X)?++pos,1:0) +#define PUTC(C) do { \ + int c_=(C); if(OUTP() || c_=='\n') low_my_putchar(c_, &this->buf); }while(0) + +#define STRCAT(STR,LEN) do { \ + INT32 x_,len_=(LEN); \ + char *str_=(STR); \ + if(OUTP()) \ + low_my_binary_strcat(str_,len_, &this->buf); \ + else \ + for(x_=0;x_<len_;x_++) \ + if(str_[x_]=='\n') \ + low_my_putchar('\n',&this->buf); \ +}while(0) + +#define CHECKWORD(X) \ + (!strncmp(X,data+pos,strlen(X)) && !isidchar(data[pos+strlen(X)])) +#define WGOBBLE(X) (CHECKWORD(X) ? (pos+=strlen(X)),1 : 0) +#define GOBBLEOP(X) \ + ((!strncmp(X,data+pos,strlen(X))) ? (pos+=strlen(X)),1 : 0) + +#define MAX_ARGS 255 +#define DEF_ARG_STRINGIFY 0x100000 +#define DEF_ARG_NOPRESPACE 0x200000 +#define DEF_ARG_NOPOSTSPACE 0x400000 +#define DEF_ARG_MASK 0x0fffff + + +struct pike_predef_s +{ + struct pike_predef_s *next; + char *name; + char *value; +}; + +static struct pike_predef_s *pike_predefs=0; +struct define_part +{ + int argument; + struct pike_string *postfix; +}; + +struct define_argument { + char *arg; + INT32 len; +}; + + +struct cpp; +struct define; +typedef void (*magic_define_fun)(struct cpp *, + struct define *, + struct define_argument *, + dynamic_buffer *); + + +struct define +{ + struct hash_entry link; /* must be first */ + magic_define_fun magic; + int args; + int num_parts; + int inside; + struct pike_string *first; + struct define_part parts[1]; +}; + +#define find_define(N) \ + (this->defines?BASEOF(hash_lookup(this->defines, N), define, link):0) + +struct cpp +{ + struct hash_table *defines; + INT32 current_line; + INT32 compile_errors; + struct pike_string *current_file; + dynamic_buffer buf; +}; + +struct define *defined_macro =0; +struct define *constant_macro =0; + +static INT32 calc(struct cpp *,char*,INT32,INT32); +static INT32 calc1(struct cpp *,char*,INT32,INT32); + +void cpp_error(struct cpp *this,char *err) +{ + this->compile_errors++; + if(this->compile_errors > 10) return; + if(get_master()) + { + ref_push_string(this->current_file); + push_int(this->current_line); + push_text(err); + SAFE_APPLY_MASTER("compile_error",3); + pop_stack(); + }else{ + (void)fprintf(stderr, "%s:%ld: %s", + this->current_file->str, + (long)this->current_line, + err); + fflush(stderr); + } +} + +/* devours one reference to 'name'! */ +static struct define *alloc_empty_define(struct pike_string *name, INT32 parts) +{ + struct define *def; + def=(struct define *)xalloc(sizeof(struct define)+ + sizeof(struct define_part) * (parts -1)); + def->magic=0; + def->args=-1; + def->inside=0; + def->num_parts=parts; + def->first=0; + def->link.s=name; + return def; +} + +static void undefine(struct cpp *this, + struct pike_string *name) +{ + INT32 e; + struct define *d; + + d=find_define(name); + + if(!d) return; + + this->defines=hash_unlink(this->defines, & d->link); + + for(e=0;e<d->num_parts;e++) + free_string(d->parts[e].postfix); + free_string(d->link.s); + if(d->first) + free_string(d->first); + free((char *)d); +} + +static void do_magic_define(struct cpp *this, + char *name, + magic_define_fun fun) +{ + struct define* def=alloc_empty_define(make_shared_string(name),0); + def->magic=fun; + this->defines=hash_insert(this->defines, & def->link); +} + +static void simple_add_define(struct cpp *this, + char *name, + char *what) +{ + struct define* def=alloc_empty_define(make_shared_string(name),0); + def->first=make_shared_string(what); + this->defines=hash_insert(this->defines, & def->link); +} + + +/* Who needs inline functions anyway? /Hubbe */ + +#define FIND_END_OF_STRING() do { \ + while(1) \ + { \ + if(pos>=len) \ + { \ + cpp_error(this,"End of file in string."); \ + break; \ + } \ + switch(data[pos++]) \ + { \ + case '\n': \ + cpp_error(this,"Newline in string."); \ + this->current_line++; \ + break; \ + case '"': break; \ + case '\\': if(data[++pos]=='\n') this->current_line++; \ + default: continue; \ + } \ + break; \ + } } while(0) + + +#define FIND_END_OF_CHAR() do { \ + int e=0; \ + while(1) \ + { \ + if(pos+1>=len) \ + { \ + cpp_error(this,"End of file in character constant."); \ + break; \ + } \ + \ + if(e++>16) \ + { \ + cpp_error(this,"Too long character constant."); \ + break; \ + } \ + \ + switch(data[pos++]) \ + { \ + case '\n': \ + cpp_error(this,"Newline in char."); \ + this->current_line++; \ + break; \ + case '\'': break; \ + case '\\': if(data[++pos]=='\n') this->current_line++; \ + default: continue; \ + } \ + break; \ + } } while(0) + +#define DUMPPOS(X) \ + fprintf(stderr,"\nPOS(%s):",X); \ + fflush(stderr); \ + write(2,data+pos,20); \ + fprintf(stderr,"\n"); \ + fflush(stderr) + +#define FIND_EOL() do { \ + this->current_line++; \ + while(pos < len && data[pos]!='\n') pos++; \ + } while(0) + +#define SKIPWHITE() do { \ + if(!isspace(data[pos])) break; \ + PUTNL(); \ + pos++; \ + } while(0) + +#define SKIPSPACE() \ + do { while(isspace(data[pos]) && data[pos]!='\n') pos++; }while (0) + +#define SKIPCOMMENT() do{ \ + pos++; \ + while(data[pos]!='*' || data[pos+1]!='/') \ + { \ + if(pos+2>=len) \ + { \ + cpp_error(this,"End of file in comment."); \ + break; \ + } \ + \ + if(data[pos]=='\n') \ + { \ + this->current_line++; \ + PUTNL(); \ + } \ + \ + pos++; \ + } \ + pos+=2; \ + }while(0) + +#define READCHAR(C) do { \ + switch(data[++pos]) \ + { \ + case 'n': C='\n'; break; \ + case 'r': C='\r'; break; \ + case 'b': C='\b'; break; \ + case 't': C='\t'; break; \ + \ + case '0': case '1': case '2': case '3': \ + case '4': case '5': case '6': case '7': \ + C=data[pos]-'0'; \ + if(data[pos+1]>='0' && data[pos+1]<='8') \ + { \ + C*=8; \ + C+=data[++pos]-'0'; \ + \ + if(data[pos+1]>='0' && data[pos+1]<='8') \ + { \ + C*=8; \ + C+=data[++pos]-'0'; \ + } \ + } \ + break; \ + \ + case '\n': \ + this->current_line++; \ + C='\n'; \ + break; \ + \ + default: \ + C=data[pos]; \ + } \ +}while (0) + + +#define READSTRING(nf) \ +while(1) \ +{ \ + pos++; \ + if(pos>=len) \ + { \ + cpp_error(this,"End of file in string."); \ + break; \ + } \ + \ + switch(data[pos]) \ + { \ + case '\n': \ + cpp_error(this,"Newline in string."); \ + this->current_line++; \ + break; \ + case '"': break; \ + case '\\': \ + { \ + int tmp; \ + READCHAR(tmp); \ + low_my_putchar(tmp, &nf); \ + continue; \ + } \ + \ + default: \ + low_my_putchar(data[pos], &nf); \ + continue; \ + } \ + pos++; \ + break; \ +} + +void PUSH_STRING(char *str, + INT32 len, + dynamic_buffer *buf) +{ + INT32 p2; + low_my_putchar('"', buf); + for(p2=0;p2<len;p2++) + { + switch(str[p2]) + { + case '\n': + low_my_putchar('\\', buf); + low_my_putchar('n', buf); + break; + + case '\t': + low_my_putchar('\\', buf); + low_my_putchar('t', buf); + break; + + case '\r': + low_my_putchar('\\', buf); + low_my_putchar('r', buf); + break; + + case '\b': + low_my_putchar('\\', buf); + low_my_putchar('b', buf); + break; + + case '\\': + case '"': + low_my_putchar('\\', buf); + low_my_putchar(str[p2], buf); + break; + + default: + if(isprint(EXTRACT_UCHAR(str+p2))) + { + low_my_putchar(str[p2], buf); + } + else + { + int c=EXTRACT_UCHAR(str+p2); + low_my_putchar('\\', buf); + low_my_putchar(((c>>6)&7)+'0', buf); + low_my_putchar(((c>>3)&7)+'0', buf); + low_my_putchar((c&7)+'0', buf); + } + break; + } + } + low_my_putchar('"', buf); +} + +#define FINDTOK() \ + do { \ + SKIPSPACE(); \ + if(data[pos]=='/') \ + { \ + INT32 tmp; \ + switch(data[pos+1]) \ + { \ + case '/': \ + FIND_EOL(); \ + break; \ + \ + case '*': \ + tmp=pos+2; \ + while(1) \ + { \ + if(data[tmp]=='*') \ + { \ + if(data[tmp+1] == '/') \ + { \ + pos=tmp+2; \ + break; \ + } \ + break; \ + } \ + \ + if(data[tmp]=='\n') \ + break; \ + tmp++; \ + } \ + } \ + } \ + break; \ + }while(1) + +static INLINE int find_end_parenthesis(struct cpp *this, + char *data, + INT32 len, + INT32 pos) /* position of first " */ +{ + while(1) + { + if(pos+1>=len) + { + cpp_error(this,"End of file while looking for end parenthesis."); + return pos; + } + + switch(data[pos++]) + { + case '\n': this->current_line++; break; + case '\'': FIND_END_OF_CHAR(); break; + case '"': FIND_END_OF_STRING(); break; + case '(': pos=find_end_parenthesis(this, data, len, pos); break; + case ')': return pos; + } + } +} + +static INT32 low_cpp(struct cpp *this, + char *data, + INT32 len, + int flags) +{ + INT32 pos, tmp, e; + + for(pos=0;pos<len;) + { +/* fprintf(stderr,"%c",data[pos]); + fflush(stderr); */ + + switch(data[pos++]) + { + case '\n': + if(flags & CPP_END_AT_NEWLINE) return pos-1; + +/* fprintf(stderr,"CURRENT LINE: %d\n",this->current_line); */ + this->current_line++; + PUTNL(); + goto do_skipwhite; + + case '\t': + case ' ': + case '\r': + PUTC(' '); + + do_skipwhite: + while(data[pos]==' ' || data[pos]=='\r' || data[pos]=='\t') + pos++; + break; + + /* Minor optimization */ + case '!': case '@': case '$': case '%': case '^': case '&': + case '*': case '(': case ')': case '-': case '=': case '+': + case '{': case '}': case ':': case '?': case '`': case ';': + case '<': case '>': case ',': case '.': case '~': case '[': + case ']': case '|': + PUTC(data[pos-1]); + break; + + default: + if(OUTP() && isidchar(data[pos-1])) + { + struct pike_string *s=0; + struct define *d=0; + tmp=pos-1; + while(isidchar(data[pos])) pos++; + + if(flags & CPP_DO_IF) + { + if(pos-tmp == 7 && !strncmp("defined",data+tmp, 7)) + { + d=defined_macro; + } + else if((pos-tmp == 4 && !strncmp("efun",data+tmp, 4)) || + (pos-tmp == 8 && !strncmp("constant",data+tmp,8))) + { + d=constant_macro; + } + else + { + goto do_find_define; + } + }else{ + do_find_define: + if((s=binary_findstring(data+tmp, pos-tmp))) + { + d=find_define(s); + } + } + + if(d && !d->inside) + { + int arg=0; + dynamic_buffer tmp; + struct define_argument arguments [MAX_ARGS]; + + if(s) s->refs++; + + if(d->args>=0) + { + SKIPWHITE(); + + if(!GOBBLE('(')) + { + cpp_error(this,"Missing '(' in macro call."); + break; + } + + for(arg=0;arg<d->args;arg++) + { + SKIPWHITE(); + arguments[arg].arg=data + pos; + if(data[pos]==')') + { + cpp_error(this,"Too few arguments to macro."); + break; + } + + while(1) + { + if(pos+1>len) + { + cpp_error(this,"End of file in macro call."); + break; + } + + switch(data[pos++]) + { + case '\n': + this->current_line++; + PUTNL(); + default: continue; + + case '"': + FIND_END_OF_STRING(); + continue; + + case '\'': + FIND_END_OF_CHAR(); + continue; + + case '(': + pos=find_end_parenthesis(this, data, len, pos); + continue; + + case ')': pos--; + case ',': + break; + } + break; + } + arguments[arg].len=data+pos-arguments[arg].arg; + } + SKIPWHITE(); + if(!GOBBLE(')')) + cpp_error(this,"Missing ) in macro call."); + } + + if(d->args >= 0 && arg != d->args) + cpp_error(this,"Wrong number of arguments to macro."); + + initialize_buf(&tmp); + if(d->magic) + { + d->magic(this, d, arguments, &tmp); + }else{ + low_my_binary_strcat(d->first->str, d->first->len, &tmp); + for(e=0;e<d->num_parts;e++) + { + char *a; + INT32 l; + + if((d->parts[e].argument & DEF_ARG_MASK) < 0 || + (d->parts[e].argument & DEF_ARG_MASK) >= arg) + { + cpp_error(this,"Macro not expanded correctly."); + continue; + } + + a=arguments[d->parts[e].argument&DEF_ARG_MASK].arg; + l=arguments[d->parts[e].argument&DEF_ARG_MASK].len; + + if(!(d->parts[e].argument & DEF_ARG_NOPRESPACE)) + low_my_putchar(' ', &tmp); + + if(d->parts[e].argument & DEF_ARG_STRINGIFY) + { + PUSH_STRING(a,l,&tmp); + }else{ + low_my_binary_strcat(a, l, &tmp); + } + + if(!(d->parts[e].argument & DEF_ARG_NOPOSTSPACE)) + low_my_putchar(' ', &tmp); + + low_my_binary_strcat(d->parts[e].postfix->str, + d->parts[e].postfix->len, + &tmp); + } + } + + /* FIXME */ + for(e=0;e<(long)tmp.s.len;e++) + if(tmp.s.str[e]=='\n') + tmp.s.str[e]=' '; + + if(s) d->inside=1; + + low_my_putchar(0, &tmp); + tmp.s.len--; + + low_cpp(this, tmp.s.str, tmp.s.len, + flags & ~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE)); + + if(s) + { + if((d=find_define(s))) + d->inside=0; + + free_string(s); + } + + toss_buffer(&tmp); + break; + }else{ + if(flags & CPP_DO_IF) + { + STRCAT(" 0 ", 3); + }else{ + STRCAT(data+tmp, pos-tmp); + } + } + }else{ + PUTC(data[pos-1]); + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + PUTC(data[pos-1]); + while(data[pos]>='0' && data[pos]<='9') PUTC(data[pos++]); + break; + + case '"': + tmp=pos-1; + FIND_END_OF_STRING(); + STRCAT(data+tmp, pos-tmp); + break; + + case '\'': + tmp=pos-1; + FIND_END_OF_CHAR(); + STRCAT(data+tmp, pos-tmp); + break; + + case '/': + if(data[pos]=='/') + { + FIND_EOL(); + break; + } + + if(data[pos]=='*') + { + PUTC(' '); + SKIPCOMMENT(); + break; + } + + PUTC(data[pos-1]); + break; + + case '#': + if(GOBBLE('!')) + { + FIND_EOL(); + break; + } + SKIPSPACE(); + + switch(data[pos]) + { + case 'l': + if(WGOBBLE("line")) + { + while(data[pos]==' ' || data[pos]=='\t') pos++; + }else{ + goto unknown_preprocessor_directive; + } + /* Fall through */ + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + char *foo=data+pos; + this->current_line=STRTOL(foo, &foo, 10)-1; + pos=foo-data; + SKIPSPACE(); + + if(data[pos]=='"') + { + dynamic_buffer nf; + initialize_buf(&nf); + + READSTRING(nf); + + free_string(this->current_file); + this->current_file=low_free_buf(&nf); + } + + FIND_EOL(); + break; + } + + case 'i': /* include, if, ifdef */ + if(WGOBBLE("include")) + { + struct svalue *save_sp=sp; + SKIPSPACE(); + + check_stack(3); + + switch(data[pos++]) + { + case '"': + { + dynamic_buffer nf; + initialize_buf(&nf); + pos--; + READSTRING(nf); + push_string(low_free_buf(&nf)); + ref_push_string(this->current_file); + push_int(1); + break; + } + + case '<': + { + INT32 tmp=pos; + while(data[pos]!='>') + { + if(data[pos]=='\n') + { + cpp_error(this,"Expecting '>' in include."); + break; + } + + pos++; + } + push_string(make_shared_binary_string(data+tmp, pos-tmp)); + ref_push_string(this->current_file); + pos++; + push_int(0); + break; + } + + default: + cpp_error(this,"Expected file to include."); + break; + } + + if(sp==save_sp) break; + + if(OUTP()) + { + struct pike_string *new_file; + + SAFE_APPLY_MASTER("handle_include",3); + + if(sp[-1].type != T_STRING) + { + cpp_error(this,"Couldn't include file."); + pop_n_elems(sp-save_sp); + break; + } + + new_file=sp[-1].u.string; + + assign_svalue_no_free(sp,sp-1); + sp++; + + SAFE_APPLY_MASTER("read_include",1); + + if(sp[-1].type != T_STRING) + { + cpp_error(this,"Couldn't read include file."); + pop_n_elems(sp-save_sp); + break; + } + + + { + char buffer[47]; + struct pike_string *save_current_file; + INT32 save_current_line; + + save_current_file=this->current_file; + save_current_line=this->current_line; + copy_shared_string(this->current_file,new_file); + + low_my_binary_strcat("# 1 ",4,&this->buf); + PUSH_STRING(new_file->str,new_file->len, & this->buf); + low_my_putchar('\n',&this->buf); + + + low_cpp(this, + sp[-1].u.string->str, + sp[-1].u.string->len, + flags&~(CPP_EXPECT_ENDIF | CPP_EXPECT_ELSE)); + + free_string(this->current_file); + this->current_file=save_current_file; + this->current_line=save_current_line; + + sprintf(buffer,"# %d ",this->current_line); + low_my_binary_strcat(buffer,strlen(buffer),&this->buf); + PUSH_STRING(this->current_file->str,this->current_file->len,& this->buf); + low_my_putchar('\n',&this->buf); + } + } + + pop_n_elems(sp-save_sp); + + break; + } + + if(WGOBBLE("if")) + { + dynamic_buffer save,tmp; + INT32 nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF; + + if(!OUTP()) + nflags|=CPP_REALLY_NO_OUTPUT; + + save=this->buf; + initialize_buf(& this->buf); + pos+=low_cpp(this,data+pos,len-pos,CPP_END_AT_NEWLINE|CPP_DO_IF); + tmp=this->buf; + this->buf=save; + + low_my_putchar(0, &tmp); + tmp.s.len--; + + calc(this,tmp.s.str,tmp.s.len,0); + toss_buffer(&tmp); + if(IS_ZERO(sp-1)) nflags|=CPP_NO_OUTPUT; + pop_stack(); + pos+=low_cpp(this,data+pos,len-pos,nflags); + break; + } + + if(WGOBBLE("ifdef")) + { + INT32 namestart,nflags; + struct pike_string *s; + SKIPSPACE(); + + if(!isidchar(data[pos])) + cpp_error(this,"#ifdef what?\n"); + + namestart=pos; + while(isidchar(data[pos])) pos++; + nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF | CPP_NO_OUTPUT; + + if(!OUTP()) + nflags|=CPP_REALLY_NO_OUTPUT; + + if((s=binary_findstring(data+namestart,pos-namestart))) + if(find_define(s)) + nflags&=~CPP_NO_OUTPUT; + + pos+=low_cpp(this,data+pos,len-pos,nflags); + break; + } + + if(WGOBBLE("ifndef")) + { + INT32 namestart,nflags; + struct pike_string *s; + SKIPSPACE(); + + if(!isidchar(data[pos])) + cpp_error(this,"#ifndef what?"); + + namestart=pos; + while(isidchar(data[pos])) pos++; + nflags=CPP_EXPECT_ELSE | CPP_EXPECT_ENDIF; + + if(!OUTP()) + nflags|=CPP_REALLY_NO_OUTPUT; + + if((s=binary_findstring(data+namestart,pos-namestart))) + if(find_define(s)) + nflags|=CPP_NO_OUTPUT; + + pos+=low_cpp(this,data+pos,len-pos,nflags); + break; + } + + goto unknown_preprocessor_directive; + + case 'e': /* endif, else, elif, error */ + if(WGOBBLE("endif")) + { + if(!(flags & CPP_EXPECT_ENDIF)) + cpp_error(this,"Unmatched #endif"); + + return pos; + } + + if(WGOBBLE("else")) + { + if(!(flags & CPP_EXPECT_ELSE)) + cpp_error(this,"Unmatched #else"); + + flags&=~CPP_EXPECT_ELSE; + flags|=CPP_EXPECT_ENDIF; + + if(flags & CPP_NO_OUTPUT) + flags&=~CPP_NO_OUTPUT; + else + flags|=CPP_NO_OUTPUT; + + break; + } + + if(WGOBBLE("elif") || WGOBBLE("elseif")) + { + if(!(flags & CPP_EXPECT_ELSE)) + cpp_error(this,"Unmatched #elif"); + + flags|=CPP_EXPECT_ENDIF; + + if(flags & CPP_NO_OUTPUT) + { + dynamic_buffer save,tmp; + save=this->buf; + initialize_buf(& this->buf); + pos+=low_cpp(this,data+pos,len-pos,CPP_END_AT_NEWLINE|CPP_DO_IF); + tmp=this->buf; + this->buf=save; + + low_my_putchar(0, &tmp); + tmp.s.len--; + + calc(this,tmp.s.str,tmp.s.len,0); + toss_buffer(&tmp); + if(!IS_ZERO(sp-1)) flags&=~CPP_NO_OUTPUT; + pop_stack(); + }else{ + FIND_EOL(); + flags|= CPP_NO_OUTPUT | CPP_REALLY_NO_OUTPUT; + } + break; + } + + if(WGOBBLE("error")) + { + INT32 foo; + SKIPSPACE(); + foo=pos; + FIND_EOL(); + pos++; + if(OUTP()) + { + push_string(make_shared_binary_string(data+foo,pos-foo)); + cpp_error(this,sp[-1].u.string->str); + } + break; + } + + goto unknown_preprocessor_directive; + + case 'd': /* define */ + if(WGOBBLE("define")) + { + dynamic_buffer str; + INT32 namestart, tmp3, nameend, argno=-1; + struct define *def; + struct svalue *partbase,*argbase=sp; + + SKIPSPACE(); + + namestart=pos; + if(!isidchar(data[pos])) + cpp_error(this,"Define what?"); + + while(isidchar(data[pos])) pos++; + nameend=pos; + + if(GOBBLE('(')) + { + argno=0; + SKIPWHITE(); + + while(data[pos]!=')') + { + INT32 tmp2; + if(argno) + { + if(!GOBBLE(',')) + cpp_error(this,"Expecting comma in macro definition."); + SKIPWHITE(); + } + tmp2=pos; + + if(!isidchar(data[pos])) + { + cpp_error(this,"Expected argument for macro."); + break; + } + + while(isidchar(data[pos])) pos++; + check_stack(1); + push_string(make_shared_binary_string(data+tmp2, pos-tmp2)); + + SKIPWHITE(); + argno++; + if(argno>=MAX_ARGS) + { + cpp_error(this,"Too many arguments in macro definition."); + pop_stack(); + argno--; + } + } + + if(!GOBBLE(')')) + cpp_error(this,"Missing ) in macro definition."); + } + + SKIPSPACE(); + + partbase=sp; + initialize_buf(&str); + + while(1) + { + INT32 extra=0; + +/* fprintf(stderr,"%c",data[pos]); + fflush(stderr); */ + + switch(data[pos++]) + { + case '/': + if(data[pos]=='/') + { + low_my_putchar(' ',&str); + FIND_EOL(); + continue; + } + + if(data[pos]=='*') + { + PUTC(' '); + SKIPCOMMENT(); + continue; + } + + low_my_putchar('/',&str); + continue; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + low_my_putchar(data[pos-1],&str); + while(data[pos]>='0' && data[pos]<='9') + low_my_putchar(data[pos++],&str); + continue; + + case '#': + if(GOBBLE('#')) + { + extra=DEF_ARG_NOPRESPACE; + while(str.s.len && isspace(str.s.str[str.s.len-1])) + str.s.len--; + }else{ + extra=DEF_ARG_STRINGIFY; + } + SKIPSPACE(); + + /* fall through */ + + default: + if(isidchar(data[pos-1])) + { + struct pike_string *s; + tmp3=pos-1; + while(isidchar(data[pos])) pos++; + if(argno>0) + { + if((s=binary_findstring(data+tmp3,pos-tmp3))) + { + for(e=0;e<argno;e++) + { + if(argbase[e].u.string == s) + { + check_stack(2); + push_string(low_free_buf(&str)); + initialize_buf(&str); + push_int(e | extra); + extra=0; + break; + } + } + if(e!=argno) continue; + } + } + low_my_binary_strcat(data+tmp3,pos-tmp3, &str); + }else{ + low_my_putchar(data[pos-1],&str); + } + extra=0; + continue; + + case '"': + tmp3=pos-1; + FIND_END_OF_STRING(); + low_my_binary_strcat(data+tmp3, pos-tmp3, &str); + continue; + + case '\'': + tmp3=pos-1; + FIND_END_OF_CHAR(); + low_my_binary_strcat(data+tmp3, pos-tmp3, &str); + continue; + + case '\\': + if(GOBBLE('\n')) + { + this->current_line++; + PUTNL(); + } + continue; + + case '\n': + PUTNL(); + this->current_line++; + case 0: + break; + } + push_string(low_free_buf(&str)); + break; + } + + if(OUTP()) + { + def=alloc_empty_define(make_shared_binary_string(data+namestart, + nameend-namestart), + (sp-partbase)/2); + copy_shared_string(def->first, partbase->u.string); + def->args=argno; + + for(e=0;e<def->num_parts;e++) + { +#if 1 + if(partbase[e*2+1].type != T_INT) + fatal("Cpp internal error, expected integer!\n"); + + if(partbase[e*2+2].type != T_STRING) + fatal("Cpp internal error, expected string!\n"); +#endif + def->parts[e].argument=partbase[e*2+1].u.integer; + copy_shared_string(def->parts[e].postfix, + partbase[e*2+2].u.string); + } + +#ifdef DEBUG + if(def->num_parts==1 && + (def->parts[0].argument & DEF_ARG_MASK) > MAX_ARGS) + fatal("Internal error in define\n"); +#endif + + this->defines=hash_insert(this->defines, & def->link); + + } + pop_n_elems(sp-argbase); + break; + } + + goto unknown_preprocessor_directive; + + case 'u': /* undefine */ + if(WGOBBLE("undefine") || WGOBBLE("undef")) + { + INT32 tmp; + struct pike_string *s; + + SKIPSPACE(); + + tmp=pos; + if(!isidchar(data[pos])) + cpp_error(this,"Undefine what?"); + + while(isidchar(data[pos])) pos++; + + if(OUTP()) + { + if((s=binary_findstring(data+pos, pos-tmp))) + undefine(this,s); + } + + break; + } + + goto unknown_preprocessor_directive; + + case 'p': /* pragma */ + if(WGOBBLE("pragma")) + { + if(OUTP()) + STRCAT("#pragma", 7); + else + FIND_EOL(); + break; + } + + default: + unknown_preprocessor_directive: + { + char buffer[180]; + int i; + for(i=0;i<(long)sizeof(buffer)-1;i++) + { + if(!isidchar(data[pos])) break; + buffer[i]=data[pos++]; + } + buffer[i]=0; + + cpp_error(this,"Unknown preprocessor directive."); + } + } + } + } + + if(flags & CPP_EXPECT_ENDIF) + error("End of file while searching for #endif\n"); + + return pos; +} + +static INT32 calcC(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + FINDTOK(); + +/* DUMPPOS("calcC"); */ + + switch(data[pos]) + { + case '(': + pos=calc1(this,data,len,pos+1); + FINDTOK(); + if(!GOBBLE(')')) + error("Missing ')'\n"); + break; + + case '0': + if(data[pos+1]=='x' || data[pos+1]=='X') + { + char *p; + push_int(STRTOL(data+pos+2, &p, 16)); + pos=p-data; + break; + } + + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + char *p1,*p2; + double f; + long l; + + f=my_strtod(data+pos, &p1); + l=STRTOL(data+pos, &p2, 0); + if(p1 > p2) + { + push_float(f); + pos=p1-data; + }else{ + push_int(l); + pos=p2-data; + } + break; + } + + case '\'': + { + int tmp; + READCHAR(tmp); + pos++; + if(!GOBBLE('\'')) + error("Missing end quote in character constant.\n"); + push_int(tmp); + break; + } + + case '"': + { + dynamic_buffer s; + initialize_buf(&s); + READSTRING(s); + push_string(low_free_buf(&s)); + break; + } + + default: +#ifdef DEBUG + if(isidchar(data[pos])) + error("Syntax error in #if (should not happen)\n"); +#endif + + error("Syntax error in #if.\n"); + } + + + FINDTOK(); + + while(GOBBLE('[')) + { + pos=calc1(this,data,len,pos); + f_index(2); + + FINDTOK(); + if(!GOBBLE(']')) + error("Missing ']'"); + } +/* DUMPPOS("after calcC"); */ + return pos; +} + +static INT32 calcB(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + FINDTOK(); + switch(data[pos]) + { + case '-': pos++; pos=calcB(this,data,len,pos); o_negate(); break; + case '!': pos++; pos=calcB(this,data,len,pos); o_not(); break; + case '~': pos++; pos=calcB(this,data,len,pos); o_compl(); break; + default: pos=calcC(this,data,len,pos); + } +/* DUMPPOS("after calcB"); */ + return pos; +} + +static INT32 calcA(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calcB(this,data,len,pos); + while(1) + { +/* DUMPPOS("inside calcA"); */ + FINDTOK(); + switch(data[pos]) + { + case '/': + if(data[1]=='/' || data[1]=='*') return pos; + pos++; + pos=calcB(this,data,len,pos); + o_divide(); + continue; + + case '*': + pos++; + pos=calcB(this,data,len,pos); + o_multiply(); + continue; + + case '%': + pos++; + pos=calcB(this,data,len,pos); + o_mod(); + continue; + } + break; + } +/* DUMPPOS("after calcA"); */ + return pos; +} + +static INT32 calc9(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calcA(this,data,len,pos); + + while(1) + { + FINDTOK(); + switch(data[pos]) + { + case '+': + pos++; + pos=calcA(this,data,len,pos); + f_add(2); + continue; + + case '-': + pos++; + pos=calcA(this,data,len,pos); + o_subtract(); + continue; + } + break; + } + +/* DUMPPOS("after calc9"); */ + return pos; +} + +static INT32 calc8(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc9(this,data,len,pos); + + while(1) + { + FINDTOK(); + if(GOBBLEOP("<<")) + { + pos=calc9(this,data,len,pos); + o_lsh(); + break; + } + + if(GOBBLEOP(">>")) + { + pos=calc9(this,data,len,pos); + o_rsh(); + break; + } + + break; + } + return pos; +} + +static INT32 calc7b(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc8(this,data,len,pos); + + while(1) + { + FINDTOK(); + + switch(data[pos]) + { + case '<': + if(data[pos]+1 == '<') break; + pos++; + if(GOBBLE('=')) + { + pos=calc8(this,data,len,pos); + f_le(2); + }else{ + pos=calc8(this,data,len,pos); + f_lt(2); + } + continue; + + case '>': + if(data[pos]+1 == '>') break; + pos++; + if(GOBBLE('=')) + { + pos=calc8(this,data,len,pos); + f_ge(2); + }else{ + pos=calc8(this,data,len,pos); + f_gt(2); + } + continue; + } + break; + } + return pos; +} + +static INT32 calc7(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc7b(this,data,len,pos); + + while(1) + { + FINDTOK(); + if(GOBBLEOP("==")) + { + pos=calc7b(this,data,len,pos); + f_eq(2); + continue; + } + + if(GOBBLEOP("!=")) + { + pos=calc7b(this,data,len,pos); + f_ne(2); + continue; + } + + break; + } + return pos; +} + +static INT32 calc6(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc7(this,data,len,pos); + + FINDTOK(); + while(data[pos] == '&' && data[pos+1]!='&') + { + pos++; + pos=calc7(this,data,len,pos); + o_and(); + } + return pos; +} + +static INT32 calc5(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc6(this,data,len,pos); + + FINDTOK(); + while(GOBBLE('^')) + { + pos=calc6(this,data,len,pos); + o_xor(); + } + return pos; +} + +static INT32 calc4(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc5(this,data,len,pos); + + FINDTOK(); + while(data[pos] == '|' && data[pos+1]!='|') + { + pos++; + pos=calc5(this,data,len,pos); + o_or(); + } + return pos; +} + +static INT32 calc3(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc4(this,data,len,pos); + + FINDTOK(); + while(GOBBLEOP("&&")) + { + check_destructed(sp-1); + if(IS_ZERO(sp-1)) + { + pos=calc4(this,data,len,pos); + pop_stack(); + }else{ + pop_stack(); + pos=calc4(this,data,len,pos); + } + } + return pos; +} + +static INT32 calc2(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc3(this,data,len,pos); + + FINDTOK(); + while(GOBBLEOP("||")) + { + check_destructed(sp-1); + if(!IS_ZERO(sp-1)) + { + pos=calc3(this,data,len,pos); + pop_stack(); + }else{ + pop_stack(); + pos=calc3(this,data,len,pos); + } + } + return pos; +} + +static INT32 calc1(struct cpp *this,char *data,INT32 len,INT32 pos) +{ + pos=calc2(this,data,len,pos); + + FINDTOK(); + + if(GOBBLE('?')) + { + pos=calc1(this,data,len,pos); + if(!GOBBLE(':')) + error("Colon expected"); + pos=calc1(this,data,len,pos); + + check_destructed(sp-3); + assign_svalue(sp-3,IS_ZERO(sp-3)?sp-1:sp-2); + pop_n_elems(2); + } + return pos; +} + +static int calc(struct cpp *this,char *data,INT32 len,INT32 tmp) +{ + JMP_BUF recovery; + INT32 pos; + +/* fprintf(stderr,"Calculating\n"); */ + + if (SETJMP(recovery)) + { + pos=tmp; + if(throw_value.type == T_ARRAY && throw_value.u.array->size) + { + union anything *a; + a=low_array_get_item_ptr(throw_value.u.array, 0, T_STRING); + if(a) + { + cpp_error(this,a->string->str); + }else{ + cpp_error(this,"Nonstandard error format."); + } + }else{ + cpp_error(this,"Nonstandard error format."); + } + FIND_EOL(); + push_int(0); + }else{ + pos=calc1(this,data,len,tmp); + check_destructed(sp-1); + } + UNSETJMP(recovery); + +/* fprintf(stderr,"Done\n"); */ + + return pos; +} + +void free_one_define(struct hash_entry *h) +{ + int e; + struct define *d=BASEOF(h, define, link); + + for(e=0;e<d->num_parts;e++) + free_string(d->parts[e].postfix); + if(d->first) + free_string(d->first); + free((char *)d); +} + +/*** Magic defines ***/ +static void insert_current_line(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + char buf[20]; + sprintf(buf," %ld ",(long)this->current_line); + low_my_binary_strcat(buf, strlen(buf),tmp); +} + +static void insert_current_file_as_string(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + PUSH_STRING(this->current_file->str, this->current_file->len, tmp); +} + +static void insert_current_time_as_string(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + time_t tmp2; + char *buf; + time(&tmp2); + buf=ctime(&tmp2); + + PUSH_STRING(buf+11, 8, tmp); +} + +static void insert_current_date_as_string(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + time_t tmp2; + char *buf; + time(&tmp2); + buf=ctime(&tmp2); + + PUSH_STRING(buf+19, 5, tmp); + PUSH_STRING(buf+4, 6, tmp); +} + +static void check_defined(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + struct pike_string *s; + s=binary_findstring(args[0].arg, args[0].len); + if(s && find_define(s)) + { + low_my_binary_strcat(" 1 ", 3,tmp); + }else{ + low_my_binary_strcat(" 0 ", 3,tmp); + } +} + +static int do_safe_index_call(struct pike_string *s); + +static void check_constant(struct cpp *this, + struct define *def, + struct define_argument *args, + dynamic_buffer *tmp) +{ + struct svalue *sv; + char *data=args[0].arg; + int res,dlen,len=args[0].len; + + while(len && isspace(data[0])) { data++; len--; } + + if(!len) + cpp_error(this,"#if constant() with empty argument.\n"); + + for(dlen=0;dlen<len;dlen++) + if(!isidchar(data[dlen])) + break; + + push_string(binary_findstring(data, dlen)); + if((sv=low_mapping_string_lookup(get_builtin_constants(), + sp[-1].u.string))) + { + pop_stack(); + push_svalue(sv); + res=1; + low_my_binary_strcat(" 1 ", 3,tmp); + }else if(get_master()) { + this->current_file->refs++; + push_string(this->current_file); + SAFE_APPLY_MASTER("resolv",2); + + res=(throw_value.type!=T_STRING) && + (!(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED)); + }else{ + res=0; + } + + while(1) + { + data+=dlen; + len-=dlen; + + while(len && isspace(data[0])) { data++; len--; } + + if(!len) break; + + if(data[0]=='.') + { + data++; + len--; + + while(len && isspace(data[0])) { data++; len--; } + + for(dlen=0;dlen<len;dlen++) + if(!isidchar(data[dlen])) + break; + + if(res) + { + res=do_safe_index_call(binary_findstring(data, dlen)); + } + }else{ + cpp_error(this, "Garbage characters in constant()\n"); + } + } + + + low_my_binary_strcat(res?" 1 ":" 0 ", 3,tmp); +} + + +static int do_safe_index_call(struct pike_string *s) +{ + int res; + JMP_BUF recovery; + + if (SETJMP(recovery)) { + res = 0; + } else { + push_string(s); + f_index(2); + + res=!(IS_ZERO(sp-1) && sp[-1].subtype == NUMBER_UNDEFINED); + } + UNSETJMP(recovery); + return res; +} + + +void f_cpp(INT32 args) +{ + struct pike_predef_s *tmpf; + struct cpp this; + if(args<1) + error("Too few arguments to cpp()\n"); + + if(sp[-args].type != T_STRING) + error("Bad argument 1 to cpp()\n"); + + if(args>1) + { + if(sp[1-args].type != T_STRING) + error("Bad argument 2 to cpp()\n"); + copy_shared_string(this.current_file, sp[1-args].u.string); + }else{ + this.current_file=make_shared_string("-"); + } + + initialize_buf(&this.buf); + this.current_line=1; + this.compile_errors=0; + this.defines=0; + do_magic_define(&this,"__LINE__",insert_current_line); + do_magic_define(&this,"__FILE__",insert_current_file_as_string); + do_magic_define(&this,"__DATE__",insert_current_date_as_string); + do_magic_define(&this,"__TIME__",insert_current_time_as_string); + simple_add_define(&this,"__PIKE__"," 1 "); + + for (tmpf=pike_predefs; tmpf; tmpf=tmpf->next) + simple_add_define(&this, tmpf->name, tmpf->value); + + low_my_binary_strcat("# 1 ",4,&this.buf); + PUSH_STRING(this.current_file->str,this.current_file->len,&this.buf); + low_my_putchar('\n',&this.buf); + + low_cpp(&this, sp[-args].u.string->str, sp[-args].u.string->len,0); + if(this.defines) + free_hashtable(this.defines, free_one_define); + + if(this.compile_errors) + { + error("Cpp() failed\n"); + }else{ + pop_n_elems(args); + free_string(this.current_file); + push_string(low_free_buf(&this.buf)); + } +} + +void init_cpp() +{ + defined_macro=alloc_empty_define(make_shared_string("defined"),0); + defined_macro->magic=check_defined; + defined_macro->args=1; + + constant_macro=alloc_empty_define(make_shared_string("constant"),0); + constant_macro->magic=check_constant; + constant_macro->args=1; + + add_efun("cpp",f_cpp,"function(string,string|void:string)",OPT_EXTERNAL_DEPEND); +} + + +void add_predefine(char *s) +{ + struct pike_predef_s *tmp=ALLOC_STRUCT(pike_predef_s); + char * pos=STRCHR(s,'='); + if(pos) + { + tmp->name=(char *)xalloc(pos-s+1); + MEMCPY(tmp->name,s,pos-s); + tmp->name[pos-s]=0; + + tmp->value=(char *)xalloc(s+strlen(s)-pos); + MEMCPY(tmp->value,pos+1,s+strlen(s)-pos); + }else{ + tmp->name=(char *)xalloc(strlen(s)+1); + MEMCPY(tmp->name,s,strlen(s)+1); + + tmp->value=(char *)xalloc(4); + MEMCPY(tmp->value," 1 ",4); + } + tmp->next=pike_predefs; + pike_predefs=tmp; +} + +void exit_cpp() +{ + struct pike_predef_s *tmp; + while((tmp=pike_predefs)) + { + free(tmp->name); + free(tmp->value); + pike_predefs=tmp->next; + free((char *)tmp); + } +} diff --git a/src/cpp.h b/src/cpp.h new file mode 100644 index 0000000000..7fcca20dba --- /dev/null +++ b/src/cpp.h @@ -0,0 +1,26 @@ +#ifndef CPP_H +#define CPP_H + +#ifndef STRUCT_HASH_ENTRY_DECLARED +struct hash_entry; +#define STRUCT_HASH_ENTRY_DECLARED +#endif + +/* Prototypes begin here */ +struct pike_predef_s; +struct define_part; +struct define_argument; +struct define; +struct cpp; +void cpp_error(struct cpp *this,char *err); +void PUSH_STRING(char *str, + INT32 len, + dynamic_buffer *buf); +void free_one_define(struct hash_entry *h); +void f_cpp(INT32 args); +void init_cpp(); +void add_predefine(char *s); +void exit_cpp(); +/* Prototypes end here */ + +#endif diff --git a/src/fd_control.c b/src/fd_control.c index 1183cb424d..11d940bca0 100644 --- a/src/fd_control.c +++ b/src/fd_control.c @@ -8,6 +8,7 @@ #ifndef TESTING #include "global.h" #include "error.h" +#include "fdlib.h" #else #undef DEBUG #endif @@ -47,8 +48,8 @@ void set_nonblocking(int fd,int which) fatal("Filedescriptor out of range.\n"); #endif -#ifdef USE_IOCTL_FIONBIO - ioctl(fd, FIONBIO, &which); +#if defined(USE_IOCTL_FIONBIO) || __NT__ + fd_ioctl(fd, FIONBIO, &which); #else #ifdef USE_FCNTL_O_NDELAY @@ -63,17 +64,12 @@ void set_nonblocking(int fd,int which) fcntl(fd, F_SETFL, which?FNDELAY:0); #else -#ifdef USE_IOCTLSOCKET_FIONBIO - ioctlsocket(fd, FIONBIO, (void *)&which); -#else - #error Do not know how to set your filedescriptors nonblocking. #endif #endif #endif #endif -#endif } int query_nonblocking(int fd) diff --git a/src/fdlib.c b/src/fdlib.c new file mode 100644 index 0000000000..99c68614eb --- /dev/null +++ b/src/fdlib.c @@ -0,0 +1,355 @@ +#include "fdlib.h" + +#ifdef HAVE_WINSOCK_H + +#define FD_SOCKET -4 +#define FD_CONSOLE -3 +#define FD_FILE -2 +#define FD_NO_MORE_FREE -1 + +long da_handle[MAX_OPEN_FILEDESCRIPTORS]; +static int fd_type[MAX_OPEN_FILEDESCRIPTORS]; +int first_free_handle; + +void fd_init() +{ + int e; + WSADATA wsadata; + + if(WSAStartup(MAKEWORD(2,0), &wsadata) != 0) + { + fatal("No winsock available.\n"); + } +/* fprintf(stderr,"Using %s\n",wsadata.szDescription); */ + + fd_type[0]=FD_CONSOLE; + da_handle[0]=GetStdHandle(STD_INPUT_HANDLE); + fd_type[1]=FD_CONSOLE; + da_handle[1]=GetStdHandle(STD_OUTPUT_HANDLE); + fd_type[2]=FD_CONSOLE; + da_handle[2]=GetStdHandle(STD_ERROR_HANDLE); + + first_free_handle=3; + for(e=3;e<MAX_OPEN_FILEDESCRIPTORS-1;e++) + fd_type[e]=e+1; + fd_type[e]=FD_NO_MORE_FREE; +} + +void fd_exit() +{ + WSACleanup(); +} + +FD fd_open(char *file, int open_mode, int create_mode) +{ + HANDLE x; + FD fd; + DWORD omode,cmode,amode; + omode=0; + if(first_free_handle == FD_NO_MORE_FREE) + { + errno=EMFILE; + return -1; + } + + if(open_mode & fd_RDONLY) omode|=GENERIC_READ; + if(open_mode & fd_WRONLY) omode|=GENERIC_WRITE; + + switch(open_mode & (fd_CREAT | fd_TRUNC | fd_EXCL)) + { + case fd_CREAT | fd_TRUNC: + cmode=CREATE_ALWAYS; + break; + + case fd_TRUNC: + case fd_TRUNC | fd_EXCL: + cmode=TRUNCATE_EXISTING; + break; + + case fd_CREAT: + cmode=OPEN_ALWAYS; break; + + case fd_CREAT | fd_EXCL: + case fd_CREAT | fd_EXCL | fd_TRUNC: + cmode=CREATE_NEW; + break; + + case 0: + case fd_EXCL: + cmode=OPEN_EXISTING; + break; + } + + if(create_mode & 4) + { + amode=FILE_ATTRIBUTE_NORMAL; + }else{ + amode=FILE_ATTRIBUTE_READONLY; + } + + x=CreateFile(file, + omode, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + cmode, + amode, + NULL); + + if(x==INVALID_HANDLE_VALUE) + { + errno=GetLastError(); + return -1; + } + + fd=first_free_handle; + first_free_handle=fd_type[fd]; + fd_type[fd]=FD_FILE; + da_handle[fd]=x; + + return fd; +} + +FD fd_socket(int domain, int type, int proto) +{ + FD fd; + SOCKET s; + if(first_free_handle == FD_NO_MORE_FREE) + { + errno=EMFILE; + return -1; + } + s=socket(domain, type, proto); + if(s==INVALID_SOCKET) + { + errno=WSAGetLastError(); + return -1; + } + + fd=first_free_handle; + first_free_handle=fd_type[fd]; + fd_type[fd]=FD_SOCKET; + da_handle[fd]=(HANDLE)s; + + return fd; +} + +FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen) +{ + FD new_fd; + SOCKET s; + if(first_free_handle == FD_NO_MORE_FREE) + { + errno=EMFILE; + return -1; + } + if(fd_type[fd]!=FD_SOCKET) + { + errno=ENOTSUPP; + return -1; + } + s=accept((SOCKET)da_handle[fd], addr, addrlen); + if(s==INVALID_SOCKET) + { + errno=WSAGetLastError(); + return -1; + } + + fd=first_free_handle; + first_free_handle=fd_type[fd]; + fd_type[fd]=FD_SOCKET; + da_handle[fd]=(HANDLE)s; + return fd; +} + +#define SOCKFUN(NAME,X1,X2) \ +int PIKE_CONCAT(fd_,NAME) X1 { int ret; \ + if(fd_type[fd] != FD_SOCKET) { \ + errno=ENOTSUPP; \ + return -1; \ + } \ + ret=NAME X2; \ + if(ret == SOCKET_ERROR) errno=WSAGetLastError(); \ + return ret; \ +} + +#define SOCKFUN1(NAME,T1) \ + SOCKFUN(NAME, (FD fd, T1 a), ((SOCKET)da_handle[fd], a) ) + +#define SOCKFUN2(NAME,T1,T2) \ + SOCKFUN(NAME, (FD fd, T1 a, T2 b), ((SOCKET)da_handle[fd], a, b) ) + +#define SOCKFUN3(NAME,T1,T2,T3) \ + SOCKFUN(NAME, (FD fd, T1 a, T2 b, T3 c), ((SOCKET)da_handle[fd], a, b, c) ) + +#define SOCKFUN4(NAME,T1,T2,T3,T4) \ + SOCKFUN(NAME, (FD fd,T1 a,T2 b,T3 c,T4 d), ((SOCKET)da_handle[fd],a,b,c,d) ) + +#define SOCKFUN5(NAME,T1,T2,T3,T4,T5) \ + SOCKFUN(NAME, (FD fd,T1 a,T2 b,T3 c,T4 d,T5 e), ((SOCKET)da_handle[fd],a,b,c,d,e)) + + +SOCKFUN2(bind, struct sockaddr *, int) +SOCKFUN2(connect, struct sockaddr *, int) +SOCKFUN4(getsockopt,int,int,void*,int*) +SOCKFUN4(setsockopt,int,int,void*,int) +SOCKFUN2(getsockname,struct sockaddr *,int*) +SOCKFUN2(getpeername,struct sockaddr *,int*) +SOCKFUN3(recv,void *,int,int) +SOCKFUN5(recvfrom,void *,int,int,struct sockaddr *,int*) +SOCKFUN5(sendto,void *,int,int,struct sockaddr *,int*) +SOCKFUN1(shutdown, int) +SOCKFUN1(listen, int) + +int fd_close(FD fd) +{ + if(!CloseHandle(da_handle[fd])) + { + errno=GetLastError(); + return -1; + } + fd_type[fd]=first_free_handle; + first_free_handle=fd; + return 0; +} + +long fd_write(FD fd, void *buf, long len) +{ + DWORD ret; + switch(fd_type[fd]) + { + case FD_SOCKET: + ret=send((SOCKET)da_handle[fd], buf, len, 0); + if(ret<0) + { + errno=WSAGetLastError(); + return -1; + } + return ret; + + case FD_CONSOLE: + case FD_FILE: + if(!WriteFile(da_handle[fd], buf, len, &ret,0) && !ret) + { + errno=GetLastError(); + return -1; + } + return ret; + + default: + errno=ENOTSUPP; + return -1; + } +} + +long fd_read(FD fd, void *buf, long len) +{ + DWORD ret; + switch(fd_type[fd]) + { + case FD_SOCKET: + ret=recv((SOCKET)da_handle[fd], buf, len, 0); + if(ret<0) + { + errno=WSAGetLastError(); + return -1; + } + return ret; + + case FD_CONSOLE: + case FD_FILE: + if(!ReadFile(da_handle[fd], buf, len, &ret,0) && !ret) + { + errno=GetLastError(); + return -1; + } + return ret; + + default: + errno=ENOTSUPP; + return -1; + } +} + +long fd_lseek(FD fd, long pos, int where) +{ + long ret; + if(fd_type[fd]!=FD_FILE) + { + errno=ENOTSUPP; + return -1; + } + + ret=LZSeek(da_handle[fd], pos, where); + if(ret<0) + { + errno=GetLastError(); + return -1; + } + return ret; +} + +int fd_fstat(FD fd, struct stat *s) +{ + int ret; + if(fd_type[fd]!=FD_FILE) + { + errno=ENOTSUPP; + return -1; + } + + ret=fstat(da_handle[fd], s); + if(ret<0) + { + errno=GetLastError(); + return -1; + } + return ret; +} + +int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t) +{ + int ret; + ret=select(fds,a,b,c,t); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; +} + + +int fd_ioctl(FD fd, int cmd, void *data) +{ + int ret; + switch(fd_type[fd]) + { + case FD_SOCKET: + ret=ioctlsocket((SOCKET)da_handle[fd], cmd, data); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; + + default: + errno=ENOTSUPP; + return -1; + } +} + + +FD fd_dup(FD fd) +{ + errno=ENOTSUPP; + return -1; +} + +FD fd_dup2(FD to, FD from) +{ + errno=ENOTSUPP; + return -1; +} + +#endif diff --git a/src/fdlib.h b/src/fdlib.h new file mode 100644 index 0000000000..1159c41d05 --- /dev/null +++ b/src/fdlib.h @@ -0,0 +1,157 @@ +#ifndef FDLIB_H +#define FDLIB_H + +#include "global.h" + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <errno.h> +#endif + +#ifdef HAVE_WINSOCK_H + + +#ifndef FD_SETSIZE +#define FD_SETSIZE MAX_OPEN_FILEDESCRIPTORS +#endif + +#include <winsock.h> +#include <winbase.h> + +typedef int FD; + +#define SOCKFUN1(NAME,T1) int PIKE_CONCAT(fd_,NAME) (FD,T1); +#define SOCKFUN2(NAME,T1,T2) int PIKE_CONCAT(fd_,NAME) (FD,T1,T2); +#define SOCKFUN3(NAME,T1,T2,T3) int PIKE_CONCAT(fd_,NAME) (FD,T1,T2,T3); +#define SOCKFUN4(NAME,T1,T2,T3,T4) int PIKE_CONCAT(fd_,NAME) (FD,T1,T2,T3,T4); +#define SOCKFUN5(NAME,T1,T2,T3,T4,T5) int PIKE_CONCAT(fd_,NAME) (FD,T1,T2,T3,T4,T5); + +/* Prototypes begin here */ +void fd_init(); +void fd_exit(); +FD fd_open(char *file, int open_mode, int create_mode); +FD fd_socket(int domain, int type, int proto); +FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen); +SOCKFUN2(bind, struct sockaddr *, int) +SOCKFUN2(connect, struct sockaddr *, int) +SOCKFUN4(getsockopt,int,int,void*,int*) +SOCKFUN4(setsockopt,int,int,void*,int) +SOCKFUN2(getsockname,struct sockaddr *,int*) +SOCKFUN2(getpeername,struct sockaddr *,int*) +SOCKFUN3(recv,void *,int,int) +SOCKFUN5(recvfrom,void *,int,int,struct sockaddr *,int*) +SOCKFUN5(sendto,void *,int,int,struct sockaddr *,int*) +SOCKFUN1(shutdown, int) +SOCKFUN1(listen, int) +int fd_close(FD fd); +long fd_write(FD fd, void *buf, long len); +long fd_read(FD fd, void *buf, long len); +long fd_lseek(FD fd, long pos, int where); +int fd_fstat(FD fd, struct stat *s); +int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t); +int fd_ioctl(FD fd, int cmd, void *data); +FD fd_dup(FD fd); +FD fd_dup2(FD to, FD from); +/* Prototypes end here */ + +#undef SOCKFUN1 +#undef SOCKFUN2 +#undef SOCKFUN3 +#undef SOCKFUN4 +#undef SOCKFUN5 + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif + +#ifndef EADDRINUSE +#define EADDRINUSE WSAEADDRINUSE +#endif + +#ifndef ENOTSUPP +#define ENOTSUPP WSAEOPNOTSUPP +#endif + +#define fd_RDONLY 1 +#define fd_WRONLY 2 +#define fd_RDWR 3 +#define fd_APPEND 4 +#define fd_CREAT 8 +#define fd_TRUNC 16 +#define fd_EXCL 32 + +#define fd_shutdown_read SD_RECEIVE +#define fd_shutdown_write SD_SEND +#define fd_shutdown_both SD_BOTH + +extern long da_handle[MAX_OPEN_FILEDESCRIPTORS]; + +#define fd_FD_CLR(X,Y) FD_CLR((SOCKET)da_handle[X],Y) +#define fd_FD_SET(X,Y) FD_SET((SOCKET)da_handle[X],Y) +#define fd_FD_ISSET(X,Y) FD_ISSET((SOCKET)da_handle[X],Y) +#define fd_FD_ZERO(X) FD_ZERO(X) + +#else + + +typedef int FD; + +#define fd_init() +#define fd_exit() + +#define fd_RDONLY O_RDONLY +#define fd_WRONLY O_WRONLY +#define fd_RDWR O_RDWR +#define fd_APPEND O_APPEND +#define fd_CREAT O_CREAT +#define fd_TRUNC O_TRUC +#define fd_EXCL O_EXCL + +#define fd_open open +#define fd_close close +#define fd_read read +#define fd_write write +#define fd_ioctl ioctl + +#define fd_socket socket +#define fd_bind bind +#define fd_connect connect +#define fd_getsockopt getsockopt +#define fd_setsockopt setsockopt +#define fd_getsockname getsockname +#define fd_getpeername getpeername +#define fd_recv recv +#define fd_sendto sendto +#define fd_recvfrom recvfrom +#define fd_shutdown shutdown +#define fd_accept accept +#define fd_lseek lseek +#define fd_fstat fstat +#define fd_dup dup +#define fd_dup2 dup2 +#define fd_listen listen + +#define fd_select select +#define fd_FD_CLR FD_CLR +#define fd_FD_SET FD_SET +#define fd_FD_ISSET FD_ISSET +#define fd_FD_ZERO FD_ZERO + +#define fd_shutdown_read 0 +#define fd_shutdown_write 1 +#define fd_shutdown_both 2 + +#endif + +#endif diff --git a/src/fsort.c b/src/fsort.c index 71256c7121..a463b22779 100644 --- a/src/fsort.c +++ b/src/fsort.c @@ -14,7 +14,7 @@ static long size; static char *tmp_area; #define SWAP(X,Y) { tmp=*(X); *(X)=*(Y); *(Y)=tmp; } -#define STEP(X,Y) ((X)+(Y)) +#define STEP(X,Y) (&((X)[(Y)])) #define ID fsort_1 typedef struct a1 { char b[1]; } b1; diff --git a/src/fsort_template.h b/src/fsort_template.h index 6c0e9fc612..0f1ba47a2f 100644 --- a/src/fsort_template.h +++ b/src/fsort_template.h @@ -1,6 +1,6 @@ #define INC(X) X=STEP(X,1) #define DEC(X) X=STEP(X,-1) -#define SIZE ((long)STEP((TYPE *)0,1)) +#define SIZE ((long)(char *)STEP((TYPE *)0,1)) static void ID(register TYPE *bas, register TYPE *last) { diff --git a/src/lex.c b/src/lex.c index d877f0e32e..859bbfabdd 100644 --- a/src/lex.c +++ b/src/lex.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: lex.c,v 1.35 1997/12/23 06:26:07 hubbe Exp $"); +RCSID("$Id: lex.c,v 1.36 1998/01/02 01:05:47 hubbe Exp $"); #include "language.h" #include "array.h" #include "lex.h" @@ -52,7 +52,7 @@ struct pike_predef_s struct pike_predef_s *next; }; -struct pike_predef_s *pike_predefs=0; +static struct pike_predef_s *pike_predefs=0; static int calc(void); static void calc1(void); @@ -797,7 +797,7 @@ static void simple_add_define(char *name,char *as,void (*magic)(void)) } } -void free_one_define(struct hash_entry *h) +static void free_one_define(struct hash_entry *h) { struct define *d; d=BASEOF(h, define, link); @@ -2195,21 +2195,21 @@ static int calc(void) } /*** Magic defines ***/ -void insert_current_line(void) +static void insert_current_line(void) { char buf[20]; sprintf(buf," %ld ",(long)current_line); UNGETSTR(buf,strlen(buf)); } -void insert_current_file_as_string(void) +static void insert_current_file_as_string(void) { UNGETSTR("\"",1); UNGETSTR(current_file->str, current_file->len); UNGETSTR("\"",1); } -void insert_current_time_as_string(void) +static void insert_current_time_as_string(void) { time_t tmp; char *buf; @@ -2221,7 +2221,7 @@ void insert_current_time_as_string(void) UNGETSTR("\"",1); } -void insert_current_date_as_string(void) +static void insert_current_date_as_string(void) { time_t tmp; char *buf; @@ -2294,6 +2294,7 @@ void end_new_file(void) } +#if 0 void add_predefine(char *s) { char buffer1[100],buffer2[10000]; @@ -2314,3 +2315,4 @@ void add_predefine(char *s) tmp->next=pike_predefs; pike_predefs=tmp; } +#endif diff --git a/src/lex.h b/src/lex.h index e74f2a789f..f26e42c470 100644 --- a/src/lex.h +++ b/src/lex.h @@ -78,10 +78,6 @@ char *get_token_name(int n); struct inputstate; struct define; void free_one_define(struct hash_entry *h); -void insert_current_line(void); -void insert_current_file_as_string(void); -void insert_current_time_as_string(void); -void insert_current_date_as_string(void); void start_new_file(int fd,struct pike_string *filename); void start_new_string(char *s,INT32 len,struct pike_string *name); void end_new_file(void); diff --git a/src/main.c b/src/main.c index aafafd9593..c4c53ef9c9 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,8 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: main.c,v 1.28 1997/12/28 09:29:10 hubbe Exp $"); +RCSID("$Id: main.c,v 1.29 1998/01/02 01:05:48 hubbe Exp $"); +#include "fdlib.h" #include "backend.h" #include "module.h" #include "object.h" @@ -22,6 +23,11 @@ RCSID("$Id: main.c,v 1.28 1997/12/28 09:29:10 hubbe Exp $"); #include "dynamic_load.h" #include "gc.h" #include "mapping.h" +#include "cpp.h" + +#ifdef HAVE_WINSOCK_H +#include "winsock.h" +#endif #include <errno.h> @@ -56,7 +62,7 @@ struct callback *add_post_master_callback(callback_func call, } -void main(int argc, char **argv, char **env) +void main(int argc, char **argv) { JMP_BUF back; int e, num; @@ -65,12 +71,15 @@ void main(int argc, char **argv, char **env) ARGV=argv; -#ifndef __NT__ - /* Close extra fds (if any) */ - for (e=3; e < MAX_OPEN_FILEDESCRIPTORS; e++) { - do { - num = close(e); - } while ((num < 0) && (errno == EINTR)); + fd_init(); + +#ifdef HAVE_WINSOCK_H + { + WSADATA wsadata; + if(WSAStartup(MAKEWORD(2,0), &wsadata) != 0) + { + fatal("No winsock available.\n"); + } } #endif @@ -218,6 +227,7 @@ void main(int argc, char **argv, char **env) init_shared_string_table(); init_interpreter(); + init_cpp(); init_lex(); init_types(); @@ -234,11 +244,11 @@ void main(int argc, char **argv, char **env) } push_array(a); - for(num=0;env[num];num++); + for(num=0;environ[num];num++); a=allocate_array_no_init(num,0); - for(num=0;env[num];num++) + for(num=0;environ[num];num++) { - ITEM(a)[num].u.string=make_shared_string(env[num]); + ITEM(a)[num].u.string=make_shared_string(environ[num]); ITEM(a)[num].type=T_STRING; } push_array(a); @@ -294,6 +304,7 @@ void low_exit_main(void) exit_dynamic_load(); exit_signals(); exit_lex(); + exit_cpp(); cleanup_interpret(); cleanup_added_efuns(); cleanup_pike_types(); diff --git a/src/modules/files/file.c b/src/modules/files/file.c index 47721c4f1d..2953bf0776 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -6,7 +6,8 @@ #define READ_BUFFER 8192 #include "global.h" -RCSID("$Id: file.c,v 1.62 1997/12/23 06:26:10 hubbe Exp $"); +RCSID("$Id: file.c,v 1.63 1998/01/02 01:06:33 hubbe Exp $"); +#include "fdlib.h" #include "interpret.h" #include "svalue.h" #include "stralloc.h" @@ -147,7 +148,7 @@ static int close_fd(int fd) { int i; THREADS_ALLOW(); - i=close(fd); + i=fd_close(fd); THREADS_DISALLOW(); if(i < 0) @@ -161,7 +162,7 @@ static int close_fd(int fd) /* Try waiting it out in blocking mode */ set_nonblocking(fd,0); THREADS_ALLOW(); - i=close(fd); + i=fd_close(fd); THREADS_DISALLOW(); if(i>= 0 || errno==EBADF) break; /* It was actually closed, good! */ @@ -513,7 +514,7 @@ static int do_close(int fd, int flags) if(files[fd].open_mode & FILE_WRITE) { set_read_callback(fd,0,0); - shutdown(fd, 0); + fd_shutdown(fd, 0); files[fd].open_mode &=~ FILE_READ; return 0; }else{ @@ -525,7 +526,7 @@ static int do_close(int fd, int flags) if(files[fd].open_mode & FILE_READ) { set_write_callback(fd,0,0); - shutdown(fd, 1); + fd_shutdown(fd, 1); files[fd].open_mode &=~ FILE_WRITE; return 0; }else{ @@ -595,7 +596,7 @@ static void file_open(INT32 args) THREADS_ALLOW(); do { - fd=open(str->str,map(flags), access); + fd=fd_open(str->str,map(flags), access); } while(fd < 0 && errno == EINTR); THREADS_DISALLOW(); @@ -639,7 +640,7 @@ static void file_seek(INT32 args) ERRNO=0; - to=lseek(FD,to,to<0 ? SEEK_END : SEEK_SET); + to=fd_lseek(FD,to,to<0 ? SEEK_END : SEEK_SET); if(to<0) ERRNO=errno; @@ -655,7 +656,7 @@ static void file_tell(INT32 args) error("File not open.\n"); ERRNO=0; - to=lseek(FD, 0L, SEEK_CUR); + to=fd_lseek(FD, 0L, SEEK_CUR); if(to<0) ERRNO=errno; @@ -680,7 +681,7 @@ static void file_stat(INT32 args) retry: THREADS_ALLOW(); - tmp=fstat(fd, &s); + tmp=fd_fstat(fd, &s); THREADS_DISALLOW(); if(tmp < 0) @@ -708,7 +709,7 @@ static void file_errno(INT32 args) static struct pike_string *simple_do_read(INT32 *amount,int fd) { char buffer[READ_BUFFER]; - *amount = read(fd, buffer, READ_BUFFER); + *amount = fd_read(fd, buffer, READ_BUFFER); if(*amount>0) return make_shared_binary_string(buffer,*amount); return 0; } @@ -961,13 +962,13 @@ static void file_set_buffer(INT32 args) if(flags & FILE_READ) { int tmp=bufsize; - setsockopt(FD,SOL_SOCKET, SO_RCVBUF, (char *)&tmp, sizeof(tmp)); + fd_setsockopt(FD,SOL_SOCKET, SO_RCVBUF, (char *)&tmp, sizeof(tmp)); } if(flags & FILE_WRITE) { int tmp=bufsize; - setsockopt(FD,SOL_SOCKET, SO_SNDBUF, (char *)&tmp, sizeof(tmp)); + fd_setsockopt(FD,SOL_SOCKET, SO_SNDBUF, (char *)&tmp, sizeof(tmp)); } #endif } @@ -1014,67 +1015,72 @@ int my_socketpair(int family, int type, int protocol, int sv[2]) if(fd==-1) { - if((fd=socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; + if((fd=fd_socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; /* I wonder what is most common a loopback on ip# 127.0.0.1 or * a loopback with the name "localhost"? * Let's hope those few people who don't have socketpair have * a loopback on 127.0.0.1 */ + MEMSET((char *)&my_addr,0,sizeof(struct sockaddr_in)); + my_addr.sin_family=AF_INET; my_addr.sin_addr.s_addr=htonl(INADDR_ANY); my_addr.sin_port=htons(0); - + + /* Bind our sockets on any port */ - if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) + if(fd_bind(fd, (struct sockaddr *)&my_addr, sizeof(addr)) < 0) { - close(fd); + fd_close(fd); fd=-1; return -1; } /* Check what ports we got.. */ len=sizeof(my_addr); - if(getsockname(fd,(struct sockaddr *)&my_addr,&len) < 0) + if(fd_getsockname(fd,(struct sockaddr *)&my_addr,&len) < 0) { - close(fd); + fd_close(fd); fd=-1; return -1; } /* Listen to connections on our new socket */ - if(listen(fd, 5) < 0) + if(fd_listen(fd, 5) < 0) { - close(fd); + fd_close(fd); fd=-1; return -1; } + + my_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); } - if((sv[1]=socket(AF_INET, SOCK_STREAM, 0)) <0) return -1; - addr.sin_addr.s_addr=inet_addr("127.0.0.1"); + if((sv[1]=fd_socket(AF_INET, SOCK_STREAM, 0)) <0) return -1; /* set_nonblocking(sv[1],1); */ - - if(connect(sv[1], (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0) + + if(fd_connect(sv[1], (struct sockaddr *)&my_addr, sizeof(addr)) < 0) { int tmp2; for(tmp2=0;tmp2<20;tmp2++) { int tmp; len=sizeof(addr); - tmp=accept(fd,(struct sockaddr *)&addr,&len); + tmp=fd_accept(fd,(struct sockaddr *)&addr,&len); - if(tmp!=-1) close(tmp); - if(connect(sv[1], (struct sockaddr *)&my_addr, sizeof(my_addr))>=0) + if(tmp!=-1) fd_close(tmp); + if(fd_connect(sv[1], (struct sockaddr *)&my_addr, sizeof(my_addr))>=0) break; } if(tmp2>=20) return -1; } + len=sizeof(addr); - if(getsockname(sv[1],(struct sockaddr *)&addr2,&len) < 0) return -1; + if(fd_getsockname(sv[1],(struct sockaddr *)&addr2,&len) < 0) return -1; /* Accept connection * Make sure this connection was our OWN connection, @@ -1086,22 +1092,23 @@ int my_socketpair(int family, int type, int protocol, int sv[2]) do { len=sizeof(addr); - sv[0]=accept(fd,(struct sockaddr *)&addr,&len); + sv[0]=fd_accept(fd,(struct sockaddr *)&addr,&len); if(sv[0] < 0) { - close(sv[1]); + fd_close(sv[1]); return -1; } /* We do not trust accept */ len=sizeof(addr); - if(getpeername(sv[0], (struct sockaddr *)&addr,&len)) return -1; + if(fd_getpeername(sv[0], (struct sockaddr *)&addr,&len)) return -1; }while(len < (int)sizeof(addr) || addr2.sin_addr.s_addr != addr.sin_addr.s_addr || addr2.sin_port != addr.sin_port); /* set_nonblocking(sv[1],0); */ + return 0; } @@ -1149,8 +1156,8 @@ static void file_pipe(INT32 args) (inout[1] >= MAX_OPEN_FILEDESCRIPTORS)) { ERRNO=EBADF; - close(inout[0]); - close(inout[1]); + fd_close(inout[0]); + fd_close(inout[1]); push_int(0); } else @@ -1302,7 +1309,7 @@ static void file_open_socket(INT32 args) do_close(FD, FILE_READ | FILE_WRITE); FD=-1; - fd=socket(AF_INET, SOCK_STREAM, 0); + fd=fd_socket(AF_INET, SOCK_STREAM, 0); if(fd >= MAX_OPEN_FILEDESCRIPTORS) { ERRNO=EBADF; @@ -1323,7 +1330,7 @@ static void file_open_socket(INT32 args) int o; if (sp[-args].type != T_INT) { - close(fd); + fd_close(fd); error("Bad argument 1 to open_socket(), expected int\n"); } if (args > 1) { @@ -1339,14 +1346,14 @@ static void file_open_socket(INT32 args) addr.sin_port = htons( ((u_short)sp[-args].u.integer) ); o=1; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) { + if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) { ERRNO=errno; close(fd); pop_n_elems(args); push_int(0); return; } - if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (fd_bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { ERRNO=errno; close(fd); pop_n_elems(args); @@ -1369,7 +1376,7 @@ static void file_set_keepalive(INT32 args) int tmp, i; check_all_args("file->set_keepalive",args, T_INT,0); tmp=sp[-args].u.integer; - i=setsockopt(FD,SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); + i=fd_setsockopt(FD,SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); if(i) { ERRNO=errno; @@ -1407,7 +1414,7 @@ static void file_connect(INT32 args) tmp=FD; THREADS_ALLOW(); - tmp=connect(tmp, (struct sockaddr *)&addr, sizeof(addr)); + tmp=fd_connect(tmp, (struct sockaddr *)&addr, sizeof(addr)); THREADS_DISALLOW(); if(tmp < 0) @@ -1458,9 +1465,9 @@ static void file_query_address(INT32 args) len=sizeof(addr); if(args > 0 && !IS_ZERO(sp-args)) { - i=getsockname(FD,(struct sockaddr *)&addr,&len); + i=fd_getsockname(FD,(struct sockaddr *)&addr,&len); }else{ - i=getpeername(FD,(struct sockaddr *)&addr,&len); + i=fd_getpeername(FD,(struct sockaddr *)&addr,&len); } pop_n_elems(args); if(i < 0 || len < (int)sizeof(addr)) diff --git a/src/modules/files/socket.c b/src/modules/files/socket.c index 5ed4210345..ce609254b9 100644 --- a/src/modules/files/socket.c +++ b/src/modules/files/socket.c @@ -4,6 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" +#include "fdlib.h" #include "interpret.h" #include "svalue.h" #include "stralloc.h" @@ -73,7 +74,7 @@ static void do_close(struct port *p, struct object *o) retry: if(p->fd >= 0) { - if(close(p->fd) < 0) + if(fd_close(p->fd) < 0) if(errno == EINTR) goto retry; @@ -141,7 +142,7 @@ static void port_listen_fd(INT32 args) return; } - if(listen(fd, 16384) < 0) + if(fd_listen(fd, 16384) < 0) { THIS->my_errno=errno; pop_n_elems(args); @@ -180,7 +181,7 @@ static void port_bind(INT32 args) if(sp[-args].type != T_INT) error("Bad argument 1 to port->bind()\n"); - fd=socket(AF_INET, SOCK_STREAM, 0); + fd=fd_socket(AF_INET, SOCK_STREAM, 0); if(fd < 0) { @@ -192,14 +193,14 @@ static void port_bind(INT32 args) if(fd >= MAX_OPEN_FILEDESCRIPTORS) { THIS->my_errno=EBADF; - close(fd); + fd_close(fd); pop_n_elems(args); push_int(0); return; } o=1; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) + if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) { THIS->my_errno=errno; close(fd); @@ -222,13 +223,13 @@ static void port_bind(INT32 args) addr.sin_family = AF_INET; THREADS_ALLOW(); - tmp=bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 || listen(fd, 16384) < 0; + tmp=fd_bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 || listen(fd, 16384) < 0; THREADS_DISALLOW(); if(tmp) { THIS->my_errno=errno; - close(fd); + fd_close(fd); pop_n_elems(args); push_int(0); return; @@ -270,7 +271,7 @@ static void port_create(INT32 args) do_close(THIS,fp->current_object); THIS->fd=0; - if(listen(THIS->fd, 16384) < 0) + if(fd_listen(THIS->fd, 16384) < 0) { THIS->my_errno=errno; }else{ @@ -304,7 +305,7 @@ static void port_accept(INT32 args) THREADS_ALLOW(); - fd=accept(this->fd, 0, &len); + fd=fd_accept(this->fd, 0, &len); THREADS_DISALLOW(); if(fd < 0) @@ -319,7 +320,7 @@ static void port_accept(INT32 args) THIS->my_errno=EBADF; pop_n_elems(args); push_int(0); - close(fd); + fd_close(fd); return; } @@ -340,7 +341,7 @@ static void socket_query_address(INT32 args) error("socket->query_address(): Socket not bound yet.\n"); len=sizeof(addr); - i=getsockname(THIS->fd,(struct sockaddr *)&addr,&len); + i=fd_getsockname(THIS->fd,(struct sockaddr *)&addr,&len); pop_n_elems(args); if(i < 0 || len < (int)sizeof(addr)) { diff --git a/src/modules/readline/readlinemod.c b/src/modules/readline/readlinemod.c index d77e7d8819..cb7418fd04 100644 --- a/src/modules/readline/readlinemod.c +++ b/src/modules/readline/readlinemod.c @@ -58,10 +58,20 @@ static void f_readline(INT32 args) error("Bad argument 1 to readline()\n"); str=sp[-args].u.string; +retry: THREADS_ALLOW(); r=readline(str->str); THREADS_DISALLOW(); +#ifdef _REENTRANT + /* Kluge! /Hubbe */ + if(!r && errno==EINTR) + { + check_threads_etc(); + goto retry; + } +#endif + pop_n_elems(args); if(r) { diff --git a/src/object.c b/src/object.c index ee5160f98c..fa6d5ef972 100644 --- a/src/object.c +++ b/src/object.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: object.c,v 1.29 1997/11/08 01:34:42 hubbe Exp $"); +RCSID("$Id: object.c,v 1.30 1998/01/02 01:05:48 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -431,9 +431,9 @@ void object_index_no_free(struct svalue *to, } -static void object_low_set_index(struct object *o, - int f, - struct svalue *from) +void object_low_set_index(struct object *o, + int f, + struct svalue *from) { struct identifier *i; struct program *p; diff --git a/src/object.h b/src/object.h index b184357d31..90bf3280e8 100644 --- a/src/object.h +++ b/src/object.h @@ -54,6 +54,9 @@ void object_index_no_free2(struct svalue *to, void object_index_no_free(struct svalue *to, struct object *o, struct svalue *index); +void object_low_set_index(struct object *o, + int f, + struct svalue *from); void object_set_index2(struct object *o, struct svalue *index, struct svalue *from); diff --git a/src/port.c b/src/port.c index 3f2e45e0ad..4c9d28a907 100644 --- a/src/port.c +++ b/src/port.c @@ -20,12 +20,30 @@ time_t time PROT((time_t *)); #endif #ifndef HAVE_GETTIMEOFDAY + +#ifdef HAVE_GETSYSTEMTIMEASFILETIME +#include <winbase.h> + +void GETTIMEOFDAY(struct timeval *t) +{ + double t; + FILETIME tmp; + GetSystemTimeAsFileTime(&tmp); + t=tmp.dwHighDateTime * pow(2.0,32) + (double)tmp.dwLowDateTime; + t/=10000000.0; + t+=11644473600.0; + t->tv_sec=floor(t); + t->tv_usec=(t - t->tv_sec)*1000000.0; +} + +#else void GETTIMEOFDAY(struct timeval *t) { t->tv_sec=(long)time(0); t->tv_usec=0; } #endif +#endif #ifndef HAVE_TIME time_t TIME(time_t *t) diff --git a/src/program.c b/src/program.c index 791f3ddfe3..da209785ff 100644 --- a/src/program.c +++ b/src/program.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: program.c,v 1.46 1997/11/08 01:34:43 hubbe Exp $"); +RCSID("$Id: program.c,v 1.47 1998/01/02 01:05:51 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -1094,6 +1094,22 @@ int define_variable(struct pike_string *name, return n; } +int simple_add_variable(char *name, + char *type, + INT32 flags) +{ + INT32 ret; + struct pike_string *name_s, *type_s; + name_s=make_shared_string(name); + type_s=parse_type(type); + + ret=define_variable(name_s, type_s, flags); + free_string(name_s); + free_string(type_s); + return ret; +} + + int add_constant(struct pike_string *name, struct svalue *c, INT32 flags) diff --git a/src/program.h b/src/program.h index 82c6fe9a20..d545499b18 100644 --- a/src/program.h +++ b/src/program.h @@ -233,6 +233,9 @@ int map_variable(char *name, int define_variable(struct pike_string *name, struct pike_string *type, INT32 flags); +int simple_add_variable(char *name, + char *type, + INT32 flags); int add_constant(struct pike_string *name, struct svalue *c, INT32 flags); diff --git a/src/stuff.c b/src/stuff.c index 3f999acabc..9a72d3351a 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -108,3 +108,14 @@ int is_more_than_one_bit(unsigned INT32 x) ((x & 0xff00ff00UL) && (x & 0x00ff00ffUL)) || ((x & 0xffff0000UL) && (x & 0x0000ffffUL)); } + +double my_strtod(char *nptr, char **endptr) +{ + double tmp=STRTOD(nptr,endptr); + if(*endptr>nptr) + { + if(endptr[0][-1]=='.') + endptr[0]--; + } + return tmp; +} diff --git a/src/stuff.h b/src/stuff.h index a277b5aca2..9b534da1ff 100644 --- a/src/stuff.h +++ b/src/stuff.h @@ -12,6 +12,7 @@ int my_log2(unsigned INT32 x); int count_bits(unsigned INT32 x); int is_more_than_one_bit(unsigned INT32 x); +double my_strtod(char *nptr, char **endptr); /* Prototypes end here */ extern INT32 hashprimes[32]; diff --git a/src/threads.c b/src/threads.c index 6b5caf684b..487f5c970a 100644 --- a/src/threads.c +++ b/src/threads.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: threads.c,v 1.47 1997/11/11 04:02:45 grubba Exp $"); +RCSID("$Id: threads.c,v 1.48 1998/01/02 01:05:54 hubbe Exp $"); int num_threads = 1; int threads_disabled = 0; @@ -15,8 +15,11 @@ int threads_disabled = 0; #include "program.h" #include "gc.h" +#define THIS_THREAD ((struct thread_state *)fp->current_storage) + struct object *thread_id; static struct callback *threads_evaluator_callback=0; +int thread_id_result_variable; MUTEX_T interpreter_lock; struct program *mutex_key = 0; @@ -73,9 +76,17 @@ void *new_thread_func(void * data) push_array_items(arg.args); arg.args=0; f_call_function(args); - pop_stack(); /* Discard the return value. /Per */ + + /* copy return value to the thread_id here */ + object_low_set_index(thread_id, + thread_id_result_variable, + sp-1); + pop_stack(); } + ((struct thread_state *)(thread_id->storage))->status=THREAD_EXITED; + co_signal(& ((struct thread_state *)(thread_id->storage))->status_change); + free((char *)data); /* Moved by per, to avoid some bugs.... */ UNSETJMP(back); @@ -110,6 +121,7 @@ void f_thread_create(INT32 args) arg=ALLOC_STRUCT(thread_starter); arg->args=aggregate_array(args); arg->id=clone_object(thread_id_prog,0); + ((struct thread_state *)arg->id->storage)->status=THREAD_RUNNING; tmp=th_create(&dummy,new_thread_func,arg); @@ -395,9 +407,40 @@ void f_thread_backtrace(INT32 args) } } +void f_thread_id_status(INT32 args) +{ + pop_n_elems(args); + push_int(THIS_THREAD->status); +} + +static void f_thread_id_result(INT32 args) +{ + struct thread_state *th=THIS_THREAD; + + SWAP_OUT_CURRENT_THREAD(); + + while(th->status != THREAD_EXITED) + co_wait(&th->status_change, &interpreter_lock); + + SWAP_IN_CURRENT_THREAD(); + + low_object_index_no_free(sp, + fp->current_object, + thread_id_result_variable); + sp++; +} + void init_thread_obj(struct object *o) { MEMSET(o->storage, 0, sizeof(struct thread_state)); + THIS_THREAD->status=THREAD_NOT_STARTED; + co_init(& THIS_THREAD->status_change); +} + + +void exit_thread_obj(struct object *o) +{ + co_destroy(& THIS_THREAD->status_change); } #ifdef DEBUG @@ -481,11 +524,15 @@ void th_init(void) start_new_program(); add_storage(sizeof(struct thread_state)); + thread_id_result_variable=simple_add_variable("result","mixed",0); add_function("backtrace",f_thread_backtrace,"function(:array)",0); + add_function("wait",f_thread_id_result,"function(:mixed)",0); + add_function("status",f_thread_id_status,"function(:int)",0); #ifdef DEBUG set_gc_mark_callback(thread_was_marked); #endif set_init_callback(init_thread_obj); + set_init_callback(exit_thread_obj); thread_id_prog=end_program(); if(!mutex_key) fatal("Failed to initialize thread program!\n"); diff --git a/src/threads.h b/src/threads.h index d89c7cd2a6..6f6dc16604 100644 --- a/src/threads.h +++ b/src/threads.h @@ -157,8 +157,16 @@ extern MUTEX_T interpreter_lock; struct svalue; struct frame; +#define THREAD_NOT_STARTED -1 +#define THREAD_RUNNING 0 +#define THREAD_EXITED 1 + struct thread_state { - int swapped; + char swapped; + char status; + COND_T status_change; + + /* Swapped variables */ struct svalue *sp,*evaluator_stack; struct svalue **mark_sp,**mark_stack; struct frame *fp; diff --git a/src/time_stuff.h b/src/time_stuff.h index 49900b51bc..459adef8d4 100644 --- a/src/time_stuff.h +++ b/src/time_stuff.h @@ -23,7 +23,6 @@ #ifdef HAVE_WINSOCK_H # include <winsock.h> -# undef HAVE_WINSOCK_H #endif #undef HAVE_SYS_TIME_H -- GitLab