:i	static char str_cmpssm_sccs_id[] = "%W% %G%";
#include "V_M_UC.h"
#include "str.h"
#include "mem.h"

/*
* Compare two string structures.  The return value is <0, 0, or >0  as
* the  first  string is lexically less than, equal to, or greater than
* the second.
*
* Note that the comparison is done with unsigned chars (bytes), making
* this  really  a  "Blk"  routine.   Experience has shown that this is
* always the right  way  to  do  the  comparison.   But  I'm  open  to
* explanations as to why this may be wrong. Perhaps we need a separate
* blk_cmpssm() routine.
*
* This routine could be made much more compact and faster, except  for
* all the debug junk. But in my experience, this debug stuff is sorely
* needed whenever you go to a new machine (or a new release of  the  C
* compiler or runtime library ;-), so I advise leaving it in.
*/
int str_cmpssm(s1,s2,msg)
	Str  *s1;	/* Input string */
	Str  *s2;	/* Input string */
	char *msg;	/* For error messages */
{	int   r=0;	/* Return value */
	int   l1, l2;
	int   c1, c2;
	byte *p1, *p2;
:f	Fenter("str_cmpssm");
:2	if (!msg) msg = unknown;
:5	V7M "Compare \"%s\" and \"%s\"",DspSP(s1),DspSP(s2) D;
	if (IsNullStr(s1)) {
		if (IsNullStr(s2)) {
:5			V7M "Both s1 and s2 null, return 0 [%s]",msg D;
			Done;	/* Both null strings */
		}
:5		V7M "Null s1, nonnull s2, return - [%s]",msg D;
		r = -1;
		Done;		/* Null s1, s2 not null */
	} else if (IsNullStr(s2)) {
:5		V7M "Nonnull s1, null s2, return + [%s]",msg D;
		r = 1;
		Done;	/* Null s2, s1 not null */
	}
/*
* Both strings are now known to be non-null.   We  run  thru  them  in
* parallel, until we find a pair of bytes that differ, or until we hit
* the end of the shorter string.
*/
	p1 = (BP)s1->v; l1 = s1->l;
	p2 = (BP)s2->v; l2 = s2->l;
	while (l1 > 0 && l2 > 0) {
		c1 = *p1++;
		c2 = *p2++;
		if (c1 < c2) {
:5			V7M "%02X='%c' < %02X='%c', return - [%s]",
:5				B8(c1),Dsp(c1),B8(c2),Dsp(c2),msg D;
			r = -1;
			Done;	/* Chars differ, s1 char less */
		} else if (c1 > c2) {
:5			V7M "%02X='%c' > %02X='%c', return + [%s]",
:5				B8(c1),Dsp(c1),B8(c2),Dsp(c2),msg D;
			r = 1;
			Done;	/* Chars differ, s2 char less */
		}
		l1--; l2--;
	}
/*
* We ran off the end of one or both of the strings. The shorter string
* is considered the earlier.
*/
	if (l1 == 0 && l2 > 0) {
:5		V7M "Equal, s1 shorter, return - [%s]",msg D;
		r = -1;
		Done;	/* Equal, s2 longer */
	}
	if (l1 > 0 && l2 == 0) {
:5		V7M "Equal, s2 shorter, return + [%s]",msg D;
		r = 1;
		Done;		/* Equal, s1 longer */
	}
	if (l1 == 0 && l2 == 0) {	/* Sanity check */
:5		V7M "Both s1 and s2 equal and same length, return 0 [%s]",msg D;
		Done;	/* Equal, same length */
	}
:7	V1M "### Can't happen: l1=%d l2=%d at end [%s].",l1,l2,msg D;
done:
:f	Fexit;
	return r;
}
