function [splines, rc] = mfs_new_splines(msg, solid, aero, splinedef, ptol)

# usage: [splines, rc] = mfs_new_splines(msg, solid, aero, splinedef, ptol)
#
# Input  msg        File handle of message file
#        solid      Structure with solid component
#        aero       Structure with aerodynamic component
#        splinedef  Structure array with spline definitions
#        ptol       Angular tolerance
#
# Output splines    Structure with spline data
#        rc         Return code: 0 means no errors
#                                1 means errors
#
# The function builds a structure with all spline data.
#
# Input data:
#
#   splinedef(:).id          Spline identifier
#   splinedef(:).type        Spline type
#   splinedef(:).lsid(:)     Identifiers of lifting surfaces
#   splinedef(:).nodes(:)    List of solid nodal point identifiers or
#                            name of a nodal point set (optional)
#   splinedef(:).data        Spline data
#
# The spline data depend on the spline type:
#
#   Torsion-bending-spline:
#
#      data.nbreaks          Number of spline breaks 
#      data.breaks(:)        Spline breaks
#
#      Either nbreaks or breaks must be defined.
#
# Output data:
#
#   splines.nofspl           Number of splines
#   splines.ids(nofspl)      Spline identifiers in ascending sort
#   splines.types{nofspl}    Spline types
#   splines.data{nofspl}     Cell array with spline data
#
# --------------------------------------------------------------------

  legal_fields = {"id", "type", "lsid", "nodes", "data"};
  req_fields   = {"id", "type", "lsid", "data"};

# Check arguments

  if (nargin != 5 || nargout != 2)
     print_usage();
  end

# Initialize

  splines = struct();

# Check input data

  if ((rc = mfs_checkfields1(msg, splinedef, req_fields, "Splines")))
     return;
  end
  if ((rc = mfs_checkfields4(msg, splinedef, legal_fields, "Splines")))
     return;
  end

# Sort the splines according to ascending identifiers

  nofspl = length(splinedef);
  splids = zeros(1, nofspl);

  for n = 1 : nofspl
      if (splinedef(n).id)
         splids(n) = splinedef(n).id;
      else
         rc = 1;
         fprintf(msg, "*E* Identifier of spline %2d undefined\n", n);
      end
  end

  if (rc) return; end
  
  [splids, index] = sort(splids);

# Check on duplicate spline identifiers

  for n = 1 : nofspl - 1
      if (splids(n) == splids(n + 1))
         rc = 1;
         fprintf(msg, "*E* Duplicate spline identifier %5d found\n",
                 splids(n));
      end
  end

  if (rc) return; end

# Get lifting surface indices

  lsno = cell(nofspl, 1);

  for n = 1 : nofspl
      m = index(n);
      lsid = splinedef(m).lsid;
      if (lsid)
         lsno{n} = lookup(aero.ls.ids, lsid, "m");
         ixb = find(lsno{n} == 0);
         if (! isempty(ixb))
            rc = 1;
            for ix = ixb
                fprintf(msg, "*E* Lifting surface %4d referenced ",
                        lsid(ix));
                fprintf(msg, "from spline %4d does not exist\n",
                        splinedef(m).id);
             end
         end
      else
         rc = 1;
         fprintf(msg, "*E* Lifting surfaces of spline %4d undefined\n",
                 splinedef(m).id);
      end
  end

  if (rc) return; end

# Get spline data

  data = cell(nofspl, 1);

  for n = 1 : nofspl
      l = lsno{n};
      m = index(n);
      spltyp{n} = splinedef(m).type;
      switch spltyp{n}
      case "tb"
         [data{n}, rc1] = mfs_new_spline_tb(msg, splinedef(m), 
                                            solid.nodes, solid.nset, 
                                            aero.ls.surfs(l), ptol);
         rc = rc || rc1;
      otherwise
         rc = 1;
         fprintf(msg, "*E* Unknown spline type %s referenced ",
                splinedef(m).type);
         fprintf(msg, "on spline %4d\n", splinedef(m).id);
      end
  end

  if (rc)
     return;
  end

# Build the spline structure

  splines = struct("nofspl", nofspl, "ids", splids);
  splines.types = spltyp;
  splines.data  = data;

end
