OpenCOBOL 1.1pre-rel
|
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 }