GnuCOBOL  2.0
A free COBOL compiler
strings.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2014 Free Software Foundation, Inc.
3  Written by Keisuke Nishida, Roger While
4 
5  This file is part of GnuCOBOL.
6 
7  The GnuCOBOL runtime library is free software: you can redistribute it
8  and/or modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation, either version 3 of the
10  License, or (at your option) any later version.
11 
12  GnuCOBOL is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GnuCOBOL. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 
22 #include "config.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stddef.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <sys/types.h>
31 
32 /* Force symbol exports */
33 #define COB_LIB_EXPIMP
34 
35 #include "libcob.h"
36 #include "coblocal.h"
37 
38 #define INSPECT_ALL 0
39 #define INSPECT_LEADING 1
40 #define INSPECT_FIRST 2
41 #define INSPECT_TRAILING 3
42 
43 #define DLM_DEFAULT_NUM 8U
44 
45 struct dlm_struct {
48 };
49 
50 /* Local variables */
51 
53  {COB_TYPE_ALPHANUMERIC, 0, 0, 0, NULL};
55  {COB_TYPE_ALPHANUMERIC_ALL, 0, 0, 0, NULL};
56 
58 static unsigned char *inspect_data;
59 static unsigned char *inspect_start;
60 static unsigned char *inspect_end;
61 static int *inspect_mark;
62 static size_t inspect_mark_size;
63 static size_t inspect_size;
65 static int inspect_sign;
67 
74 static int string_offset;
75 
76 static struct dlm_struct *dlm_list;
79 static size_t dlm_list_size;
82 static int unstring_offset;
83 static int unstring_count;
84 static int unstring_ndlms;
85 
86 static unsigned char *figurative_ptr;
87 static size_t figurative_size;
88 
91 
92 /* Local functions */
93 
94 static COB_INLINE int
95 cob_min_int (const int x, const int y)
96 {
97  if (x < y) {
98  return x;
99  }
100  return y;
101 }
102 
103 static void
104 cob_str_memcpy (cob_field *dst, unsigned char *src, const int size)
105 {
106  cob_field temp;
107 
108  temp.size = size;
109  temp.data = src;
110  temp.attr = &const_alpha_attr;
111  cob_move (&temp, dst);
112 }
113 
114 static void
116 {
117 
118  unsigned char *s;
119  size_t size1;
120  size_t size2;
121  size_t n;
122 
123  size2 = f2->size;
124  if (size2 > figurative_size) {
125  if (figurative_ptr) {
127  }
128  figurative_ptr = cob_malloc (size2);
129  figurative_size = size2;
130  }
131  size1 = 0;
132  s = figurative_ptr;
133  for (n = 0; n < size2; ++n, ++s) {
134  *s = f1->data[size1];
135  size1++;
136  if (size1 >= f1->size) {
137  size1 = 0;
138  }
139  }
140  alpha_fld.size = size2;
141  alpha_fld.data = figurative_ptr;
142 }
143 
144 static void
145 inspect_common (cob_field *f1, cob_field *f2, const int type)
146 {
147  int *mark;
148  size_t n = 0;
149  size_t j;
150  int i;
151  int len;
152 
153  if (unlikely(!f1)) {
154  f1 = &str_cob_low;
155  }
156  if (unlikely(!f2)) {
157  f2 = &str_cob_low;
158  }
159 
160  if (inspect_replacing && f1->size != f2->size) {
162  alloc_figurative (f1, f2);
163  f1 = &alpha_fld;
164  } else {
166  return;
167  }
168  }
169 
171  len = (int)(inspect_end - inspect_start);
172  if (type == INSPECT_TRAILING) {
173  for (i = len - (int)f2->size; i >= 0; --i) {
174  /* Find matching substring */
175  if (memcmp (inspect_start + i, f2->data, f2->size) == 0) {
176  /* Check if it is already marked */
177  for (j = 0; j < f2->size; ++j) {
178  if (mark[i + j] != -1) {
179  break;
180  }
181  }
182  /* If not, mark and count it */
183  if (j == f2->size) {
184  for (j = 0; j < f2->size; ++j) {
185  mark[i + j] = inspect_replacing ? f1->data[j] : 1;
186  }
187  i -= f2->size - 1;
188  n++;
189  }
190  } else {
191  break;
192  }
193  }
194  } else {
195  for (i = 0; i < (int)(len - f2->size + 1); ++i) {
196  /* Find matching substring */
197  if (memcmp (inspect_start + i, f2->data, f2->size) == 0) {
198  /* Check if it is already marked */
199  for (j = 0; j < f2->size; ++j) {
200  if (mark[i + j] != -1) {
201  break;
202  }
203  }
204  /* If not, mark and count it */
205  if (j == f2->size) {
206  for (j = 0; j < f2->size; ++j) {
207  mark[i + j] = inspect_replacing ? f1->data[j] : 1;
208  }
209  i += f2->size - 1;
210  n++;
211  if (type == INSPECT_FIRST) {
212  break;
213  }
214  }
215  } else if (type == INSPECT_LEADING) {
216  break;
217  }
218  }
219  }
220 
221  if (n > 0 && !inspect_replacing) {
222  cob_add_int (f1, (int) n, 0);
223  }
224 }
225 
226 /* Global functions */
227 
228 /* INSPECT */
229 
230 void
231 cob_inspect_init (cob_field *var, const cob_u32_t replacing)
232 {
233  size_t i;
234  size_t digcount;
235 
236  if (unlikely(COB_FIELD_IS_NUMDISP (var))) {
237  inspect_var_copy = *var;
238  inspect_var = &inspect_var_copy;
239  inspect_sign = COB_GET_SIGN (var);
240  } else {
241  inspect_var = NULL;
242  }
245  inspect_replacing = replacing;
247  inspect_end = NULL;
248  digcount = inspect_size * sizeof (int);
249  if (digcount > inspect_mark_size) {
250  if (inspect_mark) {
252  }
253  inspect_mark = cob_fast_malloc (digcount);
254  inspect_mark_size = digcount;
255  }
256  for (i = 0; i < inspect_size; ++i) {
257  inspect_mark[i] = -1;
258  }
259  cob_set_exception (0);
260 }
261 
262 void
264 {
267 }
268 
269 void
271 {
272  unsigned char *p;
273 
274  for (p = inspect_start; p < inspect_end - str->size + 1; ++p) {
275  if (memcmp (p, str->data, str->size) == 0) {
276  inspect_end = p;
277  return;
278  }
279  }
280 }
281 
282 void
284 {
285  unsigned char *p;
286 
287  for (p = inspect_start; p < inspect_end - str->size + 1; ++p) {
288  if (memcmp (p, str->data, str->size) == 0) {
289  inspect_start = p + str->size;
290  return;
291  }
292  }
294 }
295 
296 void
298 {
299  int *mark;
300  int i;
301  int n;
302  int len;
303 
305  len = (int)(inspect_end - inspect_start);
306  if (inspect_replacing) {
307  /* INSPECT REPLACING CHARACTERS f1 */
308  for (i = 0; i < len; ++i) {
309  if (mark[i] == -1) {
310  mark[i] = f1->data[0];
311  }
312  }
313  } else {
314  /* INSPECT TALLYING f1 CHARACTERS */
315  n = 0;
316  for (i = 0; i < len; ++i) {
317  if (mark[i] == -1) {
318  mark[i] = 1;
319  n++;
320  }
321  }
322  if (n > 0) {
323  cob_add_int (f1, n, 0);
324  }
325  }
326 }
327 
328 void
330 {
331  inspect_common (f1, f2, INSPECT_ALL);
332 }
333 
334 void
336 {
338 }
339 
340 void
342 {
343  inspect_common (f1, f2, INSPECT_FIRST);
344 }
345 
346 void
348 {
350 }
351 
352 void
354 {
355  size_t i;
356  size_t j;
357  size_t len;
358 
359  if (unlikely(!f1)) {
360  f1 = &str_cob_low;
361  }
362  if (unlikely(!f2)) {
363  f2 = &str_cob_low;
364  }
365  if (f1->size != f2->size) {
367  alloc_figurative (f2, f1);
368  f2 = &alpha_fld;
369  } else {
371  return;
372  }
373  }
374 
375  len = (size_t)(inspect_end - inspect_start);
376  for (j = 0; j < f1->size; ++j) {
377  for (i = 0; i < len; ++i) {
378  if (inspect_mark[i] == -1 &&
379  inspect_start[i] == f1->data[j]) {
380  inspect_start[i] = f2->data[j];
381  inspect_mark[i] = 1;
382  }
383  }
384  }
385 }
386 
387 void
389 {
390  size_t i;
391 
392  if (inspect_replacing) {
393  for (i = 0; i < inspect_size; ++i) {
394  if (inspect_mark[i] != -1) {
395  inspect_data[i] = inspect_mark[i];
396  }
397  }
398  }
399 
400  if (unlikely(inspect_var)) {
401  COB_PUT_SIGN (inspect_var, inspect_sign);
402  }
403 }
404 
405 /* STRING */
406 
407 void
409 {
410  string_dst_copy = *dst;
411  string_dst = &string_dst_copy;
412  string_ptr = NULL;
413  if (ptr) {
414  string_ptr_copy = *ptr;
415  string_ptr = &string_ptr_copy;
416  }
417  string_offset = 0;
418  cob_set_exception (0);
419 
420  if (string_ptr) {
421  string_offset = cob_get_int (string_ptr) - 1;
422  if (string_offset < 0 ||
423  string_offset >= (int)string_dst->size) {
425  }
426  }
427 }
428 
429 void
431 {
432  string_dlm = NULL;
433  if (dlm) {
434  string_dlm_copy = *dlm;
435  string_dlm = &string_dlm_copy;
436  }
437 }
438 
439 void
441 {
442  size_t src_size;
443  int i;
444  int size;
445 
446  if (cob_get_exception_code ()) {
447  return;
448  }
449 
450  src_size = src->size;
451  if (!src_size) {
452  return;
453  }
454  if (string_dlm) {
455  size = (int)(src_size - string_dlm->size + 1);
456  for (i = 0; i < size; ++i) {
457  if (memcmp (src->data + i, string_dlm->data,
458  string_dlm->size) == 0) {
459  src_size = i;
460  break;
461  }
462  }
463  }
464 
465  if (src_size <= string_dst->size - string_offset) {
466  memcpy (string_dst->data + string_offset, src->data, src_size);
467  string_offset += (int) src_size;
468  } else {
469  size = (int)(string_dst->size - string_offset);
470  memcpy (string_dst->data + string_offset, src->data, (size_t)size);
471  string_offset += size;
473  }
474 }
475 
476 void
478 {
479  if (string_ptr) {
480  cob_set_int (string_ptr, string_offset + 1);
481  }
482 }
483 
484 /* UNSTRING */
485 
486 void
487 cob_unstring_init (cob_field *src, cob_field *ptr, const size_t num_dlm)
488 {
489  unstring_src_copy = *src;
490  unstring_src = &unstring_src_copy;
491  unstring_ptr = NULL;
492  if (ptr) {
493  unstring_ptr_copy = *ptr;
494  unstring_ptr = &unstring_ptr_copy;
495  }
496 
497  unstring_offset = 0;
498  unstring_count = 0;
499  unstring_ndlms = 0;
500  cob_set_exception (0);
501  if (num_dlm > dlm_list_size) {
502  cob_free (dlm_list);
503  dlm_list = cob_malloc (num_dlm * sizeof(struct dlm_struct));
504  dlm_list_size = num_dlm;
505  }
506 
507  if (unstring_ptr) {
508  unstring_offset = cob_get_int (unstring_ptr) - 1;
509  if (unstring_offset < 0 || unstring_offset >= (int)unstring_src->size) {
511  }
512  }
513 }
514 
515 void
517 {
518  dlm_list[unstring_ndlms].uns_dlm = *dlm;
519  dlm_list[unstring_ndlms].uns_all = all;
520  unstring_ndlms++;
521 }
522 
523 void
525 {
526  unsigned char *p;
527  unsigned char *dp;
528  unsigned char *s;
529  unsigned char *dlm_data;
530  unsigned char *start;
531  size_t dlm_size = 0;
532  int i;
533  int srsize;
534  int dlsize;
535  int match_size = 0;
536  int brkpt = 0;
537 
538  if (cob_get_exception_code ()) {
539  return;
540  }
541 
542  if (unstring_offset >= (int)unstring_src->size) {
543  return;
544  }
545 
546  start = unstring_src->data + unstring_offset;
547  dlm_data = NULL;
548  if (unstring_ndlms == 0) {
549  match_size = cob_min_int ((int)COB_FIELD_SIZE (dst),
550  (int)unstring_src->size - unstring_offset);
551  cob_str_memcpy (dst, start, match_size);
552  unstring_offset += match_size;
553  } else {
554  srsize = (int) unstring_src->size;
555  s = unstring_src->data + srsize;
556  for (p = start; p < s; ++p) {
557  for (i = 0; i < unstring_ndlms; ++i) {
558  dlsize = (int) dlm_list[i].uns_dlm.size;
559  dp = dlm_list[i].uns_dlm.data;
560  if (p + dlsize > s) {
561  continue;
562  }
563  if (!memcmp (p, dp, (size_t)dlsize)) { /* delimiter equal */
564  match_size = (int)(p - start); /* count in */
565  cob_str_memcpy (dst, start, match_size); /* into */
566  unstring_offset += match_size + dlsize; /* with pointer */
567  dlm_data = dp;
568  dlm_size = dlsize;
569  if (dlm_list[i].uns_all) { /* delimited by all */
570  for (p += dlsize ; p < s; p += dlsize) {
571  if (p + dlsize > s) {
572  break;
573  }
574  if (memcmp (p, dp, (size_t)dlsize)) {
575  break;
576  }
577  unstring_offset += dlsize;
578  }
579  }
580  brkpt = 1;
581  break;
582  }
583  }
584  if (brkpt) {
585  break;
586  }
587  }
588  if (!brkpt) {
589  /* No match */
590  match_size = (int)(unstring_src->size - unstring_offset);
591  cob_str_memcpy (dst, start, match_size);
592  unstring_offset = (int) unstring_src->size;
593  dlm_data = NULL;
594  }
595  }
596  unstring_count++;
597 
598  if (dlm) {
599  if (dlm_data) {
600  cob_str_memcpy (dlm, dlm_data, (int) dlm_size);
601  } else if (COB_FIELD_IS_NUMERIC (dlm)) {
602  cob_set_int (dlm, 0);
603  } else {
604  memset (dlm->data, ' ', dlm->size);
605  }
606  }
607 
608  if (cnt) {
609  cob_set_int (cnt, match_size);
610  }
611 }
612 
613 void
615 {
616  cob_add_int (f, unstring_count, 0);
617 }
618 
619 void
621 {
622  if (unstring_offset < (int)unstring_src->size) {
624  }
625 
626  if (unstring_ptr) {
627  cob_set_int (unstring_ptr, unstring_offset + 1);
628  }
629 }
630 
631 /* Initialization/Termination */
632 
633 void
635 {
636  if (inspect_mark) {
638  inspect_mark = NULL;
639  }
640  if (dlm_list) {
641  cob_free (dlm_list);
642  dlm_list = NULL;
643  }
644  if (figurative_ptr) {
647  }
648  figurative_size = 0;
649 }
650 
651 void
653 {
655  dlm_list = cob_malloc (DLM_DEFAULT_NUM * sizeof(struct dlm_struct));
659  figurative_size = 0;
660  alpha_fld.size = 0;
661  alpha_fld.data = NULL;
662  alpha_fld.attr = &const_alpha_attr;
663  str_cob_low.size = 1;
664  str_cob_low.data = (cob_u8_ptr)"\0";
665  str_cob_low.attr = &const_strall_attr;
666 }
static void inspect_common(cob_field *f1, cob_field *f2, const int type)
Definition: strings.c:145
void cob_string_init(cob_field *dst, cob_field *ptr)
Definition: strings.c:408
static size_t inspect_mark_size
Definition: strings.c:62
void cob_free(void *mptr)
Definition: common.c:1284
static int unstring_offset
Definition: strings.c:82
#define COB_FIELD_IS_NUMDISP(f)
Definition: common.h:675
#define cob_u32_t
Definition: common.h:31
#define COB_FIELD_DATA(f)
Definition: common.h:668
void cob_unstring_init(cob_field *src, cob_field *ptr, const size_t num_dlm)
Definition: strings.c:487
static void cob_str_memcpy(cob_field *dst, unsigned char *src, const int size)
Definition: strings.c:104
static unsigned char * inspect_data
Definition: strings.c:58
int cob_add_int(cob_field *, const int, const int)
Definition: numeric.c:2195
#define DLM_DEFAULT_NUM
Definition: strings.c:43
void cob_inspect_before(const cob_field *str)
Definition: strings.c:270
#define INSPECT_ALL
Definition: strings.c:38
static cob_field * string_ptr
Definition: strings.c:69
#define COB_FIELD_IS_NUMERIC(f)
Definition: common.h:674
void cob_move(cob_field *, cob_field *)
Definition: move.c:1170
#define COB_TYPE_ALPHANUMERIC
Definition: common.h:621
static const cob_field_attr const_alpha_attr
Definition: strings.c:52
#define COB_FIELD_TYPE(f)
Definition: common.h:662
#define COB_NORMAL_BUFF
Definition: common.h:541
static cob_field str_cob_low
Definition: strings.c:90
void cob_unstring_finish(void)
Definition: strings.c:620
static cob_field * inspect_var
Definition: strings.c:57
void cob_inspect_leading(cob_field *f1, cob_field *f2)
Definition: strings.c:335
cob_field f2
Definition: cobxref.c.l.h:55
static int unstring_count
Definition: strings.c:83
#define COB_INLINE
Definition: common.h:354
void cob_inspect_init(cob_field *var, const cob_u32_t replacing)
Definition: strings.c:231
void cob_inspect_characters(cob_field *f1)
Definition: strings.c:297
#define INSPECT_FIRST
Definition: strings.c:40
#define INSPECT_TRAILING
Definition: strings.c:41
unsigned char * data
Definition: common.h:952
void cob_string_append(cob_field *src)
Definition: strings.c:440
static int * inspect_mark
Definition: strings.c:61
static size_t inspect_size
Definition: strings.c:63
int cob_get_int(cob_field *)
Definition: move.c:1626
static cob_field inspect_var_copy
Definition: strings.c:66
static cob_field * string_dst
Definition: strings.c:68
void cob_unstring_tallying(cob_field *f)
Definition: strings.c:614
void cob_string_finish(void)
Definition: strings.c:477
void cob_string_delimited(cob_field *dlm)
Definition: strings.c:430
#define COB_GET_SIGN(f)
Definition: coblocal.h:158
static COB_INLINE int cob_min_int(const int x, const int y)
Definition: strings.c:95
void cob_exit_strings(void)
Definition: strings.c:634
#define cob_u8_ptr
Definition: common.h:66
#define unlikely(x)
Definition: common.h:437
static struct dlm_struct * dlm_list
Definition: strings.c:76
EC ARGUMENT EC EC BOUND EC BOUND EC BOUND EC BOUND TABLE EC DATA EC DATA EC DATA PTR NULL
Definition: exception.def:95
static cob_field alpha_fld
Definition: strings.c:89
static cob_field * unstring_ptr
Definition: strings.c:78
static cob_field string_ptr_copy
Definition: strings.c:72
cob_field f1
Definition: cobxref.c.l.h:54
int cob_get_exception_code(void)
Definition: common.c:1193
void cob_set_exception(const int id)
Definition: common.c:1212
static size_t dlm_list_size
Definition: strings.c:79
static void alloc_figurative(const cob_field *f1, const cob_field *f2)
Definition: strings.c:115
static unsigned char * inspect_end
Definition: strings.c:60
void cob_set_int(cob_field *, const int)
Definition: move.c:1612
#define COB_PUT_SIGN(f, s)
Definition: coblocal.h:160
cob_field uns_dlm
Definition: strings.c:46
#define COB_TYPE_ALPHANUMERIC_ALL
Definition: common.h:622
void cob_inspect_finish(void)
Definition: strings.c:388
void cob_inspect_start(void)
Definition: strings.c:263
void cob_inspect_trailing(cob_field *f1, cob_field *f2)
Definition: strings.c:347
static cob_field string_dst_copy
Definition: strings.c:71
static const cob_field_attr const_strall_attr
Definition: strings.c:54
static cob_u32_t inspect_replacing
Definition: strings.c:64
#define INSPECT_LEADING
Definition: strings.c:39
static int unstring_ndlms
Definition: strings.c:84
size_t size
Definition: common.h:951
cob_u32_t uns_all
Definition: strings.c:47
const cob_field_attr * attr
Definition: common.h:953
void cob_inspect_converting(const cob_field *f1, const cob_field *f2)
Definition: strings.c:353
void cob_unstring_delimited(cob_field *dlm, const cob_u32_t all)
Definition: strings.c:516
static int string_offset
Definition: strings.c:74
void * cob_malloc(const size_t size)
Definition: common.c:1250
void cob_init_strings(void)
Definition: strings.c:652
static unsigned char * figurative_ptr
Definition: strings.c:86
void cob_inspect_after(const cob_field *str)
Definition: strings.c:283
void * cob_fast_malloc(const size_t size)
Definition: common.c:1296
static size_t figurative_size
Definition: strings.c:87
static cob_field unstring_ptr_copy
Definition: strings.c:81
static unsigned char * inspect_start
Definition: strings.c:59
void cob_unstring_into(cob_field *dst, cob_field *dlm, cob_field *cnt)
Definition: strings.c:524
static cob_field unstring_src_copy
Definition: strings.c:80
void cob_inspect_first(cob_field *f1, cob_field *f2)
Definition: strings.c:341
void cob_inspect_all(cob_field *f1, cob_field *f2)
Definition: strings.c:329
static int inspect_sign
Definition: strings.c:65
static cob_field string_dlm_copy
Definition: strings.c:73
static cob_field * unstring_src
Definition: strings.c:77
#define COB_FIELD_SIZE(f)
Definition: common.h:671
static cob_field * string_dlm
Definition: strings.c:70