c Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
c Copyright (C) ????-2008 - INRIA
c
c This file must be used under the terms of the CeCILL.
c This source file is licensed as described in the file COPYING, which
c you should have received as part of this distribution.  The terms
c are also available at
c http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
      subroutine insertfield(ilfrom,volfrom,iltos,ind,nind,lrn,lw,info)
c     insert a field (from) in a sublist "to"  of a list "tos"
c
c     ilfrom points on the first entry of the "from" data structure in
c     istk. data structure is contained in istk(ilfrom:ilfrom-1+2*volfrom)

c     ilto points on the first entry of the "to" data structure in istk
c     iltos points on the first entry of the "tos" data structure in istk
c     ind(1:nind) is the path of to in tos
c
c     is the position of the result,if info<>0
c     info
c        if 0 list has been updated "in place"
c        if 1 list needs to be stored
      include 'stack.h'
c
      integer volfrom,voltos,volto,dvol,ind(*)
      integer typfrom,typto

      integer subptr
      external subptr

      integer iadr,sadr
c
      iadr(l)=l+l-1
      sadr(l)=(l/2)+1
c
      if(istk(ilfrom).lt.0) ilfrom=iadr(istk(ilfrom+1))
      typfrom=istk(ilfrom)
      lfromt=sadr(ilfrom)
c
      if(istk(iltos).lt.0) iltos=iadr(istk(iltos+1))
      mtos=istk(iltos+1)
c     voltos is the memory used to store all fields of tos
      voltos=istk(iltos+2+mtos)-1
c     ltos points on the first entry of the "tos" fields in stk
      ltos=sadr(iltos+mtos+3)
c
c     get pointer on the inner-most modified sublist
      n=ind(nind)
      il=iltos
      if(istk(il).lt.0) il=iadr(istk(il+1))
      mi=istk(il+1)
      if(nind.gt.1) then
         do 05 k1=1,nind-1
            il=iadr(sadr(il+3+mi)+istk(il+1+ind(k1))-1)
            if(istk(il).lt.0) il=iadr(istk(il+1))
            mi=istk(il+1)
 05      continue
      endif
c
      ilto=il
      typto=istk(ilto)
      mto=istk(ilto+1)
c     volto is the memory used to store all fields of to
      volto=istk(ilto+2+mto)-1
      lto=sadr(ilto+mto+3)
c

      if(n.eq.0) then
c     .  add a new element "on the left"
         if(typfrom.eq.0) then
c     .     null element : nothing added, "to" variable is returned as it
            info=0
            return
         endif

c     .  get memory to install the resulting list (May be improved to avoid
c     .  copy when "to" list is at the top of the stack).
         info=1
         lrn=lw
         iln=iadr(lrn)
         lw1=sadr(iadr(lrn)+3+(mtos+1))+voltos+volfrom
         err=lw1-lstk(bot)
         if(err.gt.0) then
            call error(17)
            return
         endif

         if(iltos.ne.ilto) then
c     .     copy the beginning of "tos" up to the beginning of the modified sub-list.
            ltod=sadr(iltos)
            ltto=sadr(ilto)
            call unsfdcopy(ltto-ltod,stk(ltod),1,stk(lrn),1)
c     .     lrn points to the beginning of the new entry
            lrn=lrn+ltto-ltod
         endif

c     .  create new sublist:
c     .  header
         ilr=iadr(lrn)
         istk(ilr)=typto
         istk(ilr+1)=mto+1
         istk(ilr+2)=1
         istk(ilr+3)=1+volfrom
         do 10 i=1,mto
            istk(ilr+3+i)=istk(ilr+2+i)+istk(ilto+2+i)-istk(ilto+1+i)
 10      continue
c     .  added field
         lr=sadr(ilr+4+mto)
         call unsfdcopy(volfrom,stk(lfromt),1,stk(lr),1)
c     .  copy old sublist fields
         lr=lr+volfrom
         call unsfdcopy(volto,stk(lto),1,stk(lr),1)
         lr=lr+volto
         dvol=(lr-lrn)-(lto+volto-sadr(ilto))

c     .  update new data structure pointers recursively
         call updptr(iln,ind,nind-1,dvol)
c     .  copy the rest of data structure
         if(nind.gt.1) then
            ind(nind-1)=ind(nind-1)+1
            ltto=sadr(subptr(iltos,ind,nind-1))
            call unsfdcopy(ltos+voltos-ltto,stk(ltto),1,stk(lr),1)
            lr=lr+ltos+voltos-ltto
         endif
c     .  put the result in place
         lrn=sadr(iln)
c         call unsfdcopy(lr-lrn,stk(lrn),1,stk(lstk(top)),1)
c         lstk(top+1)=lstk(top)+lr-lrn
         info=1
      elseif(n.gt.mto) then
c     .  add a new elements "on the right" of the sublist
         if(typfrom.eq.0) then
c     .     from is a null element : nothing added
            info=0
            return
         endif

c     .  get memory to install the resulting list (May be improved to avoid
c     .  copy when "to" list is at the top of the stack).
         lrn=lw
         iln=iadr(lrn)
         lw1=sadr(iln+3+mtos+n-mto)+voltos+volfrom
         info=1
         err=lw1-lstk(bot)
         if(err.gt.0) then
            call error(17)
            return
         endif

         if(ilto.ne.iltos) then
c     .     copy the beginning of "tos" up to the beginning of the modified sub-list.
            ltod=sadr(iltos)
            ltto=sadr(ilto)
            err=lrn+ltto-ltod-lstk(bot)
            if(err.gt.0) then
               call error(17)
               return
            endif
            call unsfdcopy(ltto-ltod,stk(ltod),1,stk(lrn),1)
c     .     lrn points to the beginning of the new entry
            lrn=lrn+ltto-ltod
         endif

c     .  copy the beginning of the sublist header
         ilr=iadr(lrn)
         lr=sadr(ilr+3+n)
         err=lr+volto+volfrom-lstk(bot)
         if(err.gt.0) then
            call error(17)
            return
         endif
         call icopy(mto+3,istk(ilto),1,istk(ilr),1)
c     .  update fields number
         istk(ilr+1)=n
c     .  set pointers on added fields (some can be empty)
         call iset(n-mto,istk(ilr+mto+2),istk(ilr+mto+3),1)
         istk(ilr+n+2)=istk(ilr+n+1)+volfrom

c     .  copy old fields values
         call unsfdcopy(volto,stk(lto),1,stk(lr),1)
         lr=lr+volto
c     .  copy added field value
         call unsfdcopy(volfrom,stk(lfromt),1,stk(lr),1)
         lr=lr+volfrom
c
         dvol=(lr-lrn)-(lto+volto-sadr(ilto))
c     .  update new data structure pointers recursively
         call updptr(iln,ind,nind-1,dvol)
c     .  copy the rest of data structure
c???         ind(nind-1)=ind(nind-1)+n-mto
         ind(nind-1)=ind(nind-1)+1
         ltto=sadr(subptr(iltos,ind,nind-1))
         if(ltos+voltos-ltto.gt.0) then
            err=(lr+ltos+voltos-ltto)-lstk(bot)
            if(err.gt.0) then
               call error(17)
               return
            endif
            call unsfdcopy(ltos+voltos-ltto,stk(ltto),1,stk(lr),1)
            lr=lr+ltos+voltos-ltto
         endif

c     .  store result  ????
         lrn=sadr(iln)
         return
      else
c     .  replace or delete an intermediate field of the sublist
         if(typfrom.ne.0) then
c     .     replace the specified field
            if (istk(ilto+2+n)-istk(ilto+1+n).eq.volfrom) then
c     .        old and new fields have the same size,
c     .        field is  replaced in place
               lr=lto+istk(ilto+1+n)-1
               call unsfdcopy(volfrom,stk(lfromt),1,stk(lr),1)
               info=0
               return
            else
c     .        get memory to install the resulting list
c     .        (May be improved to avoid copy when "to" list is at the
c     .        top of the stack).
               iln=iadr(lw)
               lrn=lw

               info=1
c     .        dvol the size variation of modified sub-element (-old+new)
               dvol=-(istk(ilto+2+n)-istk(ilto+1+n))+volfrom
               lw1=sadr(iln+3+mtos)+voltos+dvol
               err=lw1-lstk(bot)
               if(err.gt.0) then
                  call error(17)
                  return
               endif
c     .        lr,ilr points to the entry to be replaced
               lr=lto+istk(ilto+1+n)-1
               ilr=iadr(lr)
c     .        change list type if necessary (tlist and mlist are
c     .        changed to simple list)
c     .        copy the beginning of "to" up to field to be replaced
               ltod=sadr(iltos)
               call unsfdcopy(lr-ltod,stk(ltod),1,stk(lrn),1)
               if(nind.eq.1.and.n.eq.1.and.typfrom.ne.10) istk(iln)=15

c     .        lrn points to the beginning of the new field
               lrn=lrn+lr-ltod
c     .        set new value of the entry
               call unsfdcopy(volfrom,stk(lfromt),1,stk(lrn),1)
               lrn=lrn+volfrom
c     .        copy last field of "to"
c     .        iltol points to the end of "to" data structure
               ltol=ltos+voltos
               lto=lto+istk(ilto+2+n)-1
               call unsfdcopy(ltol-lto,stk(lto),1,stk(lrn),1)
               lrn=lrn+ltol-lto
c     .        update new data structure pointers recursively
               call  updptr(iln,ind,nind,dvol)
c     .        store result
               lrn=lw
               return
            endif
         else
c     .     suppress the specified entry
c     .     get memory to install the resulting list
c     .     (May be improved to avoid copy when "to" list is at the
c     .     top of the stack).
            lrn=lw
            info=1
            iln=iadr(lrn)
            lw1=sadr(iln+3+mtos)+voltos-(istk(ilto+2+n)-istk(ilto+1+n))
            err=lw1-lstk(bot)
            if(err.gt.0) then
               call error(17)
               return
            endif
c     .     if necessary,copy the "to" list data structure up to the
c     .     beginning of the modified sub-list
            if(ilto.ne.iltos) then
c     .     copy the beginning of "to" up to  the modified sub-list
               ltod=sadr(iltos)
               ltto=sadr(ilto)
               call unsfdcopy(ltto-ltod,stk(ltod),1,stk(lrn),1)
c     .        lrn points to the beginning of the new entry
               lrn=lrn+ltto-ltod
            endif
c     .     update sub_list
c     .     ---------------
            il=iadr(lrn)
            lfrom=lto-1+istk(ilto+2+n)
c     .     copy variable header and n-1 first pointers
            call icopy(2+n,istk(ilto),1,istk(il),1)
            if(n.eq.1) istk(il)=15
c     .     reduce list size
            istk(il+1)=istk(il+1)-1
c     .     modify last pointers
            do 20 i=n,mto
               istk(il+i+2)=istk(il+i+1)+istk(ilto+i+3)-istk(ilto+i+2)
 20         continue
c     .     copy first n-1 elements
            l=sadr(il+2+mto)
            call unsfdcopy(istk(il+n+1)-1,stk(lto),1,stk(l),1)
            l=l+istk(il+n+1)-1
c     .     dvol the size variation of modified sub-element (-old+new)
            dvol=(l-sadr(il))-(lfrom-sadr(ilto))
c     .     copy last elements
            call unsfdcopy(istk(il+1+mto)-istk(il+1+n),stk(lfrom),1,
     $           stk(l),1)
            l=l+istk(il+1+mto)-istk(il+1+n)
c     .     update new data structure pointers recursively
            call updptr(iln,ind,nind-1,dvol)
c     .     copy the rest of data structure
            if(nind.gt.1) then
               ind(nind-1)=ind(nind-1)+1
               ltto=sadr(subptr(iltos,ind,nind-1))
               call unsfdcopy(ltos+voltos-ltto,stk(ltto),1,stk(l),1)
               l=l+ltos+voltos-ltto
            endif
c     .     store result
            lrn=sadr(iln)
            info=1
            return
         endif
      endif
      return
      end

