structCleanupImpl sname fields
 = do sayln' $ structCleanupProto sname ++ " {"
      flip mapM_ fields $ \(StructField{ field_name = fname, field_array = farray, field_type = ftype })
        -> case farray of
            Scalar ->
              case ftype of
                FStruct csname ->
                  sayln' $ "  " ++ structCleanup csname ++ "(&in->" ++ fname ++ ");";
                FString ->
                  do sayln' $ "  if (in->" ++ fname ++ ") {"
                     sayln' $ "    free(in->" ++ fname ++ ");"
                     sayln' $ "    in->" ++ fname ++ " = NULL;"
                     sayln' $ "  }"
                _ -> return ()
            Fixed _ ->
              case ftype of
                FStruct csname ->
                  do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++)"
                     sayln' $ "    " ++ structCleanup csname ++ "(&in->" ++ fname ++ "[i]);";
                FString ->
                  do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++) {"
                     sayln' $ "    if (in->" ++ fname ++ "[i]) {"
                     sayln' $ "      free(in->" ++ fname ++ "[i]);"
                     sayln' $ "      in->" ++ fname ++ "[i] = NULL;"
                     sayln' $ "    }"
                     sayln' $ "  }"
                _ -> return ()
            Max _ ->
              do case ftype of
                  FStruct csname ->
                    do sayln' $ "  for (int i = 0; i < in->" ++ arrayLen fname ++ "; i++)"
                       sayln' $ "    " ++ structCleanup csname ++ "(&in->" ++ fname ++ "[i]);";
                  FString ->
                    do sayln' $ "  for (int i = 0; i < in->" ++ arrayLen fname ++ "; i++) {"
                       sayln' $ "    if (in->" ++ fname ++ "[i]) {"
                       sayln' $ "      free(in->" ++ fname ++ "[i]);"
                       sayln' $ "      in->" ++ fname ++ "[i] = NULL;"
                       sayln' $ "    }"
                       sayln' $ "  }"
                  _ -> return ()
                 sayln' $ "  if (in->" ++ fname ++ ") {"
                 sayln' $ "    free(in->" ++ fname ++ ");"
                 sayln' $ "    in->" ++ fname ++ " = NULL;"
                 sayln' $ "  }"
      sayln' $ "  " ++ structInit sname ++ "(in);"
      sayln' $ "}"
structCleanupImpl sname fields
 = do sayln' $ structCleanupProto sname ++ " {"
      flip mapM_ fields $ \(StructField{ field_name = fname, field_array = farray, field_type = ftype })
        -> case farray of
            Scalar ->
              case ftype of
                FStruct csname ->
                  sayln' $ "  " ++ structCleanup csname ++ "(&in->" ++ fname ++ ");";
                FString ->
                  do sayln' $ "  if (in->" ++ fname ++ ") {"
                     sayln' $ "    free(in->" ++ fname ++ ");"
                     sayln' $ "    in->" ++ fname ++ " = NULL;"
                     sayln' $ "  }"
                _ -> return ()
            Fixed _ ->
              case ftype of
                FStruct csname ->
                  do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++)"
                     sayln' $ "    " ++ structCleanup csname ++ "(&in->" ++ fname ++ "[i]);";
                FString ->
                  do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++) {"
                     sayln' $ "    if (in->" ++ fname ++ "[i]) {"
                     sayln' $ "      free(in->" ++ fname ++ "[i]);"
                     sayln' $ "      in->" ++ fname ++ "[i] = NULL;"
                     sayln' $ "    }"
                     sayln' $ "  }"
                _ -> return ()
            Max _ ->
              do case ftype of
                  FStruct csname ->
                    do sayln' $ "  for (int i = 0; i < in->" ++ arrayLen fname ++ "; i++)"
                       sayln' $ "    " ++ structCleanup csname ++ "(&in->" ++ fname ++ "[i]);";
                  FString ->
                    do sayln' $ "  for (int i = 0; i < in->" ++ arrayLen fname ++ "; i++) {"
                       sayln' $ "    if (in->" ++ fname ++ "[i]) {"
                       sayln' $ "      free(in->" ++ fname ++ "[i]);"
                       sayln' $ "      in->" ++ fname ++ "[i] = NULL;"
                       sayln' $ "    }"
                       sayln' $ "  }"
                  _ -> return ()
                 sayln' $ "  if (in->" ++ fname ++ ") {"
                 sayln' $ "    free(in->" ++ fname ++ ");"
                 sayln' $ "    in->" ++ fname ++ " = NULL;"
                 sayln' $ "  }"
      sayln' $ "  " ++ structInit sname ++ "(in);"
      sayln' $ "}"
structCleanupImpl sname fields
 = do sayln' $ structCleanupProto sname ++ " {"
      flip mapM_ fields $ \(StructField{ field_name = fname, field_array = farray, field_type = ftype })
        -> case farray of
            Scalar ->
              case ftype of
                FStruct csname ->
                  sayln' $ "  " ++ structCleanup csname ++ "(&in->" ++ fname ++ ");";
                FString ->
                  do sayln' $ "  if (in->" ++ fname ++ ") {"
                     sayln' $ "    free(in->" ++ fname ++ ");"
                     sayln' $ "    in->" ++ fname ++ " = NULL;"
                     sayln' $ "  }"
                _ -> return ()
            Fixed _ ->
              case ftype of
                FStruct csname ->
                  do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++)"
                     sayln' $ "    " ++ structCleanup csname ++ "(&in->" ++ fname ++ "[i]);";
                FString ->
                  do sayln' $ "  for (int i = 0; i < " ++ arrayLenFixed sname fname ++ "; i++) {"
                     sayln' $ "    if (in->" ++ fname ++ "[i]) {"
                     sayln' $ "      free(in->" ++ fname ++ "[i]);"
                     sayln' $ "      in->" ++ fname ++ "[i] = NULL;"
                     sayln' $ "    }"
                     sayln' $ "  }"
                _ -> return ()
            Max _ ->
              do case ftype of
                  FStruct csname ->
                    do sayln' $ "  for (int i = 0; i < in->" ++ arrayLen fname ++ "; i++)"
                       sayln' $ "    " ++ structCleanup csname ++ "(&in->" ++ fname ++ "[i]);";
                  FString ->
                    do sayln' $ "  for (int i = 0; i < in->" ++ arrayLen fname ++ "; i++) {"
                       sayln' $ "    if (in->" ++ fname ++ "[i]) {"
                       sayln' $ "      free(in->" ++ fname ++ "[i]);"
                       sayln' $ "      in->" ++ fname ++ "[i] = NULL;"
                       sayln' $ "    }"
                       sayln' $ "  }"
                  _ -> return ()
                 sayln' $ "  if (in->" ++ fname ++ ") {"
                 sayln' $ "    free(in->" ++ fname ++ ");"
                 sayln' $ "    in->" ++ fname ++ " = NULL;"
                 sayln' $ "  }"
      sayln' $ "  " ++ structInit sname ++ "(in);"
      sayln' $ "}"