Use _CALL_DL_FCT to call function from dynamically loaded object.
[kopensolaris-gnu/glibc.git] / iconv / skeleton.c
index f905bcd..19e737a 100644 (file)
                        to cover only those characters up to the error.
 
      FUNCTION_NAME     if not set the conversion function is named `gconv'.
+
+     PREPARE_LOOP      optional code preparing the conversion loop.  Can
+                       contain variable definitions.
+     END_LOOP          also optional, may be used to store information
+
+     EXTRA_LOOP_ARGS   optional macro specifying extra arguments passed
+                       to loop function.
  */
 
 #include <assert.h>
@@ -75,6 +82,7 @@
 #define __need_size_t
 #define __need_NULL
 #include <stddef.h>
+#include <elf/ldsodefs.h>
 
 
 /* The direction objects.  */
@@ -83,7 +91,7 @@ static int from_object;
 static int to_object;
 
 # ifndef FROM_DIRECTION
-#  define FROM_DIRECTION step->data == &from_object
+#  define FROM_DIRECTION (step->data == &from_object)
 # endif
 #else
 # ifndef FROM_DIRECTION
@@ -131,17 +139,33 @@ int
 gconv_init (struct gconv_step *step)
 {
   /* Determine which direction.  */
-  if (__strcasestr (step->from_name, CHARSET_NAME) != NULL)
+  if (__strcasecmp (step->from_name, CHARSET_NAME) == 0)
     step->data = &from_object;
-  else if (__strcasestr (step->to_name, CHARSET_NAME) != NULL)
+  else if (__strcasecmp (step->to_name, CHARSET_NAME) == 0)
     step->data = &to_object;
   else
     return GCONV_NOCONV;
 
-  step->min_needed_from = MIN_NEEDED_FROM;
-  step->max_needed_from = MAX_NEEDED_FROM;
-  step->min_needed_to = MIN_NEEDED_TO;
-  step->max_needed_to = MAX_NEEDED_TO;
+  if (step->data == &from_object)
+    {
+      step->min_needed_from = MIN_NEEDED_FROM;
+      step->max_needed_from = MAX_NEEDED_FROM;
+      step->min_needed_to = MIN_NEEDED_TO;
+      step->max_needed_to = MAX_NEEDED_TO;
+    }
+  else
+    {
+      step->min_needed_from = MIN_NEEDED_TO;
+      step->max_needed_from = MAX_NEEDED_TO;
+      step->min_needed_to = MIN_NEEDED_FROM;
+      step->max_needed_to = MAX_NEEDED_FROM;
+    }
+
+#ifdef RESET_STATE
+  step->stateful = 1;
+#else
+  step->stateful = 0;
+#endif
 
   return GCONV_OK;
 }
@@ -155,6 +179,13 @@ gconv_init (struct gconv_step *step)
 #endif
 
 
+/* If no arguments have to passed to the loop function define the macro
+   as empty.  */
+#ifndef EXTRA_LOOP_ARGS
+# define EXTRA_LOOP_ARGS
+#endif
+
+
 /* This is the actual conversion function.  */
 #ifndef FUNCTION_NAME
 # define FUNCTION_NAME gconv
@@ -188,22 +219,26 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
          if (status == GCONV_OK)
 #endif
            /* Give the modules below the same chance.  */
-           status = (*fct) (next_step, next_data, NULL, NULL, written, 1);
+           status = _CALL_DL_FCT (fct, (next_step, next_data, NULL, NULL,
+                                        written, 1));
        }
     }
   else
     {
-      /* This variable is used to count the number of characters we
-         actually converted.  */
-      size_t converted = 0;
-      size_t last_converted;
-
       /* We preserve the initial values of the pointer variables.  */
       const char *inptr = *inbuf;
       char *outbuf = data->outbuf;
       char *outend = data->outbufend;
       char *outptr;
 
+      /* This variable is used to count the number of characters we
+        actually converted.  */
+      size_t converted = 0;
+
+#ifdef PREPARE_LOOP
+      PREPARE_LOOP
+#endif
+
       do
        {
          /* Remember the start value for this round.  */
@@ -211,8 +246,6 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
          /* The outbuf buffer is empty.  */
          outptr = outbuf;
 
-         /* Save the state.  */
-         last_converted = converted;
 #ifdef SAVE_RESET_STATE
          SAVE_RESET_STATE (1);
 #endif
@@ -223,14 +256,16 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
                                (const unsigned char *) inbufend,
                                (unsigned char **) &outbuf,
                                (unsigned char *) outend,
-                               data->statep, step->data, &converted);
+                               data->statep, step->data, &converted
+                               EXTRA_LOOP_ARGS);
          else
            /* Run the conversion loop.  */
            status = TO_LOOP ((const unsigned char **) inbuf,
                              (const unsigned char *) inbufend,
                              (unsigned char **) &outbuf,
                              (unsigned char *) outend,
-                             data->statep, step->data, &converted);
+                             data->statep, step->data, &converted
+                             EXTRA_LOOP_ARGS);
 
          /* If this is the last step leave the loop, there is nothgin
              we can do.  */
@@ -238,6 +273,10 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
            {
              /* Store information about how many bytes are available.  */
              data->outbuf = outbuf;
+
+             /* Remember how many characters we converted.  */
+             *written += converted;
+
              break;
            }
 
@@ -247,8 +286,8 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
              const char *outerr = data->outbuf;
              int result;
 
-             result = (*fct) (next_step, next_data, &outerr, outbuf,
-                              written, 0);
+             result = _CALL_DL_FCT (fct, (next_step, next_data, &outerr,
+                                          outbuf, written, 0));
 
              if (result != GCONV_EMPTY_INPUT)
                {
@@ -266,7 +305,6 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
                      outbuf = outptr;
 
                      /* Reset the state.  */
-                     converted = last_converted;
 # ifdef SAVE_RESET_STATE
                      SAVE_RESET_STATE (0);
 # endif
@@ -278,7 +316,7 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
                                             (unsigned char **) &outbuf,
                                             (unsigned char *) outerr,
                                             data->statep, step->data,
-                                            &converted);
+                                            &converted EXTRA_LOOP_ARGS);
                      else
                        /* Run the conversion loop.  */
                        nstatus = TO_LOOP ((const unsigned char **) inbuf,
@@ -286,7 +324,7 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
                                           (unsigned char **) &outbuf,
                                           (unsigned char *) outerr,
                                           data->statep, step->data,
-                                          &converted);
+                                          &converted EXTRA_LOOP_ARGS);
 
                      /* We must run out of output buffer space in this
                         rerun.  */
@@ -307,8 +345,12 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
        }
       while (status == GCONV_OK);
 
-      /* Remember how many characters we converted.  */
-      *written += converted;
+#ifdef END_LOOP
+      END_LOOP
+#endif
+
+      /* We finished one use of this step.  */
+      ++data->invocation_counter;
     }
 
   return status;
@@ -329,3 +371,5 @@ FUNCTION_NAME (struct gconv_step *step, struct gconv_step_data *data,
 #undef RESET_STATE
 #undef RESET_INPUT_BUFFER
 #undef FUNCTION_NAME
+#undef PREPARE_LOOP
+#undef END_LOOP