/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
*/
/*
 * AtFStk -- Attribute Filesystem Toolkit Library
 *
 * citeattr.c -- AtFS toolkit library
 *
 * Authors: Axel Mahler (Axel.Mahler@cs.tu-berlin.de)
 *          Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *
 * $Header: citeattr.c[7.0] Fri Jul 30 16:08:03 1993 andy@cs.tu-berlin.de frozen $
 */

#include <limits.h>
#include "atfs.h"
#include "bind.h"
#include "atfstk.h"

EXPORT int atExpand = TRUE;
LOCAL  int reallyExpand = TRUE;

/*=======================
 * atExpandAttrs
 *=======================*/

EXPORT int atExpandAttrs (aso, buf, bufSize, dest, destSize, mode) 
     Af_key *aso;
     char   *buf;
     size_t bufSize;
     void   *dest;
     size_t destSize;
     int    mode;
{
  /*
   *  atExpandAttrs scans the char buffer 'buf' to the extent of bufSize
   *  for strings of the form '$__attribute_name'. If such a string
   *  is found, the buffer contents up to the character preceding the
   *  first '$' will be sent to the destination output 'dest'.
   *  If an attribute with name 'atttribute_name' is set for the current
   *  attribute file, the citation-string will be substituted by the value
   *  of that attribute. Output of 'buf' contents resumes with the first 
   *  character after the blank delimiting the 'attribute_name'.
   */
  int i=0, citeNamePos=0, stringEnd, appendDollar = FALSE;
  size_t outSize = 0;
  char attrName[AF_UDANAMLEN];
  char *startPtr, *curPtr, *attrValue;

  if (mode == AT_EXPAND_FILE)
    destSize = INT_MAX;

  startPtr = curPtr = buf;

  while (i < (int)(bufSize-3)) {
    if (buf[i++] != '$')
      continue;

    if ((buf[i] != '_') || (buf[i+1] != '_'))
      continue;

    i += 2;
    if (strchr (" \n\t$", buf[i]))
      continue;

    curPtr = &(buf[i-3]);
    citeNamePos = 0;
    while ((i < bufSize) && (!strchr (" \n\t$", buf[i])))
      attrName[citeNamePos++] = buf[i++];
    /* buf[i] is the first char after attribute name */
    if ((i < bufSize) && (buf[i] == '$')) {
      appendDollar = TRUE;
      i++;
    }
    else
      appendDollar = FALSE;
    attrName[citeNamePos] = '\0';
    /* write out everything up to beginning of cite_mark */
    if ((outSize += curPtr - startPtr) >= destSize)
      return (-1);
    if (mode == AT_EXPAND_FILE)
      fwrite (startPtr, sizeof (char), curPtr - startPtr, (FILE *)dest);
    else {
      stringEnd = strlen ((char *)dest);
      strncat ((char *)dest, startPtr, curPtr - startPtr);
      if (curPtr - startPtr) ((char *)dest)[stringEnd+(curPtr-startPtr)] = '\0';
    }
    startPtr = curPtr = &(buf[i]);
    /* check for (atExpand && reallyExpand) and do attribute expansion only
     * if both are true. This causes *both* expansion switches (xpon and xpoff)
     * *not* to be expanded.
     */
    if (((attrValue = atRetAttr (aso, attrName)) == NULL) || !(atExpand && reallyExpand)) {
      outSize += strlen(attrName)+3;
      if (appendDollar) outSize++;
      if (outSize >= destSize)
	return (-1);
      if (mode == AT_EXPAND_FILE) {
	fputs ("$__", (FILE *)dest);
	fputs (attrName, (FILE *)dest);
	if (appendDollar) fputs ("$", (FILE *)dest);
      }
      else {
	strcat ((char *)dest, "$__");
	strcat ((char *)dest, attrName);
	if (appendDollar) strcat ((char *)dest, "$");
      }
    }
    else {
      if ((outSize += strlen(attrValue)) >= destSize)
	return (-1);
      if (mode == AT_EXPAND_FILE)
	fputs (attrValue, (FILE *)dest);
      else
	strcat ((char *)dest, attrValue);
    }
    reallyExpand = atExpand;
  }
  /* write remaining chars */
  if ((outSize += &buf[bufSize] - startPtr) >= destSize)
    return (-1);
  if (mode == AT_EXPAND_FILE)
    fwrite (startPtr, sizeof (char), &buf[bufSize] - startPtr, (FILE *)dest);
  else {
    stringEnd = strlen ((char *)dest);
    strncat ((char *)dest, startPtr, &buf[bufSize] - startPtr);
    if (&buf[bufSize] - startPtr) ((char *)dest)[stringEnd + (&buf[bufSize] - startPtr)] = '\0';
  }
  return (outSize);
}


