/*
 Function: The Buffmng subroutine makes the buffer management.
           The following actions take the place while processing the
           "send_data" request:
           - new buffer is allocated;
           - an incoming date is placed in the buffer;
           - the buffer inserted in a resource queue (the next
             buffer processing and deleting it from the queue
             will make by the HS).
           The following actions take the place while processing the
           "receive" request:
           - the HS places the buffer in an input resource queue;
           - the Buffmng copies date into the field which was defined
             in the "receive" request, then
           - deletes the buffer from the queue and frees the buffer memory.

 Input: A function code, a pointer to a buffer, a pointer to a buffer pool,
        a pointer to the RCB block, length of a text, a segment descriptor
        (0 - the last segment, 1 - the middle segment).
        The function code values: A - add, D - delete.
        if (code == A) --> pb -> text for filling
        if (code == D) --> pb -> buffer for deleting
                                 from the buff. pool
 Output: the return codes are: "0" - all O.K!
                               "-1" - error...

  CopyRight 1995. Nicholas Poljakov all rights reserved.

 */

#include <stdio.h>
#include <malloc.h>
#include <prefix.h>
#include <rcb.h>
#include <state1.h>
#include <string.h>

#define ADD 'A'
#define DELETE 'D'

buffmng(code, b_ptr, buff, r_ptr, length, dsc, type)
char code;           /* Request code; 'A' - add, 'D' - delete*/
char *b_ptr;         /* Pointer to text buffer  */
char **buff;         /* Field whose contained pointer to buff. chain */
struct rcb *r_ptr;   /* Pointer to RCB */
unsigned int length; /* Length of text */
unsigned char dsc;   /* Segment descriptor; 0 - Last, 1 - middle */
unsigned type;       /* DFC command code */
{
    struct prefix *prf;
    struct prefix *prf1;
    struct prefix *prf2;
    struct tp {
                 unsigned char h;
                 unsigned char l;
              } *t;
    void *prf_sv;
    char *p;

#if OS_TYPE == 1
/*********  Trace facility **********/
unsigned int rtype;   /* type of record */
unsigned int pnum;    /* point number */
char pname[8];        /* name of module */
char *drec;       /* record for dump */
int  lenr;            /* record length */

rtype = INPROC;
strcpy(pname, "buffmng");
pnum = 1;
drec = &code;
lenr = 1;
gtf(rtype, pname, pnum, drec, lenr);
/***********************************/
#endif

    t = (struct tp *)&type;
    switch (code) {
        case ADD :
                  {
                    prf = malloc(sizeof(struct prefix));
                    prf->next = NULL;
                    prf->text = b_ptr;
                    prf -> prev = NULL;
                    prf -> lt_text = length;
                    prf -> dsc = dsc;
		    prf -> type = t -> h;
                    if (buff == NULL) {
                       prf1 = r_ptr -> first_out;
                    }
                    else
                            {
				prf1 = (struct prefix *)*buff;
                            }
                    if (prf1 == NULL) {
                        if (buff == NULL) {
                            r_ptr -> first_out = prf;
                        }
                        else
				*buff = (char *)prf;
                    }
                            else {
                                    while (prf1->next != NULL) {
                                        prf1 = prf1->next;
                                        }
                                    prf1->next = prf;
                                    prf->prev = prf1; /* back pointer */
                                 }
                    break;
                  }
        case DELETE :
                  {
		    prf = (struct prefix *)b_ptr;
                    if ((p = prf->text) != NULL) {
                         free(p);
                    }
                    if (prf->next == NULL) {
                                if (prf->prev == NULL) {
                                            *buff = NULL;
                                }
                                else  {
                                            prf_sv = prf;
                                            prf = prf->prev;
                                            prf->next = NULL;
                                            prf = prf_sv;
                                }
                    }
                    else
                            {
                                prf2 = prf->next;
                                if ((prf1 = prf->prev) != NULL) {
                                     prf1->next = prf2;
                                     prf2->prev = prf1;
                                }
                                else {
				       *buff = (char *)prf2;
                                        prf2 -> prev = NULL;
                                }
                            }
                    free(prf);
                  }
                  }
    return 0;
}
