/*
 * Refer to file UPDNODES.H for copyright and version information
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "updnodes.h"
#ifdef	oldcc
#include <memory.h>
#endif	/* oldcc */

#ifndef	oldcc
void parse_line(NODE_ENTRY * maj, char * s)
#else
void parse_line(maj, s)
NODE_ENTRY * maj;
char * s;
#endif	/* oldcc */
{
    char * tag_start;
    char * tag_end;
    char * tagval_end;
    static char tag[TAG_STR_LEN];
    static char tagval[VALUE_STR_LEN];

    do {
	if (!*s)			return;
	tag_start = strchr(s, ':');
	if (!tag_start) {
#ifndef	oldcc
	    fpos_t cur;
#else
	    long cur;
#endif	/* oldcc */

	    error("Line found without tag... Line was:\n>>%s<<\n", s);
	    error("ftell(base) returns %ld\n", ftell(base));
#ifndef	oldcc
	    fgetpos(base, &cur);
	    error("fgetpos(base, &cur) returns %ld\n", cur);
#else
	    cur = ftell(base);
	    error("ftell(base) returns %ld\n", cur);
#endif	/* oldcc */
	    exit(SYSERROR);
	}
	tag_end = strchr(tag_start+1, '.');
	tagval_end = tag_end+1;			/* Prime the pump... */
	while (TRUE) {
	    tagval_end = strchr(tagval_end, ':');
	    if (!tagval_end)		break;
	    if (*(tagval_end-1) == ' ')	{
		tagval_end--;
		break;
	    }
	    tagval_end++;
	}
/*	tagval_end = strstr(tag_end+1, " :");	Replaced by above */
	if (!tagval_end) {
	    tagval_end = s + strlen(s);
	}

	memset(tag, 0, TAG_STR_LEN);
	memset(tagval, 0, VALUE_STR_LEN);

	strncpy(tag, tag_start+1, tag_end - tag_start - 1);
	if (!*(tag_end+1)) {		/* End of line instead of value */
	    tagval[0] = '\0';
	} else {
	    strncpy(tagval, tag_end + 1, tagval_end - tag_end - 1);
	}

	trim(tagval);

	min_merge(maj, tag, tagval);	/* Add the tag to the node */

	s = tagval_end;
    } while (*tagval_end);
}

#ifndef	oldcc
void min_merge(NODE_ENTRY * maj, char * tag, char * value)
#else
void min_merge(maj, tag, value)
NODE_ENTRY * maj;
char * tag;
char * value;
#endif	/* oldcc */
{
    int i;
    TAG_ENTRY * min;

    for (min = maj->tags, i = 0; i < maj->num_tags && strcmp(min->name, tag);
	    i++, min++);

    if (i == maj->num_tags) {
	if (i == TAGS_IN_NODE) {
	    error("Unable to add new tags for %s - all used.\n", maj->name);
	    exit(SYSERROR);
	}
	maj->num_tags++;
	strcpy(min->name, tag);
    }
    min->value[0] = '\0';
    strcpy(min->value, value);
}

#ifndef	oldcc
TAG_ENTRY * min_find(NODE_ENTRY * maj, char * tag)
#else
TAG_ENTRY * min_find(maj, tag)
NODE_ENTRY * maj;
char * tag;
#endif	/* oldcc */
{
    TAG_ENTRY * min;
    int i;

    if (!maj) {
	error("min_find: NULL maj pointer passed.\n");
    }

    for (i = maj->num_tags, min = maj->tags; i && min->name[0]; i--, min++) {
	if (strcmp(min->name, tag))	continue;
	return (min);
    }
    return (NULL);
}

#ifndef	oldcc
void apply_vers_delta(NODE_ENTRY * vers, NODE_ENTRY * upd)
#else
void apply_vers_delta(vers, upd)
NODE_ENTRY * vers;
NODE_ENTRY * upd;
#endif	/* oldcc */
{
    if (!strcmp(upd->action, "DEL")) {
	if (!vers->name[0]) {
	    error("DEL for %s, but %s non-existent.\n", upd->name,
		    upd->name);
	} else {
	    log_line(LOG_UPDATE, "%s deleted.\n", vers->name);
	    memset((char *) vers, 0, sizeof(NODE_ENTRY));
	}
    } else if (!strcmp(upd->action, "ADD")) {
	if (vers->name[0]) {
	    error("ADD for %s without DEL for %s.\n", upd->name, vers->name);
	    error("Doing auto DEL for %s.\n", vers->name);
	}
	memcpy((char *) vers, (char *) upd, sizeof(NODE_ENTRY));
	memset((char *) upd, 0, sizeof(NODE_ENTRY));
	log_line(LOG_UPDATE, "%s added.\n", vers->name);
    } else if (!strcmp(upd->action, "REP")) {
	min_incorporate(vers, upd);
	log_line(LOG_UPDATE, "%s updated.\n", vers->name);
    } else {
	error("Invalid action %s for %s.\n", upd->action, upd->name);
    }
}

#ifndef	oldcc
void apply_links_delta(NODE_ENTRY * links, NODE_ENTRY * upd)
#else
void apply_links_delta(links, upd)
NODE_ENTRY * links;
NODE_ENTRY * upd;
#endif	/* oldcc */
{
    if (!strcmp(upd->action, "DEL")) {
	if (!links->name[0]) {
	    error("DEL for %s, but %s non-existent.\n", upd->name,
		    upd->name);
	} else {
	    log_line(LOG_UPDATE, "%s deleted.\n", links->name);
	    memset((char *) links, 0, sizeof(NODE_ENTRY));
	}
    } else if (!strcmp(upd->action, "ADD")) {
	if (links->name[0]) {
	    error("ADD for %s without DEL for %s.\n", upd->name, links->name);
	    error("Doing auto DEL for %s.\n", links->name);
	}
	memcpy((char *) links, (char *) upd, sizeof(NODE_ENTRY));
	memset((char *) upd, 0, sizeof(NODE_ENTRY));
	log_line(LOG_UPDATE, "%s added.\n", links->name);
    } else if (!strcmp(upd->action, "REP")) {
	min_incorporate(links, upd);
	log_line(LOG_UPDATE, "%s updated.\n", links->name);
    } else {
	error("Invalid action %s for %s.\n", upd->action, upd->name);
    }
}

#ifndef	oldcc
void min_incorporate(NODE_ENTRY * orig, NODE_ENTRY * upd)
#else
void min_incorporate(orig, upd)
NODE_ENTRY * orig;
NODE_ENTRY * upd;
#endif	/* oldcc */
{
    TAG_ENTRY * min;
    int i;

    for (i = upd->num_tags, min = upd->tags; i && min->name[0]; i--, min++) {
	min_merge(orig, min->name, min->value);
    }
}
