C:/Users/Dennis/src/lang/Life_start/Life/life-1.02/source/sys.c

Go to the documentation of this file.
00001  /* Copyright by Denys Duchier, Dec 1994
00002    Simon Fraser University
00003 
00004    All new system utilities and extensions to Wild LIFE 1.01
00005    are implemented in this file and made available in LIFE
00006    module "sys"
00007    */
00008 /*      $Id: sys.c,v 1.9 1996/01/17 00:33:09 duchier Exp $       */
00009 
00010 #ifndef lint
00011 static char vcid[] = "$Id: sys.c,v 1.9 1996/01/17 00:33:09 duchier Exp $";
00012 #endif /* lint */
00013 #ifndef OS2_PORT
00014 #include <unistd.h>
00015 #endif
00016 #include "extern.h"
00017 #include "trees.h"
00018 #include "login.h"
00019 #include "types.h"
00020 #include "parser.h"
00021 #include "copy.h"
00022 #include "token.h"
00023 #include "print.h"
00024 #include "lefun.h"
00025 #include "memory.h"
00026 #ifndef OS2_PORT
00027 #include "built_ins.h"
00028 #else
00029 #include "built_in.h"
00030 #endif
00031 
00032 #include "error.h" 
00033 #include "modules.h"
00034 #include "sys.h"
00035 
00036 ptr_definition sys_bytedata; /* DENYS: BYTEDATA */
00037 ptr_definition sys_bitvector;
00038 ptr_definition sys_regexp;
00039 ptr_definition sys_stream;
00040 ptr_definition sys_file_stream;
00041 ptr_definition sys_socket_stream;
00042 
00043 long
00044 call_primitive(fun,num,argi,info)
00045      int num;
00046      psi_arg argi[];
00047      long (*fun)();
00048      void* info;
00049 {
00050 #define ARGNN 10
00051   ptr_psi_term funct,arg,result,argo[ARGNN]; /* no more than 10 arguments */
00052   ptr_node n;
00053   int allargs=1,allvalues=1,i;
00054   funct=aim->a;
00055   deref_ptr(funct);
00056   result=aim->b;
00057   for (i=0;i<num;i++) {
00058     n=find(featcmp,argi[i].feature,funct->attr_list);
00059     /* argument present */
00060     if (n) {
00061       arg = (ptr_psi_term) n->data;
00062       /* in case we don't want to evaluate the argument
00063          just follow the chain of corefs and don't do
00064          any of the other checks: they'll have do be done
00065          by fun; just go on to the next arg */
00066       if (argi[i].options&UNEVALED) {
00067         deref_ptr(arg);
00068         argo[i]=arg;
00069         continue; }
00070       /* this arg should be evaled */
00071       deref(arg);
00072       argo[i]=arg;
00073       /* arg of admissible type */
00074       if (argi[i].options&POLYTYPE) {
00075         ptr_definition *type = (ptr_definition *)argi[i].type;
00076         while (*type != NULL)
00077           if (overlap_type(arg->type,*type))
00078             goto admissible;
00079           else type++;
00080       }
00081       else {
00082         if (overlap_type(arg->type,argi[i].type))
00083           goto admissible;
00084       }
00085       /* not admissible */
00086       if (argi[i].options&JUSTFAIL) return FALSE;
00087       Errorline("Illegal argument in %P.\n",funct);
00088       return (c_abort());
00089       /* admissible */
00090     admissible:
00091       /* has value */
00092       if (arg->value) {
00093         ptr_definition *type = (ptr_definition *)argi[i].type;
00094         /* paranoid check: really correct type */
00095         if (argi[i].options&POLYTYPE) {
00096           while (*type != NULL)
00097             if (sub_type(arg->type,*type))
00098               goto correct;
00099             else type++;
00100         }
00101         else {
00102           if (sub_type(arg->type,type)) goto correct;
00103         }
00104         /* type incorrect */
00105         if (argi[i].options&JUSTFAIL) return FALSE;
00106         Errorline("Illegal argument in %P.\n",funct);
00107         return (c_abort());
00108         /* correct */
00109       correct:;
00110       }
00111       /* missing value - do we need it */
00112       else if (!(argi[i].options&NOVALUE)) allvalues=0;
00113     }
00114     /* argument missing */
00115     else {
00116       argo[i]=NULL;
00117       if (argi[i].options&MANDATORY) {
00118         Errorline("Missing argument '%s' in %P.\n",argi[i].feature,funct);
00119         return (c_abort());
00120       }
00121       else if (argi[i].options&REQUIRED) allargs=0;
00122     }
00123   }
00124   if (allargs)
00125     if (allvalues) {
00126       return fun(argo,result,funct,info);
00127     }
00128     else {
00129       for (i=0;i<num;i++) {
00130         /* if arg present and should be evaled but has no value */
00131         if (argo[i] && !(argi[i].options&UNEVALED) && !argo[i]->value)
00132           residuate(argo[i]);
00133       }
00134     }
00135   else curry();
00136   return TRUE;
00137 }
00138 
00139 /* DENYS: BYTEDATA */
00140 
00141 /******** MAKE_BYTEDATA
00142   construct a psi term of the given sort whose value points
00143   to a bytedata block that can hold the given number of bytes
00144   */
00145 static ptr_psi_term
00146 make_bytedata(sort,bytes)
00147      ptr_definition sort;
00148      unsigned long bytes;
00149 {
00150   ptr_psi_term temp_result;
00151   char *b = (char *) heap_alloc(bytes+sizeof(bytes));
00152   *((long *) b) = bytes;
00153   bzero(b+sizeof(bytes),bytes);
00154   temp_result=stack_psi_term(0);
00155   temp_result->type=sort;
00156   temp_result->value=(GENERIC)b;
00157   return temp_result;
00158 }
00159 
00160 #define BYTEDATA_SIZE(X) (*(unsigned long *)(X->value))
00161 #define BYTEDATA_DATA(X) ((char*)((char*)X->value + sizeof(unsigned long)))
00162 
00163 /* BIT VECTORS *
00164  ***************/
00165 
00166 /******** C_MAKE_BITVECTOR
00167   make a bitvector that can hold at least the given number of bits
00168 */
00169 
00170 static long
00171 make_bitvector_internal(args,result,funct)
00172      ptr_psi_term args[],result,funct;
00173 {
00174   long bits = *(REAL *)args[0]->value;
00175   if (bits < 0) {
00176     Errorline("negative argument in %P.\n",funct);
00177     return FALSE; }
00178   else {
00179     unsigned long bytes = bits / sizeof(char);
00180     ptr_psi_term temp_result;
00181     if ((bits % sizeof(char)) != 0) bytes++;
00182     temp_result = make_bytedata(sys_bitvector,bytes);
00183     push_goal(unify,temp_result,result,NULL);
00184     return TRUE; }
00185 }
00186 
00187 static long
00188 c_make_bitvector()
00189 {
00190   psi_arg args[1];
00191   SETARG(args,0, "1" , integer , REQUIRED );
00192   return call_primitive(make_bitvector_internal,NARGS(args),args,0);
00193 }
00194 
00195 #define BV_AND 0
00196 #define BV_OR  1
00197 #define BV_XOR 2
00198 
00199 static long
00200 bitvector_binop_code(bv1,bv2,result,op)
00201      unsigned long *bv1,*bv2;
00202      ptr_psi_term result;
00203      int op;
00204 {
00205   unsigned long size1 = *bv1;
00206   unsigned long size2 = *bv2;
00207   unsigned long size3 = (size1>size2)?size1:size2;
00208   ptr_psi_term temp_result = make_bytedata(sys_bitvector,size3);
00209   unsigned char *s1 = ((unsigned char*)bv1)+sizeof(size1);
00210   unsigned char *s2 = ((unsigned char*)bv2)+sizeof(size2);
00211   unsigned char *s3 = ((unsigned char *) temp_result->value) + sizeof(size3);
00212   unsigned long i;
00213   switch (op) {
00214   case BV_AND:
00215     for(i=0;i<size3;i++) s3[i] = s1[i] & s2[i];
00216     if (size1<size2) for(;i<size2;i++) s3[i] = 0;
00217     else             for(;i<size1;i++) s3[i] = 0;
00218     break;
00219   case BV_OR:
00220     for(i=0;i<size3;i++) s3[i] = s1[i] | s2[i];
00221     if (size1<size2) for(;i<size2;i++) s3[i] = s2[i];
00222     else             for(;i<size1;i++) s3[i] = s1[i];
00223     break;
00224   case BV_XOR:
00225     for(i=0;i<size3;i++) s3[i] = s1[i] ^ s2[i];
00226     if (size1<size2) for(;i<size2;i++) s3[i] = (unsigned char) 0 ^ s2[i];
00227     else             for(;i<size1;i++) s3[i] = s1[i] ^ (unsigned char) 0;
00228     break;
00229   default: return (c_abort());
00230   }
00231   push_goal(unify,temp_result,result,NULL);
00232   return TRUE;
00233 }
00234 
00235 /******** BITVECTOR_BINOP
00236 */
00237 
00238 static long
00239 bitvector_binop_internal(args,result,funct,op)
00240      ptr_psi_term args[],result,funct;
00241      void* op;
00242 {
00243   return bitvector_binop_code((unsigned long *)args[0]->value,
00244                               (unsigned long *)args[1]->value,
00245                               result,(int)op);
00246 }
00247 
00248 static long
00249 bitvector_binop(op)
00250      int op;
00251 {
00252   psi_arg args[2];
00253   SETARG(args,0, "1" , sys_bitvector , REQUIRED );
00254   SETARG(args,1, "2" , sys_bitvector , REQUIRED );
00255   return call_primitive(bitvector_binop_internal,NARGS(args),args,(void*)op);
00256 }
00257 
00258 static long
00259 c_bitvector_and()
00260 {
00261   return bitvector_binop(BV_AND);
00262 }
00263 
00264 static long
00265 c_bitvector_or()
00266 {
00267   return bitvector_binop(BV_OR);
00268 }
00269 
00270 static long
00271 c_bitvector_xor()
00272 {
00273   return bitvector_binop(BV_XOR);
00274 }
00275 
00276 #define BV_NOT   0
00277 #define BV_COUNT 1
00278 
00279 static long
00280 bitvector_unop_code(bv1,result,op)
00281      unsigned long *bv1;
00282      ptr_psi_term result;
00283      int op;
00284 {
00285   unsigned long size1 = *bv1;
00286   unsigned char *s1 = ((unsigned char*)bv1)+sizeof(size1);
00287   unsigned long i;
00288   ptr_psi_term temp_result;
00289   unsigned char *s3;
00290   switch (op) {
00291   case BV_NOT:
00292     temp_result = make_bytedata(sys_bitvector,size1);
00293     s3 = ((unsigned char *) temp_result->value) + sizeof(size1);
00294     for(i=0;i<size1;i++) s3[i] = ~(s1[i]);
00295     break;
00296   case BV_COUNT:
00297     {
00298       int cnt = 0;
00299       register unsigned char c;
00300       for(i=0;i<size1;i++) {
00301         c=s1[i];
00302         if (c & 1<<0) cnt++;
00303         if (c & 1<<1) cnt++;
00304         if (c & 1<<2) cnt++;
00305         if (c & 1<<3) cnt++;
00306         if (c & 1<<4) cnt++;
00307         if (c & 1<<5) cnt++;
00308         if (c & 1<<6) cnt++;
00309         if (c & 1<<7) cnt++; }
00310       return unify_real_result(result,(REAL) cnt);
00311     }
00312     break;
00313   default: return (c_abort());
00314   }
00315   push_goal(unify,temp_result,result,NULL);
00316   return TRUE;
00317 }
00318 
00319 /******** BITVECTOR_UNOP
00320 */
00321 
00322 static long
00323 bitvector_unop_internal(args,result,funct,op)
00324      ptr_psi_term args[],result,funct;
00325      void* op;
00326 {
00327   return bitvector_unop_code((unsigned long *)args[0]->value,
00328                              result,(int)op);
00329 }
00330 
00331 static long
00332 bitvector_unop(op)
00333      int op;
00334 {
00335   psi_arg args[1];
00336   SETARG(args,0, "1" , sys_bitvector , REQUIRED );
00337   return call_primitive(bitvector_unop_internal,NARGS(args),args,(void*)op);
00338 }
00339 
00340 static long
00341 c_bitvector_not()
00342 {
00343   return bitvector_unop(BV_NOT);
00344 }
00345 
00346 static long
00347 c_bitvector_count()
00348 {
00349   return bitvector_unop(BV_COUNT);
00350 }
00351 
00352 #define BV_GET   0
00353 #define BV_SET   1
00354 #define BV_CLEAR 2
00355 
00356 static long
00357 bitvector_bit_code(bv1,idx,result,op,funct)
00358      unsigned long * bv1;
00359      long idx;
00360      ptr_psi_term result,funct;
00361      int op;
00362 {
00363   unsigned long size1 = *bv1;
00364   unsigned char *s1 = ((unsigned char*)bv1)+sizeof(size1);
00365   unsigned long i = idx / sizeof(char);
00366   int j = idx % sizeof(char);
00367   ptr_psi_term temp_result;
00368   unsigned char *s2;
00369   if (idx<0 || idx>=size1) {
00370     Errorline("Index out of bound in %P.\n",funct);
00371     return FALSE; }
00372   switch (op) {
00373   case BV_GET:
00374     return unify_real_result(result,(REAL)((s1[i] & (1<<j))?1:0));
00375     break;
00376   case BV_SET:
00377     temp_result = make_bytedata(sys_bitvector,size1);
00378     s2 = ((unsigned char *) temp_result->value) + sizeof(size1);
00379     bcopy(s1,s2,size1);
00380     s2[i] |= 1<<j;
00381     break;
00382   case BV_CLEAR:
00383     temp_result = make_bytedata(sys_bitvector,size1);
00384     s2 = ((unsigned char *) temp_result->value) + sizeof(size1);
00385     bcopy(s1,s2,size1);
00386     s2[i] &= ~ (1<<j);
00387     break;
00388   }
00389   push_goal(unify,temp_result,result,NULL);
00390   return TRUE;
00391 }
00392 
00393 static long
00394 bitvector_bit_internal(args,result,funct,op)
00395      ptr_psi_term args[],result,funct;
00396      void* op;
00397 {
00398   return bitvector_bit_code((unsigned long *)args[0]->value,
00399                             (long)*((REAL*)args[1]->value),
00400                             result,(int)op,funct);
00401 }
00402 
00403 static long
00404 bitvector_bit(op)
00405      int op;
00406 {
00407   psi_arg args[2];
00408   SETARG(args,0, "1" , sys_bitvector , REQUIRED );
00409   SETARG(args,1, "2" , integer       , REQUIRED );
00410   return call_primitive(bitvector_bit_internal,NARGS(args),args,(void*)op);
00411 }
00412 
00413 static long
00414 c_bitvector_get()
00415 {
00416   return bitvector_bit(BV_GET);
00417 }
00418 
00419 static long
00420 c_bitvector_set()
00421 {
00422   return bitvector_bit(BV_SET);
00423 }
00424 
00425 static long
00426 c_bitvector_clear()
00427 {
00428   return bitvector_bit(BV_CLEAR);
00429 }
00430 
00431 /* REGULAR EXPRESSIONS *
00432  ***********************/
00433 
00434 #include "regexp/regexp.h"
00435 
00436 void
00437 regerror(s)
00438      char*s;
00439 {
00440   fprintf(stderr,"Regexp Error: %s\n",s);
00441 }
00442 
00443 /******** C_REGEXP_COMPILE
00444   given a string returns, compiles it into a regexp structure,
00445   then copies that structure into a bytedata block on the heap.
00446  */
00447 #ifndef OS2_PORT
00448 static long
00449 regexp_compile_internal(args,result,funct)
00450      ptr_psi_term args[],result,funct;
00451 {
00452   ptr_psi_term temp_result;
00453   regexp * re = regcomp(args[0]->value);
00454   long bytes;
00455   if (re == NULL) {
00456     Errorline("compilation of regular expression failed in %P.\n",funct);
00457     return (c_abort()); }
00458   /* compute the size of the regexp stuff.  this is essentially the size
00459      of the regexp structure + the size of the program (bytecode) including
00460      the final END opcode (i.e. 0), hence the + 1, minus the bytes that we
00461      have counted twice, i.e. those between the start of the program and
00462      the computed end of the regexp structure (i.e. in case a regexp
00463      struct is larger, maybe to respect alignment constraints, than it has
00464      to be, and also to count the 1 byte of program included in the decl
00465      of struct regexp */
00466   bytes = last_regsize();
00467   temp_result = make_bytedata(sys_regexp,bytes);
00468   /* now let's copy the regexp stuff into the bytedata block.  The regmust
00469      field must be treated specially because it is a pointer into program:
00470      we cannot simply change it to reflect the location where the program
00471      will be copied to because that may well change over time: the gc may
00472      relocate the bytedata block.  Instead, we convert regmust into an
00473      offset and each time we need to pass it to regexec or regsub we must
00474      first convert it back into a pointer then back into an offset when we
00475      are done.  Note that, if regmust is NULL we must leave it that way */
00476   if (re->regmust != NULL)
00477     re->regmust = (char *) ((unsigned long) (re->regmust - (char *)re));
00478   bcopy((char*)re,((char*)temp_result->value)+sizeof(unsigned long),bytes);
00479   free(re);                     /* free the regexp: no longer needed */
00480   /* return result */
00481   push_goal(unify,temp_result,result,NULL);
00482   return TRUE;
00483 }
00484 
00485 static long
00486 c_regexp_compile()
00487 {
00488   psi_arg args[1];
00489   SETARG(args,0, "1" , quoted_string , REQUIRED );
00490   return call_primitive(regexp_compile_internal,NARGS(args),args,0);
00491 }
00492 
00493 /******** C_REGEXP_EXECUTE
00494   Attempts to match a regexp with a string
00495   regexp_execute(RE:regexp,S:string) -> @(0=>(S0,E0),(S1,E1),...)
00496   regexp_execute(RE:regexp,S:string,@(N=>(SN,EN),...)) -> boolean
00497   2nd form only instantiates the bounds requested in the mask (3rd arg)
00498   and returns a boolean so that it can be used as a predicate.
00499   The optional argument "offset" specifies an offset into the string.
00500  */
00501 
00502 static long
00503 regexp_execute_internal(args,result,funct)
00504      ptr_psi_term args[],result,funct;
00505 {
00506   regexp * re = (regexp*)(((char *)args[0]->value)+sizeof(unsigned long));
00507   char * must = re->regmust;
00508   long offset = 0;
00509   long success = TRUE;
00510   /* check that args[3] aka "offset" is valid if present */
00511   if (args[3]) {
00512     offset = *(REAL*)args[3]->value;
00513     if (offset < 0 || offset > strlen((char*)args[1]->value)) {
00514       Errorline("Illegal offset in %P.\n",funct);
00515       return (c_abort()); }
00516   }
00517   /* convert regmust from offset into a pointer if not NULL */
00518   if (must != NULL)
00519     re->regmust = (char*)re+(unsigned long)must;
00520   /* perform operation */
00521   if (regexec(re,((char *)args[1]->value) + offset) == 0) {
00522     if (must != NULL) re->regmust = must; /* back into an offset */
00523     return FALSE;
00524   }
00525   else {
00526     /* construct result of match */
00527     char **sp = re->startp;
00528     char **ep = re->endp;
00529     int i;
00530     char buffer[5];             /* in case NSUBEXP ever gets increased */
00531     ptr_node n3;
00532     if (must != NULL) re->regmust = must; /* back into an offset */
00533     if (args[2]) {
00534       /* only instantiate the numeric features present in args[2]
00535          then return true */
00536       for (i=0;i<NSUBEXP;i++,sp++,ep++) {
00537         if (*sp==NULL) break;
00538         sprintf(buffer,"%d",i);
00539         n3=find(featcmp,buffer,args[2]->attr_list);
00540         if (n3) {
00541           ptr_psi_term psi = (ptr_psi_term) n3->data;
00542           /* need to add 1 to these offsets because somehow life strings
00543              are 1-based rather than 0-based.  Who is the moron who made
00544              that decision?  This isn't Pascal! */
00545           ptr_psi_term bounds = stack_pair(stack_int(*sp - (char *)args[1]->value + 1),
00546                                            stack_int(*ep - (char *)args[1]->value + 1));
00547           push_goal(unify,psi,bounds,NULL);
00548         }
00549       }
00550       /* return true */
00551       unify_bool_result(result,TRUE);
00552     }
00553     else {
00554       /* create a term to represent all the groups and return it */
00555       ptr_psi_term psi = stack_psi_term(4);
00556       psi->type = top;
00557       for (i=0;i<NSUBEXP;i++,sp++,ep++) {
00558         if (*sp==NULL) break;
00559         sprintf(buffer,"%d",i);
00560         { ptr_psi_term bounds = stack_pair(stack_int(*sp - (char *)args[1]->value + 1),
00561                                            stack_int(*ep - (char *)args[1]->value + 1));
00562           stack_insert_copystr(buffer,&(psi->attr_list),bounds); }
00563       }
00564       /* return the new term */
00565       push_goal(unify,psi,result,NULL);
00566     }
00567     return TRUE;
00568   }
00569 }
00570 
00571 static long
00572 c_regexp_execute()
00573 {
00574   psi_arg args[4];
00575   SETARG(args,0, "1"      , sys_regexp    , REQUIRED );
00576   SETARG(args,1, "2"      , quoted_string , REQUIRED );
00577   SETARG(args,2, "3"      , top           , OPTIONAL|NOVALUE );
00578   SETARG(args,3, "offset" , integer       , OPTIONAL );
00579   return call_primitive(regexp_execute_internal,NARGS(args),args,0);
00580 }
00581 #endif
00582 /* FILE STREAMS *
00583  ****************/
00584 
00585 /* when a fp is opened for updating an input operation
00586    should not follow an output operation without an intervening
00587    flush or file positioning operation; and the other way around
00588    too.  I am going to keep track of what operations have been
00589    applied so that flush will be automatically invoked when
00590    necessary */
00591 
00592 #define FP_NONE   0
00593 #define FP_INPUT  1
00594 #define FP_OUTPUT 2
00595 
00596 typedef struct a_stream {
00597   FILE *fp;
00598   int op;
00599 } *ptr_stream;
00600 
00601 #define FP_PREPARE(s,OP) \
00602   if (s->op != OP && s->op != FP_NONE) fflush(s->fp); \
00603   s->op = OP;
00604 
00605 ptr_psi_term
00606 fileptr2stream(fp,typ)
00607      FILE*fp;
00608      ptr_definition*typ;
00609 {
00610   ptr_psi_term result = make_bytedata(typ,sizeof(struct a_stream));
00611   ((ptr_stream)BYTEDATA_DATA(result))->fp = fp;
00612   ((ptr_stream)BYTEDATA_DATA(result))->op = FP_NONE;
00613   return result;
00614 }
00615 
00616 static long
00617 int2stream_internal(args,result,funct)
00618      ptr_psi_term args[],result,funct;
00619 {
00620   FILE *fp = fdopen((int)*(REAL*)args[0]->value,
00621                     (char*)args[1]->value);
00622   if (fp==NULL) return FALSE;
00623   else {
00624     push_goal(unify,fileptr2stream(fp,sys_stream),result,NULL);
00625 /*    ptr_psi_term temp_result = make_bytedata(sys_stream,sizeof(fp));
00626     *(FILE**)BYTEDATA_DATA(temp_result) = fp;
00627     push_goal(unify,temp_result,result,NULL); */
00628     return TRUE;
00629   }
00630 }
00631 
00632 static long
00633 c_int2stream()
00634 {
00635   psi_arg args[2];
00636   SETARG(args,0,"1",integer,REQUIRED);
00637   SETARG(args,1,"2",quoted_string,REQUIRED);
00638   return call_primitive(int2stream_internal,NARGS(args),args,0);
00639 }
00640 
00641 static long
00642 fopen_internal(args,result,funct)
00643      ptr_psi_term args[],result,funct;
00644 {
00645   FILE *fp = fopen((char*)args[0]->value,
00646                    (char*)args[1]->value);
00647   if (fp==NULL) return FALSE;
00648   else {
00649 /*    ptr_psi_term temp_result = make_bytedata(sys_file_stream,sizeof(fp));
00650     *(FILE**)BYTEDATA_DATA(temp_result) = fp;
00651 */
00652     push_goal(unify,fileptr2stream(fp,sys_file_stream),result,NULL);
00653     return TRUE;
00654   }
00655 }
00656 
00657 static long
00658 c_fopen()
00659 {
00660   psi_arg args[2];
00661   SETARG(args,0, "1" , quoted_string , REQUIRED );
00662   SETARG(args,1, "2" , quoted_string , REQUIRED );
00663   return call_primitive(fopen_internal,NARGS(args),args,0);
00664 }
00665 
00666 static long
00667 fclose_internal(args,result,funct)
00668      ptr_psi_term args[],result,funct;
00669 {
00670   if (fclose(((ptr_stream)BYTEDATA_DATA(args[0]))->fp) != 0)
00671     return FALSE;
00672   else
00673     return TRUE;
00674 }
00675 
00676 static long
00677 c_fclose()
00678 {
00679   psi_arg args[1];
00680   SETARG(args,0, "1" , sys_stream , REQUIRED );
00681   return call_primitive(fclose_internal,NARGS(args),args,0);
00682 }
00683 
00684 static long
00685 fwrite_internal(args,result,funct)
00686      ptr_psi_term args[],result,funct;
00687 {
00688   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00689   /*FILE* fp = *(FILE**)BYTEDATA_DATA(args[0]);*/
00690   char* txt = (char*)args[1]->value;
00691   FP_PREPARE(srm,FP_OUTPUT);
00692   if (txt && *txt!='\0' &&
00693       fwrite((void*)txt,sizeof(char),strlen(txt),srm->fp)<=0)
00694     return FALSE;
00695   return TRUE;
00696 }
00697 
00698 static long
00699 c_fwrite()
00700 {
00701   psi_arg args[2];
00702   SETARG(args,0,"1",sys_stream,MANDATORY);
00703   SETARG(args,1,"2",quoted_string,MANDATORY);
00704   return call_primitive(fwrite_internal,NARGS(args),args,0);
00705 }
00706 
00707 static long
00708 fflush_internal(args,result,funct)
00709      ptr_psi_term args[],result,funct;
00710 {
00711   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00712   /*FILE* fp = *(FILE**)BYTEDATA_DATA(args[0]);*/
00713   srm->op = FP_NONE;
00714   if (fflush(srm->fp)!=0) return FALSE;
00715   return TRUE;
00716 }
00717 
00718 static long
00719 c_fflush()
00720 {
00721   psi_arg args[1];
00722   SETARG(args,0,"1",sys_stream,MANDATORY);
00723   return call_primitive(fflush_internal,NARGS(args),args,0);
00724 }
00725 
00726 static long
00727 get_buffer_internal(args,result,funct)
00728      ptr_psi_term args[],result,funct;
00729 {
00730   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00731   /*FILE* fp = *(FILE**)BYTEDATA_DATA(args[0]);*/
00732   long size = *(REAL*)args[1]->value;
00733   ptr_psi_term t = stack_psi_term(4);
00734   t->type = quoted_string;
00735   t->value=(GENERIC)heap_alloc(size+1);
00736   bzero((char*)t->value,size+1);
00737   FP_PREPARE(srm,FP_INPUT);
00738   if (fread((void*)t->value,sizeof(char),size,srm->fp) <= 0)
00739     return FALSE;
00740   push_goal(unify,t,result,NULL);
00741   return TRUE;
00742 }
00743 
00744 static long
00745 c_get_buffer()
00746 {
00747   psi_arg args[2];
00748   SETARG(args,0,"1",sys_stream,REQUIRED);
00749   SETARG(args,1,"2",integer,REQUIRED);
00750   return call_primitive(get_buffer_internal,NARGS(args),args,0);
00751 }
00752 
00753 #define TEXTBUFSIZE 5000
00754 
00755 struct text_buffer {
00756   struct text_buffer *next;
00757   int top;
00758   char data[TEXTBUFSIZE];
00759 };
00760 
00761 /* find the first match for character c starting from index idx in
00762    buffer buf.  if found place new buffer and index in rbuf and
00763    ridx and return 1, else return 0
00764    */
00765 int
00766 text_buffer_next(buf,idx,c,rbuf,ridx)
00767      struct text_buffer *buf,**rbuf;
00768      char c;
00769      int idx,*ridx;
00770 {
00771   while (buf) {
00772     while (idx<buf->top)
00773       if (buf->data[idx] == c) {
00774         *rbuf=buf;
00775         *ridx=idx;
00776         return 1;
00777       }
00778       else idx++;
00779     buf=buf->next;
00780     idx=0;
00781   }
00782   return 0;
00783 }
00784 
00785 /* compare string str with text in buffer buf starting at index idx.
00786    if the text to the end matches a prefix of the string, return
00787    pointer to remaining suffix of str to be matched, else return 0.
00788    */
00789 char*
00790 text_buffer_cmp(buf,idx,str)
00791      struct text_buffer *buf;
00792      int idx;
00793      char *str;
00794 {
00795   while (buf) {
00796     while (idx<buf->top)
00797       if (!*str || buf->data[idx] != *str)
00798         return 0;
00799       else { idx++; str++; }
00800     if (!*str && !buf->next) return str;
00801     else {
00802       buf=buf->next;
00803       idx=0;
00804     }
00805   }
00806   return 0;
00807 }
00808 
00809 /* add a character at the end of a buffer.  if the buffer is
00810    full, allocate a new buffer and link it to the current one,
00811    then overwrite the variable holding the pointer to the
00812    current buffer with the pointer to the new buffer.
00813    */
00814 void
00815 text_buffer_push(buf,c)
00816      struct text_buffer **buf;
00817      char c;
00818 {
00819   if ((*buf)->top < TEXTBUFSIZE)
00820     (*buf)->data[(*buf)->top++] = c;
00821   else {
00822     (*buf)->next = (struct text_buffer *)
00823       malloc(sizeof(struct text_buffer));
00824     if (!(*buf)->next) {
00825       fprintf(stderr,"Fatal error: malloc failed in text_buffer_push\n");
00826       exit(-1);
00827     }
00828     bzero((char*)(*buf)->next,sizeof(struct text_buffer));
00829     *buf = (*buf)->next;
00830     (*buf)->top = 1;
00831     (*buf)->data[0]=c;
00832   }
00833 }
00834 
00835 /* free a linked list of buffers */
00836 void
00837 text_buffer_free(buf)
00838      struct text_buffer *buf;
00839 {
00840   struct text_buffer *next;
00841   while (buf) {
00842     next = buf->next;
00843     free(buf);
00844     buf=next;
00845   }
00846 }
00847 
00848 static long
00849 get_record_internal(args,result,funct)
00850      ptr_psi_term args[],result,funct;
00851 {
00852   struct text_buffer rootbuf;
00853   struct text_buffer *curbuf = &rootbuf;
00854   struct text_buffer *lastbuf = &rootbuf;
00855   int lastidx = 0,size;
00856   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00857   FILE *fp = srm->fp; /*FILE* fp = *(FILE**)BYTEDATA_DATA(args[0]);*/
00858   char *sep = (char*)args[1]->value;
00859   int c;
00860   ptr_psi_term t;
00861   char *cursep = sep;
00862 
00863   FP_PREPARE(srm,FP_INPUT);
00864   bzero((char*)&rootbuf,sizeof(rootbuf));
00865   if (!sep || !*sep) {
00866     /* no separator: just grab as much as you can */
00867     while ((c=getc(fp)) != EOF)
00868       text_buffer_push(&curbuf,(char)c);
00869     goto PackUpAndLeave;
00870   }
00871 
00872   if (sep[1]=='\0') {
00873     /* only one char in string */
00874     while ((c=getc(fp)) != EOF) {
00875       text_buffer_push(&curbuf,(char)c);
00876       if (c==*sep) break;
00877     }
00878     goto PackUpAndLeave;
00879   }
00880 
00881   /* general case: multicharacter separator */
00882 
00883  WaitForStart:
00884   if ((c=getc(fp)) == EOF) goto PackUpAndLeave;
00885   text_buffer_push(&curbuf,(char)c);
00886   if (c==*sep) {
00887     cursep = sep+1;
00888     lastbuf=curbuf;
00889     lastidx=curbuf->top - 1;
00890     goto MatchNext;
00891   }
00892   else goto WaitForStart;
00893 
00894  MatchNext:
00895   if (!*cursep || (c=getc(fp))==EOF) goto PackUpAndLeave;
00896   text_buffer_push(&curbuf,(char)c);
00897   if (c!=*cursep) goto TryAgain;
00898   cursep++;
00899   goto MatchNext;
00900 
00901  TryAgain:
00902   if (!text_buffer_next(lastbuf,lastidx+1,*sep,&lastbuf,&lastidx))
00903     goto WaitForStart;
00904   if (!(cursep=text_buffer_cmp(lastbuf,lastidx,sep)))
00905     goto TryAgain;
00906   goto MatchNext;
00907 
00908  PackUpAndLeave:
00909   /* compute how much space we need */
00910   for(lastbuf=&rootbuf,size=0;lastbuf!=NULL;lastbuf=lastbuf->next)
00911     size += lastbuf->top;
00912   t=stack_psi_term(0);
00913   t->type=quoted_string;
00914   t->value=(GENERIC)heap_alloc(size+1);
00915   for(lastbuf=&rootbuf,sep=(char*)t->value;
00916       lastbuf!=NULL;sep+=lastbuf->top,lastbuf=lastbuf->next)
00917     bcopy(lastbuf->data,sep,lastbuf->top);
00918   ((char*)t->value)[size]='\0';
00919   text_buffer_free(rootbuf.next);
00920   push_goal(unify,t,result,NULL);
00921   return TRUE;
00922 }
00923 
00924 static long
00925 c_get_record()
00926 {
00927   psi_arg args[2];
00928   SETARG(args,0,"1",sys_stream,REQUIRED);
00929   SETARG(args,1,"2",quoted_string,REQUIRED);
00930   return call_primitive(get_record_internal,NARGS(args),args,0);
00931 }
00932 
00933 static long
00934 get_code_internal(args,result,funct)
00935      ptr_psi_term args[],result,funct;
00936 {
00937   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00938   int c;
00939   FP_PREPARE(srm,FP_INPUT);
00940   if ((c=getc(srm->fp)) == EOF) return FALSE;
00941   else return unify_real_result(result,(REAL)c);
00942 }
00943 
00944 static long
00945 c_get_code()
00946 {
00947   psi_arg args[1];
00948   SETARG(args,0,"1",sys_stream,REQUIRED);
00949   return call_primitive(get_code_internal,NARGS(args),args,0);
00950 }
00951 
00952 static long
00953 ftell_internal(args,result,funct)
00954      ptr_psi_term args[],result,funct;
00955 {
00956   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00957   if (srm->op != FP_NONE || srm->op != FP_INPUT) {
00958     fflush(srm->fp);
00959     srm->op = FP_NONE;
00960   }
00961   return unify_real_result(result,(REAL)ftell(srm->fp));
00962 /*  *(FILE**)BYTEDATA_DATA(args[0])));*/
00963 }
00964 
00965 static long
00966 c_ftell()
00967 {
00968   psi_arg args[1];
00969   SETARG(args,0,"1",sys_file_stream,REQUIRED);
00970   return call_primitive(ftell_internal,NARGS(args),args,0);
00971 }
00972 
00973 #ifndef SEEK_SET
00974 #define SEEK_SET 0
00975 #endif
00976 #ifndef SEEK_CUR
00977 #define SEEK_CUR 1
00978 #endif
00979 #ifndef SEEK_END
00980 #define SEEK_END 2
00981 #endif
00982 
00983 static long
00984 fseek_internal(args,result,funct)
00985      ptr_psi_term args[],result,funct;
00986 {
00987   ptr_stream srm = (ptr_stream)BYTEDATA_DATA(args[0]);
00988   srm->op = FP_NONE;
00989   return
00990     (fseek(srm->fp ,
00991            (long)*(REAL*)args[1]->value,
00992            args[2]?(long)*(REAL*)args[2]->value:SEEK_SET) < 0)
00993       ?FALSE:TRUE;
00994 }
00995 
00996 static long
00997 c_fseek()
00998 {
00999   psi_arg args[3];
01000   SETARG(args,0,"1",sys_file_stream,MANDATORY);
01001   SETARG(args,1,"2",integer,MANDATORY);
01002   SETARG(args,2,"3",integer,OPTIONAL);
01003   return call_primitive(fseek_internal,NARGS(args),args,0);
01004 }
01005 
01006 static long
01007 stream2sys_stream_internal(args,result,funct)
01008      ptr_psi_term args[],result,funct;
01009 {
01010   push_goal(unify,fileptr2stream((FILE*)args[0]->value,sys_stream),
01011             result,NULL);
01012   return TRUE;
01013 }
01014 
01015 static long
01016 c_stream2sys_stream()
01017 {
01018   psi_arg args[1];
01019   SETARG(args,0,"1",stream,REQUIRED);
01020   return call_primitive(stream2sys_stream_internal,NARGS(args),args,0);
01021 }
01022 
01023 static long
01024 sys_stream2stream_internal(args,result,funct)
01025      ptr_psi_term args[],result,funct;
01026 {
01027   ptr_psi_term tmp;
01028   tmp=stack_psi_term(4);
01029   tmp->type=stream;
01030   tmp->value=(GENERIC)((ptr_stream)BYTEDATA_DATA(args[0]))->fp;
01031   push_goal(unify,tmp,result,NULL);
01032   return TRUE;
01033 }
01034 
01035 static long
01036 c_sys_stream2stream()
01037 {
01038   psi_arg args[1];
01039   SETARG(args,0,"1",sys_stream,REQUIRED);
01040   return call_primitive(sys_stream2stream_internal,NARGS(args),args,0);
01041 }
01042 
01043 /* SOCKETS AND NETWORKING *
01044  **************************/
01045 #ifndef OS2_PORT
01046 #include <sys/socket.h>
01047 #include <netinet/in.h>
01048 #include <sys/un.h>
01049 #include <netdb.h>
01050 #include <arpa/inet.h>
01051 #include <ctype.h>
01052 
01053 static long
01054 socket_internal(args,result,funct)
01055      ptr_psi_term args[],result,funct;
01056 {
01057   int addr_family=AF_INET,type=SOCK_STREAM,protocol=0;
01058   char *s;
01059   int fd;
01060 
01061   if (args[0]) {
01062     s=(char*)args[0]->value;
01063     if      (!strcmp(s,"AF_UNIX")) addr_family=AF_UNIX;
01064     else if (!strcmp(s,"AF_INET")) addr_family=AF_INET;
01065     else {
01066       Errorline("Unknown address family in %P.\n",funct);
01067       return FALSE; }
01068   }
01069 
01070   if (args[1]) {
01071     s=(char*)args[1]->value;
01072     if      (!strcmp(s,"SOCK_STREAM")) type=SOCK_STREAM;
01073     else if (!strcmp(s,"SOCK_DGRAM" )) type=SOCK_DGRAM;
01074     else if (!strcmp(s,"SOCK_RAW"   )) {
01075       Errorline("SOCK_RAW not supported in %P.\n",funct);
01076       return FALSE; }
01077     else {
01078       Errorline("Unknown socket type in %P.\n",funct);
01079       return FALSE; }
01080   }
01081 
01082   if ((fd=socket(addr_family,type,protocol))<0)
01083     return FALSE;
01084 
01085   { FILE*fp = fdopen(fd,"r+");
01086     ptr_psi_term t;
01087 
01088     if (fp==NULL) {
01089       Errorline("fdopen failed on socket in %P.\n",funct);
01090       return FALSE;
01091     }
01092 
01093 /*    t = make_bytedata(sys_socket_stream,sizeof(fp));
01094     *(FILE**)BYTEDATA_DATA(t) = fp;*/
01095     push_goal(unify,fileptr2stream(fp,sys_socket_stream),result,NULL);
01096   }
01097   return TRUE;
01098 }
01099 
01100 static long
01101 c_socket()
01102 {
01103   psi_arg args[2];
01104   SETARG(args,0,"1",quoted_string,OPTIONAL);
01105   SETARG(args,1,"2",quoted_string,OPTIONAL);
01106   return call_primitive(socket_internal,NARGS(args),args,0);
01107 }
01108 
01109 int
01110 is_ipaddr(s)
01111      char*s;
01112 {
01113   if (s==NULL) return 0;
01114   while (*s)
01115     if (!isdigit(*s) && *s!='.') return 0;
01116     else s++;
01117   return 1;
01118 }
01119 
01120 static long
01121 bind_or_connect_internal(args,result,funct,info)
01122      ptr_psi_term args[],result,funct;
01123      void*info;
01124 {
01125   int fd = fileno(((ptr_stream)BYTEDATA_DATA(args[0]))->fp); 
01126   int do_bind = info==NULL;
01127 
01128   if (args[1] || args[2]) {
01129     /* bind or connect in the internet domain */
01130     struct sockaddr_in name;
01131     char* hostname = args[1]?(char*)args[1]->value:NULL;
01132     int port;
01133     if (!args[2]) {
01134       Errorline("Missing port number in %P.\n",funct);
01135       return FALSE;
01136     }
01137 
01138     bzero((char*)&name,sizeof(name));
01139     name.sin_family = AF_INET;
01140     name.sin_port = htons((unsigned short)*(REAL*)args[2]->value);
01141 
01142     if (!hostname || *hostname=='\0' || !strcasecmp(hostname,"localhost"))
01143       name.sin_addr.s_addr = INADDR_ANY;
01144     else {
01145       struct hostent * h;
01146       int ipaddr;
01147       if ((ipaddr=is_ipaddr(hostname))) {
01148         int i = inet_addr(hostname);
01149         h = gethostbyaddr((char*)&i,sizeof(i),AF_INET);
01150       } else h = gethostbyname(hostname);
01151       if (h==NULL) {
01152         Errorline("%s failed for %P.\n",
01153                   ipaddr?"gethostbyaddr":"gethostbyname",funct);
01154         return FALSE;
01155       }
01156       bcopy(h->h_addr,(char*)&(name.sin_addr.s_addr),h->h_length);
01157     }
01158     if ((do_bind?
01159          bind(fd,(struct sockaddr *)&name,sizeof(name)):
01160          connect(fd,(struct sockaddr *)&name,sizeof(name))) < 0) {
01161       Errorline("%s failed in %P.\n",do_bind?"bind":"connect",funct);
01162       return FALSE;
01163     }
01164   }
01165   else if (args[3]) {
01166     /* bind in the unix domain */
01167     struct sockaddr_un name;
01168     char* path = (char*)args[3]->value;
01169 
01170     name.sun_family = AF_UNIX;
01171     strcpy(name.sun_path,path);
01172 
01173     if ((do_bind?
01174          bind(fd,(struct sockaddr *)&name,sizeof(name)):
01175          connect(fd,(struct sockaddr *)&name,sizeof(name))) < 0) {
01176       Errorline("%s failed in %P.\n",do_bind?"bind":"connect",funct);
01177       return FALSE;
01178     }
01179   }
01180   else {
01181     Errorline("Too few arguments in %P.\n",funct);
01182     return FALSE;
01183   }
01184   return TRUE;
01185 }
01186 
01187 static long
01188 c_bind()
01189 {
01190   psi_arg args[4];
01191   SETARG(args,0,"1",sys_socket_stream,MANDATORY);
01192   SETARG(args,1,"host",quoted_string,OPTIONAL);
01193   SETARG(args,2,"port",integer,OPTIONAL);
01194   SETARG(args,3,"path",quoted_string,OPTIONAL);
01195   return call_primitive(bind_or_connect_internal,NARGS(args),args,NULL);
01196 }
01197 
01198 static long
01199 c_connect()
01200 {
01201   psi_arg args[4];
01202   SETARG(args,0,"1",sys_socket_stream,MANDATORY);
01203   SETARG(args,1,"host",quoted_string,OPTIONAL);
01204   SETARG(args,2,"port",integer,OPTIONAL);
01205   SETARG(args,3,"path",quoted_string,OPTIONAL);
01206   return call_primitive(bind_or_connect_internal,NARGS(args),args,(void*)1);
01207 }
01208 
01209 static long
01210 listen_internal(args,result,funct)
01211      ptr_psi_term args[],result,funct;
01212 {
01213   int fd = fileno(((ptr_stream)BYTEDATA_DATA(args[0]))->fp); 
01214   int n = *(REAL*)args[1]->value;
01215 
01216   if (listen(fd,n) < 0) return FALSE;
01217   return TRUE;
01218 }
01219 
01220 static long
01221 c_listen()
01222 {
01223   psi_arg args[2];
01224   SETARG(args,0,"1",sys_socket_stream,MANDATORY);
01225   SETARG(args,1,"2",integer,MANDATORY);
01226   return call_primitive(listen_internal,NARGS(args),args,0);
01227 }
01228 
01229 static long
01230 accept_internal(args,result,funct)
01231      ptr_psi_term args[],result,funct;
01232 {
01233   int fd = fileno(((ptr_stream)BYTEDATA_DATA(args[0]))->fp); 
01234   int s;
01235 
01236   if ((s=accept(fd,NULL,NULL)) < 0) return FALSE;
01237   else {
01238     FILE * fp = fdopen(s,"r+");
01239     ptr_psi_term t;
01240 
01241     if (fp==NULL) {
01242       Errorline("fdopen failed on socket in %P.\n",funct);
01243       return FALSE;
01244     }
01245 
01246 /*    t = make_bytedata(sys_socket_stream,sizeof(fp));
01247     *(FILE**)BYTEDATA_DATA(t) = fp;*/
01248     push_goal(unify,fileptr2stream(fp,sys_socket_stream),result,NULL);
01249     return TRUE;
01250   }
01251 }
01252 
01253 static long
01254 c_accept()
01255 {
01256   psi_arg args[1];
01257   SETARG(args,0,"1",sys_socket_stream,REQUIRED);
01258   return call_primitive(accept_internal,NARGS(args),args,0);
01259 }
01260 #endif
01261 /* SYSTEM ERRORS *
01262  *****************/
01263 
01264 static long
01265 errno_internal(args,result,funct)
01266      ptr_psi_term args[],result,funct;
01267 {
01268   push_goal(unify,stack_int(errno),result,NULL);
01269   return TRUE;
01270 }
01271 
01272 static long
01273 c_errno()
01274 {
01275   return call_primitive(errno_internal,0,NULL,0);
01276 }
01277 
01278 /* some systems are missing these declarations */
01279 #ifndef OS2_PORT
01280 extern char *sys_errlist[];
01281 extern int sys_nerr;
01282 
01283 static long
01284 errmsg_internal(args,result,funct)
01285      ptr_psi_term args[],result,funct;
01286 {
01287   long n = args[0]?(long)*(REAL*)args[0]->value:errno;
01288   if (n<0 || n>=sys_nerr) return FALSE;
01289   else {
01290     push_goal(unify,stack_string(sys_errlist[n]),result,NULL);
01291     return TRUE;
01292   }
01293 }
01294 
01295 static long
01296 c_errmsg()
01297 {
01298   psi_arg args[1];
01299   SETARG(args,0, "1" , integer , OPTIONAL );
01300   return call_primitive(errmsg_internal,NARGS(args),args,0);
01301 }
01302 #endif
01303 /* MODULES *
01304  ***********/
01305 
01306 /******** C_IMPORT_SYMBOL
01307   import a public symbol from another module into the current one,
01308   optionally renaming it.
01309   */
01310 
01311 static long
01312 import_symbol_internal(args,result,funct)
01313      ptr_psi_term args[],result,funct;
01314 {
01315   ptr_keyword key;
01316 
01317   if (args[1])
01318     key=args[1]->type->keyword;
01319   else
01320     key=hash_lookup(current_module->symbol_table,
01321                     args[0]->type->keyword->symbol);
01322 
01323   if (key)
01324     if (key->definition->type != undef) {
01325       Errorline("symbol %s already defined in %P.",key->combined_name,funct);
01326       return FALSE;
01327     }
01328     else key->definition=args[0]->type;
01329   else {
01330     /* adapted from update_symbol in modules.c */
01331     /* Add 'module#symbol' to the symbol table */
01332     key=HEAP_ALLOC(struct wl_keyword);
01333     key->module=current_module;
01334     /* use same name */
01335     key->symbol=args[0]->type->keyword->symbol;
01336     key->combined_name=
01337       heap_copy_string(make_module_token(current_module,key->symbol));
01338     key->public=FALSE;
01339     key->private_feature=FALSE;
01340     key->definition=args[0]->type; /* use given definition */
01341         
01342     hash_insert(current_module->symbol_table,key->symbol,key);
01343   }
01344   return TRUE;
01345 }
01346 
01347 static long
01348 c_import_symbol()
01349 {
01350   psi_arg args[2];
01351   SETARG(args,0,"1",top,MANDATORY|UNEVALED);
01352   SETARG(args,1,"as",top,OPTIONAL|NOVALUE|UNEVALED);
01353   return call_primitive(import_symbol_internal,NARGS(args),args,0);
01354 }
01355 
01356 /* PROCESSES *
01357  *************/
01358 #ifndef OS2_PORT
01359 static long
01360 fork_internal(args,result,funct)
01361      ptr_psi_term args[],result,funct;
01362 {
01363   pid_t id = fork();
01364   if (id < 0) return FALSE;
01365   else  return unify_real_result(result,(REAL)id);
01366 }
01367 
01368 static long
01369 c_fork()
01370 {
01371   return call_primitive(fork_internal,0,NULL,0);
01372 }
01373 
01374 typedef struct {
01375   char * name;
01376   ptr_psi_term value;
01377 } psi_feature;
01378 
01379 #define SETFEATURE(lst,n,nam,val) ((lst[n].name=nam),(lst[n].value=val))
01380 
01381 static long
01382 unify_pterm_result(t,sym,lst,n)
01383      ptr_psi_term t;
01384      ptr_definition sym;
01385      psi_feature lst[];
01386      int n;
01387 {
01388   ptr_psi_term u;
01389   int i;
01390   if (n<0) {
01391     fprintf(stderr,"unify_pterm_result called with n<0: n=%d\n",n);
01392     exit(-1);
01393   }
01394   u=stack_psi_term(4);
01395   u->type=sym;
01396   for(i=0;i<n;i++)
01397     stack_insert(featcmp,lst[i].name,&(u->attr_list),lst[i].value);
01398   push_goal(unify,t,u,NULL);
01399   return TRUE;
01400 }
01401 #endif
01402 char *
01403 get_numeric_feature(n)
01404      long n;
01405 {
01406   if      (n==1) return one;
01407   else if (n==2) return two;
01408   else if (n==3) return three;
01409   else {
01410     char buf[100];
01411     sprintf(buf,"%d",n);
01412     return heap_copy_string(buf);
01413   }
01414 }
01415 #ifndef OS2_PORT
01416 #ifndef WIFEXITED
01417 #include <sys/wait.h>
01418 #endif
01419 
01420 ptr_definition sys_process_no_children;
01421 ptr_definition sys_process_exited;
01422 ptr_definition sys_process_signaled;
01423 ptr_definition sys_process_stopped;
01424 ptr_definition sys_process_continued;
01425 
01426 static long
01427 unify_wait_result(result,id,status)
01428      ptr_psi_term result;
01429      pid_t id;
01430      int status;
01431 {
01432   int n=2;
01433   ptr_definition sym;
01434   psi_feature lst[2];
01435   SETFEATURE(lst,0,one,stack_int(id));
01436   if (id == -1 || status == -1) {
01437     if (errno==ECHILD) {
01438       sym = sys_process_no_children;
01439       n=0;
01440     }
01441     else return FALSE;
01442   }
01443   else if (WIFEXITED(status)) {
01444     SETFEATURE(lst,1,two,stack_int(WEXITSTATUS(status)));
01445     sym = sys_process_exited;
01446   }
01447   else if (WIFSIGNALED(status)) {
01448     SETFEATURE(lst,1,two,stack_int(WTERMSIG(status)));
01449     sym = sys_process_signaled;
01450   }
01451   else if (WIFSTOPPED(status)) {
01452     SETFEATURE(lst,1,two,stack_int(WSTOPSIG(status)));
01453     sym = sys_process_stopped;
01454   }
01455 #ifdef WIFCONTINUED
01456   else if (WIFCONTINUED(status)) {
01457     sym = sys_process_continued;
01458     n=1;
01459   }
01460 #endif
01461   else {
01462     Errorline("Unexpected wait status: %d",status);
01463     return FALSE;
01464   }
01465   return unify_pterm_result(result,sym,lst,n);
01466 }
01467 
01468 static long
01469 wait_internal(args,result,funct)
01470      ptr_psi_term args[],result,funct;
01471 {
01472   int status;
01473   pid_t id = wait(&status);
01474   return unify_wait_result(result,id,status);
01475 }
01476 
01477 static long
01478 c_wait()
01479 {
01480   return call_primitive(wait_internal,0,NULL,0);
01481 }
01482 
01483 static long
01484 waitpid_internal(args,result,funct)
01485      ptr_psi_term args[],result,funct;
01486 {
01487   int status;
01488   pid_t id = waitpid((pid_t)(long)*(REAL*)args[0]->value,&status,
01489                      args[1]?(int)(long)*(REAL*)args[1]->value:0);
01490   return unify_wait_result(result,id,status);
01491 }
01492 
01493 static long
01494 c_waitpid()
01495 {
01496   psi_arg args[2];
01497   SETARG(args,0,"1",integer,REQUIRED);
01498   SETARG(args,1,"2",integer,OPTIONAL);
01499   return call_primitive(waitpid_internal,NARGS(args),args,0);
01500 }
01501 
01502 static long
01503 kill_internal(args,result,funct)
01504      ptr_psi_term args[],result,funct;
01505 {
01506   return (kill((pid_t)*(REAL*)args[0]->value,
01507                (int)*(REAL*)args[1]->value)==0)?TRUE:FALSE;
01508 }
01509 
01510 static long
01511 c_kill()
01512 {
01513   psi_arg args[2];
01514   SETARG(args,0,"1",integer,MANDATORY);
01515   SETARG(args,1,"2",integer,MANDATORY);
01516   return call_primitive(kill_internal,NARGS(args),args,0);
01517 }
01518 #endif
01519 /* MISCELLANEOUS *
01520  ****************/
01521 #ifndef OS2_PORT
01522 static long
01523 cuserid_internal(args,result,funct)
01524      ptr_psi_term args[],result,funct;
01525 {
01526   char name[L_cuserid+1];
01527   if (*cuserid(name) == '\0') return FALSE;
01528   else {
01529     push_goal(unify,result,stack_string(name),NULL);
01530     return TRUE;
01531   }
01532 }
01533 
01534 static long
01535 c_cuserid()
01536 {
01537   return call_primitive(cuserid_internal,0,NULL,0);
01538 }
01539 
01540 #ifndef MAXHOSTNAMELEN
01541 #include <sys/param.h>
01542 #endif
01543 
01544 static long
01545 gethostname_internal(args,result,funct)
01546      ptr_psi_term args[],result,funct;
01547 {
01548   char name[MAXHOSTNAMELEN+1];
01549   if (gethostname(name,MAXHOSTNAMELEN+1) == 0) {
01550     push_goal(unify,result,stack_string(name),NULL);
01551     return TRUE;
01552   }
01553   else return FALSE;
01554 }
01555 
01556 static long
01557 c_gethostname()
01558 {
01559   return call_primitive(gethostname_internal,0,NULL,0);
01560 }
01561 #endif
01562 /* LAZY PROJECT
01563  ***************/
01564 
01565 static long
01566 lazy_project_internal(args,result,funct)
01567      ptr_psi_term args[],result,funct;
01568 {
01569   ptr_node n;
01570   char buffer[100];
01571   if (args[1]->type == top) {
01572     residuate(args[0]);
01573     residuate(args[1]);
01574     return TRUE;
01575   }
01576   if (sub_type(args[1]->type,integer) && args[1]->value)
01577     sprintf(buffer,"%d",(long)*(REAL*)args[1]->value);
01578   else if (sub_type(args[1]->type,quoted_string) && args[1]->value)
01579     strcpy(buffer,(char*)args[1]->value);
01580   else
01581     strcpy(buffer,args[1]->type->keyword->symbol);
01582   n=find(featcmp,buffer,args[0]->attr_list);
01583   if (n) push_goal(unify,n->data,result,NULL);
01584   /* this is all bullshit because projection should residuate
01585      on its 2nd arg until it becomes value.  In particular, think
01586      of using `int' as a feature when it is clear that `int' may
01587      subsequently be refined to a particular integer. */
01588   else residuate(args[0]);
01589   return TRUE;
01590 }
01591 
01592 static long
01593 c_lazy_project()
01594 {
01595   psi_arg args[2];
01596   SETARG(args,0,"1",top,REQUIRED|NOVALUE);
01597   SETARG(args,1,"2",top,REQUIRED|NOVALUE);
01598   return call_primitive(lazy_project_internal,NARGS(args),args,0);
01599 }
01600 
01601 /* WAIT_ON_FEATURE
01602  ******************/
01603 
01604 static long
01605 wait_on_feature_internal(args,result,funct)
01606      ptr_psi_term args[],result,funct;
01607 {
01608   char buffer[100];
01609   if (args[1]->type == top) {
01610     residuate(args[0]);
01611     residuate(args[1]);
01612     return TRUE;
01613   }
01614   if (sub_type(args[1]->type,integer) && args[1]->value)
01615     sprintf(buffer,"%d",(long)*(REAL*)args[1]->value);
01616   else if (sub_type(args[1]->type,quoted_string) && args[1]->value)
01617     strcpy(buffer,(char*)args[1]->value);
01618   else
01619     strcpy(buffer,args[1]->type->keyword->symbol);
01620   if (find(featcmp,buffer,args[0]->attr_list))
01621     push_goal(prove,args[2],DEFRULES,NULL);
01622   /* this is all bullshit because projection should residuate
01623      on its 2nd arg until it becomes value.  In particular, think
01624      of using `int' as a feature when it is clear that `int' may
01625      subsequently be refined to a particular integer. */
01626   else residuate(args[0]);
01627   return TRUE;
01628 }
01629 
01630 static long
01631 c_wait_on_feature()
01632 {
01633   psi_arg args[3];
01634   SETARG(args,0,"1",top,MANDATORY|NOVALUE);
01635   SETARG(args,1,"2",top,MANDATORY|NOVALUE);
01636   SETARG(args,2,"3",top,MANDATORY|NOVALUE|UNEVALED);
01637   return call_primitive(wait_on_feature_internal,NARGS(args),args,0);
01638 }
01639 
01640 static long
01641 my_wait_on_feature_internal(args,result,funct)
01642      ptr_psi_term args[],result,funct;
01643 {
01644   char buffer[100];
01645   if (args[1]->type == top) {
01646     residuate(args[0]);
01647     residuate(args[1]);
01648     return TRUE;
01649   }
01650   if (sub_type(args[1]->type,integer) && args[1]->value)
01651     sprintf(buffer,"%d",(long)*(REAL*)args[1]->value);
01652   else if (sub_type(args[1]->type,quoted_string) && args[1]->value)
01653     strcpy(buffer,(char*)args[1]->value);
01654   else
01655     strcpy(buffer,args[1]->type->keyword->symbol);
01656   if (find(featcmp,buffer,args[0]->attr_list)) {
01657     unify_bool_result(result,TRUE);
01658     push_goal(prove,args[2],DEFRULES,NULL);
01659   }
01660   /* this is all bullshit because projection should residuate
01661      on its 2nd arg until it becomes value.  In particular, think
01662      of using `int' as a feature when it is clear that `int' may
01663      subsequently be refined to a particular integer. */
01664   else residuate(args[0]);
01665   return TRUE;
01666 }
01667 
01668 static long
01669 c_my_wait_on_feature()
01670 {
01671   psi_arg args[3];
01672   SETARG(args,0,"1",top,MANDATORY|NOVALUE);
01673   SETARG(args,1,"2",top,MANDATORY|NOVALUE);
01674   SETARG(args,2,"3",top,MANDATORY|NOVALUE|UNEVALED);
01675   return call_primitive(my_wait_on_feature_internal,NARGS(args),args,0);
01676 }
01677 
01678 /* CALL_ONCE
01679  ************/
01680 /*
01681    call_once(G) -> T | G,!,T=true;T=false.
01682    */
01683 
01684 static long
01685 call_once_internal(args,result,funct)
01686      ptr_psi_term args[],result,funct;
01687 {
01688   ptr_psi_term value;
01689   ptr_choice_point cutpt = choice_stack;
01690   resid_aim=NULL;
01691   value = stack_psi_term(4);
01692   value->type = false;
01693   push_choice_point(unify,result,value,NULL);
01694   value = stack_psi_term(4);
01695   value->type = true;
01696   push_goal(unify,result,value,NULL);
01697   push_goal(general_cut,cutpt,NULL,NULL);
01698   push_goal(prove,args[0],DEFRULES,NULL);
01699   return TRUE;
01700 }
01701 
01702 static long
01703 c_call_once()
01704 {
01705   psi_arg args[1];
01706   SETARG(args,0,"1",top,MANDATORY|NOVALUE|UNEVALED);
01707   return call_primitive(call_once_internal,NARGS(args),args,0);
01708 }
01709 
01710 static long
01711 apply1_internal(args,result,funct)
01712      ptr_psi_term args[],result,funct;
01713 {
01714   long success=TRUE;
01715   if (args[0]->type==top) residuate(args[0]);
01716   else if (args[0]->type->type!=function) {
01717     Errorline("1st arg not a function in %P.\n",funct);
01718     success=FALSE;
01719   }
01720   else {
01721     char buffer[1000];
01722     char * feat;
01723     ptr_psi_term fun;
01724     if (sub_type(args[1]->type,integer) && args[1]->value)
01725       feat = get_numeric_feature((long)*(REAL*)args[1]->value);
01726     else if (sub_type(args[1]->type,quoted_string) && args[1]->value)
01727       feat = (char*)args[1]->value;
01728     else
01729       feat = heap_copy_string(args[1]->type->keyword->symbol);
01730     clear_copy();
01731     fun=distinct_copy(args[0]);
01732     stack_insert(featcmp,feat,&(fun->attr_list),args[2]);
01733     push_goal(eval,fun,result,fun->type->rule);
01734   }
01735   return success;
01736 }
01737 
01738 static long
01739 c_apply1()
01740 {
01741   psi_arg args[3];
01742   SETARG(args,0,"1",top,REQUIRED|NOVALUE);
01743   SETARG(args,1,"2",top,REQUIRED|NOVALUE);
01744   SETARG(args,2,"3",top,REQUIRED|NOVALUE);
01745   return call_primitive(apply1_internal,NARGS(args),args,0);
01746 }
01747 #ifndef OS2_PORT
01748 static long
01749 getpid_internal(args,result,funct)
01750      ptr_psi_term args[],result,funct;
01751 {
01752   return unify_real_result(result,(REAL)getpid());
01753 }
01754 
01755 static long
01756 c_getpid()
01757 {
01758   return call_primitive(getpid_internal,0,0,0);
01759 }
01760 #endif
01761 /********************************************************************
01762   INITIALIZATION FUNCTIONS
01763   *******************************************************************/
01764 
01765 #ifdef LIFE_NDBM
01766 extern void make_ndbm_type_links();
01767 #endif
01768 
01769 void
01770 make_sys_type_links()
01771 {
01772 #ifdef LIFE_NDBM
01773   make_ndbm_type_links();
01774 #endif
01775   make_type_link(sys_bitvector    ,sys_bytedata);
01776   make_type_link(sys_regexp       ,sys_bytedata);
01777   make_type_link(sys_stream       ,sys_bytedata);
01778   make_type_link(sys_file_stream  ,sys_stream);
01779   make_type_link(sys_socket_stream,sys_stream);
01780   make_type_link(sys_bytedata     ,built_in); /* DENYS: BYTEDATA */
01781 }
01782 
01783 #ifdef LIFE_NDBM
01784 extern void check_ndbm_definitions();
01785 #endif
01786 
01787 void
01788 check_sys_definitions()
01789 {
01790   check_definition(&sys_bytedata);      /* DENYS: BYTEDATA */
01791   check_definition(&sys_bitvector);
01792   check_definition(&sys_regexp);
01793   check_definition(&sys_stream);
01794   check_definition(&sys_file_stream);
01795 #ifndef OS2_PORT
01796   check_definition(&sys_socket_stream);
01797   check_definition(&sys_process_no_children);
01798   check_definition(&sys_process_exited);
01799   check_definition(&sys_process_signaled);
01800   check_definition(&sys_process_stopped);
01801   check_definition(&sys_process_continued);
01802 #endif
01803 #ifdef LIFE_NDBM
01804   check_ndbm_definitions();
01805 #endif
01806 }
01807 
01808 #ifdef LIFE_DBM
01809 extern void insert_dbm_builtins();
01810 #endif
01811 #ifdef LIFE_NDBM
01812 extern void insert_ndbm_builtins();
01813 #endif
01814 
01815 void
01816 insert_sys_builtins()
01817 {
01818   ptr_module curmod = current_module;
01819   set_current_module(sys_module);
01820 
01821   sys_bytedata          =update_symbol(sys_module,"bytedata"); /* DENYS: BYTEDATA */
01822   sys_bitvector         =update_symbol(sys_module,"bitvector");
01823   sys_regexp            =update_symbol(sys_module,"regexp");
01824   sys_stream            =update_symbol(sys_module,"stream");
01825   sys_file_stream       =update_symbol(sys_module,"file_stream");
01826 #ifndef OS2_PORT
01827   sys_socket_stream     =update_symbol(sys_module,"socket_stream");
01828   sys_process_no_children=update_symbol(sys_module,"process_no_children");
01829   sys_process_exited    =update_symbol(sys_module,"process_exited");
01830   sys_process_signaled  =update_symbol(sys_module,"process_signaled");
01831   sys_process_stopped   =update_symbol(sys_module,"process_stopped");
01832   sys_process_continued =update_symbol(sys_module,"process_continued");
01833 #endif
01834   /* DENYS: BYTEDATA */
01835   /* purely for illustration
01836   new_built_in(sys_module,"string_to_bytedata",function,c_string_to_bytedata);
01837   new_built_in(sys_module,"bytedata_to_string",function,c_bytedata_to_string);
01838   */
01839   new_built_in(sys_module,"make_bitvector"      ,function ,c_make_bitvector);
01840   new_built_in(sys_module,"bitvector_and"       ,function ,c_bitvector_and);
01841   new_built_in(sys_module,"bitvector_or"        ,function ,c_bitvector_or);
01842   new_built_in(sys_module,"bitvector_xor"       ,function ,c_bitvector_xor);
01843   new_built_in(sys_module,"bitvector_not"       ,function ,c_bitvector_not);
01844   new_built_in(sys_module,"bitvector_count"     ,function ,c_bitvector_count);
01845   new_built_in(sys_module,"bitvector_get"       ,function ,c_bitvector_get);
01846   new_built_in(sys_module,"bitvector_set"       ,function ,c_bitvector_set);
01847   new_built_in(sys_module,"bitvector_clear"     ,function ,c_bitvector_clear);
01848 #ifndef OS2_PORT
01849   new_built_in(sys_module,"regexp_compile"      ,function ,c_regexp_compile);
01850   new_built_in(sys_module,"regexp_execute"      ,function ,c_regexp_execute);
01851 #endif
01852   new_built_in(sys_module,"int2stream"          ,function ,c_int2stream);
01853   new_built_in(sys_module,"fopen"               ,function ,c_fopen);
01854   new_built_in(sys_module,"fclose"              ,function ,c_fclose);
01855   new_built_in(sys_module,"get_buffer"          ,function ,c_get_buffer);
01856   new_built_in(sys_module,"get_record"          ,function ,c_get_record);
01857   new_built_in(sys_module,"get_code"            ,function ,c_get_code);
01858   new_built_in(sys_module,"ftell"               ,function ,c_ftell);
01859   new_built_in(sys_module,"fseek"               ,predicate,c_fseek);
01860 #ifndef OS2_PORT
01861   new_built_in(sys_module,"socket"              ,function ,c_socket);
01862   new_built_in(sys_module,"bind"                ,predicate,c_bind);
01863   new_built_in(sys_module,"connect"             ,predicate,c_connect);
01864 #endif
01865   new_built_in(sys_module,"fwrite"              ,predicate,c_fwrite);
01866   new_built_in(sys_module,"fflush"              ,predicate,c_fflush);
01867 #ifndef OS2_PORT
01868   new_built_in(sys_module,"listen"              ,predicate,c_listen);
01869   new_built_in(sys_module,"accept"              ,function ,c_accept);
01870 #endif
01871   new_built_in(sys_module,"errno"               ,function ,c_errno);
01872 #ifndef OS2_PORT
01873   new_built_in(sys_module,"errmsg"              ,function ,c_errmsg);
01874 #endif
01875   new_built_in(sys_module,"import_symbol"       ,predicate,c_import_symbol);
01876 #ifndef OS2_PORT
01877   new_built_in(sys_module,"fork"                ,function ,c_fork);
01878   new_built_in(sys_module,"wait"                ,function ,c_wait);
01879   new_built_in(sys_module,"waitpid"             ,function ,c_waitpid);
01880   new_built_in(sys_module,"kill"                ,predicate,c_kill);
01881   new_built_in(sys_module,"cuserid"             ,function ,c_cuserid);
01882   new_built_in(sys_module,"gethostname"         ,function ,c_gethostname);
01883 #endif
01884 
01885   new_built_in(sys_module,"lazy_project"        ,function ,c_lazy_project);
01886   new_built_in(sys_module,"wait_on_feature"     ,predicate,c_wait_on_feature);
01887   new_built_in(sys_module,"my_wait_on_feature"  ,function ,c_my_wait_on_feature);
01888   new_built_in(sys_module,"apply1"              ,function ,c_apply1);
01889 #ifndef OS2_PORT
01890   new_built_in(sys_module,"getpid"              ,function ,c_getpid);
01891 #endif
01892   new_built_in(sys_module,"stream2sys_stream"   ,function ,c_stream2sys_stream);
01893   new_built_in(sys_module,"sys_stream2stream"   ,function ,c_sys_stream2stream);
01894 #ifdef LIFE_DBM
01895   insert_dbm_builtins();
01896 #endif
01897 #ifdef LIFE_NDBM
01898   insert_ndbm_builtins();
01899 #endif
01900   set_current_module(bi_module);
01901   new_built_in(bi_module ,"call_once"           ,function ,c_call_once);
01902   set_current_module(curmod);
01903 }

Generated on Sat Jan 26 08:48:07 2008 for WildLife by  doxygen 1.5.4