OpenCOBOL 1.1pre-rel
strings.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002-2009 Keisuke Nishida
00003  * Copyright (C) 2007-2009 Roger While
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public License
00007  * as published by the Free Software Foundation; either version 2.1,
00008  * or (at your option) any later version.
00009  * 
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU Lesser General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; see the file COPYING.LIB.  If
00017  * not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor
00018  * Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include "config.h"
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <stdarg.h>
00026 #include <string.h>
00027 #include <sys/types.h>
00028 
00029 #include "move.h"
00030 #include "coblocal.h"
00031 #include "numeric.h"
00032 #include "strings.h"
00033 
00034 #define INSPECT_ALL             0
00035 #define INSPECT_LEADING         1
00036 #define INSPECT_FIRST           2
00037 #define INSPECT_TRAILING        3
00038 
00039 #define DLM_DEFAULT_NUM         8
00040 
00041 struct dlm_struct {
00042         cob_field       *uns_dlm;
00043         int             uns_all;
00044 };
00045 
00046 static cob_field                *inspect_var;
00047 static unsigned char            *inspect_data;
00048 static unsigned char            *inspect_start;
00049 static unsigned char            *inspect_end;
00050 static int                      *inspect_mark = NULL;
00051 static size_t                   lastsize = 0;
00052 static size_t                   inspect_size;
00053 static int                      inspect_replacing;
00054 static int                      inspect_sign;
00055 static cob_field                inspect_var_copy;
00056 
00057 static cob_field                *string_dst;
00058 static cob_field                *string_ptr;
00059 static cob_field                *string_dlm;
00060 static cob_field                string_dst_copy;
00061 static cob_field                string_ptr_copy;
00062 static cob_field                string_dlm_copy;
00063 static int                      string_offset;
00064 
00065 static struct dlm_struct        *dlm_list = NULL;
00066 static cob_field                *unstring_src;
00067 static cob_field                *unstring_ptr;
00068 static cob_field                unstring_src_copy;
00069 static cob_field                unstring_ptr_copy;
00070 static int                      unstring_offset;
00071 static int                      unstring_count;
00072 static int                      unstring_ndlms;
00073 
00074 static cob_field_attr           alpha_attr;
00075 static cob_field                alpha_fld;
00076 
00077 static COB_INLINE int
00078 cob_min_int (const int x, const int y)
00079 {
00080         if (x < y) {
00081                 return x;
00082         }
00083         return y;
00084 }
00085 
00086 static void
00087 alloc_figurative (const cob_field *f1, const cob_field *f2)
00088 {
00089         static unsigned char    *figptr = NULL;
00090         static size_t           figsize = 0;
00091 
00092         unsigned char           *s;
00093         size_t                  size1;
00094         size_t                  size2;
00095         size_t                  n;
00096 
00097         size2 = f2->size;
00098         if (size2 > figsize) {
00099                 if (figptr) {
00100                         free (figptr);
00101                 }
00102                 figptr = cob_malloc (size2);
00103                 figsize = size2;
00104         }
00105         size1 = 0;
00106         s = figptr;
00107         for (n = 0; n < size2; n++, s++) {
00108                 *s = f1->data[size1];
00109                 size1++;
00110                 if (size1 >= f1->size) {
00111                         size1 = 0;
00112                 }
00113         }
00114         alpha_fld.size = size2;
00115         alpha_fld.data = figptr;
00116 }
00117 
00118 static void
00119 inspect_common (cob_field *f1, cob_field *f2, const int type)
00120 {
00121         int             *mark;
00122         size_t          n = 0;
00123         size_t          j;
00124         int             i;
00125         int             len;
00126 
00127         if (unlikely(!f1)) {
00128                 f1 = &cob_low;
00129         }
00130         if (unlikely(!f2)) {
00131                 f2 = &cob_low;
00132         }
00133 
00134         if (inspect_replacing && f1->size != f2->size) {
00135                 if (COB_FIELD_TYPE (f1) == COB_TYPE_ALPHANUMERIC_ALL) {
00136                         alloc_figurative (f1, f2);
00137                         f1 = &alpha_fld;
00138                 } else {
00139                         cob_set_exception (COB_EC_RANGE_INSPECT_SIZE);
00140                         return;
00141                 }
00142         }
00143 
00144         mark = &inspect_mark[inspect_start - inspect_data];
00145         len = (int)(inspect_end - inspect_start);
00146         if (type == INSPECT_TRAILING) {
00147                 for (i = len - f2->size; i >= 0; i--) {
00148                         /* find matching substring */
00149                         if (memcmp (inspect_start + i, f2->data, f2->size) == 0) {
00150                                 /* check if it is already marked */
00151                                 for (j = 0; j < f2->size; j++) {
00152                                         if (mark[i + j] != -1) {
00153                                                 break;
00154                                         }
00155                                 }
00156                                 /* if not, mark and count it */
00157                                 if (j == f2->size) {
00158                                         for (j = 0; j < f2->size; j++) {
00159                                                 mark[i + j] = inspect_replacing ? f1->data[j] : 1;
00160                                         }
00161                                         i -= f2->size - 1;
00162                                         n++;
00163                                 }
00164                         } else {
00165                                 break;
00166                         }
00167                 }
00168         } else {
00169                 for (i = 0; i < (int)(len - f2->size + 1); i++) {
00170                         /* find matching substring */
00171                         if (memcmp (inspect_start + i, f2->data, f2->size) == 0) {
00172                                 /* check if it is already marked */
00173                                 for (j = 0; j < f2->size; j++) {
00174                                         if (mark[i + j] != -1) {
00175                                                 break;
00176                                         }
00177                                 }
00178                                 /* if not, mark and count it */
00179                                 if (j == f2->size) {
00180                                         for (j = 0; j < f2->size; j++) {
00181                                                 mark[i + j] = inspect_replacing ? f1->data[j] : 1;
00182                                         }
00183                                         i += f2->size - 1;
00184                                         n++;
00185                                         if (type == INSPECT_FIRST) {
00186                                                 break;
00187                                         }
00188                                 }
00189                         } else if (type == INSPECT_LEADING) {
00190                                 break;
00191                         }
00192                 }
00193         }
00194 
00195         if (n > 0 && !inspect_replacing) {
00196                 cob_add_int (f1, (int) n);
00197         }
00198 }
00199 
00200 /*
00201  * INSPECT
00202  */
00203 
00204 void
00205 cob_inspect_init (cob_field *var, const int replacing)
00206 {
00207         size_t          i;
00208         size_t          digcount;
00209 
00210         inspect_var_copy = *var;
00211         inspect_var = &inspect_var_copy;
00212         inspect_replacing = replacing;
00213         inspect_sign = cob_get_sign (var);
00214         inspect_size = COB_FIELD_SIZE (var);
00215         inspect_data = COB_FIELD_DATA (var);
00216         inspect_start = NULL;
00217         inspect_end = NULL;
00218         digcount = inspect_size * sizeof (int);
00219         if (digcount > lastsize) {
00220                 free (inspect_mark);
00221                 inspect_mark = cob_malloc (digcount);
00222                 lastsize = digcount;
00223         }
00224         for (i = 0; i < inspect_size; i++) {
00225                 inspect_mark[i] = -1;
00226         }
00227         cob_exception_code = 0;
00228 }
00229 
00230 void
00231 cob_inspect_start (void)
00232 {
00233         inspect_start = inspect_data;
00234         inspect_end = inspect_data + inspect_size;
00235 }
00236 
00237 void
00238 cob_inspect_before (const cob_field *str)
00239 {
00240         unsigned char   *p;
00241 
00242         for (p = inspect_start; p < inspect_end - str->size + 1; p++) {
00243                 if (memcmp (p, str->data, str->size) == 0) {
00244                         inspect_end = p;
00245                         return;
00246                 }
00247         }
00248 }
00249 
00250 void
00251 cob_inspect_after (const cob_field *str)
00252 {
00253         unsigned char   *p;
00254 
00255         for (p = inspect_start; p < inspect_end - str->size + 1; p++) {
00256                 if (memcmp (p, str->data, str->size) == 0) {
00257                         inspect_start = p + str->size;
00258                         return;
00259                 }
00260         }
00261         inspect_start = inspect_end;
00262 }
00263 
00264 void
00265 cob_inspect_characters (cob_field *f1)
00266 {
00267         int     *mark;
00268         int     i;
00269         int     n;
00270         int     len;
00271 
00272         mark = &inspect_mark[inspect_start - inspect_data];
00273         len = (int)(inspect_end - inspect_start);
00274         if (inspect_replacing) {
00275                 /* INSPECT REPLACING CHARACTERS f1 */
00276                 for (i = 0; i < len; i++) {
00277                         if (mark[i] == -1) {
00278                                 mark[i] = f1->data[0];
00279                         }
00280                 }
00281         } else {
00282                 /* INSPECT TALLYING f1 CHARACTERS */
00283                 n = 0;
00284                 for (i = 0; i < len; i++) {
00285                         if (mark[i] == -1) {
00286                                 mark[i] = 1;
00287                                 n++;
00288                         }
00289                 }
00290                 if (n > 0) {
00291                         cob_add_int (f1, n);
00292                 }
00293         }
00294 }
00295 
00296 void
00297 cob_inspect_all (cob_field *f1, cob_field *f2)
00298 {
00299         inspect_common (f1, f2, INSPECT_ALL);
00300 }
00301 
00302 void
00303 cob_inspect_leading (cob_field *f1, cob_field *f2)
00304 {
00305         inspect_common (f1, f2, INSPECT_LEADING);
00306 }
00307 
00308 void
00309 cob_inspect_first (cob_field *f1, cob_field *f2)
00310 {
00311         inspect_common (f1, f2, INSPECT_FIRST);
00312 }
00313 
00314 void
00315 cob_inspect_trailing (cob_field *f1, cob_field *f2)
00316 {
00317         inspect_common (f1, f2, INSPECT_TRAILING);
00318 }
00319 
00320 void
00321 cob_inspect_converting (cob_field *f1, cob_field *f2)
00322 {
00323         size_t  i;
00324         size_t  j;
00325         size_t  len;
00326 
00327         len = (size_t)(inspect_end - inspect_start);
00328         for (j = 0; j < f1->size; j++) {
00329                 for (i = 0; i < len; i++) {
00330                         if (inspect_mark[i] == -1 && inspect_start[i] == f1->data[j]) {
00331                                 inspect_start[i] = f2->data[j];
00332                                 inspect_mark[i] = 1;
00333                         }
00334                 }
00335         }
00336 }
00337 
00338 void
00339 cob_inspect_finish (void)
00340 {
00341         size_t  i;
00342 
00343         if (inspect_replacing) {
00344                 for (i = 0; i < inspect_size; i++) {
00345                         if (inspect_mark[i] != -1) {
00346                                 inspect_data[i] = inspect_mark[i];
00347                         }
00348                 }
00349         }
00350 
00351         cob_put_sign (inspect_var, inspect_sign);
00352 }
00353 
00354 /*
00355  * STRING
00356  */
00357 
00358 void
00359 cob_string_init (cob_field *dst, cob_field *ptr)
00360 {
00361         string_dst_copy = *dst;
00362         string_dst = &string_dst_copy;
00363         string_ptr = NULL;
00364         if (ptr) {
00365                 string_ptr_copy = *ptr;
00366                 string_ptr = &string_ptr_copy;
00367         }
00368         string_offset = 0;
00369         cob_exception_code = 0;
00370 
00371         if (string_ptr) {
00372                 string_offset = cob_get_int (string_ptr) - 1;
00373                 if (string_offset < 0 || string_offset >= (int)string_dst->size) {
00374                         cob_set_exception (COB_EC_OVERFLOW_STRING);
00375                 }
00376         }
00377 }
00378 
00379 void
00380 cob_string_delimited (cob_field *dlm)
00381 {
00382         string_dlm = NULL;
00383         if (dlm) {
00384                 string_dlm_copy = *dlm;
00385                 string_dlm = &string_dlm_copy;
00386         }
00387 }
00388 
00389 void
00390 cob_string_append (cob_field *src)
00391 {
00392         size_t  src_size;
00393         int     i;
00394         int     size;
00395 
00396         if (cob_exception_code) {
00397                 return;
00398         }
00399 
00400         src_size = src->size;
00401         if (string_dlm) {
00402                 size = (int)(src_size - string_dlm->size + 1);
00403                 for (i = 0; i < size; i++) {
00404                         if (memcmp (src->data + i, string_dlm->data, string_dlm->size) == 0) {
00405                                 src_size = i;
00406                                 break;
00407                         }
00408                 }
00409         }
00410 
00411         if (src_size <= string_dst->size - string_offset) {
00412                 memcpy (string_dst->data + string_offset, src->data, src_size);
00413                 string_offset += (int) src_size;
00414         } else {
00415                 size = (int)(string_dst->size - string_offset);
00416                 memcpy (string_dst->data + string_offset, src->data, (size_t)size);
00417                 string_offset += size;
00418                 cob_set_exception (COB_EC_OVERFLOW_STRING);
00419         }
00420 }
00421 
00422 void
00423 cob_string_finish (void)
00424 {
00425         if (string_ptr) {
00426                 cob_set_int (string_ptr, string_offset + 1);
00427         }
00428 }
00429 
00430 /*
00431  * UNSTRING
00432  */
00433 
00434 void
00435 cob_unstring_init (cob_field *src, cob_field *ptr, const size_t num_dlm)
00436 {
00437         static size_t   udlmcount = 0;
00438 
00439         unstring_src_copy = *src;
00440         unstring_src = &unstring_src_copy;
00441         unstring_ptr = NULL;
00442         if (ptr) {
00443                 unstring_ptr_copy = *ptr;
00444                 unstring_ptr = &unstring_ptr_copy;
00445         }
00446 
00447         unstring_offset = 0;
00448         unstring_count = 0;
00449         unstring_ndlms = 0;
00450         cob_exception_code = 0;
00451         if (!dlm_list) {
00452                 if (num_dlm <= DLM_DEFAULT_NUM) {
00453                         dlm_list = cob_malloc (DLM_DEFAULT_NUM * sizeof(struct dlm_struct));
00454                         udlmcount = DLM_DEFAULT_NUM;
00455                 } else {
00456                         dlm_list = cob_malloc (num_dlm * sizeof(struct dlm_struct));
00457                         udlmcount = num_dlm;
00458                 }
00459         } else {
00460                 if (num_dlm > udlmcount) {
00461                         free (dlm_list);
00462                         dlm_list = cob_malloc (num_dlm * sizeof(struct dlm_struct));
00463                         udlmcount = num_dlm;
00464                 }
00465         }
00466 
00467         if (unstring_ptr) {
00468                 unstring_offset = cob_get_int (unstring_ptr) - 1;
00469                 if (unstring_offset < 0 || unstring_offset >= (int)unstring_src->size) {
00470                         cob_set_exception (COB_EC_OVERFLOW_UNSTRING);
00471                 }
00472         }
00473 }
00474 
00475 void
00476 cob_unstring_delimited (cob_field *dlm, const int all)
00477 {
00478         dlm_list[unstring_ndlms].uns_dlm = dlm;
00479         dlm_list[unstring_ndlms].uns_all = all;
00480         unstring_ndlms++;
00481 }
00482 
00483 void
00484 cob_unstring_into (cob_field *dst, cob_field *dlm, cob_field *cnt)
00485 {
00486         unsigned char   *p;
00487         unsigned char   *dp;
00488         unsigned char   *s;
00489         unsigned char   *dlm_data;
00490         unsigned char   *start;
00491         size_t          dlm_size = 0;
00492         int             i;
00493         int             srsize;
00494         int             dlsize;
00495         int             match_size = 0;
00496         int             brkpt = 0;
00497 
00498         if (cob_exception_code) {
00499                 return;
00500         }
00501 
00502         if (unstring_offset >= (int)unstring_src->size) {
00503                 return;
00504         }
00505 
00506         start = unstring_src->data + unstring_offset;
00507         dlm_data = NULL;
00508         if (unstring_ndlms == 0) {
00509                 match_size = cob_min_int ((int)COB_FIELD_SIZE (dst),
00510                                           (int)unstring_src->size - unstring_offset);
00511                 cob_memcpy (dst, start, match_size);
00512                 unstring_offset += match_size;
00513         } else {
00514 
00515                 srsize = (int) unstring_src->size;
00516                 s = unstring_src->data + srsize;
00517                 for (p = start; p < s; p++) {
00518                         for (i = 0; i < unstring_ndlms; i++) {
00519                                 dlsize = (int) dlm_list[i].uns_dlm->size;
00520                                 dp = dlm_list[i].uns_dlm->data;
00521                                 if (p + dlsize > s) {
00522                                         break;
00523                                 }
00524                                 if (!memcmp (p, dp, (size_t)dlsize)) {
00525                                         match_size = (int)(p - start);
00526                                         cob_memcpy (dst, start, match_size);
00527                                         unstring_offset += match_size + dlsize;
00528                                         dlm_data = dp;
00529                                         dlm_size = dlsize;
00530                                         if (dlm_list[i].uns_all) {
00531                                                 for (p++ ; p < s; p++) {
00532                                                         if (p + dlsize > s) {
00533                                                                 break;
00534                                                         }
00535                                                         if (memcmp (p, dp, (size_t)dlsize)) {
00536                                                                 break;
00537                                                         }
00538                                                         unstring_offset += dlsize;
00539                                                 }
00540                                         }
00541                                         brkpt = 1;
00542                                         break;
00543                                 }
00544                         }
00545                         if (brkpt) {
00546                                 break;
00547                         }
00548                 }
00549                 if (!brkpt) {
00550                         /* no match */
00551                         match_size = (int)(unstring_src->size - unstring_offset);
00552                         cob_memcpy (dst, start, match_size);
00553                         unstring_offset = (int) unstring_src->size;
00554                         dlm_data = NULL;
00555                 }
00556         }
00557         unstring_count++;
00558 
00559         if (dlm) {
00560                 if (dlm_data) {
00561                         cob_memcpy (dlm, dlm_data, (int) dlm_size);
00562                 } else if (COB_FIELD_IS_NUMERIC (dlm)) {
00563                         cob_move (&cob_zero, dlm);
00564                 } else {
00565                         cob_move (&cob_space, dlm);
00566                 }
00567         }
00568 
00569         if (cnt) {
00570                 cob_set_int (cnt, match_size);
00571         }
00572 }
00573 
00574 void
00575 cob_unstring_tallying (cob_field *f)
00576 {
00577         cob_add_int (f, unstring_count);
00578 }
00579 
00580 void
00581 cob_unstring_finish (void)
00582 {
00583         if (unstring_offset < (int)unstring_src->size) {
00584                 cob_set_exception (COB_EC_OVERFLOW_UNSTRING);
00585         }
00586 
00587         if (unstring_ptr) {
00588                 cob_set_int (unstring_ptr, unstring_offset + 1);
00589         }
00590 }
00591 
00592 /* Initialization */
00593 
00594 void
00595 cob_init_strings (void)
00596 {
00597         inspect_mark = cob_malloc (COB_MEDIUM_BUFF);
00598         lastsize = COB_MEDIUM_BUFF;
00599         alpha_attr.type = COB_TYPE_ALPHANUMERIC;
00600         alpha_attr.digits = 0;
00601         alpha_attr.scale = 0;
00602         alpha_attr.flags = 0;
00603         alpha_attr.pic = NULL;
00604         alpha_fld.size = 0;
00605         alpha_fld.data = NULL;
00606         alpha_fld.attr = &alpha_attr;
00607 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines