
#include "V_M_UC.h"
#include "str.h"

/*
* Check a string structure for validity. Return the number of errors. The only
* errors counted are the ones that might prevent use of the string. We may add
* diagnostic messages for situations that aren't  strictly  errors,  as  added
* debugging aids.
*/
int str_chksm(src,msg)
	Str *src;	/* The Str data structure to check */
	char*msg;	/* Message describing the string */
{	int  e=0;	/* Number of errors */
	if (!msg) msg = unknown;
/*
* Overflow check: if a string is allocated, we must have l <= m.
*/
	if (src->m) {				/* Is the string allocated? */
		if (src->m < src->l) {	/* The l field must be valid */
			V2M "### Invalid string l=%d > m=%d [%s]",src->l,src->m,msg D;
			++e;
		}
	}
/*
* Null strings must not have positive l or m fields.
*/
	if (!src->v) {	/* Is there a string at all? */
		if (src->l || src->m) {	/* If not, it must not have a length */
			V2M "### Invalid null string v=%X l=%d m=%d [%s]",
				src->v,src->l,src->m,msg D;
			++e;
		}
	}
/*
* If the p field is nonnull, it must be within [v,v+m], and should  be
* within  [v,v+l]  (except while extending the string).  We might make
* this mandatory for non-null strings sometime, by changing the  first
* test to the v field.
*/
	if (src->p) {		/* Is there a p field? */
		if (U(src->p) < U(src->v)) {
			V2M "### Invalid string p=%X < v=%X [%s]",
				src->p,src->v,src->l,src->v+src->l,msg D;
			src->p = src->v;
			++e;
		}
		if (src->m && (U(src->p) > (U(src->v) + src->m))) {
			V2M "### Invalid string p=%X > v=%X + m=%d end=%X [%s]",
				src->p,src->v,src->m,src->v+src->m,msg D;
			src->p = src->v;
			++e;
		}
		if (U(src->p) > (U(src->v) + src->l)) {
			V4M "??? Suspect string p=%X > v=%X + l=%d end=%X [%s]",
				src->p,src->v,src->l,src->v+src->l,msg D;
			src->p = src->v;
			/* This isn't fatal, so we don't count it */
		}
	}
	return e;
}
