home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / plbin.zip / pl / src / pl-atom.c < prev    next >
C/C++ Source or Header  |  1993-02-23  |  7KB  |  355 lines

  1. /*  pl-atom.c,v 1.3 1993/02/23 13:16:25 jan Exp
  2.  
  3.     Copyright (c) 1990 Jan Wielemaker. All rights reserved.
  4.     See ../LICENCE to find out about your rights.
  5.     jan@swi.psy.uva.nl
  6.  
  7.     Purpose: atom management
  8. */
  9.  
  10. #include "pl-incl.h"
  11. #include "pl-ctype.h"
  12.  
  13. static Atom atomTable[ATOMHASHSIZE];
  14.  
  15. Atom
  16. lookupAtom(s)
  17. char *s;
  18. { int v = stringHashValue(s, ATOMHASHSIZE);
  19.   register Atom a;
  20.  
  21.   for(a = atomTable[v]; a && !isRef((word)a); a = a->next)
  22.   { if (streq(s, a->name) )
  23.       return a;
  24.   }
  25.   a = (Atom)allocHeap(sizeof(struct atom));
  26.   a->next = atomTable[v];
  27.   a->type = ATOM_TYPE;
  28.   a->name = store_string(s);
  29.   atomTable[v] = a;
  30.   statistics.atoms++;
  31.  
  32.   return a;
  33. }
  34.  
  35.  
  36. word
  37. pl_atom_hashstat(i, n)
  38. Word i, n;
  39. { int m;
  40.   register Atom a;
  41.  
  42.   if ( !isInteger(*i) || valNum(*i) < 0 || valNum(*i) >= ATOMHASHSIZE )
  43.     fail;
  44.   for(m = 0, a = atomTable[valNum(*i)]; a && !isRef((word)a); a = a->next)
  45.     m++;
  46.  
  47.   return unifyAtomic(n, consNum(m));
  48. }
  49.  
  50.  
  51. struct atom atoms[] = {
  52. #include "pl-atom.ic"
  53. { (Atom)NULL,    ATOM_TYPE,    (char *)NULL }
  54. };
  55.  
  56. /* Note that the char * of the atoms is copied to the data segment.  This
  57.    is done because some functions temporary change the char string associated
  58.    with an atom (pl_concat_atom()) and GCC puts char constants in the text
  59.    segment.
  60. */
  61.  
  62. void
  63. initAtoms()
  64. { register int n;
  65.  
  66.   { register Atom *a;
  67.     for(n=0, a=atomTable; n < (ATOMHASHSIZE-1); n++, a++)
  68.       *a = (Atom) makeRef(a+1);
  69.   }
  70.  
  71.   { register Atom a;
  72.     register int v;
  73.  
  74.     for( a = &atoms[0]; a->name; a++)
  75.     { a->name = store_string(a->name);
  76.       v = stringHashValue(a->name, ATOMHASHSIZE);
  77.       a->next = atomTable[v];
  78.       atomTable[v] = a;
  79.       statistics.atoms++;
  80.     }
  81.   }    
  82. }
  83.  
  84.  
  85. word
  86. pl_current_atom(a, h)
  87. Word a;
  88. word h;
  89. { Atom atom;
  90.  
  91.   switch( ForeignControl(h) )
  92.   { case FRG_FIRST_CALL:
  93.       if ( isAtom(*a) ) succeed;
  94.       if ( !isVar(*a) ) fail;
  95.  
  96.       atom = atomTable[0];
  97.       break;
  98.     case FRG_REDO:
  99.       atom = (Atom) ForeignContextAddress(h);
  100.       break;
  101.     case FRG_CUTTED:
  102.     default:
  103.       succeed;
  104.   }
  105.  
  106.   for(; atom; atom = atom->next)
  107.   { while(isRef((word)atom) )
  108.     { atom = *((Atom *)unRef(atom));
  109.       if (atom == (Atom) NULL)
  110.     fail;
  111.     }
  112.     if (unifyAtomic(a, atom) == FALSE)
  113.       continue;
  114.  
  115.     return_next_table(Atom, atom);
  116.   }
  117.  
  118.   fail;
  119. }
  120.  
  121. #ifdef O_EXTEND_ATOMS
  122.  
  123. #define ALT_MAX 256        /* maximum number of alternatives */
  124. #define ALT_SIZ 80        /* maximum length of one alternative */
  125.  
  126. #define IS_MODULE    0x1
  127. #define IS_FUNCTOR    0x2
  128. #define IS_PROCEDURE    0x4
  129.  
  130. #define stringMatch(m)    (stringAtom((m)->name))
  131.  
  132. typedef struct match *Match;
  133.  
  134. struct match
  135. { Atom    name;
  136.   short length;
  137.   short    flags;
  138. };
  139.  
  140. forwards bool     allAlpha P((char *));
  141. forwards short    type_flags P((Atom));
  142. forwards void    listAtoms P((int, Match));
  143.  
  144. char *
  145. extendAtom(prefix, unique)
  146. char *prefix;
  147. bool *unique;
  148. { Atom a = atomTable[0];
  149.   bool first = TRUE;
  150.   static char common[LINESIZ];
  151.   int lp = (int) strlen(prefix);
  152.  
  153.   *unique = TRUE;
  154.  
  155.   for(; a; a = a->next)
  156.   { while( isRef((word)a) )
  157.     { a = *((Atom *)unRef(a));
  158.       if ( a == (Atom)NULL)
  159.     goto out;
  160.     }
  161.     if ( strprefix(stringAtom(a), prefix) )
  162.     { if ( strlen(stringAtom(a)) >= LINESIZ )
  163.     continue;
  164.       if ( first == TRUE )
  165.       { strcpy(common, stringAtom(a)+lp);
  166.     first = FALSE;
  167.       } else
  168.       { char *s = common;
  169.     char *q = stringAtom(a)+lp;
  170.     while( *s && *s == *q )
  171.       s++, q++;
  172.     *s = EOS;
  173.     *unique = FALSE;
  174.       }
  175.     }
  176.   }
  177.  
  178. out:
  179.   return first == TRUE ? (char *)NULL : common;
  180. }
  181.  
  182.  
  183. word
  184. pl_complete_atom(prefix, common, unique)
  185. Word prefix, common, unique;
  186. { char *p, *s;
  187.   bool u;
  188.   char buf[LINESIZ];
  189.     
  190.   if ( (p = toString(*prefix)) == NULL )
  191.     return warning("$complete_atom/3: instanstiation fault");
  192.   strcpy(buf, p);
  193.   if ( (s = extendAtom(p, &u)) != NULL )
  194.   { strcat(buf, s);
  195.     TRY(unifyStringWithList(buf, common));
  196.     return unifyAtomic(unique, u ? ATOM_unique : ATOM_not_unique);
  197.   }
  198.  
  199.   fail;
  200. }
  201.  
  202.  
  203. static int
  204. compareMatch(m1, m2)
  205. Match m1, m2;
  206. { return strcmp(stringMatch(m1), stringMatch(m2));
  207. }
  208.  
  209.  
  210. static short
  211. type_flags(name)
  212. Atom name;
  213. { short flags;
  214.  
  215.   flags = 0;
  216.   if ( isCurrentModule(name) != (Module) NULL )
  217.     flags |= IS_MODULE;
  218.   if ( atomIsFunctor(name) >= 0 )
  219.   { flags |= IS_FUNCTOR;
  220.     if ( atomIsProcedure(name) )
  221.       flags |= IS_PROCEDURE;
  222.   }
  223.  
  224.   return flags;
  225. }
  226.  
  227.  
  228. static void
  229. listAtoms(nm, vm)
  230. int nm;
  231. Match vm;
  232. { int maxlength = 8;
  233.   int columns, colwidth;
  234.   int rows, spaces;
  235.   int n, m, r, c;
  236.  
  237.   for(n = 0; n < nm; n++ )
  238.     if ( vm[n].length+3 > maxlength )
  239.       maxlength = vm[n].length+3;
  240.  
  241.   columns = 78 / maxlength;
  242.   if ( columns == 0 )
  243.     columns = 1;
  244.   colwidth = 78 / columns;
  245.   rows = (nm + columns - 1) / columns;
  246.  
  247.   for(r = 0; r < rows; r++)
  248.   { for(c = 0; c < columns; c++)
  249.     { n = c * rows + r;
  250.       if ( n >= nm )
  251.         continue;
  252.       Putf("%s", stringMatch(&vm[n]));
  253.       spaces = colwidth - vm[n].length;
  254.       if ( vm[n].flags & IS_MODULE )
  255.       { Put(':');
  256.     spaces--;
  257.       }
  258.       if ( vm[n].flags & IS_PROCEDURE )
  259.       { Put('*');
  260.     spaces--;
  261.       } else
  262.       { if ( vm[n].flags & IS_FUNCTOR )
  263.     { Put('/');
  264.       spaces--;
  265.     }
  266.       }
  267.       for( m=0; m < spaces; m++ )
  268.         Put(' ');
  269.     }
  270.     Put('\n');
  271.   }
  272. }
  273.  
  274. static bool
  275. allAlpha(s)
  276. register char *s;
  277. { for( ; *s; s++)
  278.    if ( !isAlpha(*s) )
  279.      fail;
  280.  
  281.   succeed;
  282. }
  283.  
  284. bool
  285. extend_alternatives(prefix, altv, altn)
  286. char *prefix;
  287. struct match *altv;
  288. int *altn;
  289. { Atom a = atomTable[0];
  290.   char *as;
  291.   int l;
  292.  
  293.   *altn = 0;
  294.   for(; a; a=a->next)
  295.   { while( a && isRef((word)a) )
  296.       a = *((Atom *)unRef(a));
  297.     if ( a == (Atom) NULL )
  298.       break;
  299.     
  300.     as = stringAtom(a);
  301.     if ( strprefix(as, prefix) &&
  302.      allAlpha(as) &&
  303.      (l = (int)strlen(as)) < ALT_SIZ )
  304.     { Match m = &altv[(*altn)++];
  305.       m->name = a;
  306.       m->length = l;
  307.       m->flags = type_flags(m->name);
  308.       if ( *altn > ALT_MAX )
  309.     break;
  310.     }
  311.   }
  312.   
  313.   qsort(altv, *altn, sizeof(struct match), compareMatch);
  314.  
  315.   succeed;
  316. }
  317.  
  318. bool
  319. extendAlternatives(prefix)
  320. char *prefix;
  321. { struct match altv[ALT_MAX];
  322.   int altn;
  323.  
  324.   extend_alternatives(prefix, altv, &altn);
  325.   listAtoms(altn, altv);
  326.  
  327.   succeed;
  328. }
  329.  
  330. word
  331. pl_atom_completions(prefix, alts)
  332. Word prefix, alts;
  333. { char *p;
  334.   char buf[LINESIZ];
  335.   struct match altv[ALT_MAX];
  336.   int altn;
  337.   int i;
  338.  
  339.   if ( (p = toString(*prefix)) == NULL )
  340.     return warning("$atom_completions/2: instanstiation fault");
  341.   strcpy(buf, p);
  342.  
  343.   extend_alternatives(buf, altv, &altn);
  344.   
  345.   for(i=0; i<altn; i++)
  346.   { TRY(unifyFunctor(alts, FUNCTOR_dot2));
  347.     TRY(unifyAtomic(argTermP(*alts, 0), altv[i].name));
  348.     alts = argTermP(*alts, 1);
  349.     deRef(alts);
  350.   }
  351.   return unifyAtomic(alts, ATOM_nil);
  352.  
  353. #endif /* O_EXTEND_ATOMS */
  354.