anchor.diff:              task, print_control, &
               char_state, bool_state, int_state, real_state)
   
  -       ! Do the 'calculate function and gradient' task
  -       if (task(1:2) == 'FG') then
  -          ! Try to get away with not converting Fortran arrays to C
  +       ! Interpret the returned task
  +       call interpret_task(task, state, message)
  +
  +       ! Act on the current state
  +       if (state(1:7) == 'EVAL_FG') then
  +          ! Calculate function and gradient.  Try to get away with not
  +          ! converting Fortran arrays to C.
   
             ! Call objective function
  -          error_code_c = func_pointer(dim_c, point, func_value, &
  -               callback_data, error_message_length_c, error_message_c)
  -          if (error_code_c /= LBFGSB_OK) exit
  +          status_c = func_pointer(dim_c, point, func_value, &
  +               callback_data, status_message_length_c, status_message_c)
  +          if (status_c /= LBFGSB_STATUS_SUCCESS) exit
   
             ! Call objective function gradient
  -          error_code_c = grad_pointer(dim_c, point, grad_value, &
  -               callback_data, error_message_length_c, error_message_c)
  -          if (error_code_c /= LBFGSB_OK) exit
  +          status_c = grad_pointer(dim_c, point, grad_value, &
  +               callback_data, status_message_length_c, status_message_c)
  +          if (status_c /= LBFGSB_STATUS_SUCCESS) exit
  +       else if (state(1:7) == 'WARNING') then
  +          ! TODO handle warnings
  +       else if (state(1:5) == 'NEW_X') then
  +          ! TODO handle logging
          end if
  -
  -       ! Nothing to do for other tasks (NEW_X just means a step was
  -       ! taken to the current x)
       end do
   
  -    ! Analyze task and error state to see how to return
  -    if (error_code_c == LBFGSB_OK) then
  +    ! Analyze status and state to see how to return
  +    if (status_c == LBFGSB_STATUS_SUCCESS) then
          ! Objective and gradient evaluations were OK but L-BFGS-B may not
          ! be.  Regardless, take what we can from the outputs.
          min_x_c = point
          min_f_c = func_value
          min_g_c = grad_value
   
  -       ! Copy task into error message
  -       call convert_f_c_string(task, error_message_length_c, error_message_c)
  -
          ! Check for normal or problematic termination
  -       if (task(1:4) == 'CONV') then
  +       select case (state)
  +       case ('CONVERGENCE')
             ! Converged.  Normal termination.  Leave error (task) message
             ! as it may be informative.
  -          error_code_c = LBFGSB_OK
  -       else if (task(1:4) == 'ABNO') then
  +          status_c = LBFGSB_STATUS_SUCCESS
  +       case ('ABNORMAL')
             ! Could not satisfy termination conditions.  Result is best
             ! approximation.
  -          error_code_c = LBFGSB_APPROXIMATE
  -       else if (task(1:5) == 'ERROR') then
  -          ! Runtime or user error
  -          error_code_c = LBFGSB_RUNTIME_ERROR
  -       else
  -          ! Unrecognized task
  -          error_code_c = LBFGSB_TASK_ERROR
  -       end if
  +          status_c = LBFGSB_STATUS_APPROXIMATE
  +       case ('WARNING')
  +          status_c = LBFGSB_STATUS_WARNING
  +       case ('ERROR_USAGE')
  +          ! User error
  +          status_c = LBFGSB_STATUS_USAGE_ERROR
  +       case ('ERROR_INTERNAL')
  +          ! Runtime or internal error
  +          status_c = LBFGSB_STATUS_INTERNAL_ERROR
  +       case default
  +          ! Unrecognized state
  +          status_c = LBFGSB_STATUS_INTERNAL_ERROR
  +          message = 'Error: Unrecognized state: '//task
  +       end select
  +
  +       ! Copy task message into status message
  +       call convert_f_c_string(message, status_message_length_c, status_message_c)
       else
          ! There was a problem computing the objective or the gradient.
          ! The error message and code were already properly set by the
  
positive.code:     type(c_funptr), intent(in), value :: func, grad
      type(c_ptr), intent(in), value :: callback_data
      integer(c_int), intent(in), value :: dim_c, approximation_size_c, &
           error_message_length_c, debug_c
      real(c_double), intent(in), value :: f_tolerance_c, g_tolerance_c
      integer(c_int), intent(in) :: bounds_control_c(dim_c)
      real(c_double), intent(in) :: lower_bounds_c(dim_c), &
           upper_bounds_c(dim_c), initial_point_c(dim_c)
      character(c_char), intent(out) :: &
           error_message_c(error_message_length_c)
      real(c_double), intent(out) :: min_x_c(dim_c), min_f_c, &
           min_g_c(dim_c)
      integer(c_int) :: error_code_c
  
      ! Locals (scalars before arrays)
      ! Fortran versions of arguments
  
negative.code:     upper_bounds = upper_bounds_c
      point = initial_point_c
  
      ! Start with an empty status message (fill entire string with nulls)
      status_message_c = c_null_char
  
      ! Translate f_tolerance to f_factor.  The convergence tolerance for
      ! the objective function is computed by the L-BFGS-B code as
  