Jade Maintenance (Was: RE: Sorted table of contents?)

Subject: Jade Maintenance (Was: RE: Sorted table of contents?)
From: Avi Kivity <Avi@xxxxxxxxxxxxx>
Date: Wed, 28 Apr 1999 15:10:32 +0200
On Wednesday, April 28, 1999 12:08 PM, Peter Nilsson
[SMTP:pnidv96@xxxxxxxxxxxxxx] wrote:
> On Mon, 26 Apr 1999, Avi Kivity wrote:
> 
> > The (string|char)(-ci)?(([<>]=?)|=)\? function family is not
> > implemented by
> > Jade (except for string=?), but I have a patch which does that
> > which I can
> > post.
> > 
> Have you submitted it to James Clark for future inclusion? Does your

No, since it hasn't been designed or tested for total compliance with the
standard (I'm not even sure what that entails - maybe it works as-is).

> patch
> support different languages?

It just calls the wcs* functions supplied by the run-time library, so there
is a good chance it violates the letter of the standard (though it agrees in
spirit).

> 
> In my opinion, we should try to have the whole expresion language
> implemented, because it's not hard and will be useful someday. I

Absolutely. And doing it bit by bit, on a need-this-feature-today, is the
way to go for the simple stuff. There just needs to be an active maintainer.
My company can probably host a CVS server for this, and perhaps help a
little in Jade maintenance.

> posted a
> patch with some trivial primitives to James some month ago, but
> received
> no answer. Anyone who knows if he is actively maintaining jade? (I
> know he
> is a busy man, and I am not complaining - just wondering...)
> 

I sent him a defect report on the dsssl standard and received no reply as
well. I hope it's just a very long vacation.

Here's the patch, in case anyone's interested:

 <<RE: jade patches>> 
Remember the deadthread 'Future of DSSSL'? It's bound to the future of Jade.
Since I don't see anyone implementing a major feature (transformation,
regexp, page-seq), maybe we can try the incremental approach.

Hopefully,
- Avi
--- Begin Message ---
Subject: RE: jade patches
From: Avi Kivity <Avi@xxxxxxxxxxxxx>
Date: Tue, 27 Apr 1999 18:45:38 +0200
On Tuesday, April 27, 1999 9:26 AM, De-Wille_Eberhard
[SMTP:eberhard.de-wille@xxxxxxxxxxxxx] wrote:
> Dear Avi,
> 
> thank you your help. However the patches for jade regarding 
> string|char)(-ci)?(([<>]=?)|=)\? function family
> were not attached. Please resend.
> 
> Thanks
> Eberhard

Patches are against our local version of Jade, so they may not apply
smoothly. It should be a simple matter to do a manual merge, though. The
patch is not very pretty, but works fine.

Index: Jade/style/primitive.cpp
===================================================================
RCS file: /usr/local/cvs/test/modules/SGML/Jade/style/primitive.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- primitive.cpp	1998/11/08 06:18:22	1.1
+++ primitive.cpp	1999/02/25 18:16:29	1.2
@@ -17,6 +17,8 @@
 #include <limits.h>
 #include <stdio.h>
 #include <time.h>
+#include <ctype.h>
+#include <string.h>
 
 #ifdef DSSSL_NAMESPACE
 namespace DSSSL_NAMESPACE {
@@ -477,12 +479,147 @@
     return interp.makeFalse();
 }
 
+DEFPRIMITIVE(IsCharBigger, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (c1 > c2)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharSmaller, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (c1 < c2)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharBiggerEqual, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (c1 >= c2)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharSmallerEqual, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (c1 <= c2)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharEqual_ci, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (toupper(c1) == toupper(c2))
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharBigger_ci, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (toupper(c1) > toupper(c2))
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharSmaller_ci, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (toupper(c1) < toupper(c2))
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharBiggerEqual_ci, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (toupper(c1) >= toupper(c2))
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsCharSmallerEqual_ci, argc, argv, context, interp, loc)
+{
+  Char c1, c2;
+  if (!argv[0]->charValue(c1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 0, argv[0]);
+  if (!argv[1]->charValue(c2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAChar, 1, argv[1]);
+  if (toupper(c1) <= toupper(c2))
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
 DEFPRIMITIVE(String, argc, argv, context, interp, loc)
 {
   StringObj *obj = new (interp) StringObj;
   for (int i = 0; i < argc; i++) {
     Char c;
-    if (!argv[i]->charValue(c)) 
+    if (!argv[i]->charValue(c))
       return argError(interp, loc,
 		      InterpreterMessages::notAChar, i, argv[i]);
     *obj += c;
@@ -541,6 +678,225 @@
 		    InterpreterMessages::notAString, 1, argv[1]);
   if (n1 == n2
       && (n1 == 0 || memcmp(s1, s2, n1*sizeof(Char)) == 0))
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringBigger, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int count=min(n1,n2);
+  int comp=wcsncmp(s1,s2,count);
+  if (comp==0) comp=n1-n2;
+  if (comp>0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringSmaller, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int count=min(n1,n2);
+  int comp=wcsncmp(s1,s2,count);
+  if (comp==0) comp=n1-n2;
+  if (comp<0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringBiggerEqual, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int count=min(n1,n2);
+  int comp=wcsncmp(s1,s2,count);
+  if (comp==0) comp=n1-n2;
+  if (comp>=0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringSmallerEqual, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int count=min(n1,n2);
+  int comp=wcsncmp(s1,s2,count);
+  if (comp==0) comp=n1-n2;
+  if (comp<=0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringEqual_ci, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int comp;
+  //the stupid following if statements are because the
+  //  wcsncmpi function cannot deal with empty strings
+  if(0==n1 && 0==n2) comp=0;
+  else if(0==n2) comp=1;
+  else if(0==n1) comp=-1;
+  else
+  {
+  		int count=min(n1,n2);
+  		comp=wcsncmpi(s1,s2,count);
+  }
+  if (comp==0) comp=n1-n2;
+  if (comp==0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringBigger_ci, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int comp;
+  //the stupid following if statements are because the
+  //  wcsncmpi function cannot deal with empty strings
+  if(0==n1 && 0==n2) comp=0;
+  else if(0==n2) comp=1;
+  else if(0==n1) comp=-1;
+  else
+  {
+  		int count=min(n1,n2);
+  		comp=wcsncmpi(s1,s2,count);
+  }
+  if (0==comp) comp=n1-n2;
+  if (comp>0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringSmaller_ci, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int comp;
+  //the stupid following if statements are because the
+  //  wcsncmpi function cannot deal with empty strings
+  if(0==n1 && 0==n2) comp=0;
+  else if(0==n2) comp=1;
+  else if(0==n1) comp=-1;
+  else
+  {
+  		int count=min(n1,n2);
+  		comp=wcsncmpi(s1,s2,count);
+  }
+  if (0==comp) comp=n1-n2;
+  if (comp==0) comp=n1-n2;
+  if (comp<0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringBiggerEqual_ci, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int comp;
+  //the stupid following if statements are because the
+  //  wcsncmpi function cannot deal with empty strings
+  if(0==n1 && 0==n2) comp=0;
+  else if(0==n2) comp=1;
+  else if(0==n1) comp=-1;
+  else
+  {
+  		int count=min(n1,n2);
+  		comp=wcsncmpi(s1,s2,count);
+  }
+  if (0==comp) comp=n1-n2;
+  if (comp==0) comp=n1-n2;
+  if (comp>=0)
+    return interp.makeTrue();
+  else
+    return interp.makeFalse();
+}
+
+DEFPRIMITIVE(IsStringSmallerEqual_ci, argc, argv, context, interp, loc)
+{
+  const Char *s1, *s2;
+  size_t n1, n2;
+  if (!argv[0]->stringData(s1, n1))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 0, argv[0]);
+  if (!argv[1]->stringData(s2, n2))
+    return argError(interp, loc,
+		    InterpreterMessages::notAString, 1, argv[1]);
+  int comp;
+  //the stupid following if statements are because the
+  //  wcsncmpi function cannot deal with empty strings
+  if(0==n1 && 0==n2) comp=0;
+  else if(0==n2) comp=1;
+  else if(0==n1) comp=-1;
+  else
+  {
+  		int count=min(n1,n2);
+  		comp=wcsncmpi(s1,s2,count);
+  }
+  if (0==comp) comp=n1-n2;
+  if (comp==0) comp=n1-n2;
+  if (comp<=0)
     return interp.makeTrue();
   else
     return interp.makeFalse();
Index: Jade/style/primitive.h
===================================================================
RCS file: /usr/local/cvs/test/modules/SGML/Jade/style/primitive.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- primitive.h	1998/11/08 06:18:39	1.1
+++ primitive.h	1999/02/25 18:16:29	1.2
@@ -27,11 +27,29 @@
 PRIMITIVE(IsQuantity, "quantity?", 1, 0, 0)
 PRIMITIVE(IsChar, "char?", 1, 0, 0)
 PRIMITIVE(IsCharEqual, "char=?", 2, 0, 0)
+PRIMITIVE(IsCharBigger, "char>?", 2, 0, 0)
+PRIMITIVE(IsCharSmaller, "char<?", 2, 0, 0)
+PRIMITIVE(IsCharBiggerEqual, "char>=?", 2, 0, 0)
+PRIMITIVE(IsCharSmallerEqual, "char<=?", 2, 0, 0)
+PRIMITIVE(IsCharEqual_ci, "char-ci=?", 2, 0, 0)
+PRIMITIVE(IsCharBigger_ci, "char-ci>?", 2, 0, 0)
+PRIMITIVE(IsCharSmaller_ci, "char-ci<?", 2, 0, 0)
+PRIMITIVE(IsCharBiggerEqual_ci, "char-ci>=?", 2, 0, 0)
+PRIMITIVE(IsCharSmallerEqual_ci, "char-ci<=?", 2, 0, 0)
 PRIMITIVE(String, "string", 0, 0, 1)
 PRIMITIVE(SymbolToString, "symbol->string", 1, 0, 0)
 PRIMITIVE(StringToSymbol, "string->symbol", 1, 0, 0)
 PRIMITIVE(StringLength, "string-length", 1, 0, 0)
 PRIMITIVE(IsStringEqual, "string=?", 2, 0, 0)
+PRIMITIVE(IsStringBigger, "string>?", 2, 0, 0)
+PRIMITIVE(IsStringSmaller, "string<?", 2, 0, 0)
+PRIMITIVE(IsStringBiggerEqual, "string>=?", 2, 0, 0)
+PRIMITIVE(IsStringSmallerEqual, "string<=?", 2, 0, 0)
+PRIMITIVE(IsStringEqual_ci, "string-ci=?", 2, 0, 0)
+PRIMITIVE(IsStringBigger_ci, "string-ci>?", 2, 0, 0)
+PRIMITIVE(IsStringSmaller_ci, "string-ci<?", 2, 0, 0)
+PRIMITIVE(IsStringBiggerEqual_ci, "string-ci>=?", 2, 0, 0)
+PRIMITIVE(IsStringSmallerEqual_ci, "string-ci<=?", 2, 0, 0)
 PRIMITIVE(StringAppend, "string-append", 0, 0, 1)
 PRIMITIVE(StringRef, "string-ref", 2, 0, 0)
 PRIMITIVE(Substring, "substring", 3, 0, 0)



Enjoy!

--- End Message ---
Current Thread