
/* ###--------------------------------------------------------------### */
/*									*/
/* file		: pat_drvpat.c						*/
/* date		: Dec  3 1993						*/
/* version	: v104							*/
/* author	: Pirouz BAZARGAN SABET					*/
/* content	: pat format driver from pat structures			*/
/*									*/
/* ###--------------------------------------------------------------### */

#include <stdio.h>
#include <time.h>
#include MUT_H
#include PAT_H

/* ###--------------------------------------------------------------### */
/* function	: dclini						*/
/* description	: scan the initialization list, gather all elements of	*/
/*		  an array of register and print a line for each	*/
/*		  register						*/
/* called func.	: none							*/
/* ###--------------------------------------------------------------### */

static void dclini (fp, ptpat)

FILE         *fp;
struct papat *ptpat;

  {
  struct paini *ptini = ptpat->PAINI;
  char          buffer  [1024];		/* register's value		*/
  char          name    [ 256];		/* current register's root name	*/
  int           indx  ;			/* current register's index	*/
  char          oldname [ 256];		/* previous root name		*/
  char          direction = '?';	/* array's direction		*/
  int           redvar;			/* = 2 if (name + index)	*/
  int           oldred;			/* previous value of redvar	*/
  int           left  ;			/* the left  bound of an array	*/
  int           right ;			/* the right bound of an array	*/
  int           i = 0 ;

	/* ###------------------------------------------------------### */
	/*    split the register's name into a root name and an index.	*/
	/* ###------------------------------------------------------### */

  fprintf (fp,"\n-- modification of registers\n");
  oldred = sscanf (ptini->NAME, "%s %d", oldname, &left);

  strcpy (name, oldname);
  redvar    = oldred;
  right     = left;
  buffer[i] = ptini->VALUE;

  i++;
  ptini = ptini->NEXT;

  while (ptini != NULL)
    {
	/* ###------------------------------------------------------### */
	/*    scan the PAINI list ...					*/
	/* split the register's name into a root name and an index.	*/
	/* ###------------------------------------------------------### */

    redvar = sscanf (ptini->NAME, "%s %d", name, &indx);

    if ( (!strcmp (name, oldname)) && (oldred == 2) && (redvar == 2) &&
         ( (((direction == '?') || (direction == 'U')) && (indx == right+1)) ||
           (((direction == '?') || (direction == 'D')) && (indx == right-1)) ))
      {
	/* ###------------------------------------------------------### */
	/*    If the root name is the same as the previous root name	*/
	/* and indexes are continus (continuing inside an array		*/
	/* register) :							*/
	/*   consider the current index as the right bound of the array	*/
	/*   continue inspecting the next PAINI.			*/
	/* ###------------------------------------------------------### */

      if (direction == '?')
        {
        if (indx == (right + 1))
          direction = 'U';
        else
          direction = 'D';
        }

      right = indx;
      }

    else
      {
	/* ###------------------------------------------------------### */
	/*    Otherwies, a new register has been matched. Print the	*/
	/* initialization statement relative to the previous register:	*/
	/*								*/
	/*    - if the previous register was a scalar (root), produce a	*/
	/*    one bit initialization statement.				*/
	/*								*/
	/*    - if the previous register was an array (root + index),	*/
	/*    compare print a line depending on its direction.		*/
	/* ###------------------------------------------------------### */

      buffer[i] = '\0';
      if (oldred == 1)
        fprintf (fp, "%s <= \'%s\';\n", oldname, buffer);
      else
        {
        switch (direction)
          {
          case 'U' :
            fprintf (fp, "%s (%d to %d) <= B\"%s\";\n", oldname, left,
                                                        right  , buffer);
            break;
          case 'D' :
            fprintf (fp, "%s (%d downto %d) <= B\"%s\";\n", oldname, left,
                                                            right  , buffer);
            break;
          case '?' :
            fprintf (fp, "%s (%d) <= \'%s\';\n", oldname, left, buffer);
            break;
          }
        }

      direction = '?';
      i         = 0;
      left      = indx;
      right     = indx;
      oldred    = redvar;
      strcpy (oldname, name);
      }

    buffer[i] = ptini->VALUE;
    i++;
    ptini = ptini->NEXT;
    }

	/* ###------------------------------------------------------### */
	/*    make the same actions when the end of the list has been	*/
	/* reached							*/
	/* ###------------------------------------------------------### */

  buffer[i] = '\0';
  if (redvar == 1)
    fprintf (fp, "%s <= \'%s\';\n", name, buffer);
  else
    {
    switch (direction)
      {
      case 'U' :
        fprintf (fp, "%s (%d to %d) <= B\"%s\";\n", oldname, left,
                                                    right  , buffer);
        break;
      case 'D' :
        fprintf (fp, "%s (%d downto %d) <= B\"%s\";\n", oldname, left,
                                                        right  , buffer);
        break;
      case '?' :
        fprintf (fp, "%s (%d) <= \'%s\';\n", oldname, left, buffer);
        break;
      }
    }

  }

/* ###--------------------------------------------------------------### */
/* function	: pat_drvpat						*/
/* dexcription	: produce a text file corresponding to a sequence of	*/
/*		  patterns						*/
/* called func.	: dclini, mbkalloc, mbkfree, pat_error			*/
/* ###--------------------------------------------------------------### */

int pat_drvpat (fp, ptseq, labelsiz)

FILE         *fp;		/* result file pointer			*/
struct paseq *ptseq;		/* paseq structure to be drived		*/
unsigned int  labelsiz;		/* length of the longest label		*/

  {
  struct papat *ptpat = NULL;	/* current pattern			*/
  struct paevt *ptevt = NULL;	/* current event			*/
  struct pacom *ptcom = NULL;	/* current comment			*/
  struct pacom *svcom = NULL;	/* last comment of OLDPACOM		*/
  struct pagrp *ptgrp = NULL;	/* current input-output array		*/
  struct paiol *ptiol = NULL;	/* current input-output	element		*/

  int           iol_idx = 0;	/* index in input-output list		*/
  int           stt_nbr = 0;	/* # of statements since last comment	*/
  int           pat_nbr = 0;	/* # of patterns			*/

  int           row    = 1;	/* maximum length of I/O names		*/
  int           column = 5;	/* number of char. in a pattern		*/
  static char  *model;		/* pattern's model : "   :?1 2 34;"	*/
  static char  *buffer;		/* one pattern created from model	*/
  char         *signam;		/* input-output names (vertical)	*/

  int           indx;
  int           left;		/* left  bound of an array declaration	*/
  int           right;		/* right bound of an array declaration	*/
  int           redvar;
  int           oldred;
  char          name[256];
  char          oldname[256];
  int           i,j,compare;
  char          sflag = 'S';	/* processed or unprocessed pattern	*/
  char          seprt;		/* name separator left paren. or comma	*/
  int           length;		/* length of string			*/
  int           tmpc;
  time_t        clock;
  char          format;		/* input-output declaration format	*/
  char         *mode;		/* input-output's mode			*/
  char         *direc;		/* input-output array's direction	*/
  int           ret_val = 1;	/* value to be returned			*/

  static char  *value;
  static char  *blank = ";;;;;;;;;;;;;;;;;\n";
  static char  *line  = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";

  if (ptseq != NULL)
    {
	/* ###------------------------------------------------------### */
	/*    for an empty structure exit with out making any action.	*/
	/* Otherwise print the header message.				*/
	/* ###------------------------------------------------------### */

    if (ptseq->DRVSEQ == 0)
      {
      fprintf (fp, "\n-- description generated by Pat driver v104\n");
      time    (&clock);
      fprintf (fp, "--\t\t\tdate : %s\n", ctime(&clock));

      if (ptseq->NAME != NULL)
        fprintf (fp, "\n--\t\tsequence : %s\n\n", ptseq->NAME);

      fprintf (fp, "-- input / output list :\n");
      }

	/* ###------------------------------------------------------### */
	/*    check the consistency of the sequence of patterns		*/
	/* ###------------------------------------------------------### */

    if (ptseq->ERRFLG != 0)
      {
      pat_error (101, NULL, ' ', 0);
      fprintf   (fp , "cannot drive erroneous sequence of patterns\n");
      }
    else
      {
      if (ptseq->DRVSEQ == 0)
	{

	/* ###------------------------------------------------------### */
	/*    if the declaration par has not been drived ...		*/
	/*    scan the input-output list to :				*/
	/*       - print the input-output declaration 			*/
	/*       - compute the number of characters in a pattern	*/
	/*         (including pattern labels) : column			*/
	/* ###------------------------------------------------------### */

	/* ###------------------------------------------------------### */
	/*    add the length of the longest pattern's label to the	*/
	/* length of the pattern. 					*/
	/* ###------------------------------------------------------### */

        column += labelsiz;

        ptiol = ptseq->PAIOL;
        ptgrp = ptseq->PAGRP;
        ptcom = ptseq->DECCOM;

        while (ptiol != NULL)
          {

	/* ###------------------------------------------------------### */
	/*    for each input-output ...					*/
	/* ###------------------------------------------------------### */

	/* ###------------------------------------------------------### */
	/*    print a comment line if needed				*/
	/* ###------------------------------------------------------### */

          if ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
            fprintf (fp, "\n");

          while ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
            {
            fprintf (fp, "# %s\n", ptcom->TEXT);
            ptcom = ptcom->NEXT;
            stt_nbr = 0;
            }

	/* ###------------------------------------------------------### */
	/*    prepare input-output's format and mode 			*/
	/* ###------------------------------------------------------### */

          format = ptiol->FORMAT;
          switch (ptiol->MODE)
            {
            case 'I':
              mode = "in      "; break;
            case 'O':
            case 'B':
            case 'Z':
              mode = "out     "; break;
            case 'R':
              mode = "register"; break;
            case 'T':
              mode = "inout   "; break;
            case 'S':
            case 'W':
            case 'X':
            case 'U':
              mode = "signal  "; break;
            }

	/* ###------------------------------------------------------### */
	/*    increment the length of the pattern for an output ('?')	*/
	/* ###------------------------------------------------------### */

          if (ptiol->MODE != 'I')
            column++;

          if ((ptgrp != NULL) && (iol_idx == ptgrp->FINDEX))
            {
	/* ###------------------------------------------------------### */
	/*    for an actual or virtual array ...			*/
	/* ###------------------------------------------------------### */

            switch (ptiol->FORMAT)
              {
	/* ###------------------------------------------------------### */
	/*    increment the length of the pattern by the number of	*/
	/* characters needed for the value of the array (including	*/
	/* extra blank characters)					*/
	/* ###------------------------------------------------------### */

              case 'X':
                column += ((ptgrp->LENGTH - 1) / 4) + 1;
                break;
              case 'O':
                column += ((ptgrp->LENGTH - 1) / 3) + 1;
                break;
              case 'B':
                column += ptgrp->LENGTH;
                break;
              }
            column += ptiol->BLANK;

	/* ###------------------------------------------------------### */
	/*    change the maximum length of input-outputs if the	 length	*/
	/* of the current array's name is bigger			*/
	/* ###------------------------------------------------------### */

            length = strlen (ptgrp->NAME);
            if (row < length)
              row = length;

            if (ptgrp->FLAG == 0)
              {
	/* ###------------------------------------------------------### */
	/*    print out the declaration of an actual array		*/
	/* ###------------------------------------------------------### */

              sscanf (ptiol->NAME, "%s %d", name, &left);
              ptiol += ptgrp->LENGTH - 1;
              sscanf (ptiol->NAME, "%s %d", name, &right);

              if (left < right)
                direc = "to";
              else
                direc = "downto";

              fprintf (fp, "%s %s (%d %s %d) %c", mode , name, left, direc,
                                                  right, format);
              }
            else
              {
	/* ###------------------------------------------------------### */
	/*    print out the declaration of a virtual array :		*/
	/*       - mode and name					*/
	/*       - for each subelement, its name and if it is an array,	*/
	/*         its left and right bound and direction		*/
	/* ###------------------------------------------------------### */

              fprintf (fp, "%s %s ", mode, ptgrp->NAME);
              seprt = '(';
              oldred = sscanf (ptiol->NAME, "%s %d", oldname, &left);
              redvar = oldred;
              right  = left;
              strcpy (name, oldname);
              ptiol = ptiol->NEXT;
              for (i=1 ; i<ptgrp->LENGTH; i++)
                {
                redvar = sscanf (ptiol->NAME, "%s %d", name, &indx);
          
                if (!strcmp (name, oldname))
                  right = indx;
                else
                  {
                  if (oldred == 1)
                    fprintf (fp, "%c %s", seprt, oldname);
                  else
                    {
                    if (left < right)
                      direc = "to";
                    else
                      direc = "downto";
                    fprintf (fp, "%c %s (%d %s %d)", seprt, oldname, left,
                                                     direc, right);
                    }
                  left   = indx;
                  oldred = redvar;
                  strcpy (oldname, name);
                  seprt = ',';
                  }
                ptiol++;
                }
          
              ptiol--;
              if (redvar == 1)
                fprintf (fp, "%c %s ) %c", seprt, name, format);
              else
                {
                if (left < right)
                  direc = "to";
                else
                  direc = "downto";
                  fprintf (fp, "%c %s (%d %s %d) ) %c", seprt, name , left,
                                                        direc, right, format);
                }
              }
            iol_idx += ptgrp->LENGTH;
            ptgrp    = ptgrp->NEXT;
            }
          else
            {

	/* ###------------------------------------------------------### */
	/*    for a scalar input-output :				*/
	/*       - print the declaration 				*/
	/*       - change the maximum length of input-outputs' name	*/
	/*       - increment the length of the pattern			*/
	/* ###------------------------------------------------------### */

            redvar = sscanf (ptiol->NAME, "%s %d", name, &indx);
            if (redvar == 1)
              fprintf (fp, "%s %s %c", mode, name, format);
            else
              fprintf (fp, "%s %s (%d) %c", mode, name, indx, format);

            length = strlen (ptiol->NAME);
            if (row < length)
              row = length;

            column += ptiol->BLANK + 1;
            iol_idx++;
            }

	/* ###------------------------------------------------------### */
	/*    print semicolons and '\n'					*/
	/* ###------------------------------------------------------### */

          fprintf (fp, "%s", &blank [16 - ptiol->BLANK]);
          ptiol = ptiol->NEXT;
          stt_nbr++;
          }

	/* ###------------------------------------------------------### */
	/*    make enough allocation					*/
	/* for 2 patterns           : model, buffer			*/
	/* for input-output's names : signam				*/
	/* for                      : value				*/
	/* ###------------------------------------------------------### */

        model  = mbkalloc (sizeof(char) * column * 2);
        signam = mbkalloc (sizeof(char) * column * row);
	value  = mbkalloc (sizeof(char) * (ptseq->IOLNBR));

	/* ###------------------------------------------------------### */
	/*    begin initialisation of value, model and signam:		*/
	/*								*/
	/* value  : unknown value (*) for all inputs-outputs		*/
	/* model represents the format of the pattern : "    :     ;"	*/
	/* signam : "--        \n" * number of rows			*/
	/* ###------------------------------------------------------### */

	for (i=0 ; i<ptseq->IOLNBR ; i++) 
	  value [i] = '*';

        for (i=0 ; i<column ; i++)
          model[i] = ' ';

        for (i=0 ; i<row ; i++)
          {
          signam[    (i * column)] = '-';
          signam[1 + (i * column)] = '-';

          for (j=2 ; j<column ; j++)
            signam[j + (i * column)] = ' ';

          signam[j - 1 + (i * column)] = '\n';
          }

        signam[(row * column) - 1] = '\0';
        model [column - 2]         = ';';
        model [column - 1]         = '\0';

        buffer   = model    + column;
        i        = labelsiz + 1;
        model[i] = ':';
        i += 2;

	/* ###------------------------------------------------------### */
	/*    continue initialization of model and signam:		*/
	/*								*/
	/* model represents the format of the pattern : "    : ?1234;"	*/
	/*       1,2,3,4 : the value of 1, 2, 3 or, 4, input-outputs is	*/
	/*                 to be combined to constitute this character	*/
	/* signam will contain the name of input-outputs one character	*/
	/*        per line						*/
	/* ###------------------------------------------------------### */

        ptgrp   = ptseq->PAGRP;
        ptiol   = ptseq->PAIOL;
        iol_idx = 0;

        while (ptiol != NULL)
          {
          if (ptiol->MODE != 'I')
            model[i++] = '?';

          if ((ptgrp != NULL) && (iol_idx == ptgrp->FINDEX))
            {
            j = 0;
            while (ptgrp->NAME[j] != '\0')
              {
              signam[i + (j * column)] = ptgrp->NAME[j];
              j++;
              }
            switch (ptiol->FORMAT)
              {
              case 'X':
                model[i++] = ((ptgrp->LENGTH - 1) % 4) + 1;
                for (j=0 ; j<((ptgrp->LENGTH - 1) / 4); j++)
                  model[i++] = 4;
                break;
              case 'O':
                model[i++] = ((ptgrp->LENGTH - 1) % 3) + 1;
                for (j=0 ; j<((ptgrp->LENGTH - 1) / 3) ; j++)
                  model[i++] = 3;
                break;
              case 'B':
                for (j=0 ; j<ptgrp->LENGTH ; j++)
                  model[i++] = 1;
                break;
              }
            iol_idx += ptgrp->LENGTH;
            ptiol    = ptseq->PAIOL + iol_idx - 1;
            
            ptgrp    = ptgrp->NEXT;
            }
          else
            {
            j = 0;
            while (ptiol->NAME[j] != '\0')
              {
              signam[i + (j * column)] = ptiol->NAME[j];
              j++;
              }
            model[i++] = 1;
            iol_idx++;
            }

          i     += ptiol->BLANK;
          ptiol  = ptiol->NEXT;
          }
  
	/* ###------------------------------------------------------### */
	/*    print a comment line if needed				*/
	/* ###------------------------------------------------------### */

        if ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
          fprintf (fp, "\n");

        while ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
          {
          fprintf (fp, "# %s\n", ptcom->TEXT);
          ptcom = ptcom->NEXT;
          stt_nbr = 0;
          }

	/* ###------------------------------------------------------### */
	/*    begin printing the pattern description part		*/
	/* ###------------------------------------------------------### */


        fprintf (fp, "\nbegin\n");
        stt_nbr = 0;
  
        fprintf (fp, "\n-- Pattern description :\n\n");
        fprintf (fp, "%s\n\n", signam);

        }

	/* ###------------------------------------------------------### */
	/*    for every sub-sequence ...				*/
	/* ###------------------------------------------------------### */

      ptiol   = ptseq->PAIOL;
      ptpat   = ptseq->CURPAT;
      ptcom   = ptseq->CURCOM;
      pat_nbr = ptseq->PATNBR;

      if (ptseq->DRVSEQ < (ptseq->SUBSEQ - 1))
        {
	/* ###------------------------------------------------------### */
	/*    if the old sub-sequence has not been drived		*/
	/* ###------------------------------------------------------### */

        fprintf (fp, "\n-- Beware : some patterns may be missing\n\n");

        if (ptseq->OLDPAT != NULL)
          {
          ptpat = ptseq->OLDPAT;
          while (ptpat->NEXT != ptseq->CURPAT)
            {
            pat_nbr++;
            ptpat = ptpat->NEXT;
            }
          ptpat = ptseq->OLDPAT;
          }

	/* ###------------------------------------------------------### */
	/*    if any old comment exists, merge old and current comments	*/
	/* lists							*/
	/* ###------------------------------------------------------### */

        if (ptseq->OLDCOM != NULL)
          {
          ptcom = ptseq->OLDCOM;
          while (ptcom->NEXT != NULL)
            ptcom = ptcom->NEXT;

          svcom       = ptcom;
          ptcom->NEXT = ptseq->CURCOM;
          ptcom       = ptseq->OLDCOM;
          }
        }

      while ((ptpat != NULL) && (pat_nbr > 0))
        {
        i       = 0;
	iol_idx = 0;

	/* ###------------------------------------------------------### */
	/*    check for processed or unprocessed patterns		*/
	/* ###------------------------------------------------------### */

        if ((ptpat->SIMFLAG == 'U') && (sflag == 'S'))
          fprintf (fp, "\n-- Beware : unprocessed patterns\n\n");

        sflag = ptpat->SIMFLAG;

	/* ###------------------------------------------------------### */
	/*    print a comment line if needed				*/
	/*    print initialisation if needed				*/
	/* ###------------------------------------------------------### */

        if ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
          fprintf (fp, "\n");

        while ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
          {
          fprintf (fp, "# %s\n", ptcom->TEXT);
          ptcom   = ptcom->NEXT;
          stt_nbr = 0;
          }

        if (ptpat->PAINI != NULL)
	  {
           dclini (fp, ptpat);
	   fprintf(fp, "\n");
	  }

	/* ###------------------------------------------------------### */
	/*    for each event of the pattern :				*/
	/*      - print an error message if simulation and user values	*/
	/*        mismatch						*/
	/*      - copy the event in the value string			*/
	/* ###------------------------------------------------------### */

        ptevt = ptpat->PAEVT;
        while (ptevt != NULL)
          {
          iol_idx =  ptevt->INDEX;
          if ((ptevt->USRVAL != '*') && (ptevt->USRVAL != ptevt->SIMVAL))
            {
            ptiol = ptseq->PAIOL + iol_idx; 

            if (sscanf (ptiol->NAME, "%s %d", name, &indx) == 2)
              sprintf (name, "%s(%d)", name, indx);
            fprintf (fp  , "-- error on `%s` expected value: %c\n",
                     name, ptevt->USRVAL);
            }
          value[iol_idx] = ptevt->SIMVAL;
          ptevt = ptevt->NEXT;
          }

	/* ###------------------------------------------------------### */
	/*    copy the pattern's label in buffer			*/
	/* ###------------------------------------------------------### */

        if (ptpat->LABEL != NULL)
          {
          while ((ptpat->LABEL[i] != '\0') && (i <= labelsiz))
            {
            buffer[i] = ptpat->LABEL[i];
            i++;
            }
          }

	/* ###------------------------------------------------------### */
	/*    fill buffer with the pattern's value : take 1, 2, 3 or, 4	*/
	/* paiol structures to form the value in the buffer		*/
	/* ###------------------------------------------------------### */

	iol_idx = 0;
	ptiol   = ptseq->PAIOL;

        while ((buffer[i] = model[i]) != '\0')
          {
          if ((model[i] >= 1) && (model[i] <= 4))
            {
            tmpc = 0;
            for (j=0 ; j<model[i] ; j++)
              {
              if (tmpc != '*')
                {
                switch (value[iol_idx])
                  {
                  case '+':
                    tmpc = (tmpc << 1) + 1; compare = 1; break;
                  case '-':
                    tmpc = tmpc << 1;       compare = 1; break;
                  case '0':
                    tmpc = tmpc << 1;       compare = 0; break;
                  case '1':
                    tmpc = (tmpc << 1) + 1; compare = 0; break;
                  case '*':
                    tmpc = '*';             compare = 1; break;
                  }
                }
              iol_idx++;
	      ptiol++;
              }
            if (tmpc == '*')
              buffer[i] = '*';
            else
              {
              if (tmpc < 10)
                buffer[i] = '0' + tmpc;
              else
                buffer[i] = 'a' + tmpc - 10;
              }
            if (((ptiol - 1)->MODE == 'T') && (buffer[i-1] == '?') &&
                ( compare          == 0))
              buffer[i-1] = ' ';
            }
          i++;
          }

        fprintf (fp, "%s%s%s", buffer, &blank [17 - ptpat->BLANK],
                                       &line  [18 - ptpat->BLANK]);

        stt_nbr++;
        pat_nbr--;

        ptpat = ptpat->NEXT;
        }

	/* ###------------------------------------------------------### */
	/*    print a comment line if needed				*/
	/* ###------------------------------------------------------### */

      if ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
        fprintf (fp, "\n");

      while ((ptcom != NULL) && (ptcom->POSITION == stt_nbr))
        {
        fprintf (fp, "# %s\n", ptcom->TEXT);
        ptcom = ptcom->NEXT;
        stt_nbr = 0;
        }

	/* ###------------------------------------------------------### */
	/*    restore the original old and current comments lists	*/
	/* ###------------------------------------------------------### */

      if (svcom != NULL)
        svcom->NEXT = NULL;

	/* ###------------------------------------------------------### */
	/*    for the last subsequence print a save (if	needed) and	*/
	/* the end statement. Release allocated buffers (model, signam,	*/
	/* value).							*/
	/* ###------------------------------------------------------### */

      if (ptseq->ENDFLG == 'Y')
        {
        if (ptseq->SAVFLG == 'Y')
          fprintf (fp, "\nsave;\n");

        fprintf (fp, "\nend;\n");

        mbkfree (model );
        mbkfree (signam);
	mbkfree (value );
        }

	/* ###------------------------------------------------------### */
	/*    update the drived subsequence number			*/
	/* ###------------------------------------------------------### */

      ptseq->DRVSEQ = ptseq->SUBSEQ;

	/* ###------------------------------------------------------### */
	/*    return 0 if no error					*/
	/* ###------------------------------------------------------### */

      ret_val = 0;
      }
    }

  return (ret_val);
  }
