CUBRID Engine  latest
condition_handler.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 
20 /*
21  * condition_handler.c : condition handling module
22  */
23 
24 #ident "$Id$"
25 
26 #include "config.h"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <limits.h>
32 #include <assert.h>
33 
34 #include "porting.h"
35 #include "condition_handler.h"
36 #include "condition_handler_code.h"
37 #include "message_catalog.h"
38 #include "adjustable_array.h"
39 #include "condition_handler_err.h"
40 #include "intl_support.h"
41 
42 /* format type of condition argument */
44 {
53 };
55 
56 /* condition argument value structure */
57 typedef struct co_argument CO_ARGUMENT;
59 {
61  union
62  {
63  int int_value;
64  double double_value;
67  long double long_double_value;
68  } value;
69 };
70 
71 /* Constants for parsing message text. */
72 #define MAX_FLOAT_WIDTH (128*MB_LEN_MAX) /* Max size of float string */
73 #define MAX_INT_WIDTH (64*MB_LEN_MAX) /* Max size of integer string */
74 #define MAX_POINTER_WIDTH (128*MB_LEN_MAX) /* Max size of pointer string */
75 
76 #define SPACE() L" \t"
77 #define DIGITS() L"0123456789"
78 #define INTEGER_SPECS() L"dioxXuc"
79 #define STRING_SPECS() L"s"
80 #define POINTER_SPECS() L"p"
81 #define FLOAT_SPECS() L"fgGeE"
82 #define FLAGS() L"- +0#"
83 #define WC_CSPEC() L'%'
84 #define WC_PSPEC() L'$'
85 #define WC_RADIX() L'.'
86 #define SHORT_SPEC() L'h'
87 #define LONG_SPEC() L'l'
88 #define LONG_DOUBLE_SPEC() L'L'
89 
90 #define GET_WC( wc, mbs, size) (size = mbtowc( &wc, mbs, MB_LEN_MAX), wc)
91 
92 #define REPORT_LINE_WIDTH 72
93 #define REPORT_LINE_INDENT 9
94 
95 /* Current condition data. */
96 static int co_Current_code = 0;
101 
105 
106 
107 static int co_signalv (int code, const char *format, va_list args);
108 #if defined(ENABLE_UNUSED_FUNCTION)
109 static const char *co_print_parameter (int p, CO_FORMAT_TYPE type, const char *format, int width);
110 #endif
111 static int co_find_conversion (const char *format, int from, int *start, CO_FORMAT_TYPE * type, int *position,
112  int *width);
113 
114 static const char *co_conversion_spec (const char *cspec, int size);
115 
116 /*
117  * co_signal() - signal a condition by recording the code, default message, and
118  * parameters used to report the condition
119  * return: condition code
120  * 0 if success.
121  * CO_ERR_BAD_FORMAT if format contains invalid format char.
122  * CO_ERR_BAD_CODE if invalid code.
123  * CO_ERR_BAD_POSITION if format contains a position specifier.
124  * code(in): condition code
125  * format(in): printf-style format string that defines the default
126  * message for the condition
127  *
128  * Note:
129  * The format string contains a conversion specifier for each following
130  * parameter value, in order. The format cannot contain position specifiers.
131  * The reason is that the format string controls how the following parameters
132  * are interpreted. Therefore, the conversion specs in the format must match the
133  * parameters in order and number.
134  */
135 int
136 co_signal (int code, const char *format, ...)
137 {
138  int error;
139  va_list args;
140 
141  assert (format != NULL);
142 
143  va_start (args, format);
144  error = co_signalv (code, format, args);
145  va_end (args);
146  return error;
147 }
148 
149 #if defined(ENABLE_UNUSED_FUNCTION)
150 /*
151  * co_code_module() - return module identifier for the given condition code
152  * return: module identifier
153  * code(in): condition code
154  */
155 int
156 co_code_module (int code)
157 {
158  return (-code) / CO_MAX_CODE;
159 }
160 
161 /*
162  * co_code_id() - return the code identifier for the given codition code
163  * return: code identifier
164  * code(in): condition code
165  */
166 int
167 co_code_id (int code)
168 {
169  return ((-code) % CO_MAX_CODE) + 1;
170 }
171 
172 /*
173  * co_report() - print current condition messageto the given file
174  * return: none
175  * file(in/out): output FILE pointer
176  * severity(in): condition severity level
177  * CO_WARNING_SEVERITY: The user should be aware of the condition but does
178  * not necessarily need to respond to it.
179  * CO_ERROR_SEVERITY: Something has gone wrong. The user should do
180  * something to correct or undo the condition.
181  * CO_FATAL_SEVERITY: Fatal internal error. The program cannot continue.
182  *
183  * Note: If severity is CO_FATAL_SEVERITY, abort() is called after printing
184  * the message.
185  */
186 void
187 co_report (FILE * file, CO_SEVERITY severity)
188 {
189  static const int co_Report_msg_width = REPORT_LINE_WIDTH - REPORT_LINE_INDENT;
190 
191  char label[MB_LEN_MAX * 32];
192  char line[MB_LEN_MAX * REPORT_LINE_WIDTH];
193  const char *message;
194  int label_length;
195  int msg_length;
196  int length;
197  int line_length;
198  int code;
199 
200  assert (file != NULL);
201 
202  code = co_code ();
203  if (!code)
204  {
205  /* No condition to report!! */
206  return;
207  }
208 
209  /* Get condition module/code label. */
210  sprintf (label, " (%d/%d)", co_code_module (code), co_code_id (code));
211 
212  /* Print severity. */
213  switch (severity)
214  {
215  case CO_FATAL_SEVERITY:
216  message = "Quit:";
217  break;
218  case CO_ERROR_SEVERITY:
219  message = "Error:";
220  break;
221  default:
222  message = "Warning:";
223  }
224  fprintf (file, "%-*s", REPORT_LINE_INDENT, message);
225 
226  /* Print message lines. */
227  message = co_message ();
228  for (msg_length = intl_mbs_len (message), label_length = intl_mbs_len (label);
229  (length = msg_length + label_length) > co_Report_msg_width;
230  message = intl_mbs_nth (message, line_length), message += intl_mbs_spn (message, SPACE ()), msg_length =
231  intl_mbs_len (message))
232  {
233  /* Look for word break for next line. */
234  if (msg_length <= co_Report_msg_width)
235  {
236  /* Break at code label. */
237  line_length = msg_length;
238  }
239  else
240  {
241  /* Break at word break. */
242  int nbytes;
243  wchar_t wc;
244  for (line_length = co_Report_msg_width;
245  line_length > 0 && (nbytes = mbtowc (&wc, intl_mbs_nth (message, line_length), MB_LEN_MAX))
246  && !wcschr (SPACE (), wc); line_length--)
247  {
248  ;
249  }
250  if (line_length == 0)
251  {
252  /* Couldn't find word break. */
253  line_length = co_Report_msg_width;
254  }
255  }
256 
257  if (message != NULL)
258  {
259  int len;
260  const char *cptr = intl_mbs_nth (message, line_length);
261  if (cptr == NULL)
262  {
263  len = intl_mbs_len (message);
264  }
265  else
266  {
267  len = cptr - message;
268  }
269 
270  /* Print next message line. */
271  strncpy (line, message, len);
272  line[len] = '\0';
273  fprintf (file, "%s\n%-*s", line, REPORT_LINE_INDENT, "");
274  }
275  }
276 
277  /* Print last line with code label. */
278  fprintf (file, "%s%s\n\n", message, label);
279 
280  if (severity == CO_FATAL_SEVERITY)
281  {
282  abort ();
283  }
284 }
285 
286 /*
287  * co_message() - return a message for the current condition
288  * return: NULL if current condition code is 0,
289  * current condition message string otherwise
290  *
291  * Note:
292  * The caller must not modify or free the returned message string. The
293  * message pointed to by the return value may be changed by the next
294  * call to co_signal(v).
295  *
296  */
297 const char *
298 co_message (void)
299 {
300  int width;
301  int default_position = 0;
302  int start, end;
303  int length;
304  CO_FORMAT_TYPE type;
305  int position;
306  const char *parameter;
307 
308  if (!co_code ())
309  {
310  return NULL;
311  }
312 
313  /* Message already retrieved? */
315  {
316  /* For each conversion specification in message... */
317  for (start = 0;
318  (start =
319  co_find_conversion ((const char *) adj_ar_get_buffer (co_Current_message), start, &end, &type, &position,
320  &width)) != ADJ_AR_EOA; start += length)
321  {
322  /* Get formatted parameter string. */
323  if (type == FORMAT_LITERAL)
324  {
325  parameter = "%";
326  }
327  else
328  {
329  int index;
330 
331  if (position)
332  {
333  index = position;
334  }
335  else
336  {
337  index = default_position;
338  }
339  parameter =
340  co_print_parameter (index, type,
341  co_conversion_spec ((const char *) adj_ar_get_buffer (co_Current_message) + start,
342  end - start), width);
343  }
344 
345  /* Replace conversion spec with formatted parameter string. */
346  length = (parameter != NULL) ? strlen (parameter) : 0;
347  adj_ar_replace (co_Current_message, parameter, length, start, end);
348 
349  if (type != FORMAT_LITERAL)
350  {
351  default_position++;
352  }
353  }
354 
356  }
357  return (const char *) adj_ar_get_buffer (co_Current_message);
358 
359 }
360 #endif
361 
362 /*
363  * co_code() - return the current condition code
364  * return: current condition code
365  */
366 int
367 co_code (void)
368 {
369  return co_Current_code;
370 }
371 
372 #if defined (ENABLE_UNUSED_FUNCTION)
373 /*
374  * co_put_detail() - change the current condition detail level.
375  * return: condition code
376  * 0 if success,
377  * CO_ERR_BAD_DETAIL if invalid detail value is given.
378  * level(in): new condition detail level
379  * CO_DETAIL_USER: Show detail needed by users to understand
380  * and respond to reported conditions.
381  * CO_DETAIL_DBA: Show detail needed by a DBA to understand
382  * and respond to reported conditions.
383  * CO_DETAIL_DEBUG: Show detail needed to locate the source of
384  * internal errors causing conditions.
385  */
386 int
387 co_put_detail (CO_DETAIL level)
388 {
389  int error = 0;
390 
391  if (level < CO_DETAIL_USER || level >= CO_DETAIL_MAX)
392  {
393  error = CO_ERR_BAD_DETAIL;
395  }
396  else
397  {
398  co_Current_detail = level;
399  }
400 
401  return error;
402 
403 }
404 #endif /* ENABLE_UNUSED_FUNCTION */
405 
406 /*
407  * co_final() - clean up all memory allocated in this module
408  * return: none
409  */
410 void
411 co_final (void)
412 {
413  if (co_Current_arguments)
414  {
415  adj_ar_free (co_Current_arguments);
416  co_Current_arguments = NULL;
417  }
418 
419  if (co_String_values)
420  {
421  adj_ar_free (co_String_values);
422  co_String_values = NULL;
423  }
424 
425  if (co_Current_message)
426  {
427  adj_ar_free (co_Current_message);
428  co_Current_message = NULL;
429  }
430 
431  if (co_Conversion_buffer != NULL)
432  {
433  adj_ar_free (co_Conversion_buffer);
434  co_Conversion_buffer = NULL;
435  }
436 
437  if (co_Parameter_string != NULL)
438  {
439  adj_ar_free (co_Parameter_string);
440  co_Parameter_string = NULL;
441  }
442 }
443 
444 /*
445  * co_signal() - an alternate form of co_signal
446  * return: condition code
447  * 0 if success.
448  * CO_ERR_BAD_FORMAT if format contains invalid format char.
449  * CO_ERR_BAD_CODE if invalid code.
450  * CO_ERR_BAD_POSITION if format contains a position specifier.
451  * code(in): condition code
452  * format(in): printf-style format string
453  * args(in) : parameter values specified by format string
454  */
455 static int
456 co_signalv (int code, const char *format, va_list args)
457 {
458  int error;
459  int start, end;
460 
461  /* Check for bad code value. */
462  if (code > 0)
463  {
465  return CO_ERR_BAD_CODE;
466  }
467 
468  /* Initialize current condition state. */
469  if (!co_Current_arguments)
470  {
471  co_Current_arguments = adj_ar_new (sizeof (CO_ARGUMENT), 0, 2.0);
472  co_Current_message = adj_ar_new (sizeof (char), 64 * MB_LEN_MAX, 2.0);
473  co_String_values = adj_ar_new (sizeof (char), 64 * MB_LEN_MAX, 2.0);
474  }
475  co_Current_code = code;
476  adj_ar_remove (co_Current_arguments, 0, ADJ_AR_EOA);
477  adj_ar_remove (co_Current_message, 0, ADJ_AR_EOA);
478  adj_ar_remove (co_String_values, 0, ADJ_AR_EOA);
480 
481  /* Save default message */
482  adj_ar_append (co_Current_message, format, (int) strlen (format) + 1);
483 
484  /* Initialize args for new condition. */
485  for (error = 0, start = 0; !error; start = end)
486  {
487  CO_ARGUMENT arg;
488  CO_FORMAT_TYPE type;
489  int position;
490  int width;
491 
492  start = co_find_conversion (format, start, &end, &type, &position, &width);
493  if (start == ADJ_AR_EOA)
494  {
495  break;
496  }
497 
498  if (position)
499  {
500  error = CO_ERR_BAD_POSITION;
502  }
503  else if (type != FORMAT_LITERAL)
504  {
505  char *string;
506  int nchars;
507 
508  arg.format = type;
509  switch (arg.format)
510  {
511  case FORMAT_STRING:
512  string = va_arg (args, char *);
513  nchars = (int) strlen (string) + 1;
514 
515  /* Save offset to arg in array of string values. */
516  adj_ar_append (co_String_values, (void *) string, nchars);
517  arg.value.int_value = adj_ar_length (co_String_values) - nchars;
518  break;
519 
520  case FORMAT_INTEGER:
521  arg.value.int_value = va_arg (args, int);
522  break;
523 
524  case FORMAT_FLOAT:
525  arg.value.double_value = va_arg (args, double);
526  break;
527 
528  case FORMAT_POINTER:
529  arg.value.pointer_value = va_arg (args, void *);
530  break;
531 
532  case FORMAT_LONG_INTEGER:
533  arg.value.long_int_value = va_arg (args, long);
534  break;
535 
536  case FORMAT_LONG_DOUBLE:
537  arg.value.long_double_value = va_arg (args, long double);
538  break;
539 
540  default:
541  error = CO_ERR_BAD_FORMAT;
542  co_signal (error, CO_ER_FMT_BAD_FORMAT, co_conversion_spec (format + start, end - start));
543  }
544 
545  if (!error)
546  {
547  /* Append next arg to array of arg values. */
548  adj_ar_append (co_Current_arguments, (void *) &arg, 1);
549  }
550  }
551  }
552 
553  return error;
554 }
555 
556 #if defined(ENABLE_UNUSED_FUNCTION)
557 /*
558  * co_print_parameter() - print given parameter using given format
559  * return: formatted parameter string
560  * index(in): index of parameter to print
561  * type(in): parameter format type
562  * format(in) : parameter format string
563  * width(in) : parameter field width
564  */
565 static const char *
566 co_print_parameter (int index, CO_FORMAT_TYPE type, const char *format, int width)
567 {
568  static const char *bad_index = "?";
569  static const char *bad_type = "*";
570  CO_ARGUMENT *arg;
571  char *string;
572 
573  if (!co_Parameter_string)
574  {
575  co_Parameter_string = adj_ar_new (sizeof (char), 32 * MB_LEN_MAX, 2.0);
576  if (co_Parameter_string == NULL)
577  {
578  return NULL;
579  }
580  }
581  adj_ar_remove (co_Parameter_string, 0, ADJ_AR_EOA);
582 
583  /* Adjust position to 0-based index. */
584  index--;
585 
586  /* Adjust width to char size. */
587  width *= MB_LEN_MAX;
588 
589  /* Valid parameter index? */
590  if (index < 0 || index >= adj_ar_length (co_Current_arguments))
591  {
592  adj_ar_replace (co_Parameter_string, bad_index, strlen (bad_index) + 1, 0, ADJ_AR_EOA);
593  }
594  else
595  {
596  /* Format matches arg type? */
597  arg = (CO_ARGUMENT *) adj_ar_get_buffer (co_Current_arguments) + index;
598  if (type != arg->format)
599  {
600  adj_ar_replace (co_Parameter_string, bad_type, strlen (bad_type) + 1, 0, ADJ_AR_EOA);
601  }
602  else
603  {
604  /* Print parameter into string array. */
605  switch (type)
606  {
607  case FORMAT_STRING:
608  string = (char *) adj_ar_get_buffer (co_String_values) + arg->value.int_value;
609  adj_ar_initialize (co_Parameter_string, NULL,
610  width > (int) strlen (string) ? width + 1 : (int) strlen (string) + 1);
611  sprintf ((char *) adj_ar_get_buffer (co_Parameter_string), format, string);
612  break;
613 
614  case FORMAT_INTEGER:
615  adj_ar_initialize (co_Parameter_string, NULL, width > MAX_INT_WIDTH ? width + 1 : MAX_INT_WIDTH);
616  sprintf ((char *) adj_ar_get_buffer (co_Parameter_string), format, arg->value.int_value);
617  break;
618 
619  case FORMAT_FLOAT:
620  adj_ar_initialize (co_Parameter_string, NULL, width > MAX_FLOAT_WIDTH ? width + 1 : MAX_FLOAT_WIDTH);
621  sprintf ((char *) adj_ar_get_buffer (co_Parameter_string), format, arg->value.double_value);
622  break;
623 
624  case FORMAT_POINTER:
625  adj_ar_initialize (co_Parameter_string, NULL, width > MAX_POINTER_WIDTH ? width + 1 : MAX_POINTER_WIDTH);
626  sprintf ((char *) adj_ar_get_buffer (co_Parameter_string), format, arg->value.pointer_value);
627  break;
628 
629  case FORMAT_LONG_INTEGER:
630  adj_ar_initialize (co_Parameter_string, NULL, width > MAX_INT_WIDTH ? width + 1 : MAX_INT_WIDTH);
631  sprintf ((char *) adj_ar_get_buffer (co_Parameter_string), format, arg->value.long_int_value);
632  break;
633 
634  case FORMAT_LONG_DOUBLE:
635  adj_ar_initialize (co_Parameter_string, NULL, width > MAX_FLOAT_WIDTH ? width + 1 : MAX_FLOAT_WIDTH);
636  sprintf ((char *) adj_ar_get_buffer (co_Parameter_string), format, arg->value.long_double_value);
637  break;
638 
639  default:
640  /* Should never get here. */
641  adj_ar_replace (co_Parameter_string, bad_type, strlen (bad_type) + 1, 0, ADJ_AR_EOA);
642  break;
643  }
644  }
645  }
646 
647  return (const char *) adj_ar_get_buffer (co_Parameter_string);
648 }
649 #endif
650 
651 /*
652  * co_find_conversion() - return a description of the next conversion spec in
653  * the given format string, starting at the given position
654  * return: ADJ_AR_EOF if no more conversion specs are found,
655  * index of the first char in the conversion spec otherwise.
656  * format(in): format string
657  * from(in): start position to scan
658  * end(out): end of conversion spec
659  * type(out): parameter format type returned (%, d, f, p, or s)
660  * position(out): position specifier returned (0 if none)
661  * width(out): field width of format returned (0 if none)
662  */
663 static int
664 co_find_conversion (const char *format, int from, int *end, CO_FORMAT_TYPE * type, int *position, int *width)
665 {
666  const char *p;
667  wchar_t wc;
668  int csize;
669  int result = 0;
670  int val;
671 
672  /* No more conversion specs? */
673  const char *start = intl_mbs_chr (format + from, WC_CSPEC ());
674  if (!start)
675  {
676  return ADJ_AR_EOA;
677  }
678 
679  /* Parse next conversion spec. */
680  p = intl_mbs_nth (start, 1);
681  if (!p)
682  {
683  return ADJ_AR_EOA;
684  }
685  *position = 0;
686 
687  /* Handle %% spec */
688  if (GET_WC (wc, p, csize) == WC_CSPEC ())
689  {
690  *type = FORMAT_LITERAL;
691  *width = 0;
692  }
693  else
694  {
695  CO_FORMAT_TYPE length_type;
696  char *rest;
697 
698  /* Return position specifier. */
699  result = str_to_int32 (&val, &rest, p, 10);
700  if (result == 0 && val > 0 && GET_WC (wc, rest, csize) == WC_PSPEC ())
701  {
702  *position = val;
703  p = rest + csize;
704  }
705  else
706  {
707  *position = 0;
708  }
709 
710  /* Skip flags. */
711  p += intl_mbs_spn (p, FLAGS ());
712 
713  /* Width specified? */
714  result = str_to_int32 (&val, &rest, p, 10);
715  if (result == 0)
716  {
717  *width = val;
718 
719  /* Yes, skip precision. */
720  p = rest;
721  if (GET_WC (wc, p, csize) == WC_RADIX ())
722  {
723  while (wcschr (DIGITS (), GET_WC (wc, (p += csize), csize)))
724  {
725  ;
726  }
727  }
728  }
729 
730  /* Check for short/long specifier. */
731  GET_WC (wc, p, csize);
732  switch (wc)
733  {
734  case SHORT_SPEC ():
735  length_type = FORMAT_INTEGER;
736  p += csize;
737  break;
738  case LONG_SPEC ():
739  length_type = FORMAT_LONG_INTEGER;
740  p += csize;
741  break;
742  case LONG_DOUBLE_SPEC ():
743  length_type = FORMAT_LONG_DOUBLE;
744  p += csize;
745  break;
746  default:
747  length_type = FORMAT_UNKNOWN;
748  }
749 
750  /* Return format type. */
751  GET_WC (wc, p, csize);
752 
753  if (wcschr (INTEGER_SPECS (), wc))
754  {
755  *type = FORMAT_INTEGER;
756  }
757  else if (wcschr (STRING_SPECS (), wc))
758  {
759  *type = FORMAT_STRING;
760  }
761  else if (wcschr (FLOAT_SPECS (), wc))
762  {
763  *type = FORMAT_FLOAT;
764  }
765  else if (wcschr (POINTER_SPECS (), wc))
766  {
767  *type = FORMAT_POINTER;
768  }
769  else
770  {
771  *type = FORMAT_UNKNOWN;
772  }
773 
774  /* Reconcile conversion char with short/long spec. */
775  if ((length_type == FORMAT_INTEGER && *type != FORMAT_INTEGER)
776  || (length_type == FORMAT_LONG_INTEGER && *type != FORMAT_INTEGER) || (length_type == FORMAT_LONG_DOUBLE
777  && *type != FORMAT_FLOAT))
778  {
779  /* Invalid combination! */
780  *type = FORMAT_UNKNOWN;
781  }
782  else if (length_type != FORMAT_UNKNOWN)
783  {
784  /* Conversion type modified by short/long spec. */
785  *type = length_type;
786  }
787  }
788 
789  /* Return end of conversion spec. */
790  *end = CAST_STRLEN (p + csize - format);
791 
792  /* Return start of conversion spec. */
793  return CAST_STRLEN (start - format);
794 }
795 
796 /*
797  * co_conversion_spec() - return the same conversion spec with any position
798  * specifier removed
799  * return: modified conversion spec string
800  * cspec(in): conversion spec string
801  * size(in): size of cspec
802  */
803 static const char *
804 co_conversion_spec (const char *cspec, int size)
805 {
806  const char *new_cspec, *end;
807 
808  /* Copy conversion spec to NUL-terminated array. */
809  if (!co_Conversion_buffer)
810  {
811  co_Conversion_buffer = adj_ar_new (sizeof (char), 4 * MB_LEN_MAX, 2.0);
812  if (co_Conversion_buffer == NULL)
813  {
814  return NULL;
815  }
816  }
817  adj_ar_replace (co_Conversion_buffer, cspec, size, 0, ADJ_AR_EOA);
818  adj_ar_append (co_Conversion_buffer, "\0", 1);
819  new_cspec = (const char *) adj_ar_get_buffer (co_Conversion_buffer);
820 
821  /* Is there a position specifier? */
822  end = intl_mbs_chr (new_cspec, WC_PSPEC ());
823  if (end)
824  {
825  /*
826  * remove position specifier from conversion spec, i.e. remove
827  * all chars following initial '%' up through final '$'.
828  */
829  adj_ar_remove (co_Conversion_buffer, mblen (new_cspec, MB_LEN_MAX),
830  CAST_STRLEN (end + mblen (end, MB_LEN_MAX) - new_cspec));
831  }
832 
833  return new_cspec;
834 }
void * pointer_value
static ADJ_ARRAY * co_Conversion_buffer
int intl_mbs_len(const char *mbs)
Definition: intl_support.c:183
#define GET_WC(wc, mbs, size)
static CO_DETAIL co_Current_detail
static int co_Current_code
#define CO_ERR_BAD_CODE
#define FLAGS()
#define REPORT_LINE_INDENT
char * intl_mbs_chr(const char *mbs, wchar_t wc)
Definition: intl_support.c:149
#define CO_MAX_CODE
#define CO_ER_FMT_BAD_CODE
#define MAX_FLOAT_WIDTH
static ADJ_ARRAY * co_String_values
#define INTEGER_SPECS()
const char * intl_mbs_nth(const char *mbs, size_t n)
Definition: intl_support.c:219
CO_SEVERITY
#define ADJ_AR_EOA
#define CO_ER_FMT_BAD_FORMAT
int co_code(void)
#define CO_ER_FMT_BAD_DETAIL
#define SPACE()
void * adj_ar_get_buffer(const ADJ_ARRAY *adj_array_p)
int co_signal(int code, const char *format,...)
#define CAST_STRLEN
Definition: porting.h:470
#define WC_RADIX()
#define LONG_SPEC()
union co_argument::@3 value
int intl_mbs_spn(const char *mbs, const wchar_t *chars)
Definition: intl_support.c:269
#define SHORT_SPEC()
int adj_ar_length(const ADJ_ARRAY *adj_array_p)
#define MAX_INT_WIDTH
CO_FORMAT_TYPE format
#define FLOAT_SPECS()
#define assert(x)
static const char * co_conversion_spec(const char *cspec, int size)
#define WC_CSPEC()
static int co_Message_completed
#define DIGITS()
long double long_double_value
#define CO_ERR_BAD_POSITION
#define NULL
Definition: freelistheap.h:34
int str_to_int32(int *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2346
int adj_ar_replace(ADJ_ARRAY *adj_array_p, const void *src, int src_length, int start, int end)
int adj_ar_append(ADJ_ARRAY *adj_array_p, const void *src, int src_length)
#define MB_LEN_MAX
Definition: intl_support.h:53
#define WC_PSPEC()
int adj_ar_remove(ADJ_ARRAY *adj_array_p, int start, int end)
static ADJ_ARRAY * co_Parameter_string
co_format_type
static void error(const char *msg)
Definition: gencat.c:331
void co_final(void)
static ADJ_ARRAY * co_Current_message
#define strlen(s1)
Definition: intl_support.c:43
static int co_find_conversion(const char *format, int from, int *start, CO_FORMAT_TYPE *type, int *position, int *width)
#define POINTER_SPECS()
CO_DETAIL
#define CO_ERR_BAD_DETAIL
enum co_format_type CO_FORMAT_TYPE
static int co_signalv(int code, const char *format, va_list args)
#define CO_ER_FMT_BAD_POSITION
#define LONG_DOUBLE_SPEC()
#define MAX_POINTER_WIDTH
ADJ_ARRAY * adj_ar_new(int element_size, int min, float growth_rate)
#define REPORT_LINE_WIDTH
#define CO_ERR_BAD_FORMAT
#define STRING_SPECS()
const char ** p
Definition: dynamic_load.c:945
static ADJ_ARRAY * co_Current_arguments
int adj_ar_initialize(ADJ_ARRAY *adj_array_p, const void *initial, int initial_length)
void adj_ar_free(ADJ_ARRAY *adj_array_p)