OpenCOBOL 1.1pre-rel
|
00001 /* 00002 * Copyright (C) 2001-2009 Keisuke Nishida 00003 * Copyright (C) 2007-2009 Roger While 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2, or (at your option) 00008 * any later version. 00009 * 00010 * This program 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 General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this software; see the file COPYING. If not, write to 00017 * 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 <string.h> 00026 #include <ctype.h> 00027 #include <time.h> 00028 #ifdef HAVE_SYS_TIME_H 00029 #include <sys/time.h> 00030 #endif 00031 #ifdef _WIN32 00032 #define WINDOWS_LEAN_AND_MEAN 00033 #include <windows.h> 00034 #endif 00035 00036 #ifdef HAVE_LOCALE_H 00037 #include <locale.h> 00038 #endif 00039 00040 #include "cobc.h" 00041 #include "tree.h" 00042 00043 struct system_table { 00044 const char *syst_name; 00045 const int syst_params; 00046 }; 00047 00048 struct expr_node { 00049 /* The token of this node. 00050 * 'x' - values (cb_tree) 00051 * '+', '-', '*', '/', '^' - arithmetic operators 00052 * '=', '~', '<', '>', '[', ']' - relational operators 00053 * '!', '&', '|' - logical operators 00054 * '(', ')' - parentheses 00055 */ 00056 int token; 00057 /* The value itself if this node is a value */ 00058 cb_tree value; 00059 }; 00060 00061 #define START_STACK_SIZE 32 00062 #define TOKEN(offset) (expr_stack[expr_index + offset].token) 00063 #define VALUE(offset) (expr_stack[expr_index + offset].value) 00064 00065 #define dpush(x) decimal_stack = cb_cons (x, decimal_stack) 00066 00067 #define cb_emit(x) \ 00068 current_statement->body = cb_list_add (current_statement->body, x) 00069 #define cb_emit_list(l) \ 00070 current_statement->body = cb_list_append (current_statement->body, l) 00071 00072 /* Global variables */ 00073 00074 size_t sending_id = 0; 00075 size_t suppress_warn = 0; 00076 00077 /* Local variables */ 00078 00079 static cb_tree decimal_stack = NULL; 00080 00081 static const char *inspect_func; 00082 static cb_tree inspect_data; 00083 00084 static int expr_op; /* last operator */ 00085 static cb_tree expr_lh; /* last left hand */ 00086 00087 static int expr_index; /* stack index */ 00088 static int expr_stack_size; /* stack max size */ 00089 static struct expr_node *expr_stack; /* expr node stack */ 00090 00091 static char expr_prio[256]; 00092 00093 static const struct system_table system_tab[] = { 00094 #undef COB_SYSTEM_GEN 00095 #define COB_SYSTEM_GEN(x, y, z) { x, y }, 00096 #include "libcob/system.def" 00097 { NULL, 0 } 00098 }; 00099 00100 static const char *const bin_set_funcs[] = { 00101 NULL, 00102 "cob_setswp_u16_binary", 00103 "cob_setswp_u24_binary", 00104 "cob_setswp_u32_binary", 00105 "cob_setswp_u40_binary", 00106 "cob_setswp_u48_binary", 00107 "cob_setswp_u56_binary", 00108 "cob_setswp_u64_binary", 00109 NULL, 00110 "cob_setswp_s16_binary", 00111 "cob_setswp_s24_binary", 00112 "cob_setswp_s32_binary", 00113 "cob_setswp_s40_binary", 00114 "cob_setswp_s48_binary", 00115 "cob_setswp_s56_binary", 00116 "cob_setswp_s64_binary" 00117 }; 00118 00119 static const char *const bin_compare_funcs[] = { 00120 "cob_cmp_u8_binary", 00121 "cob_cmp_u16_binary", 00122 "cob_cmp_u24_binary", 00123 "cob_cmp_u32_binary", 00124 "cob_cmp_u40_binary", 00125 "cob_cmp_u48_binary", 00126 "cob_cmp_u56_binary", 00127 "cob_cmp_u64_binary", 00128 "cob_cmp_s8_binary", 00129 "cob_cmp_s16_binary", 00130 "cob_cmp_s24_binary", 00131 "cob_cmp_s32_binary", 00132 "cob_cmp_s40_binary", 00133 "cob_cmp_s48_binary", 00134 "cob_cmp_s56_binary", 00135 "cob_cmp_s64_binary", 00136 "cob_cmp_u8_binary", 00137 "cob_cmpswp_u16_binary", 00138 "cob_cmpswp_u24_binary", 00139 "cob_cmpswp_u32_binary", 00140 "cob_cmpswp_u40_binary", 00141 "cob_cmpswp_u48_binary", 00142 "cob_cmpswp_u56_binary", 00143 "cob_cmpswp_u64_binary", 00144 "cob_cmp_s8_binary", 00145 "cob_cmpswp_s16_binary", 00146 "cob_cmpswp_s24_binary", 00147 "cob_cmpswp_s32_binary", 00148 "cob_cmpswp_s40_binary", 00149 "cob_cmpswp_s48_binary", 00150 "cob_cmpswp_s56_binary", 00151 "cob_cmpswp_s64_binary" 00152 }; 00153 00154 static const char *const bin_add_funcs[] = { 00155 "cob_add_u8_binary", 00156 "cob_add_u16_binary", 00157 "cob_add_u24_binary", 00158 "cob_add_u32_binary", 00159 "cob_add_u40_binary", 00160 "cob_add_u48_binary", 00161 "cob_add_u56_binary", 00162 "cob_add_u64_binary", 00163 "cob_add_s8_binary", 00164 "cob_add_s16_binary", 00165 "cob_add_s24_binary", 00166 "cob_add_s32_binary", 00167 "cob_add_s40_binary", 00168 "cob_add_s48_binary", 00169 "cob_add_s56_binary", 00170 "cob_add_s64_binary", 00171 "cob_add_u8_binary", 00172 "cob_addswp_u16_binary", 00173 "cob_addswp_u24_binary", 00174 "cob_addswp_u32_binary", 00175 "cob_addswp_u40_binary", 00176 "cob_addswp_u48_binary", 00177 "cob_addswp_u56_binary", 00178 "cob_addswp_u64_binary", 00179 "cob_add_s8_binary", 00180 "cob_addswp_s16_binary", 00181 "cob_addswp_s24_binary", 00182 "cob_addswp_s32_binary", 00183 "cob_addswp_s40_binary", 00184 "cob_addswp_s48_binary", 00185 "cob_addswp_s56_binary", 00186 "cob_addswp_s64_binary" 00187 }; 00188 00189 static const char *const bin_sub_funcs[] = { 00190 "cob_sub_u8_binary", 00191 "cob_sub_u16_binary", 00192 "cob_sub_u24_binary", 00193 "cob_sub_u32_binary", 00194 "cob_sub_u40_binary", 00195 "cob_sub_u48_binary", 00196 "cob_sub_u56_binary", 00197 "cob_sub_u64_binary", 00198 "cob_sub_s8_binary", 00199 "cob_sub_s16_binary", 00200 "cob_sub_s24_binary", 00201 "cob_sub_s32_binary", 00202 "cob_sub_s40_binary", 00203 "cob_sub_s48_binary", 00204 "cob_sub_s56_binary", 00205 "cob_sub_s64_binary", 00206 "cob_sub_u8_binary", 00207 "cob_subswp_u16_binary", 00208 "cob_subswp_u24_binary", 00209 "cob_subswp_u32_binary", 00210 "cob_subswp_u40_binary", 00211 "cob_subswp_u48_binary", 00212 "cob_subswp_u56_binary", 00213 "cob_subswp_u64_binary", 00214 "cob_sub_s8_binary", 00215 "cob_subswp_s16_binary", 00216 "cob_subswp_s24_binary", 00217 "cob_subswp_s32_binary", 00218 "cob_subswp_s40_binary", 00219 "cob_subswp_s48_binary", 00220 "cob_subswp_s56_binary", 00221 "cob_subswp_s64_binary" 00222 }; 00223 00224 static const char *const align_bin_compare_funcs[] = { 00225 "cob_cmp_u8_binary", 00226 "cob_cmp_align_u16_binary", 00227 "cob_cmp_u24_binary", 00228 "cob_cmp_align_u32_binary", 00229 "cob_cmp_u40_binary", 00230 "cob_cmp_u48_binary", 00231 "cob_cmp_u56_binary", 00232 "cob_cmp_align_u64_binary", 00233 "cob_cmp_s8_binary", 00234 "cob_cmp_align_s16_binary", 00235 "cob_cmp_s24_binary", 00236 "cob_cmp_align_s32_binary", 00237 "cob_cmp_s40_binary", 00238 "cob_cmp_s48_binary", 00239 "cob_cmp_s56_binary", 00240 "cob_cmp_align_s64_binary", 00241 "cob_cmp_u8_binary", 00242 "cob_cmpswp_align_u16_binary", 00243 "cob_cmpswp_u24_binary", 00244 "cob_cmpswp_align_u32_binary", 00245 "cob_cmpswp_u40_binary", 00246 "cob_cmpswp_u48_binary", 00247 "cob_cmpswp_u56_binary", 00248 "cob_cmpswp_align_u64_binary", 00249 "cob_cmp_s8_binary", 00250 "cob_cmpswp_align_s16_binary", 00251 "cob_cmpswp_s24_binary", 00252 "cob_cmpswp_align_s32_binary", 00253 "cob_cmpswp_s40_binary", 00254 "cob_cmpswp_s48_binary", 00255 "cob_cmpswp_s56_binary", 00256 "cob_cmpswp_align_s64_binary" 00257 }; 00258 00259 static const char *const align_bin_add_funcs[] = { 00260 "cob_add_u8_binary", 00261 "cob_add_align_u16_binary", 00262 "cob_add_u24_binary", 00263 "cob_add_align_u32_binary", 00264 "cob_add_u40_binary", 00265 "cob_add_u48_binary", 00266 "cob_add_u56_binary", 00267 "cob_add_align_u64_binary", 00268 "cob_add_s8_binary", 00269 "cob_add_align_s16_binary", 00270 "cob_add_s24_binary", 00271 "cob_add_align_s32_binary", 00272 "cob_add_s40_binary", 00273 "cob_add_s48_binary", 00274 "cob_add_s56_binary", 00275 "cob_add_align_s64_binary", 00276 "cob_add_u8_binary", 00277 "cob_addswp_u16_binary", 00278 "cob_addswp_u24_binary", 00279 "cob_addswp_u32_binary", 00280 "cob_addswp_u40_binary", 00281 "cob_addswp_u48_binary", 00282 "cob_addswp_u56_binary", 00283 "cob_addswp_u64_binary", 00284 "cob_add_s8_binary", 00285 "cob_addswp_s16_binary", 00286 "cob_addswp_s24_binary", 00287 "cob_addswp_s32_binary", 00288 "cob_addswp_s40_binary", 00289 "cob_addswp_s48_binary", 00290 "cob_addswp_s56_binary", 00291 "cob_addswp_s64_binary" 00292 }; 00293 00294 static const char *const align_bin_sub_funcs[] = { 00295 "cob_sub_u8_binary", 00296 "cob_sub_align_u16_binary", 00297 "cob_sub_u24_binary", 00298 "cob_sub_align_u32_binary", 00299 "cob_sub_u40_binary", 00300 "cob_sub_u48_binary", 00301 "cob_sub_u56_binary", 00302 "cob_sub_align_u64_binary", 00303 "cob_sub_s8_binary", 00304 "cob_sub_align_s16_binary", 00305 "cob_sub_s24_binary", 00306 "cob_sub_align_s32_binary", 00307 "cob_sub_s40_binary", 00308 "cob_sub_s48_binary", 00309 "cob_sub_s56_binary", 00310 "cob_sub_align_s64_binary", 00311 "cob_sub_u8_binary", 00312 "cob_subswp_u16_binary", 00313 "cob_subswp_u24_binary", 00314 "cob_subswp_u32_binary", 00315 "cob_subswp_u40_binary", 00316 "cob_subswp_u48_binary", 00317 "cob_subswp_u56_binary", 00318 "cob_subswp_u64_binary", 00319 "cob_sub_s8_binary", 00320 "cob_subswp_s16_binary", 00321 "cob_subswp_s24_binary", 00322 "cob_subswp_s32_binary", 00323 "cob_subswp_s40_binary", 00324 "cob_subswp_s48_binary", 00325 "cob_subswp_s56_binary", 00326 "cob_subswp_s64_binary" 00327 }; 00328 00329 /* functions */ 00330 00331 static size_t 00332 cb_validate_one (cb_tree x) 00333 { 00334 cb_tree y; 00335 00336 if (x == cb_error_node) { 00337 return 1; 00338 } 00339 if (!x) { 00340 return 0; 00341 } 00342 if (CB_REFERENCE_P (x)) { 00343 y = cb_ref (x); 00344 if (y == cb_error_node) { 00345 return 1; 00346 } 00347 if (CB_FIELD_P (y) && CB_FIELD (y)->level == 88) { 00348 cb_error_x (x, _("Invalid use of 88 level item")); 00349 return 1; 00350 } 00351 } 00352 return 0; 00353 } 00354 00355 static size_t 00356 cb_validate_list (cb_tree l) 00357 { 00358 for (; l; l = CB_CHAIN (l)) { 00359 if (cb_validate_one (CB_VALUE (l))) { 00360 return 1; 00361 } 00362 } 00363 return 0; 00364 } 00365 00366 static cb_tree 00367 cb_check_group_name (cb_tree x) 00368 { 00369 cb_tree y; 00370 00371 if (x == cb_error_node) { 00372 return cb_error_node; 00373 } 00374 00375 if (CB_REFERENCE_P (x)) { 00376 y = cb_ref (x); 00377 if (y == cb_error_node) { 00378 return cb_error_node; 00379 } 00380 if (CB_FIELD_P (y) && CB_FIELD (y)->children != NULL && 00381 CB_REFERENCE (x)->offset == NULL) { 00382 return x; 00383 } 00384 } 00385 00386 cb_error_x (x, _("'%s' is not group name"), cb_name (x)); 00387 return cb_error_node; 00388 } 00389 00390 static cb_tree 00391 cb_check_numeric_name (cb_tree x) 00392 { 00393 if (x == cb_error_node) { 00394 return cb_error_node; 00395 } 00396 00397 if (CB_REFERENCE_P (x) 00398 && CB_FIELD_P (cb_ref (x)) 00399 && CB_TREE_CATEGORY (x) == CB_CATEGORY_NUMERIC) { 00400 return x; 00401 } 00402 00403 cb_error_x (x, _("'%s' is not a numeric name"), cb_name (x)); 00404 return cb_error_node; 00405 } 00406 00407 static cb_tree 00408 cb_check_numeric_edited_name (cb_tree x) 00409 { 00410 if (x == cb_error_node) { 00411 return cb_error_node; 00412 } 00413 00414 if (CB_REFERENCE_P (x) 00415 && CB_FIELD_P (cb_ref (x)) 00416 && (CB_TREE_CATEGORY (x) == CB_CATEGORY_NUMERIC 00417 || CB_TREE_CATEGORY (x) == CB_CATEGORY_NUMERIC_EDITED)) { 00418 return x; 00419 } 00420 00421 cb_error_x (x, _("'%s' is not numeric or numeric-edited name"), cb_name (x)); 00422 return cb_error_node; 00423 } 00424 00425 cb_tree 00426 cb_check_numeric_value (cb_tree x) 00427 { 00428 if (x == cb_error_node) { 00429 return cb_error_node; 00430 } 00431 00432 if (CB_TREE_CATEGORY (x) == CB_CATEGORY_NUMERIC) { 00433 return x; 00434 } 00435 00436 cb_error_x (x, _("'%s' is not a numeric value"), cb_name (x)); 00437 return cb_error_node; 00438 } 00439 00440 static cb_tree 00441 cb_check_integer_value (cb_tree x) 00442 { 00443 struct cb_literal *l; 00444 struct cb_field *f; 00445 cb_tree y; 00446 00447 if (x == cb_error_node) { 00448 return cb_error_node; 00449 } 00450 00451 if (CB_TREE_CATEGORY (x) != CB_CATEGORY_NUMERIC) { 00452 goto invalid; 00453 } 00454 00455 switch (CB_TREE_TAG (x)) { 00456 case CB_TAG_CONST: 00457 if (x != cb_zero) { 00458 goto invalid; 00459 } 00460 return x; 00461 case CB_TAG_LITERAL: 00462 l = CB_LITERAL (x); 00463 if (l->sign < 0 || l->scale > 0) { 00464 goto invliteral; 00465 } 00466 return x; 00467 case CB_TAG_REFERENCE: 00468 y = cb_ref (x); 00469 if (y == cb_error_node) { 00470 return cb_error_node; 00471 } 00472 f = CB_FIELD (y); 00473 if (f->pic->scale > 0) { 00474 goto invalid; 00475 } 00476 return x; 00477 case CB_TAG_BINARY_OP: 00478 /* TODO: need to check */ 00479 return x; 00480 case CB_TAG_INTRINSIC: 00481 /* TODO: need to check */ 00482 return x; 00483 default: 00484 invalid: 00485 cb_error_x (x, _("'%s' is not an integer value"), cb_name (x)); 00486 return cb_error_node; 00487 } 00488 invliteral: 00489 cb_error_x (x, _("A positive numeric integer is required here")); 00490 return cb_error_node; 00491 } 00492 00493 void 00494 cb_build_registers (void) 00495 { 00496 #if !defined(__linux__) && !defined(__CYGWIN__) && defined(HAVE_TIMEZONE) 00497 long contz; 00498 #endif 00499 time_t t; 00500 char buff[48]; 00501 00502 /* RETURN-CODE */ 00503 if (!current_program->nested_level) { 00504 current_program->cb_return_code = 00505 cb_build_index (cb_build_reference ("RETURN-CODE"), 00506 cb_zero, 0, NULL); 00507 cb_field (current_program->cb_return_code)->flag_is_global = 1; 00508 } 00509 00510 /* SORT-RETURN */ 00511 current_program->cb_sort_return = 00512 cb_build_index (cb_build_reference ("SORT-RETURN"), cb_zero, 0, NULL); 00513 cb_field (current_program->cb_sort_return)->flag_no_init = 1; 00514 00515 /* NUMBER-OF-CALL-PARAMETERS */ 00516 current_program->cb_call_params = 00517 cb_build_index (cb_build_reference ("NUMBER-OF-CALL-PARAMETERS"), cb_zero, 0, NULL); 00518 cb_field (current_program->cb_call_params)->flag_no_init = 1; 00519 00520 /* TALLY */ 00521 /* 01 TALLY GLOBAL PICTURE 9(9) USAGE COMP-5 VALUE ZERO. */ 00522 /* TALLY/EXAMINE not standard/supported */ 00523 00524 t = time (NULL); 00525 00526 /* WHEN-COMPILED */ 00527 memset (buff, 0, sizeof (buff)); 00528 strftime (buff, 17, "%m/%d/%y%H.%M.%S", localtime (&t)); 00529 cb_build_constant (cb_build_reference ("WHEN-COMPILED"), 00530 cb_build_alphanumeric_literal ((ucharptr)buff, 16)); 00531 00532 /* FUNCTION WHEN-COMPILED */ 00533 memset (buff, 0, sizeof (buff)); 00534 #if defined(__linux__) || defined(__CYGWIN__) 00535 strftime (buff, 22, "%Y%m%d%H%M%S00%z", localtime (&t)); 00536 #elif defined(HAVE_TIMEZONE) 00537 strftime (buff, 17, "%Y%m%d%H%M%S00", localtime (&t)); 00538 if (timezone <= 0) { 00539 contz = -timezone; 00540 buff[16] = '+'; 00541 } else { 00542 contz = timezone; 00543 buff[16] = '-'; 00544 } 00545 sprintf (&buff[17], "%2.2ld%2.2ld", contz / 3600, contz % 60); 00546 #else 00547 strftime (buff, 22, "%Y%m%d%H%M%S0000000", localtime (&t)); 00548 #endif 00549 cb_intr_whencomp = cb_build_alphanumeric_literal ((ucharptr)buff, 21); 00550 00551 /* FUNCTION PI */ 00552 memset (buff, 0, sizeof (buff)); 00553 strcpy (buff, "31415926535897932384626433832795029"); 00554 cb_intr_pi = cb_build_numeric_literal (0, (ucharptr)buff, 34); 00555 00556 /* FUNCTION E */ 00557 memset (buff, 0, sizeof (buff)); 00558 strcpy (buff, "27182818284590452353602874713526625"); 00559 cb_intr_e = cb_build_numeric_literal (0, (ucharptr)buff, 34); 00560 } 00561 00562 char * 00563 cb_encode_program_id (const char *name) 00564 { 00565 unsigned char *p; 00566 const unsigned char *s; 00567 unsigned char buff[COB_SMALL_BUFF]; 00568 00569 p = buff; 00570 s = (const unsigned char *)name; 00571 /* encode the initial digit */ 00572 if (isdigit (*s)) { 00573 p += sprintf ((char *)p, "_%02X", *s++); 00574 } 00575 /* encode invalid letters */ 00576 for (; *s; s++) { 00577 if (isalnum (*s) || *s == '_') { 00578 *p++ = *s; 00579 } else if (*s == '-') { 00580 *p++ = '_'; 00581 *p++ = '_'; 00582 } else { 00583 p += sprintf ((char *)p, "_%02X", *s); 00584 } 00585 } 00586 *p = 0; 00587 return strdup ((char *)buff); 00588 } 00589 00590 const char * 00591 cb_build_program_id (cb_tree name, cb_tree alt_name) 00592 { 00593 const char *s; 00594 00595 /* This needs some more thought, should we generate an entry 00596 point per program source name ? 00597 if (alt_name) { 00598 s = (char *)CB_LITERAL (alt_name)->data; 00599 } else if (CB_LITERAL_P (name)) { 00600 s = (char *)CB_LITERAL (name)->data; 00601 } else { 00602 s = (char *)CB_NAME (name); 00603 } 00604 00605 if (!cb_flag_main && strcmp (s, source_name)) { 00606 cb_warning (_("Source name '%s' differs from PROGRAM-ID '%s'"), 00607 source_name, s); 00608 current_program->source_name = strdup (source_name); 00609 } 00610 End comment out */ 00611 00612 if (alt_name) { 00613 current_program->orig_source_name = strdup ((char *)CB_LITERAL (alt_name)->data); 00614 s = (char *)CB_LITERAL (alt_name)->data; 00615 } else if (CB_LITERAL_P (name)) { 00616 current_program->orig_source_name = strdup ((char *)CB_LITERAL (name)->data); 00617 s = cb_encode_program_id ((char *)CB_LITERAL (name)->data); 00618 } else { 00619 current_program->orig_source_name = strdup (CB_NAME (name)); 00620 s = cb_encode_program_id (CB_NAME (name)); 00621 } 00622 if (cobc_check_valid_name (current_program->orig_source_name)) { 00623 cb_error (_("PROGRAM-ID '%s' invalid"), current_program->orig_source_name); 00624 } 00625 return s; 00626 } 00627 00628 void 00629 cb_define_switch_name (cb_tree name, cb_tree sname, cb_tree flag, cb_tree ref) 00630 { 00631 cb_tree switch_id; 00632 cb_tree value; 00633 00634 if (name == cb_error_node) { 00635 return; 00636 } 00637 if (sname == cb_error_node) { 00638 return; 00639 } 00640 if (CB_SYSTEM_NAME (sname)->category != CB_SWITCH_NAME) { 00641 cb_error_x (ref, _("Switch-name is expected '%s'"), CB_NAME (ref)); 00642 } else { 00643 switch_id = cb_int (CB_SYSTEM_NAME (sname)->token); 00644 value = cb_build_funcall_1 ("cob_get_switch", switch_id); 00645 if (flag == cb_int0) { 00646 value = cb_build_negation (value); 00647 } 00648 cb_build_constant (name, value); 00649 } 00650 } 00651 00652 cb_tree 00653 cb_build_section_name (cb_tree name, int sect_or_para) 00654 { 00655 cb_tree x; 00656 00657 if (name == cb_error_node) { 00658 return cb_error_node; 00659 } 00660 00661 if (CB_REFERENCE (name)->word->count > 0) { 00662 x = CB_VALUE (CB_REFERENCE (name)->word->items); 00663 /* Used as a non-label name or used as a section name. 00664 Duplicate paragraphs are allowed if not referenced; 00665 Checked in typeck.c */ 00666 if (!CB_LABEL_P (x) || sect_or_para == 0 00667 || (sect_or_para && CB_LABEL_P (x) && CB_LABEL (x)->is_section)) { 00668 redefinition_error (name); 00669 return cb_error_node; 00670 } 00671 } 00672 00673 return name; 00674 } 00675 00676 cb_tree 00677 cb_build_assignment_name (struct cb_file *cfile, cb_tree name) 00678 { 00679 const char *s; 00680 const char *p; 00681 00682 if (name == cb_error_node) { 00683 return cb_error_node; 00684 } 00685 00686 switch (CB_TREE_TAG (name)) { 00687 case CB_TAG_LITERAL: 00688 if (strcmp ((char *)(CB_LITERAL(name)->data), "$#@DUMMY@#$") == 0) { 00689 cfile->special = 2; 00690 } 00691 return name; 00692 00693 case CB_TAG_REFERENCE: 00694 s = CB_REFERENCE (name)->word->name; 00695 if (strcasecmp (s, "KEYBOARD") == 0) { 00696 s = "#DUMMY#"; 00697 cfile->special = 1; 00698 return cb_build_alphanumeric_literal ((ucharptr)s, strlen (s)); 00699 } 00700 switch (cb_assign_clause) { 00701 case CB_ASSIGN_COBOL2002: 00702 /* TODO */ 00703 return cb_error_node; 00704 00705 case CB_ASSIGN_MF: 00706 if (cfile->external_assign) { 00707 p = strrchr (s, '-'); 00708 if (p) { 00709 s = p + 1; 00710 } 00711 return cb_build_alphanumeric_literal ((ucharptr)s, strlen (s)); 00712 } 00713 current_program->reference_list = 00714 cb_list_add (current_program->reference_list, name); 00715 return name; 00716 00717 case CB_ASSIGN_IBM: 00718 /* check organization */ 00719 if (strncmp (s, "S-", 2) == 0 || 00720 strncmp (s, "AS-", 3) == 0) { 00721 goto org; 00722 } 00723 /* skip the device label if exists */ 00724 if ((p = strchr (s, '-')) != NULL) { 00725 s = p + 1; 00726 } 00727 /* check organization again */ 00728 if (strncmp (s, "S-", 2) == 0 || 00729 strncmp (s, "AS-", 3) == 0) { 00730 org: 00731 /* skip it for now */ 00732 s = strchr (s, '-') + 1; 00733 } 00734 /* convert the name into literal */ 00735 return cb_build_alphanumeric_literal ((ucharptr)s, strlen (s)); 00736 } 00737 00738 default: 00739 return cb_error_node; 00740 } 00741 } 00742 00743 cb_tree 00744 cb_build_index (cb_tree x, cb_tree values, int indexed_by, struct cb_field *qual) 00745 { 00746 struct cb_field *f; 00747 00748 f = CB_FIELD (cb_build_field (x)); 00749 f->usage = CB_USAGE_INDEX; 00750 cb_validate_field (f); 00751 if (values) { 00752 f->values = cb_list_init (values); 00753 } 00754 if (qual) { 00755 f->index_qual = qual; 00756 } 00757 f->flag_indexed_by = indexed_by; 00758 current_program->working_storage = cb_field_add (current_program->working_storage, f); 00759 return x; 00760 } 00761 00762 cb_tree 00763 cb_build_identifier (cb_tree x) 00764 { 00765 struct cb_reference *r; 00766 struct cb_field *f; 00767 struct cb_field *p; 00768 const char *name; 00769 cb_tree v; 00770 cb_tree e1; 00771 cb_tree e2; 00772 cb_tree l; 00773 cb_tree sub; 00774 int offset; 00775 int length; 00776 int n; 00777 00778 if (x == cb_error_node) { 00779 return cb_error_node; 00780 } 00781 00782 r = CB_REFERENCE (x); 00783 name = r->word->name; 00784 00785 /* resolve reference */ 00786 v = cb_ref (x); 00787 if (v == cb_error_node) { 00788 return cb_error_node; 00789 } 00790 00791 /* check if it is a data name */ 00792 if (!CB_FIELD_P (v)) { 00793 if (r->subs) { 00794 cb_error_x (x, _("'%s' cannot be subscripted"), name); 00795 return cb_error_node; 00796 } 00797 if (r->offset) { 00798 cb_error_x (x, _("'%s' cannot be reference modified"), name); 00799 return cb_error_node; 00800 } 00801 return x; 00802 } 00803 f = CB_FIELD (v); 00804 00805 /* BASED check */ 00806 if (CB_EXCEPTION_ENABLE (COB_EC_BOUND_PTR)) { 00807 for (p = f; p->parent; p = p->parent) { 00808 ; 00809 } 00810 if (current_statement) { 00811 if (p->flag_item_based || 00812 (f->storage == CB_STORAGE_LINKAGE && 00813 !p->flag_is_pdiv_parm)) { 00814 current_statement->null_check = cb_build_funcall_2 ( 00815 "cob_check_based", 00816 cb_build_address (cb_build_field_reference (p, NULL)), 00817 cb_build_string0 ((ucharptr)name)); 00818 } 00819 } 00820 } 00821 00822 /* check the number of subscripts */ 00823 if (!r->all && cb_list_length (r->subs) != f->indexes) { 00824 switch (f->indexes) { 00825 case 0: 00826 cb_error_x (x, _("'%s' cannot be subscripted"), name); 00827 return cb_error_node; 00828 case 1: 00829 cb_error_x (x, _("'%s' requires 1 subscript"), name); 00830 return cb_error_node; 00831 default: 00832 cb_error_x (x, _("'%s' requires %d subscripts"), name, f->indexes); 00833 return cb_error_node; 00834 } 00835 } 00836 00837 /* subscript check */ 00838 if (!r->all && r->subs) { 00839 l = r->subs; 00840 for (p = f; p; p = p->parent) { 00841 if (p->flag_occurs) { 00842 sub = cb_check_integer_value (CB_VALUE (l)); 00843 00844 l = CB_CHAIN (l); 00845 00846 if (sub == cb_error_node) { 00847 continue; 00848 } 00849 00850 /* compile-time check */ 00851 if (CB_LITERAL_P (sub)) { 00852 n = cb_get_int (sub); 00853 if (n < 1 || n > p->occurs_max) { 00854 cb_error_x (x, _("Subscript of '%s' out of bounds: %d"), 00855 name, n); 00856 } 00857 } 00858 00859 /* run-time check */ 00860 if (CB_EXCEPTION_ENABLE (COB_EC_BOUND_SUBSCRIPT)) { 00861 if (p->occurs_depending) { 00862 e1 = cb_build_funcall_4 ("cob_check_odo", 00863 cb_build_cast_integer (p->occurs_depending), 00864 cb_int (p->occurs_min), 00865 cb_int (p->occurs_max), 00866 cb_build_string0 00867 ((ucharptr)(cb_field (p->occurs_depending)->name))); 00868 e2 = cb_build_funcall_4 ("cob_check_subscript", 00869 cb_build_cast_integer (sub), 00870 cb_int1, 00871 cb_build_cast_integer (p->occurs_depending), 00872 cb_build_string0 ((ucharptr)name)); 00873 r->check = cb_list_add (r->check, e1); 00874 r->check = cb_list_add (r->check, e2); 00875 } else { 00876 if (!CB_LITERAL_P (sub)) { 00877 e1 = cb_build_funcall_4 ("cob_check_subscript", 00878 cb_build_cast_integer (sub), 00879 cb_int1, 00880 cb_int (p->occurs_max), 00881 cb_build_string0 ((ucharptr)name)); 00882 r->check = cb_list_add (r->check, e1); 00883 } 00884 } 00885 } 00886 } 00887 } 00888 } 00889 00890 /* reference modification check */ 00891 if (r->offset) { 00892 /* compile-time check */ 00893 if (CB_LITERAL_P (r->offset)) { 00894 offset = cb_get_int (r->offset); 00895 if (offset < 1 || offset > f->size) { 00896 cb_error_x (x, _("Offset of '%s' out of bounds: %d"), name, offset); 00897 } else if (r->length && CB_LITERAL_P (r->length)) { 00898 length = cb_get_int (r->length); 00899 if (length < 1 || length > f->size - offset + 1) { 00900 cb_error_x (x, _("Length of '%s' out of bounds: %d"), 00901 name, length); 00902 } 00903 } 00904 } 00905 00906 /* run-time check */ 00907 if (CB_EXCEPTION_ENABLE (COB_EC_BOUND_REF_MOD)) { 00908 if (!CB_LITERAL_P (r->offset) 00909 || (r->length && !CB_LITERAL_P (r->length))) { 00910 e1 = cb_build_funcall_4 ("cob_check_ref_mod", 00911 cb_build_cast_integer (r->offset), 00912 r->length ? cb_build_cast_integer (r->length) : 00913 cb_int1, cb_int (f->size), 00914 cb_build_string0 ((ucharptr)f->name)); 00915 r->check = cb_list_add (r->check, e1); 00916 } 00917 } 00918 } 00919 00920 if (f->storage == CB_STORAGE_CONSTANT) { 00921 return CB_VALUE (f->values); 00922 } 00923 00924 return x; 00925 } 00926 00927 static cb_tree 00928 cb_build_length_1 (cb_tree x) 00929 { 00930 struct cb_field *f; 00931 cb_tree e; 00932 cb_tree size; 00933 00934 f = CB_FIELD (cb_ref (x)); 00935 00936 if (cb_field_variable_size (f) == NULL) { 00937 /* constant size */ 00938 return cb_int (cb_field_size (x)); 00939 } else { 00940 /* variable size */ 00941 e = NULL; 00942 for (f = f->children; f; f = f->sister) { 00943 size = cb_build_length_1 (cb_build_field_reference (f, x)); 00944 if (f->occurs_depending) { 00945 size = cb_build_binary_op (size, '*', f->occurs_depending); 00946 } else if (f->occurs_max > 1) { 00947 size = cb_build_binary_op (size, '*', cb_int (f->occurs_max)); 00948 } 00949 e = e ? cb_build_binary_op (e, '+', size) : size; 00950 } 00951 return e; 00952 } 00953 } 00954 00955 cb_tree 00956 cb_build_const_length (cb_tree x) 00957 { 00958 struct cb_field *f; 00959 char buff[64]; 00960 00961 if (x == cb_error_node) { 00962 return cb_error_node; 00963 } 00964 if (CB_REFERENCE_P (x) && cb_ref (x) == cb_error_node) { 00965 return cb_error_node; 00966 } 00967 00968 memset (buff, 0, sizeof (buff)); 00969 f = CB_FIELD (cb_ref (x)); 00970 if (f->flag_any_length) { 00971 cb_error (_("ANY LENGTH item not allowed here")); 00972 return cb_error_node; 00973 } 00974 if (f->level == 88) { 00975 cb_error (_("88 level item not allowed here")); 00976 return cb_error_node; 00977 } 00978 if (!f->flag_is_verified) { 00979 cb_validate_field (f); 00980 } 00981 sprintf (buff, "%d", f->memory_size); 00982 return cb_build_numeric_literal (0, (ucharptr)buff, 0); 00983 } 00984 00985 cb_tree 00986 cb_build_length (cb_tree x) 00987 { 00988 struct cb_field *f; 00989 struct cb_literal *l; 00990 cb_tree temp; 00991 char buff[64]; 00992 00993 if (x == cb_error_node) { 00994 return cb_error_node; 00995 } 00996 if (CB_REFERENCE_P (x) && cb_ref (x) == cb_error_node) { 00997 return cb_error_node; 00998 } 00999 01000 memset (buff, 0, sizeof (buff)); 01001 if (CB_LITERAL_P (x)) { 01002 l = CB_LITERAL (x); 01003 sprintf (buff, "%d", (int)l->size); 01004 return cb_build_numeric_literal (0, (ucharptr)buff, 0); 01005 } 01006 if (CB_REF_OR_FIELD_P (x)) { 01007 f = CB_FIELD (cb_ref (x)); 01008 if (f->flag_any_length) { 01009 return cb_build_any_intrinsic (cb_list_init (x)); 01010 } 01011 if (cb_field_variable_size (f) == NULL) { 01012 sprintf (buff, "%d", cb_field_size (x)); 01013 return cb_build_numeric_literal (0, (ucharptr)buff, 0); 01014 } 01015 } 01016 if (CB_INTRINSIC_P (x)) { 01017 return cb_build_any_intrinsic (cb_list_init (x)); 01018 } 01019 temp = cb_build_index (cb_build_filler (), NULL, 0, NULL); 01020 CB_FIELD (cb_ref (temp))->usage = CB_USAGE_LENGTH; 01021 CB_FIELD (cb_ref (temp))->count++; 01022 cb_emit (cb_build_assign (temp, cb_build_length_1 (x))); 01023 return temp; 01024 } 01025 01026 cb_tree 01027 cb_build_address (cb_tree x) 01028 { 01029 if (x == cb_error_node || 01030 (CB_REFERENCE_P (x) && cb_ref (x) == cb_error_node)) { 01031 return cb_error_node; 01032 } 01033 01034 return cb_build_cast_address (x); 01035 } 01036 01037 cb_tree 01038 cb_build_ppointer (cb_tree x) 01039 { 01040 struct cb_field *f; 01041 01042 if (x == cb_error_node || 01043 (CB_REFERENCE_P (x) && cb_ref (x) == cb_error_node)) { 01044 return cb_error_node; 01045 } 01046 01047 if (CB_REFERENCE_P (x)) { 01048 f = cb_field (cb_ref(x)); 01049 f->count++; 01050 } 01051 return cb_build_cast_ppointer (x); 01052 } 01053 01054 /* validate program */ 01055 01056 static int 01057 get_value (cb_tree x) 01058 { 01059 if (x == cb_space) { 01060 return ' '; 01061 } else if (x == cb_zero) { 01062 return '0'; 01063 } else if (x == cb_quote) { 01064 return '"'; 01065 } else if (x == cb_norm_low) { 01066 return 0; 01067 } else if (x == cb_norm_high) { 01068 return 255; 01069 } else if (x == cb_null) { 01070 return 0; 01071 } else if (CB_TREE_CLASS (x) == CB_CLASS_NUMERIC) { 01072 return cb_get_int (x) - 1; 01073 } else { 01074 return CB_LITERAL (x)->data[0]; 01075 } 01076 } 01077 01078 void 01079 cb_validate_program_environment (struct cb_program *prog) 01080 { 01081 cb_tree x; 01082 cb_tree y; 01083 cb_tree l; 01084 cb_tree ls; 01085 struct cb_alphabet_name *ap; 01086 unsigned char *data; 01087 size_t dupls; 01088 size_t unvals; 01089 size_t count; 01090 int lower; 01091 int upper; 01092 int size; 01093 int n; 01094 int i; 01095 int lastval; 01096 int values[256]; 01097 01098 /* Check ALPHABET clauses */ 01099 for (l = current_program->alphabet_name_list; l; l = CB_CHAIN (l)) { 01100 ap = CB_ALPHABET_NAME (CB_VALUE (l)); 01101 if (ap->type != CB_ALPHABET_CUSTOM) { 01102 continue; 01103 } 01104 ap->low_val_char = 0; 01105 ap->high_val_char = 255; 01106 dupls = 0; 01107 unvals = 0; 01108 count = 0; 01109 lastval = 0; 01110 for (n = 0; n < 256; n++) { 01111 values[n] = -1; 01112 } 01113 for (y = ap->custom_list; y; y = CB_CHAIN (y)) { 01114 if (count > 255) { 01115 unvals = 1; 01116 break; 01117 } 01118 x = CB_VALUE (y); 01119 if (CB_PAIR_P (x)) { 01120 /* X THRU Y */ 01121 lower = get_value (CB_PAIR_X (x)); 01122 upper = get_value (CB_PAIR_Y (x)); 01123 lastval = upper; 01124 if (!count) { 01125 ap->low_val_char = lower; 01126 } 01127 if (lower < 0 || lower > 255) { 01128 unvals = 1; 01129 continue; 01130 } 01131 if (upper < 0 || upper > 255) { 01132 unvals = 1; 01133 continue; 01134 } 01135 if (lower <= upper) { 01136 for (i = lower; i <= upper; i++) { 01137 if (values[i] != -1) { 01138 dupls = 1; 01139 } 01140 values[i] = i; 01141 count++; 01142 } 01143 } else { 01144 for (i = lower; i >= upper; i--) { 01145 if (values[i] != -1) { 01146 dupls = 1; 01147 } 01148 values[i] = i; 01149 count++; 01150 } 01151 } 01152 } else if (CB_LIST_P (x)) { 01153 /* X ALSO Y ... */ 01154 if (!count) { 01155 ap->low_val_char = get_value (CB_VALUE (x)); 01156 } 01157 for (ls = x; ls; ls = CB_CHAIN (ls)) { 01158 n = get_value (CB_VALUE (ls)); 01159 if (!CB_CHAIN (ls)) { 01160 lastval = n; 01161 } 01162 if (n < 0 || n > 255) { 01163 unvals = 1; 01164 continue; 01165 } 01166 if (values[n] != -1) { 01167 dupls = 1; 01168 } 01169 values[n] = n; 01170 count++; 01171 } 01172 } else { 01173 /* literal */ 01174 if (CB_TREE_CLASS (x) == CB_CLASS_NUMERIC) { 01175 n = get_value (x); 01176 lastval = n; 01177 if (!count) { 01178 ap->low_val_char = n; 01179 } 01180 if (n < 0 || n > 255) { 01181 unvals = 1; 01182 continue; 01183 } 01184 if (values[n] != -1) { 01185 dupls = 1; 01186 } 01187 values[n] = n; 01188 count++; 01189 } else if (CB_LITERAL_P (x)) { 01190 size = (int)CB_LITERAL (x)->size; 01191 data = CB_LITERAL (x)->data; 01192 if (!count) { 01193 ap->low_val_char = data[0]; 01194 } 01195 lastval = data[size - 1]; 01196 for (i = 0; i < size; i++) { 01197 n = data[i]; 01198 if (values[n] != -1) { 01199 dupls = 1; 01200 } 01201 values[n] = n; 01202 count++; 01203 } 01204 } else { 01205 n = get_value (x); 01206 lastval = n; 01207 if (!count) { 01208 ap->low_val_char = n; 01209 } 01210 if (n < 0 || n > 255) { 01211 unvals = 1; 01212 continue; 01213 } 01214 if (values[n] != -1) { 01215 dupls = 1; 01216 } 01217 values[n] = n; 01218 count++; 01219 } 01220 } 01221 } 01222 if (dupls || unvals) { 01223 if (dupls) { 01224 cb_error_x (l, _("Duplicate character values in alphabet '%s'"), 01225 cb_name (CB_VALUE(l))); 01226 } 01227 if (unvals) { 01228 cb_error_x (l, _("Invalid character values in alphabet '%s'"), 01229 cb_name (CB_VALUE(l))); 01230 } 01231 ap->low_val_char = 0; 01232 ap->high_val_char = 255; 01233 continue; 01234 } 01235 /* Calculate HIGH-VALUE */ 01236 /* If all 256 values have been specified, HIGH-VALUE is the last one */ 01237 /* Otherwise if HIGH-VALUE has been specified, find the highest */ 01238 /* value that has not been used */ 01239 if (count == 256) { 01240 ap->high_val_char = lastval; 01241 } else if (values[255] != -1) { 01242 for (n = 254; n >= 0; n--) { 01243 if (values[n] == -1) { 01244 ap->high_val_char = n; 01245 break; 01246 } 01247 } 01248 } 01249 } 01250 /* Rest HIGH/LOW-VALUES */ 01251 cb_low = cb_norm_low; 01252 cb_high = cb_norm_high; 01253 /* resolve the program collating sequence */ 01254 if (!prog->collating_sequence) { 01255 return; 01256 } 01257 x = cb_ref (prog->collating_sequence); 01258 /* RXWRXW 01259 if (x == cb_error_node) { 01260 prog->collating_sequence = NULL; 01261 return; 01262 } 01263 */ 01264 if (!CB_ALPHABET_NAME_P (x)) { 01265 cb_error_x (prog->collating_sequence, _("'%s' not alphabet name"), 01266 cb_name (prog->collating_sequence)); 01267 prog->collating_sequence = NULL; 01268 return; 01269 } 01270 if (CB_ALPHABET_NAME (x)->type != CB_ALPHABET_CUSTOM) { 01271 return; 01272 } 01273 if (CB_ALPHABET_NAME (x)->low_val_char) { 01274 cb_low = cb_build_alphanumeric_literal ((ucharptr)"\0", 1); 01275 CB_LITERAL(cb_low)->data[0] = CB_ALPHABET_NAME (x)->low_val_char; 01276 CB_LITERAL(cb_low)->all = 1; 01277 } 01278 if (CB_ALPHABET_NAME (x)->high_val_char != 255){ 01279 cb_high = cb_build_alphanumeric_literal ((ucharptr)"\0", 1); 01280 CB_LITERAL(cb_high)->data[0] = CB_ALPHABET_NAME (x)->high_val_char; 01281 CB_LITERAL(cb_high)->all = 1; 01282 } 01283 } 01284 01285 void 01286 cb_validate_program_data (struct cb_program *prog) 01287 { 01288 cb_tree l; 01289 cb_tree x; 01290 cb_tree assign; 01291 struct cb_field *p; 01292 struct cb_file *f; 01293 unsigned char *c; 01294 01295 for (l = current_program->file_list; l; l = CB_CHAIN (l)) { 01296 f = CB_FILE (CB_VALUE (l)); 01297 if (!f->finalized) { 01298 finalize_file (f, NULL); 01299 } 01300 } 01301 /* build undeclared assignment name now */ 01302 if (cb_assign_clause == CB_ASSIGN_MF) { 01303 for (l = current_program->file_list; l; l = CB_CHAIN (l)) { 01304 assign = CB_FILE (CB_VALUE (l))->assign; 01305 if (!assign) { 01306 continue; 01307 } 01308 if (CB_REFERENCE_P (assign)) { 01309 for (x = current_program->file_list; x; x = CB_CHAIN (x)) { 01310 if (!strcmp (CB_FILE (CB_VALUE (x))->name, 01311 CB_REFERENCE (assign)->word->name)) { 01312 redefinition_error (assign); 01313 } 01314 } 01315 p = check_level_78 (CB_REFERENCE (assign)->word->name); 01316 if (p) { 01317 c = (unsigned char *)CB_LITERAL(CB_VALUE(p->values))->data; 01318 assign = CB_TREE (build_literal (CB_CATEGORY_ALPHANUMERIC, c, strlen ((char *)c))); 01319 CB_FILE (CB_VALUE (l))->assign = assign; 01320 } 01321 } 01322 if (CB_REFERENCE_P (assign) && CB_REFERENCE (assign)->word->count == 0) { 01323 if (cb_warn_implicit_define) { 01324 cb_warning (_("'%s' will be implicitly defined"), CB_NAME (assign)); 01325 } 01326 x = cb_build_implicit_field (assign, COB_SMALL_BUFF); 01327 p = current_program->working_storage; 01328 CB_FIELD (x)->count++; 01329 if (p) { 01330 while (p->sister) { 01331 p = p->sister; 01332 } 01333 p->sister = CB_FIELD (x); 01334 } else { 01335 current_program->working_storage = CB_FIELD (x); 01336 } 01337 } 01338 if (CB_REFERENCE_P (assign)) { 01339 x = cb_ref (assign); 01340 if (CB_FIELD_P (x) && CB_FIELD (x)->level == 88) { 01341 cb_error_x (assign, _("ASSIGN data item '%s' invalid"), CB_NAME (assign)); 01342 } 01343 } 01344 } 01345 } 01346 01347 if (prog->cursor_pos) { 01348 x = cb_ref (prog->cursor_pos); 01349 if (x == cb_error_node) { 01350 prog->cursor_pos = NULL; 01351 } else if (CB_FIELD(x)->size != 6 && CB_FIELD(x)->size != 4) { 01352 cb_error_x (prog->cursor_pos, _("'%s' CURSOR is not 4 or 6 characters long"), 01353 cb_name (prog->cursor_pos)); 01354 prog->cursor_pos = NULL; 01355 } 01356 } 01357 if (prog->crt_status) { 01358 x = cb_ref (prog->crt_status); 01359 if (x == cb_error_node) { 01360 prog->crt_status = NULL; 01361 } else if (CB_FIELD(x)->size != 4) { 01362 cb_error_x (prog->crt_status, _("'%s' CRT STATUS is not 4 characters long"), 01363 cb_name (prog->crt_status)); 01364 prog->crt_status = NULL; 01365 } 01366 } else { 01367 l = cb_build_reference ("COB-CRT-STATUS"); 01368 p = CB_FIELD (cb_build_field (l)); 01369 p->usage = CB_USAGE_DISPLAY; 01370 p->pic = CB_PICTURE (cb_build_picture ("9(4)")); 01371 cb_validate_field (p); 01372 p->flag_no_init = 1; 01373 /* Do not initialize/bump ref count here 01374 p->values = cb_list_init (cb_zero); 01375 p->count++; 01376 */ 01377 current_program->working_storage = 01378 cb_field_add (current_program->working_storage, p); 01379 prog->crt_status = l; 01380 /* RXWRXW - Maybe better 01381 prog->crt_status = cb_build_index (cb_build_reference ("COB-CRT-STATUS"), cb_zero, 0, NULL); 01382 */ 01383 } 01384 01385 /* resolve all references so far */ 01386 for (l = cb_list_reverse (prog->reference_list); l; l = CB_CHAIN (l)) { 01387 cb_ref (CB_VALUE (l)); 01388 } 01389 for (l = current_program->file_list; l; l = CB_CHAIN (l)) { 01390 f = CB_FILE (CB_VALUE (l)); 01391 if (f->record_depending && f->record_depending != cb_error_node) { 01392 x = f->record_depending; 01393 if (cb_ref (x) != cb_error_node) { 01394 /* RXW - This breaks old legacy programs 01395 if (CB_REF_OR_FIELD_P(x)) { 01396 p = cb_field (x); 01397 switch (p->storage) { 01398 case CB_STORAGE_WORKING: 01399 case CB_STORAGE_LOCAL: 01400 case CB_STORAGE_LINKAGE: 01401 break; 01402 default: 01403 cb_error (_("RECORD DEPENDING item must be in WORKING/LOCAL/LINKAGE section")); 01404 } 01405 } else { 01406 */ 01407 if (!CB_REFERENCE_P(x) && !CB_FIELD_P(x)) { 01408 cb_error (_("Invalid RECORD DEPENDING item")); 01409 } 01410 } 01411 } 01412 } 01413 } 01414 01415 void 01416 cb_validate_program_body (struct cb_program *prog) 01417 { 01418 /* resolve all labels */ 01419 cb_tree l; 01420 cb_tree x; 01421 cb_tree v; 01422 01423 for (l = cb_list_reverse (prog->label_list); l; l = CB_CHAIN (l)) { 01424 x = CB_VALUE (l); 01425 v = cb_ref (x); 01426 if (CB_LABEL_P (v)) { 01427 CB_LABEL (v)->need_begin = 1; 01428 if (CB_REFERENCE (x)->length) { 01429 CB_LABEL (v)->need_return = 1; 01430 } 01431 } else if (v != cb_error_node) { 01432 cb_error_x (x, _("'%s' not procedure name"), cb_name (x)); 01433 } 01434 } 01435 01436 prog->file_list = cb_list_reverse (prog->file_list); 01437 prog->exec_list = cb_list_reverse (prog->exec_list); 01438 } 01439 01440 /* 01441 * Expressions 01442 */ 01443 01444 static void 01445 cb_expr_init (void) 01446 { 01447 static int initialized = 0; 01448 01449 if (initialized == 0) { 01450 /* init priority talble */ 01451 expr_prio['x'] = 0; 01452 expr_prio['^'] = 1; 01453 expr_prio['*'] = 2; 01454 expr_prio['/'] = 2; 01455 expr_prio['+'] = 3; 01456 expr_prio['-'] = 3; 01457 expr_prio['='] = 4; 01458 expr_prio['~'] = 4; 01459 expr_prio['<'] = 4; 01460 expr_prio['>'] = 4; 01461 expr_prio['['] = 4; 01462 expr_prio[']'] = 4; 01463 expr_prio['!'] = 5; 01464 expr_prio['&'] = 6; 01465 expr_prio['|'] = 7; 01466 expr_prio[')'] = 8; 01467 expr_prio['('] = 9; 01468 expr_prio[0] = 10; 01469 /* init stack */ 01470 expr_stack_size = START_STACK_SIZE; 01471 expr_stack = cobc_malloc (sizeof (struct expr_node) * START_STACK_SIZE); 01472 expr_stack[0].token = 0; /* dummy */ 01473 expr_stack[1].token = 0; /* dummy */ 01474 expr_stack[2].token = 0; /* dummy */ 01475 initialized = 1; 01476 } 01477 01478 expr_op = 0; 01479 expr_lh = NULL; 01480 expr_index = 3; 01481 } 01482 01483 static int 01484 expr_reduce (int token) 01485 { 01486 /* Example: 01487 * index: -3 -2 -1 0 01488 * token: 'x' '*' 'x' '+' ... 01489 */ 01490 01491 int op; 01492 01493 while (expr_prio[TOKEN (-2)] <= expr_prio[token]) { 01494 /* Reduce the expression depending on the last operator */ 01495 op = TOKEN (-2); 01496 switch (op) { 01497 case 'x': 01498 return 0; 01499 01500 case '+': 01501 case '-': 01502 case '*': 01503 case '/': 01504 case '^': 01505 /* Arithmetic operators: 'x' op 'x' */ 01506 if (TOKEN (-1) != 'x' || TOKEN (-3) != 'x') { 01507 return -1; 01508 } 01509 TOKEN (-3) = 'x'; 01510 VALUE (-3) = cb_build_binary_op (VALUE (-3), op, VALUE (-1)); 01511 expr_index -= 2; 01512 break; 01513 01514 case '!': 01515 /* Negation: '!' 'x' */ 01516 if (TOKEN (-1) != 'x') { 01517 return -1; 01518 } 01519 /* 'x' '=' 'x' '|' '!' 'x' */ 01520 if (expr_lh) { 01521 if (CB_TREE_CLASS (VALUE (-1)) != CB_CLASS_BOOLEAN) { 01522 VALUE (-1) = cb_build_binary_op (expr_lh, expr_op, VALUE (-1)); 01523 } 01524 } 01525 TOKEN (-2) = 'x'; 01526 VALUE (-2) = cb_build_negation (VALUE (-1)); 01527 expr_index -= 1; 01528 break; 01529 01530 case '&': 01531 case '|': 01532 /* Logical AND/OR: 'x' op 'x' */ 01533 if (TOKEN (-1) != 'x' || TOKEN (-3) != 'x') { 01534 return -1; 01535 } 01536 /* 'x' '=' 'x' '|' 'x' */ 01537 if (expr_lh) { 01538 if (CB_TREE_CLASS (VALUE (-1)) != CB_CLASS_BOOLEAN) { 01539 VALUE (-1) = cb_build_binary_op (expr_lh, expr_op, VALUE (-1)); 01540 } 01541 if (CB_TREE_CLASS (VALUE (-3)) != CB_CLASS_BOOLEAN) { 01542 VALUE (-3) = cb_build_binary_op (expr_lh, expr_op, VALUE (-3)); 01543 } 01544 } 01545 /* warning for complex expressions without explicit parentheses 01546 (i.e., "a OR b AND c" or "a AND b OR c") */ 01547 if (cb_warn_parentheses && op == '|') { 01548 if ((CB_BINARY_OP_P (VALUE (-3)) 01549 && CB_BINARY_OP (VALUE (-3))->op == '&') 01550 || (CB_BINARY_OP_P (VALUE (-1)) 01551 && CB_BINARY_OP (VALUE (-1))->op == '&')) { 01552 cb_warning (_("Suggest parentheses around AND within OR")); 01553 } 01554 } 01555 TOKEN (-3) = 'x'; 01556 VALUE (-3) = cb_build_binary_op (VALUE (-3), op, VALUE (-1)); 01557 expr_index -= 2; 01558 break; 01559 01560 case '(': 01561 case ')': 01562 return 0; 01563 01564 default: 01565 /* Relational operators */ 01566 if (TOKEN (-1) != 'x') { 01567 return -1; 01568 } 01569 switch (TOKEN (-3)) { 01570 case 'x': 01571 /* Simple condition: 'x' op 'x' */ 01572 if (VALUE (-3) == cb_error_node || VALUE (-1) == cb_error_node) { 01573 VALUE (-3) = cb_error_node; 01574 } else { 01575 expr_lh = VALUE (-3); 01576 if (CB_REF_OR_FIELD_P (expr_lh)) { 01577 if (cb_field (expr_lh)->level == 88) { 01578 VALUE (-3) = cb_error_node; 01579 return -1; 01580 } 01581 } 01582 if (CB_REF_OR_FIELD_P (VALUE(-1))) { 01583 if (cb_field (VALUE(-1))->level == 88) { 01584 VALUE (-3) = cb_error_node; 01585 return -1; 01586 } 01587 } 01588 expr_op = op; 01589 TOKEN (-3) = 'x'; 01590 if (CB_TREE_CLASS (VALUE (-1)) != CB_CLASS_BOOLEAN) { 01591 VALUE (-3) = cb_build_binary_op (expr_lh, op, VALUE (-1)); 01592 } else { 01593 VALUE (-3) = VALUE (-1); 01594 } 01595 } 01596 expr_index -= 2; 01597 break; 01598 case '&': 01599 case '|': 01600 /* Complex condition: 'x' '=' 'x' '|' op 'x' */ 01601 if (VALUE (-1) == cb_error_node) { 01602 VALUE (-2) = cb_error_node; 01603 } else { 01604 expr_op = op; 01605 TOKEN (-2) = 'x'; 01606 if (CB_TREE_CLASS (VALUE (-1)) != CB_CLASS_BOOLEAN) { 01607 VALUE (-2) = cb_build_binary_op (expr_lh, op, VALUE (-1)); 01608 } else { 01609 VALUE (-2) = VALUE (-1); 01610 } 01611 } 01612 expr_index -= 1; 01613 break; 01614 default: 01615 return -1; 01616 } 01617 break; 01618 } 01619 } 01620 01621 /* handle special case "op OR x AND" */ 01622 if (token == '&' && TOKEN (-2) == '|' && CB_TREE_CLASS (VALUE (-1)) != CB_CLASS_BOOLEAN) { 01623 TOKEN (-1) = 'x'; 01624 VALUE (-1) = cb_build_binary_op (expr_lh, expr_op, VALUE (-1)); 01625 } 01626 01627 return 0; 01628 } 01629 01630 static void 01631 cb_expr_shift_sign (const int op) 01632 { 01633 int have_not = 0; 01634 01635 if (TOKEN (-1) == '!') { 01636 have_not = 1; 01637 expr_index--; 01638 } 01639 expr_reduce ('='); 01640 if (TOKEN (-1) == 'x') { 01641 VALUE (-1) = cb_build_binary_op (VALUE (-1), op, cb_zero); 01642 if (have_not) { 01643 VALUE (-1) = cb_build_negation (VALUE (-1)); 01644 } 01645 } 01646 } 01647 01648 static void 01649 cb_expr_shift_class (const char *name) 01650 { 01651 int have_not = 0; 01652 01653 if (TOKEN (-1) == '!') { 01654 have_not = 1; 01655 expr_index--; 01656 } 01657 expr_reduce ('='); 01658 if (TOKEN (-1) == 'x') { 01659 VALUE (-1) = cb_build_funcall_1 (name, VALUE (-1)); 01660 if (have_not) { 01661 VALUE (-1) = cb_build_negation (VALUE (-1)); 01662 } 01663 } 01664 } 01665 01666 static void 01667 cb_expr_shift (int token, cb_tree value) 01668 { 01669 switch (token) { 01670 case 'x': 01671 /* sign ZERO condition */ 01672 if (value == cb_zero) { 01673 if (TOKEN (-1) == 'x' || TOKEN (-1) == '!') { 01674 cb_expr_shift_sign ('='); 01675 return; 01676 } 01677 } 01678 01679 /* class condition */ 01680 if (CB_REFERENCE_P (value) 01681 && CB_CLASS_NAME_P (cb_ref (value))) { 01682 cb_expr_shift_class (CB_CLASS_NAME (cb_ref (value))->cname); 01683 return; 01684 } 01685 01686 /* unary sign */ 01687 if ((TOKEN (-1) == '+' || TOKEN (-1) == '-') && TOKEN (-2) != 'x') { 01688 if (TOKEN (-1) == '-') { 01689 value = cb_build_binary_op (cb_zero, '-', value); 01690 } 01691 expr_index -= 1; 01692 } 01693 break; 01694 01695 case '(': 01696 /* 'x' op '(' --> '(' 'x' op */ 01697 switch (TOKEN (-1)) { 01698 case '=': 01699 case '~': 01700 case '<': 01701 case '>': 01702 case '[': 01703 case ']': 01704 expr_op = TOKEN (-1); 01705 if (TOKEN (-2) == 'x') { 01706 expr_lh = VALUE (-2); 01707 } 01708 } 01709 break; 01710 01711 case ')': 01712 /* enclose by parentheses */ 01713 expr_reduce (token); 01714 if (TOKEN (-2) == '(') { 01715 value = cb_build_parenthesis (VALUE (-1)); 01716 expr_index -= 2; 01717 cb_expr_shift ('x', value); 01718 return; 01719 } 01720 break; 01721 01722 default: 01723 /* '<' '|' '=' --> '[' */ 01724 /* '>' '|' '=' --> ']' */ 01725 if (token == '=' && TOKEN (-1) == '|' && (TOKEN (-2) == '<' || TOKEN (-2) == '>')) { 01726 token = (TOKEN (-2) == '<') ? '[' : ']'; 01727 expr_index -= 2; 01728 } 01729 01730 /* '!' '=' --> '~', etc. */ 01731 if (TOKEN (-1) == '!') { 01732 switch (token) { 01733 case '=': 01734 token = '~'; 01735 expr_index--; 01736 break; 01737 case '~': 01738 token = '='; 01739 expr_index--; 01740 break; 01741 case '<': 01742 token = ']'; 01743 expr_index--; 01744 break; 01745 case '>': 01746 token = '['; 01747 expr_index--; 01748 break; 01749 case '[': 01750 token = '>'; 01751 expr_index--; 01752 break; 01753 case ']': 01754 token = '<'; 01755 expr_index--; 01756 break; 01757 } 01758 } 01759 break; 01760 } 01761 01762 /* reduce */ 01763 expr_reduce (token); 01764 01765 /* allocate sufficient stack memory */ 01766 if (expr_index >= expr_stack_size) { 01767 expr_stack_size *= 2; 01768 expr_stack = cobc_realloc (expr_stack, sizeof (struct expr_node) * expr_stack_size); 01769 } 01770 01771 /* put on the stack */ 01772 TOKEN (0) = token; 01773 VALUE (0) = value; 01774 expr_index++; 01775 } 01776 01777 static void 01778 expr_expand (cb_tree *x) 01779 { 01780 struct cb_binary_op *p; 01781 01782 start: 01783 /* remove parenthesis */ 01784 if (CB_BINARY_OP_P (*x)) { 01785 p = CB_BINARY_OP (*x); 01786 if (p->op == '@') { 01787 *x = p->x; 01788 goto start; 01789 } 01790 expr_expand (&p->x); 01791 if (p->y) { 01792 expr_expand (&p->y); 01793 } 01794 } 01795 } 01796 01797 static cb_tree 01798 cb_expr_finish (void) 01799 { 01800 expr_reduce (0); /* reduce all */ 01801 01802 if (expr_index != 4) { 01803 cb_error (_("Invalid expression")); 01804 return cb_error_node; 01805 } 01806 01807 if (!expr_stack[3].value) { 01808 cb_error (_("Invalid expression")); 01809 return cb_error_node; 01810 } 01811 expr_expand (&expr_stack[3].value); 01812 if (expr_stack[3].token != 'x') { 01813 cb_error (_("Invalid expression")); 01814 return cb_error_node; 01815 } 01816 return expr_stack[3].value; 01817 } 01818 01819 cb_tree 01820 cb_build_expr (cb_tree list) 01821 { 01822 cb_tree l; 01823 /* RXW 01824 cb_tree x; 01825 */ 01826 int op; 01827 01828 cb_expr_init (); 01829 01830 for (l = list; l; l = CB_CHAIN (l)) { 01831 op = CB_PURPOSE_INT (l); 01832 switch (op) { 01833 case '9': /* NUMERIC */ 01834 cb_expr_shift_class ("cob_is_numeric"); 01835 break; 01836 case 'A': /* ALPHABETIC */ 01837 cb_expr_shift_class ("cob_is_alpha"); 01838 break; 01839 case 'L': /* ALPHABETIC_LOWER */ 01840 cb_expr_shift_class ("cob_is_lower"); 01841 break; 01842 case 'U': /* ALPHABETIC_UPPER */ 01843 cb_expr_shift_class ("cob_is_upper"); 01844 break; 01845 case 'P': /* POSITIVE */ 01846 cb_expr_shift_sign ('>'); 01847 break; 01848 case 'N': /* NEGATIVE */ 01849 cb_expr_shift_sign ('<'); 01850 break; 01851 case 'O': /* OMITTED */ 01852 current_statement->null_check = NULL; 01853 cb_expr_shift_class ("cob_is_omitted"); 01854 break; 01855 /* RXW 01856 case 'x': 01857 if (CB_VALUE (l) && CB_REFERENCE_P (CB_VALUE (l))) { 01858 x = CB_CHAIN (l); 01859 if (x && cb_field (CB_VALUE (l))->level == 88) { 01860 switch (CB_PURPOSE_INT (x)) { 01861 case '&': 01862 case '|': 01863 case '(': 01864 case ')': 01865 break; 01866 default: 01867 cb_error (_("Invalid condition")); 01868 break; 01869 } 01870 } 01871 } 01872 cb_expr_shift (op, CB_VALUE (l)); 01873 break; 01874 */ 01875 default: 01876 cb_expr_shift (op, CB_VALUE (l)); 01877 break; 01878 } 01879 } 01880 01881 return cb_expr_finish (); 01882 } 01883 01884 /* 01885 * Numerical operation 01886 */ 01887 01888 static cb_tree 01889 build_store_option (cb_tree x, cb_tree round_opt) 01890 { 01891 int opt = 0; 01892 01893 if (round_opt == cb_int1) { 01894 opt |= COB_STORE_ROUND; 01895 } 01896 01897 switch (CB_FIELD (cb_ref (x))->usage) { 01898 case CB_USAGE_COMP_5: 01899 case CB_USAGE_COMP_X: 01900 if (current_statement->handler1) { 01901 opt |= COB_STORE_KEEP_ON_OVERFLOW; 01902 } 01903 break; 01904 default: 01905 if (!cb_binary_truncate) { 01906 if (current_statement->handler1) { 01907 opt |= COB_STORE_KEEP_ON_OVERFLOW; 01908 } 01909 break; 01910 } 01911 01912 /* RXW Fixme - It seems as though we have NEVER implemented TRUNC, 01913 Code has always been wrong. Hmm. The following statement would 01914 activate what was intended but ... 01915 What should we do here? 01916 if (current_statement->handler1) { 01917 */ 01918 if (current_statement->handler_id) { 01919 opt |= COB_STORE_KEEP_ON_OVERFLOW; 01920 } else if (cb_binary_truncate) { 01921 opt |= COB_STORE_TRUNC_ON_OVERFLOW; 01922 } 01923 break; 01924 } 01925 01926 return cb_int (opt); 01927 } 01928 01929 static cb_tree 01930 decimal_alloc (void) 01931 { 01932 cb_tree x; 01933 01934 x = cb_build_decimal (current_program->decimal_index); 01935 current_program->decimal_index++; 01936 if (current_program->decimal_index > current_program->decimal_index_max) { 01937 current_program->decimal_index_max = current_program->decimal_index; 01938 } 01939 return x; 01940 } 01941 01942 static void 01943 decimal_free (void) 01944 { 01945 current_program->decimal_index--; 01946 } 01947 01948 static void 01949 decimal_compute (const int op, cb_tree x, cb_tree y) 01950 { 01951 const char *func; 01952 01953 switch (op) { 01954 case '+': 01955 func = "cob_decimal_add"; 01956 break; 01957 case '-': 01958 func = "cob_decimal_sub"; 01959 break; 01960 case '*': 01961 func = "cob_decimal_mul"; 01962 break; 01963 case '/': 01964 func = "cob_decimal_div"; 01965 break; 01966 case '^': 01967 func = "cob_decimal_pow"; 01968 break; 01969 default: 01970 fprintf (stderr, "Unexpected operation %d\n", op); 01971 ABORT (); 01972 } 01973 dpush (cb_build_funcall_2 (func, x, y)); 01974 } 01975 01976 static void 01977 decimal_expand (cb_tree d, cb_tree x) 01978 { 01979 struct cb_literal *l; 01980 struct cb_field *f; 01981 struct cb_binary_op *p; 01982 cb_tree t; 01983 01984 switch (CB_TREE_TAG (x)) { 01985 case CB_TAG_CONST: 01986 if (x == cb_zero) { 01987 dpush (cb_build_funcall_2 ("cob_decimal_set_int", d, cb_int0)); 01988 current_program->gen_decset = 1; 01989 } else { 01990 fprintf (stderr, "Unexpected constant expansion\n"); 01991 ABORT (); 01992 } 01993 break; 01994 case CB_TAG_LITERAL: 01995 /* set d, N */ 01996 l = CB_LITERAL (x); 01997 if (l->size < 10 && l->scale == 0) { 01998 dpush (cb_build_funcall_2 ("cob_decimal_set_int", d, cb_build_cast_integer (x))); 01999 current_program->gen_decset = 1; 02000 } else { 02001 dpush (cb_build_funcall_2 ("cob_decimal_set_field", d, x)); 02002 } 02003 break; 02004 case CB_TAG_REFERENCE: 02005 /* set d, X */ 02006 f = cb_field (x); 02007 /* check numeric */ 02008 if (CB_EXCEPTION_ENABLE (COB_EC_DATA_INCOMPATIBLE)) { 02009 if (f->usage == CB_USAGE_DISPLAY || f->usage == CB_USAGE_PACKED) { 02010 dpush (cb_build_funcall_2 ("cob_check_numeric", 02011 x, cb_build_string0 ((ucharptr)(f->name)))); 02012 } 02013 } 02014 02015 if (cb_fits_int (x)) { 02016 if (f->pic->have_sign) { 02017 dpush (cb_build_funcall_2 ("cob_decimal_set_int", d, cb_build_cast_integer (x))); 02018 current_program->gen_decset = 1; 02019 } else { 02020 dpush (cb_build_funcall_2 ("cob_decimal_set_uint", d, cb_build_cast_integer (x))); 02021 current_program->gen_udecset = 1; 02022 } 02023 } else { 02024 dpush (cb_build_funcall_2 ("cob_decimal_set_field", d, x)); 02025 } 02026 break; 02027 case CB_TAG_BINARY_OP: 02028 /* set d, X 02029 * set t, Y 02030 * OP d, t */ 02031 p = CB_BINARY_OP (x); 02032 t = decimal_alloc (); 02033 decimal_expand (d, p->x); 02034 decimal_expand (t, p->y); 02035 decimal_compute (p->op, d, t); 02036 decimal_free (); 02037 break; 02038 case CB_TAG_INTRINSIC: 02039 dpush (cb_build_funcall_2 ("cob_decimal_set_field", d, x)); 02040 break; 02041 default: 02042 fprintf (stderr, "Unexpected tree tag %d\n", CB_TREE_TAG (x)); 02043 ABORT (); 02044 } 02045 } 02046 02047 static void 02048 decimal_assign (cb_tree x, cb_tree d, cb_tree round_opt) 02049 { 02050 dpush (cb_build_funcall_3 ("cob_decimal_get_field", d, x, build_store_option (x, round_opt))); 02051 } 02052 02053 static cb_tree 02054 build_decimal_assign (cb_tree vars, int op, cb_tree val) 02055 { 02056 cb_tree l; 02057 cb_tree t; 02058 cb_tree s1 = NULL; 02059 cb_tree d; 02060 02061 d = decimal_alloc (); 02062 02063 /* set d, VAL */ 02064 decimal_expand (d, val); 02065 02066 if (op == 0) { 02067 for (l = vars; l; l = CB_CHAIN (l)) { 02068 /* set VAR, d */ 02069 decimal_assign (CB_VALUE (l), d, CB_PURPOSE (l)); 02070 s1 = cb_list_add (s1, cb_list_reverse (decimal_stack)); 02071 decimal_stack = NULL; 02072 } 02073 } else { 02074 t = decimal_alloc (); 02075 for (l = vars; l; l = CB_CHAIN (l)) { 02076 /* set t, VAR 02077 * OP t, d 02078 * set VAR, t 02079 */ 02080 decimal_expand (t, CB_VALUE (l)); 02081 decimal_compute (op, t, d); 02082 decimal_assign (CB_VALUE (l), t, CB_PURPOSE (l)); 02083 s1 = cb_list_add (s1, cb_list_reverse (decimal_stack)); 02084 decimal_stack = NULL; 02085 } 02086 decimal_free (); 02087 } 02088 02089 decimal_free (); 02090 return s1; 02091 } 02092 02093 void 02094 cb_emit_arithmetic (cb_tree vars, int op, cb_tree val) 02095 { 02096 cb_tree l; 02097 struct cb_field *f; 02098 02099 val = cb_check_numeric_value (val); 02100 if (op) { 02101 cb_list_map (cb_check_numeric_name, vars); 02102 } else { 02103 cb_list_map (cb_check_numeric_edited_name, vars); 02104 } 02105 02106 if (cb_validate_one (val)) { 02107 return; 02108 } 02109 if (cb_validate_list (vars)) { 02110 return; 02111 } 02112 02113 if (!CB_BINARY_OP_P (val)) { 02114 if (op == '+' || op == '-') { 02115 if (CB_EXCEPTION_ENABLE (COB_EC_DATA_INCOMPATIBLE) && 02116 (CB_REF_OR_FIELD_P (val))) { 02117 f = cb_field (val); 02118 if (f->usage == CB_USAGE_DISPLAY || 02119 f->usage == CB_USAGE_PACKED) { 02120 cb_emit (cb_build_funcall_2 ("cob_check_numeric", 02121 val, 02122 cb_build_string0 ((ucharptr)(f->name)))); 02123 } 02124 } 02125 for (l = vars; l; l = CB_CHAIN (l)) { 02126 if (CB_EXCEPTION_ENABLE (COB_EC_DATA_INCOMPATIBLE) && 02127 (CB_REF_OR_FIELD_P (CB_VALUE(l)))) { 02128 f = cb_field (CB_VALUE(l)); 02129 if (f->usage == CB_USAGE_DISPLAY || 02130 f->usage == CB_USAGE_PACKED) { 02131 cb_emit (cb_build_funcall_2 ("cob_check_numeric", 02132 CB_VALUE(l), 02133 cb_build_string0 ((ucharptr)(f->name)))); 02134 } 02135 } 02136 if (op == '+') { 02137 CB_VALUE (l) = cb_build_add (CB_VALUE (l), val, CB_PURPOSE (l)); 02138 } else { 02139 CB_VALUE (l) = cb_build_sub (CB_VALUE (l), val, CB_PURPOSE (l)); 02140 } 02141 } 02142 cb_emit_list (vars); 02143 return; 02144 } 02145 } 02146 02147 cb_emit (build_decimal_assign (vars, op, val)); 02148 } 02149 02150 /* 02151 * Condition 02152 */ 02153 02154 static cb_tree 02155 build_cond_88 (cb_tree x) 02156 { 02157 struct cb_field *f; 02158 cb_tree l; 02159 cb_tree t; 02160 cb_tree c1 = NULL; 02161 cb_tree c2; 02162 02163 f = cb_field (x); 02164 /* refer to parent's data storage */ 02165 x = cb_build_field_reference (f->parent, x); 02166 f->parent->count++; 02167 02168 /* build condition */ 02169 for (l = f->values; l; l = CB_CHAIN (l)) { 02170 t = CB_VALUE (l); 02171 if (CB_PAIR_P (t)) { 02172 /* VALUE THRU VALUE */ 02173 c2 = cb_build_binary_op (cb_build_binary_op (CB_PAIR_X (t), '[', x), 02174 '&', cb_build_binary_op (x, '[', CB_PAIR_Y (t))); 02175 } else { 02176 /* VALUE */ 02177 c2 = cb_build_binary_op (x, '=', t); 02178 } 02179 if (c1 == NULL) { 02180 c1 = c2; 02181 } else { 02182 c1 = cb_build_binary_op (c1, '|', c2); 02183 } 02184 } 02185 return c1; 02186 } 02187 02188 static cb_tree 02189 cb_build_optim_cond (struct cb_binary_op *p) 02190 { 02191 struct cb_field *f; 02192 struct cb_field *fy; 02193 const char *s; 02194 size_t n; 02195 02196 if (CB_REF_OR_FIELD_P (p->y)) { 02197 fy = cb_field (p->y); 02198 if (!fy->pic->have_sign && (fy->usage == CB_USAGE_BINARY || 02199 fy->usage == CB_USAGE_COMP_5 || 02200 fy->usage == CB_USAGE_COMP_X)) { 02201 return cb_build_funcall_2 ("cob_cmp_uint", p->x, cb_build_cast_integer (p->y)); 02202 } 02203 } 02204 if (CB_REF_OR_FIELD_P (p->x)) { 02205 f = cb_field (p->x); 02206 if (!f->pic->scale && f->usage == CB_USAGE_PACKED) { 02207 if (f->pic->digits < 10) { 02208 return cb_build_funcall_2 ("cob_cmp_packed_int", 02209 p->x, 02210 cb_build_cast_integer (p->y)); 02211 } else { 02212 return cb_build_funcall_2 ("cob_cmp_packed", 02213 p->x, 02214 cb_build_cast_integer (p->y)); 02215 } 02216 } 02217 if (!f->pic->scale && f->usage == CB_USAGE_DISPLAY && 02218 !f->flag_sign_leading && !f->flag_sign_separate) { 02219 if (cb_fits_int (p->x)) { 02220 if (!f->pic->have_sign) { 02221 return cb_build_funcall_3 ("cob_cmp_numdisp", 02222 cb_build_cast_address (p->x), 02223 cb_int (f->size), 02224 cb_build_cast_integer (p->y)); 02225 } else { 02226 return cb_build_funcall_3 ("cob_cmp_sign_numdisp", 02227 cb_build_cast_address (p->x), 02228 cb_int (f->size), 02229 cb_build_cast_integer (p->y)); 02230 } 02231 } else if (cb_fits_long_long (p->x)) { 02232 if (!f->pic->have_sign) { 02233 return cb_build_funcall_3 ("cob_cmp_long_numdisp", 02234 cb_build_cast_address (p->x), 02235 cb_int (f->size), 02236 cb_build_cast_integer (p->y)); 02237 } else { 02238 return cb_build_funcall_3 ("cob_cmp_long_sign_numdisp", 02239 cb_build_cast_address (p->x), 02240 cb_int (f->size), 02241 cb_build_cast_integer (p->y)); 02242 } 02243 } 02244 } 02245 if (!f->pic->scale && (f->usage == CB_USAGE_BINARY || 02246 f->usage == CB_USAGE_COMP_5 || 02247 f->usage == CB_USAGE_INDEX || 02248 f->usage == CB_USAGE_COMP_X)) { 02249 n = (f->size - 1) + (8 * (f->pic->have_sign ? 1 : 0)) + 02250 (16 * (f->flag_binary_swap ? 1 : 0)); 02251 #if defined(COB_NON_ALIGNED) && !defined(_MSC_VER) 02252 switch (f->size) { 02253 case 2: 02254 #ifdef COB_SHORT_BORK 02255 s = bin_compare_funcs[n]; 02256 break; 02257 #endif 02258 case 4: 02259 case 8: 02260 if (f->storage != CB_STORAGE_LINKAGE && 02261 f->indexes == 0 && (f->offset % f->size) == 0) { 02262 s = align_bin_compare_funcs[n]; 02263 } else { 02264 s = bin_compare_funcs[n]; 02265 } 02266 break; 02267 default: 02268 s = bin_compare_funcs[n]; 02269 break; 02270 } 02271 #else 02272 s = bin_compare_funcs[n]; 02273 #endif 02274 if (s) { 02275 return cb_build_funcall_2 (s, 02276 cb_build_cast_address (p->x), 02277 cb_build_cast_integer (p->y)); 02278 } 02279 } 02280 } 02281 return cb_build_funcall_2 ("cob_cmp_int", p->x, cb_build_cast_integer (p->y)); 02282 } 02283 02284 static int 02285 cb_chk_num_cond (cb_tree x, cb_tree y) 02286 { 02287 struct cb_field *fx; 02288 struct cb_field *fy; 02289 02290 if (!CB_REFERENCE_P (x) && !CB_FIELD_P (x)) { 02291 return 0; 02292 } 02293 if (!CB_REFERENCE_P (y) && !CB_FIELD_P (y)) { 02294 return 0; 02295 } 02296 if (CB_TREE_CATEGORY (x) != CB_CATEGORY_NUMERIC) { 02297 return 0; 02298 } 02299 if (CB_TREE_CATEGORY (y) != CB_CATEGORY_NUMERIC) { 02300 return 0; 02301 } 02302 if (CB_TREE_CLASS (x) != CB_CLASS_NUMERIC) { 02303 return 0; 02304 } 02305 if (CB_TREE_CLASS (y) != CB_CLASS_NUMERIC) { 02306 return 0; 02307 } 02308 fx = cb_field (x); 02309 fy = cb_field (y); 02310 if (fx->usage != CB_USAGE_DISPLAY) { 02311 return 0; 02312 } 02313 if (fy->usage != CB_USAGE_DISPLAY) { 02314 return 0; 02315 } 02316 if (fx->pic->have_sign || fy->pic->have_sign) { 02317 return 0; 02318 } 02319 if (fx->size != fy->size) { 02320 return 0; 02321 } 02322 if (fx->pic->scale != fy->pic->scale) { 02323 return 0; 02324 } 02325 return 1; 02326 } 02327 02328 static int 02329 cb_chk_alpha_cond (cb_tree x) 02330 { 02331 if (current_program->alphabet_name_list) { 02332 return 0; 02333 } 02334 if (CB_LITERAL_P (x)) { 02335 return 1; 02336 } 02337 if (!CB_REFERENCE_P (x) && !CB_FIELD_P (x)) { 02338 return 0; 02339 } 02340 if (CB_TREE_CATEGORY (x) != CB_CATEGORY_ALPHANUMERIC && 02341 CB_TREE_CATEGORY (x) != CB_CATEGORY_ALPHABETIC) { 02342 return 0; 02343 } 02344 if (cb_field_variable_size (cb_field (x))) { 02345 return 0; 02346 } 02347 if (cb_field_size (x) < 0) { 02348 return 0; 02349 } 02350 return 1; 02351 } 02352 02353 cb_tree 02354 cb_build_cond (cb_tree x) 02355 { 02356 int size1; 02357 int size2; 02358 struct cb_field *f; 02359 struct cb_binary_op *p; 02360 cb_tree d1; 02361 cb_tree d2; 02362 02363 switch (CB_TREE_TAG (x)) { 02364 case CB_TAG_CONST: 02365 case CB_TAG_FUNCALL: 02366 return x; 02367 case CB_TAG_REFERENCE: 02368 if (!CB_FIELD_P (cb_ref (x))) { 02369 return cb_build_cond (cb_ref (x)); 02370 } 02371 02372 f = cb_field (x); 02373 02374 /* level 88 condition */ 02375 if (f->level == 88) { 02376 /* We need to build a 88 condition at every occurrence 02377 instead of once at the beginning because a 88 item 02378 may be subscripted (i.e., it is not a constant tree). */ 02379 return cb_build_cond (build_cond_88 (x)); 02380 } 02381 02382 cb_error_x (x, _("Invalid expression")); 02383 return cb_error_node; 02384 case CB_TAG_BINARY_OP: 02385 p = CB_BINARY_OP (x); 02386 switch (p->op) { 02387 case '!': 02388 return cb_build_negation (cb_build_cond (p->x)); 02389 case '&': 02390 case '|': 02391 return cb_build_binary_op (cb_build_cond (p->x), p->op, cb_build_cond (p->y)); 02392 default: 02393 if (CB_INDEX_P (p->x) || CB_INDEX_P (p->y) 02394 || CB_TREE_CLASS (p->x) == CB_CLASS_POINTER 02395 || CB_TREE_CLASS (p->y) == CB_CLASS_POINTER) { 02396 x = cb_build_binary_op (p->x, '-', p->y); 02397 } else if (CB_BINARY_OP_P (p->x) || CB_BINARY_OP_P (p->y)) { 02398 /* decimal comparison */ 02399 d1 = decimal_alloc (); 02400 d2 = decimal_alloc (); 02401 02402 decimal_expand (d1, p->x); 02403 decimal_expand (d2, p->y); 02404 dpush (cb_build_funcall_2 ("cob_decimal_cmp", d1, d2)); 02405 decimal_free (); 02406 decimal_free (); 02407 x = cb_list_reverse (decimal_stack); 02408 decimal_stack = NULL; 02409 } else { 02410 if (cb_chk_num_cond (p->x, p->y)) { 02411 size1 = cb_field_size (p->x); 02412 x = cb_build_funcall_3 ("memcmp", 02413 cb_build_cast_address (p->x), 02414 cb_build_cast_address (p->y), 02415 cb_int (size1)); 02416 break; 02417 } 02418 if (CB_TREE_CLASS (p->x) == CB_CLASS_NUMERIC 02419 && CB_TREE_CLASS (p->y) == CB_CLASS_NUMERIC 02420 && cb_fits_int (p->y)) { 02421 x = cb_build_optim_cond (p); 02422 break; 02423 } 02424 02425 /* field comparison */ 02426 if ((CB_REF_OR_FIELD_P (p->x)) 02427 && (CB_TREE_CATEGORY (p->x) == CB_CATEGORY_ALPHANUMERIC || 02428 CB_TREE_CATEGORY (p->x) == CB_CATEGORY_ALPHABETIC) 02429 && (cb_field_size (p->x) == 1) 02430 && (!current_program->alphabet_name_list) 02431 && (p->y == cb_space || p->y == cb_low || 02432 p->y == cb_high || p->y == cb_zero)) { 02433 x = cb_build_funcall_2 ("$G", p->x, p->y); 02434 break; 02435 } 02436 if (cb_chk_alpha_cond (p->x) && cb_chk_alpha_cond (p->y)) { 02437 size1 = cb_field_size (p->x); 02438 size2 = cb_field_size (p->y); 02439 } else { 02440 size1 = 0; 02441 size2 = 0; 02442 } 02443 if (size1 == 1 && size2 == 1) { 02444 x = cb_build_funcall_2 ("$G", p->x, p->y); 02445 } else if (size1 != 0 && size1 == size2) { 02446 x = cb_build_funcall_3 ("memcmp", 02447 cb_build_cast_address (p->x), 02448 cb_build_cast_address (p->y), 02449 cb_int (size1)); 02450 } else { 02451 if (CB_TREE_CLASS (p->x) == CB_CLASS_NUMERIC && p->y == cb_zero) { 02452 x = cb_build_optim_cond (p); 02453 } else { 02454 x = cb_build_funcall_2 ("cob_cmp", p->x, p->y); 02455 } 02456 } 02457 } 02458 } 02459 return cb_build_binary_op (x, p->op, p->y); 02460 default: 02461 cb_error_x (x, _("Invalid expression")); 02462 return cb_error_node; 02463 } 02464 /* NOT REACHED */ 02465 return x; 02466 } 02467 02468 /* 02469 * ADD/SUBTRACT CORRESPONDING 02470 */ 02471 02472 static cb_tree 02473 cb_build_optim_add (cb_tree v, cb_tree n) 02474 { 02475 size_t z; 02476 const char *s; 02477 struct cb_field *f; 02478 02479 if (CB_REF_OR_FIELD_P (v)) { 02480 f = cb_field (v); 02481 if (!f->pic->scale && (f->usage == CB_USAGE_BINARY || 02482 f->usage == CB_USAGE_COMP_5 || 02483 f->usage == CB_USAGE_COMP_X)) { 02484 z = (f->size - 1) + (8 * (f->pic->have_sign ? 1 : 0)) + 02485 (16 * (f->flag_binary_swap ? 1 : 0)); 02486 #if defined(COB_NON_ALIGNED) && !defined(_MSC_VER) 02487 switch (f->size) { 02488 case 2: 02489 #ifdef COB_SHORT_BORK 02490 s = bin_add_funcs[z]; 02491 break; 02492 #endif 02493 case 4: 02494 case 8: 02495 if (f->storage != CB_STORAGE_LINKAGE && 02496 f->indexes == 0 && (f->offset % f->size) == 0) { 02497 s = align_bin_add_funcs[z]; 02498 } else { 02499 s = bin_add_funcs[z]; 02500 } 02501 break; 02502 default: 02503 s = bin_add_funcs[z]; 02504 break; 02505 } 02506 #else 02507 if (f->usage == CB_USAGE_COMP_5) { 02508 switch (f->size) { 02509 case 1: 02510 case 2: 02511 case 4: 02512 case 8: 02513 return cb_build_assign (v, cb_build_binary_op (v, '+', n)); 02514 } 02515 } 02516 s = bin_add_funcs[z]; 02517 #endif 02518 if (s) { 02519 return cb_build_funcall_2 (s, 02520 cb_build_cast_address (v), 02521 cb_build_cast_integer (n)); 02522 } 02523 } else if (!f->pic->scale && f->usage == CB_USAGE_PACKED && 02524 f->pic->digits < 10) { 02525 return cb_build_funcall_2 ("cob_add_packed_int", 02526 v, cb_build_cast_integer (n)); 02527 } 02528 02529 } 02530 return cb_build_funcall_2 ("cob_add_int", v, cb_build_cast_integer (n)); 02531 } 02532 02533 static cb_tree 02534 cb_build_optim_sub (cb_tree v, cb_tree n) 02535 { 02536 size_t z; 02537 const char *s; 02538 struct cb_field *f; 02539 02540 if (CB_REF_OR_FIELD_P (v)) { 02541 f = cb_field (v); 02542 if (!f->pic->scale && (f->usage == CB_USAGE_BINARY || 02543 f->usage == CB_USAGE_COMP_5 || 02544 f->usage == CB_USAGE_COMP_X)) { 02545 z = (f->size - 1) + (8 * (f->pic->have_sign ? 1 : 0)) + 02546 (16 * (f->flag_binary_swap ? 1 : 0)); 02547 #if defined(COB_NON_ALIGNED) && !defined(_MSC_VER) 02548 switch (f->size) { 02549 case 2: 02550 #ifdef COB_SHORT_BORK 02551 s = bin_sub_funcs[z]; 02552 break; 02553 #endif 02554 case 4: 02555 case 8: 02556 if (f->storage != CB_STORAGE_LINKAGE && 02557 f->indexes == 0 && (f->offset % f->size) == 0) { 02558 s = align_bin_sub_funcs[z]; 02559 } else { 02560 s = bin_sub_funcs[z]; 02561 } 02562 break; 02563 default: 02564 s = bin_sub_funcs[z]; 02565 break; 02566 } 02567 #else 02568 if (f->usage == CB_USAGE_COMP_5) { 02569 switch (f->size) { 02570 case 1: 02571 case 2: 02572 case 4: 02573 case 8: 02574 return cb_build_assign (v, cb_build_binary_op (v, '-', n)); 02575 } 02576 } 02577 s = bin_sub_funcs[z]; 02578 #endif 02579 if (s) { 02580 return cb_build_funcall_2 (s, 02581 cb_build_cast_address (v), 02582 cb_build_cast_integer (n)); 02583 } 02584 } 02585 02586 } 02587 return cb_build_funcall_2 ("cob_sub_int", v, cb_build_cast_integer (n)); 02588 } 02589 02590 cb_tree 02591 cb_build_add (cb_tree v, cb_tree n, cb_tree round_opt) 02592 { 02593 cb_tree opt; 02594 struct cb_field *f; 02595 02596 #ifdef COB_NON_ALIGNED 02597 if (CB_INDEX_P (v)) { 02598 return cb_build_move (cb_build_binary_op (v, '+', n), v); 02599 } 02600 if (CB_TREE_CLASS (v) == CB_CLASS_POINTER) { 02601 current_program->gen_ptrmanip = 1; 02602 return cb_build_funcall_3 ("cob_pointer_manip", v, n, cb_int0); 02603 } 02604 #else 02605 if (CB_INDEX_P (v) || CB_TREE_CLASS (v) == CB_CLASS_POINTER) { 02606 return cb_build_move (cb_build_binary_op (v, '+', n), v); 02607 } 02608 #endif 02609 02610 if (CB_REF_OR_FIELD_P (v)) { 02611 f = cb_field (v); 02612 f->count++; 02613 } 02614 if (CB_REF_OR_FIELD_P (n)) { 02615 f = cb_field (n); 02616 f->count++; 02617 } 02618 if (round_opt == cb_high) { 02619 if (cb_fits_int (n)) { 02620 return cb_build_optim_add (v, n); 02621 } else { 02622 return cb_build_funcall_3 ("cob_add", v, n, cb_int0); 02623 } 02624 } 02625 opt = build_store_option (v, round_opt); 02626 if (opt == cb_int0 && cb_fits_int (n)) { 02627 return cb_build_optim_add (v, n); 02628 } 02629 return cb_build_funcall_3 ("cob_add", v, n, opt); 02630 } 02631 02632 cb_tree 02633 cb_build_sub (cb_tree v, cb_tree n, cb_tree round_opt) 02634 { 02635 cb_tree opt; 02636 struct cb_field *f; 02637 02638 #ifdef COB_NON_ALIGNED 02639 if (CB_INDEX_P (v)) { 02640 return cb_build_move (cb_build_binary_op (v, '-', n), v); 02641 } 02642 if (CB_TREE_CLASS (v) == CB_CLASS_POINTER) { 02643 current_program->gen_ptrmanip = 1; 02644 return cb_build_funcall_3 ("cob_pointer_manip", v, n, cb_int1); 02645 } 02646 #else 02647 if (CB_INDEX_P (v) || CB_TREE_CLASS (v) == CB_CLASS_POINTER) { 02648 return cb_build_move (cb_build_binary_op (v, '-', n), v); 02649 } 02650 #endif 02651 02652 if (CB_REF_OR_FIELD_P (v)) { 02653 f = cb_field (v); 02654 f->count++; 02655 } 02656 if (CB_REF_OR_FIELD_P (n)) { 02657 f = cb_field (n); 02658 f->count++; 02659 } 02660 opt = build_store_option (v, round_opt); 02661 if (opt == cb_int0 && cb_fits_int (n)) { 02662 return cb_build_optim_sub (v, n); 02663 } 02664 return cb_build_funcall_3 ("cob_sub", v, n, opt); 02665 } 02666 02667 static void 02668 emit_corresponding (cb_tree (*func) (cb_tree f1, cb_tree f2, cb_tree f3), 02669 cb_tree x1, cb_tree x2, cb_tree opt) 02670 { 02671 struct cb_field *f1, *f2; 02672 cb_tree t1; 02673 cb_tree t2; 02674 02675 for (f1 = cb_field (x1)->children; f1; f1 = f1->sister) { 02676 if (!f1->redefines && !f1->flag_occurs) { 02677 for (f2 = cb_field (x2)->children; f2; f2 = f2->sister) { 02678 if (!f2->redefines && !f2->flag_occurs) { 02679 if (strcmp (f1->name, f2->name) == 0) { 02680 t1 = cb_build_field_reference (f1, x1); 02681 t2 = cb_build_field_reference (f2, x2); 02682 if (f1->children && f2->children) { 02683 emit_corresponding (func, t1, t2, opt); 02684 } else { 02685 cb_emit (func (t1, t2, opt)); 02686 } 02687 } 02688 } 02689 } 02690 } 02691 } 02692 } 02693 02694 void 02695 cb_emit_corresponding (cb_tree (*func) (cb_tree f1, cb_tree f2, cb_tree f3), 02696 cb_tree x1, cb_tree x2, cb_tree opt) 02697 { 02698 x1 = cb_check_group_name (x1); 02699 x2 = cb_check_group_name (x2); 02700 02701 if (cb_validate_one (x1)) { 02702 return; 02703 } 02704 if (cb_validate_one (x2)) { 02705 return; 02706 } 02707 02708 emit_corresponding (func, x1, x2, opt); 02709 } 02710 02711 static void 02712 emit_move_corresponding (cb_tree x1, cb_tree x2) 02713 { 02714 struct cb_field *f1, *f2; 02715 cb_tree t1; 02716 cb_tree t2; 02717 02718 for (f1 = cb_field (x1)->children; f1; f1 = f1->sister) { 02719 if (!f1->redefines && !f1->flag_occurs) { 02720 for (f2 = cb_field (x2)->children; f2; f2 = f2->sister) { 02721 if (!f2->redefines && !f2->flag_occurs) { 02722 if (strcmp (f1->name, f2->name) == 0) { 02723 t1 = cb_build_field_reference (f1, x1); 02724 t2 = cb_build_field_reference (f2, x2); 02725 if (f1->children && f2->children) { 02726 emit_move_corresponding (t1, t2); 02727 } else { 02728 cb_emit (cb_build_move (t1, t2)); 02729 } 02730 } 02731 } 02732 } 02733 } 02734 } 02735 } 02736 02737 void 02738 cb_emit_move_corresponding (cb_tree x1, cb_tree x2) 02739 { 02740 cb_tree l; 02741 cb_tree v; 02742 02743 x1 = cb_check_group_name (x1); 02744 if (cb_validate_one (x1)) { 02745 return; 02746 } 02747 for (l = x2; l; l = CB_CHAIN(l)) { 02748 v = CB_VALUE(l); 02749 v = cb_check_group_name (v); 02750 if (cb_validate_one (v)) { 02751 return; 02752 } 02753 emit_move_corresponding (x1, v); 02754 } 02755 } 02756 02757 static void 02758 output_screen_from (struct cb_field *p, const size_t sisters) 02759 { 02760 int type; 02761 02762 if (sisters && p->sister) { 02763 output_screen_from (p->sister, 1); 02764 } 02765 if (p->children) { 02766 output_screen_from (p->children, 1); 02767 } 02768 02769 type = (p->children ? COB_SCREEN_TYPE_GROUP : 02770 p->values ? COB_SCREEN_TYPE_VALUE : 02771 (p->size > 0) ? COB_SCREEN_TYPE_FIELD : COB_SCREEN_TYPE_ATTRIBUTE); 02772 if (type == COB_SCREEN_TYPE_FIELD && p->screen_from) { 02773 cb_emit (cb_build_funcall_2 ("cob_move", p->screen_from, CB_TREE (p))); 02774 } 02775 } 02776 02777 static void 02778 output_screen_to (struct cb_field *p, const size_t sisters) 02779 { 02780 int type; 02781 02782 if (sisters && p->sister) { 02783 output_screen_to (p->sister, 1); 02784 } 02785 if (p->children) { 02786 output_screen_to (p->children, 1); 02787 } 02788 02789 type = (p->children ? COB_SCREEN_TYPE_GROUP : 02790 p->values ? COB_SCREEN_TYPE_VALUE : 02791 (p->size > 0) ? COB_SCREEN_TYPE_FIELD : COB_SCREEN_TYPE_ATTRIBUTE); 02792 if (type == COB_SCREEN_TYPE_FIELD && p->screen_to) { 02793 cb_emit (cb_build_funcall_2 ("cob_move", CB_TREE (p), p->screen_to)); 02794 } 02795 } 02796 02797 /* 02798 * ACCEPT statement 02799 */ 02800 02801 void 02802 cb_emit_accept (cb_tree var, cb_tree pos, cb_tree fgc, cb_tree bgc, 02803 cb_tree scroll, int dispattrs) 02804 { 02805 cb_tree line; 02806 cb_tree column; 02807 02808 if (cb_validate_one (var)) { 02809 return; 02810 } 02811 if (cb_validate_one (pos)) { 02812 return; 02813 } 02814 if (cb_validate_one (fgc)) { 02815 return; 02816 } 02817 if (cb_validate_one (bgc)) { 02818 return; 02819 } 02820 if (cb_validate_one (scroll)) { 02821 return; 02822 } 02823 if (current_program->flag_screen) { 02824 /* Bump ref count to force CRT STATUS field generation */ 02825 cb_field (current_program->crt_status)->count++; 02826 if ((CB_REF_OR_FIELD_P (var)) && 02827 CB_FIELD (cb_ref (var))->storage == CB_STORAGE_SCREEN) { 02828 output_screen_from (CB_FIELD (cb_ref (var)), 0); 02829 gen_screen_ptr = 1; 02830 if (pos) { 02831 if (CB_PAIR_P (pos)) { 02832 line = CB_PAIR_X (pos); 02833 column = CB_PAIR_Y (pos); 02834 cb_emit (cb_build_funcall_3 ("cob_screen_accept", 02835 var, line, column)); 02836 } else { 02837 cb_emit (cb_build_funcall_3 ("cob_screen_accept", 02838 var, pos, NULL)); 02839 } 02840 } else { 02841 cb_emit (cb_build_funcall_3 ("cob_screen_accept", 02842 var, NULL, NULL)); 02843 } 02844 gen_screen_ptr = 0; 02845 output_screen_to (CB_FIELD (cb_ref (var)), 0); 02846 } else { 02847 if (pos || fgc || bgc) { 02848 if (!pos) { 02849 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02850 var, NULL, NULL, fgc, bgc, 02851 scroll, cb_int (dispattrs))); 02852 } else if (CB_PAIR_P (pos)) { 02853 line = CB_PAIR_X (pos); 02854 column = CB_PAIR_Y (pos); 02855 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02856 var, line, column, fgc, bgc, 02857 scroll, cb_int (dispattrs))); 02858 } else { 02859 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02860 var, pos, NULL, fgc, bgc, 02861 scroll, cb_int (dispattrs))); 02862 } 02863 } else { 02864 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02865 var, NULL, NULL, fgc, bgc, 02866 scroll, cb_int (dispattrs))); 02867 } 02868 } 02869 } else if (pos || fgc || bgc || scroll) { 02870 /* Bump ref count to force CRT STATUS field generation */ 02871 cb_field (current_program->crt_status)->count++; 02872 if (!pos) { 02873 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02874 var, NULL, NULL, fgc, bgc, scroll, 02875 cb_int (dispattrs))); 02876 } else if (CB_PAIR_P (pos)) { 02877 line = CB_PAIR_X (pos); 02878 column = CB_PAIR_Y (pos); 02879 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02880 var, line, column, fgc, bgc, scroll, 02881 cb_int (dispattrs))); 02882 } else { 02883 cb_emit (cb_build_funcall_7 ("cob_field_accept", 02884 var, pos, NULL, fgc, bgc, scroll, 02885 cb_int (dispattrs))); 02886 } 02887 } else { 02888 cb_emit (cb_build_funcall_1 ("cob_accept", var)); 02889 } 02890 } 02891 02892 void 02893 cb_emit_accept_line_or_col (cb_tree var, const int l_or_c) 02894 { 02895 if (cb_validate_one (var)) { 02896 return; 02897 } 02898 cb_emit (cb_build_funcall_2 ("cob_screen_line_col", var, cb_int (l_or_c))); 02899 } 02900 02901 void 02902 cb_emit_accept_date (cb_tree var) 02903 { 02904 if (cb_validate_one (var)) { 02905 return; 02906 } 02907 cb_emit (cb_build_funcall_1 ("cob_accept_date", var)); 02908 } 02909 02910 void 02911 cb_emit_accept_date_yyyymmdd (cb_tree var) 02912 { 02913 if (cb_validate_one (var)) { 02914 return; 02915 } 02916 cb_emit (cb_build_funcall_1 ("cob_accept_date_yyyymmdd", var)); 02917 } 02918 02919 void 02920 cb_emit_accept_day (cb_tree var) 02921 { 02922 if (cb_validate_one (var)) { 02923 return; 02924 } 02925 cb_emit (cb_build_funcall_1 ("cob_accept_day", var)); 02926 } 02927 02928 void 02929 cb_emit_accept_day_yyyyddd (cb_tree var) 02930 { 02931 if (cb_validate_one (var)) { 02932 return; 02933 } 02934 cb_emit (cb_build_funcall_1 ("cob_accept_day_yyyyddd", var)); 02935 } 02936 02937 void 02938 cb_emit_accept_day_of_week (cb_tree var) 02939 { 02940 if (cb_validate_one (var)) { 02941 return; 02942 } 02943 cb_emit (cb_build_funcall_1 ("cob_accept_day_of_week", var)); 02944 } 02945 02946 void 02947 cb_emit_accept_time (cb_tree var) 02948 { 02949 if (cb_validate_one (var)) { 02950 return; 02951 } 02952 cb_emit (cb_build_funcall_1 ("cob_accept_time", var)); 02953 } 02954 02955 void 02956 cb_emit_accept_command_line (cb_tree var) 02957 { 02958 if (cb_validate_one (var)) { 02959 return; 02960 } 02961 cb_emit (cb_build_funcall_1 ("cob_accept_command_line", var)); 02962 } 02963 02964 void 02965 cb_emit_get_environment (cb_tree envvar, cb_tree envval) 02966 { 02967 if (cb_validate_one (envvar)) { 02968 return; 02969 } 02970 if (cb_validate_one (envval)) { 02971 return; 02972 } 02973 cb_emit (cb_build_funcall_2 ("cob_get_environment", envvar, envval)); 02974 } 02975 02976 void 02977 cb_emit_accept_environment (cb_tree var) 02978 { 02979 if (cb_validate_one (var)) { 02980 return; 02981 } 02982 cb_emit (cb_build_funcall_1 ("cob_accept_environment", var)); 02983 } 02984 02985 void 02986 cb_emit_accept_arg_number (cb_tree var) 02987 { 02988 if (cb_validate_one (var)) { 02989 return; 02990 } 02991 cb_emit (cb_build_funcall_1 ("cob_accept_arg_number", var)); 02992 } 02993 02994 void 02995 cb_emit_accept_arg_value (cb_tree var) 02996 { 02997 if (cb_validate_one (var)) { 02998 return; 02999 } 03000 cb_emit (cb_build_funcall_1 ("cob_accept_arg_value", var)); 03001 } 03002 03003 void 03004 cb_emit_accept_mnemonic (cb_tree var, cb_tree mnemonic) 03005 { 03006 if (cb_validate_one (var)) { 03007 return; 03008 } 03009 switch (CB_SYSTEM_NAME (cb_ref (mnemonic))->token) { 03010 case CB_DEVICE_CONSOLE: 03011 case CB_DEVICE_SYSIN: 03012 cb_emit (cb_build_funcall_1 ("cob_accept", var)); 03013 break; 03014 default: 03015 cb_error_x (mnemonic, _("Invalid input stream '%s'"), 03016 cb_name (mnemonic)); 03017 break; 03018 } 03019 } 03020 03021 void 03022 cb_emit_accept_name (cb_tree var, cb_tree name) 03023 { 03024 cb_tree sys; 03025 03026 if (cb_validate_one (var)) { 03027 return; 03028 } 03029 if (CB_REFERENCE (name)->word->count == 0) { 03030 sys = lookup_system_name (CB_NAME (name)); 03031 03032 if (sys != cb_error_node) { 03033 switch (CB_SYSTEM_NAME (sys)->token) { 03034 case CB_DEVICE_CONSOLE: 03035 case CB_DEVICE_SYSIN: 03036 cb_warning_x (name, _("'%s' undefined in SPECIAL-NAMES"), CB_NAME (name)); 03037 cb_emit (cb_build_funcall_1 ("cob_accept", var)); 03038 return; 03039 default: 03040 break; 03041 } 03042 } 03043 } 03044 03045 cb_error_x (name, _("'%s' undefined in SPECIAL-NAMES"), CB_NAME (name)); 03046 } 03047 03048 /* 03049 * ALLOCATE statement 03050 */ 03051 03052 void 03053 cb_emit_allocate (cb_tree target1, cb_tree target2, cb_tree size, cb_tree initialize) 03054 { 03055 cb_tree x; 03056 char buff[32]; 03057 03058 if (cb_validate_one (target1)) { 03059 return; 03060 } 03061 if (cb_validate_one (target2)) { 03062 return; 03063 } 03064 if (cb_validate_one (size)) { 03065 return; 03066 } 03067 if (target1) { 03068 if (!(CB_REFERENCE_P(target1) && 03069 cb_field (target1)->flag_item_based)) { 03070 cb_error_x (CB_TREE(current_statement), 03071 _("Target of ALLOCATE is not a BASED item")); 03072 } 03073 } 03074 if (target2) { 03075 if (!(CB_REFERENCE_P(target2) && 03076 CB_TREE_CLASS (target2) == CB_CLASS_POINTER)) { 03077 cb_error_x (CB_TREE(current_statement), 03078 _("Target of RETURNING is not a data pointer")); 03079 } 03080 } 03081 if (size) { 03082 if (CB_TREE_CLASS (size) != CB_CLASS_NUMERIC) { 03083 cb_error_x (CB_TREE(current_statement), 03084 _("The CHARACTERS field of ALLOCATE must be numeric")); 03085 } 03086 } 03087 if (target1) { 03088 sprintf (buff, "%d", cb_field (target1)->memory_size); 03089 x = cb_build_numeric_literal (0, (ucharptr)buff, 0); 03090 cb_emit (cb_build_funcall_3 ("cob_allocate", 03091 cb_build_cast_addr_of_addr (target1), target2, x)); 03092 } else { 03093 cb_emit (cb_build_funcall_3 ("cob_allocate", 03094 NULL, target2, size)); 03095 } 03096 if (initialize && target1) { 03097 current_statement->handler2 = 03098 cb_build_initialize (target1, cb_true, NULL, cb_true, 0); 03099 } 03100 } 03101 03102 03103 /* 03104 * CALL statement 03105 */ 03106 03107 void 03108 cb_emit_call (cb_tree prog, cb_tree using, cb_tree returning, 03109 cb_tree on_exception, cb_tree not_on_exception) 03110 { 03111 cb_tree l; 03112 cb_tree x; 03113 const struct system_table *psyst; 03114 int is_sys_call = 0; 03115 03116 if (CB_INTRINSIC_P (prog)) { 03117 if (CB_INTRINSIC(prog)->intr_tab->category != CB_CATEGORY_ALPHANUMERIC) { 03118 cb_error (_("Only alphanumeric FUNCTION types are allowed here")); 03119 return; 03120 } 03121 } 03122 if (returning) { 03123 if (CB_TREE_CLASS(returning) != CB_CLASS_NUMERIC && 03124 CB_TREE_CLASS(returning) != CB_CLASS_POINTER) { 03125 cb_error (_("Invalid RETURNING field")); 03126 return; 03127 } 03128 } 03129 for (l = using; l; l = CB_CHAIN (l)) { 03130 x = CB_VALUE (l); 03131 if (x == cb_error_node) { 03132 continue; 03133 } 03134 if (CB_CONST_P (x) && x != cb_null) { 03135 cb_error_x (x, _("Figurative constant invalid here")); 03136 } 03137 if ((CB_REFERENCE_P (x) && CB_FIELD_P(CB_REFERENCE(x)->value)) 03138 || CB_FIELD_P (x)) { 03139 if (cb_field (x)->level == 88) { 03140 cb_error_x (x, _("'%s' Not a data name"), CB_NAME (x)); 03141 return; 03142 } 03143 if (cb_warn_call_params && 03144 CB_PURPOSE_INT (l) == CB_CALL_BY_REFERENCE) { 03145 if (cb_field (x)->level != 01 && 03146 cb_field (x)->level != 77) { 03147 cb_warning_x (x, _("'%s' is not 01 or 77 level item"), CB_NAME (x)); 03148 } 03149 } 03150 } 03151 } 03152 03153 if (CB_LITERAL_P(prog)) { 03154 for (psyst = (const struct system_table *)&system_tab[0]; psyst->syst_name; psyst++) { 03155 if (!strcmp((const char *)CB_LITERAL(prog)->data, 03156 (const char *)psyst->syst_name)) { 03157 if (psyst->syst_params > cb_list_length (using)) { 03158 cb_error (_("Wrong number of CALL parameters for '%s'"), 03159 (char *)psyst->syst_name); 03160 return; 03161 } 03162 is_sys_call = 1; 03163 break; 03164 } 03165 } 03166 } 03167 03168 cb_emit (cb_build_call (prog, using, on_exception, not_on_exception, 03169 returning, is_sys_call)); 03170 } 03171 03172 /* 03173 * CANCEL statement 03174 */ 03175 03176 void 03177 cb_emit_cancel (cb_tree prog) 03178 { 03179 if (cb_validate_one (prog)) { 03180 return; 03181 } 03182 cb_emit (cb_build_funcall_1 ("cob_field_cancel", prog)); 03183 } 03184 03185 /* 03186 * CLOSE statement 03187 */ 03188 03189 void 03190 cb_emit_close (cb_tree file, cb_tree opt) 03191 { 03192 if (file == cb_error_node) { 03193 return; 03194 } 03195 file = cb_ref (file); 03196 if (file == cb_error_node) { 03197 return; 03198 } 03199 current_statement->file = file; 03200 if (CB_FILE (file)->organization == COB_ORG_SORT) { 03201 cb_error_x (CB_TREE (current_statement), 03202 _("Operation not allowed on SORT files")); 03203 } 03204 cb_emit (cb_build_funcall_3 ("cob_close", file, opt, 03205 CB_FILE(file)->file_status)); 03206 } 03207 03208 /* 03209 * COMMIT statement 03210 */ 03211 03212 void 03213 cb_emit_commit (void) 03214 { 03215 cb_emit (cb_build_funcall_0 ("cob_commit")); 03216 } 03217 03218 /* 03219 * CONTINUE statement 03220 */ 03221 03222 void 03223 cb_emit_continue (void) 03224 { 03225 cb_emit (cb_build_continue ()); 03226 } 03227 03228 /* 03229 * DELETE statement 03230 */ 03231 03232 void 03233 cb_emit_delete (cb_tree file) 03234 { 03235 if (file == cb_error_node) { 03236 return; 03237 } 03238 file = cb_ref (file); 03239 if (file == cb_error_node) { 03240 return; 03241 } 03242 current_statement->file = file; 03243 if (CB_FILE (file)->organization == COB_ORG_SORT) { 03244 cb_error_x (CB_TREE (current_statement), 03245 _("Operation not allowed on SORT files")); 03246 } 03247 cb_emit (cb_build_funcall_2 ("cob_delete", file, CB_FILE(file)->file_status)); 03248 } 03249 03250 /* 03251 * DISPLAY statement 03252 */ 03253 03254 void 03255 cb_emit_env_name (cb_tree value) 03256 { 03257 if (cb_validate_one (value)) { 03258 return; 03259 } 03260 cb_emit (cb_build_funcall_1 ("cob_display_environment", value)); 03261 } 03262 03263 void 03264 cb_emit_env_value (cb_tree value) 03265 { 03266 if (cb_validate_one (value)) { 03267 return; 03268 } 03269 cb_emit (cb_build_funcall_1 ("cob_display_env_value", value)); 03270 } 03271 03272 void 03273 cb_emit_arg_number (cb_tree value) 03274 { 03275 if (cb_validate_one (value)) { 03276 return; 03277 } 03278 cb_emit (cb_build_funcall_1 ("cob_display_arg_number", value)); 03279 } 03280 03281 void 03282 cb_emit_command_line (cb_tree value) 03283 { 03284 if (cb_validate_one (value)) { 03285 return; 03286 } 03287 cb_emit (cb_build_funcall_1 ("cob_display_command_line", value)); 03288 } 03289 03290 void 03291 cb_emit_display (cb_tree values, cb_tree upon, cb_tree no_adv, cb_tree pos, 03292 cb_tree fgc, cb_tree bgc, cb_tree scroll, int dispattrs) 03293 { 03294 cb_tree l; 03295 cb_tree x; 03296 cb_tree line; 03297 cb_tree column; 03298 cb_tree p; 03299 03300 if (cb_validate_list (values)) { 03301 return; 03302 } 03303 if (cb_validate_one (pos)) { 03304 return; 03305 } 03306 if (cb_validate_one (fgc)) { 03307 return; 03308 } 03309 if (cb_validate_one (bgc)) { 03310 return; 03311 } 03312 if (cb_validate_one (scroll)) { 03313 return; 03314 } 03315 for (l = values; l; l = CB_CHAIN (l)) { 03316 x = CB_VALUE (l); 03317 if (x == cb_error_node) { 03318 return; 03319 } 03320 03321 switch (CB_TREE_TAG (x)) { 03322 case CB_TAG_LITERAL: 03323 case CB_TAG_INTRINSIC: 03324 case CB_TAG_CONST: 03325 case CB_TAG_STRING: 03326 case CB_TAG_INTEGER: 03327 break; 03328 case CB_TAG_REFERENCE: 03329 if (!CB_FIELD_P(CB_REFERENCE(x)->value)) { 03330 cb_error_x (x, _("'%s' is an invalid type for DISPLAY operand"), cb_name (x)); 03331 return; 03332 } 03333 break; 03334 default: 03335 cb_error_x (x, _("Invalid type for DISPLAY operand")); 03336 return; 03337 } 03338 } 03339 if (upon == cb_error_node) { 03340 return; 03341 } 03342 03343 x = CB_VALUE (values); 03344 if ((CB_REF_OR_FIELD_P (x)) && 03345 CB_FIELD (cb_ref (x))->storage == CB_STORAGE_SCREEN) { 03346 output_screen_from (CB_FIELD (cb_ref (x)), 0); 03347 gen_screen_ptr = 1; 03348 if (pos) { 03349 if (CB_PAIR_P (pos)) { 03350 line = CB_PAIR_X (pos); 03351 column = CB_PAIR_Y (pos); 03352 if (line == NULL) { 03353 line = cb_one; 03354 } 03355 if (column == NULL) { 03356 column = cb_one; 03357 } 03358 cb_emit (cb_build_funcall_3 ("cob_screen_display", x, 03359 line, column)); 03360 } else { 03361 cb_emit (cb_build_funcall_3 ("cob_screen_display", x, 03362 pos, NULL)); 03363 } 03364 } else { 03365 cb_emit (cb_build_funcall_3 ("cob_screen_display", x, 03366 NULL, NULL)); 03367 } 03368 gen_screen_ptr = 0; 03369 } else if (pos || fgc || bgc || scroll || dispattrs) { 03370 if (!pos) { 03371 cb_emit (cb_build_funcall_7 ("cob_field_display", 03372 CB_VALUE (values), NULL, NULL, fgc, bgc, 03373 scroll, cb_int (dispattrs))); 03374 } else if (CB_PAIR_P (pos)) { 03375 line = CB_PAIR_X (pos); 03376 column = CB_PAIR_Y (pos); 03377 if (line == NULL) { 03378 line = cb_one; 03379 } 03380 if (column == NULL) { 03381 column = cb_one; 03382 } 03383 cb_emit (cb_build_funcall_7 ("cob_field_display", 03384 CB_VALUE (values), line, column, fgc, bgc, 03385 scroll, cb_int (dispattrs))); 03386 } else { 03387 cb_emit (cb_build_funcall_7 ("cob_field_display", 03388 CB_VALUE (values), pos, NULL, fgc, bgc, 03389 scroll, cb_int (dispattrs))); 03390 } 03391 } else { 03392 /* DISPLAY x ... [UPON device-name] */ 03393 p = cb_build_funcall_3 ("cob_display", upon, no_adv, values); 03394 CB_FUNCALL(p)->varcnt = cb_list_length (values); 03395 cb_emit (p); 03396 for (l = values; l; l = CB_CHAIN (l)) { 03397 x = CB_VALUE (l); 03398 if (CB_FIELD_P (x)) { 03399 CB_FIELD (cb_ref (x))->count++; 03400 } 03401 } 03402 } 03403 } 03404 03405 cb_tree 03406 cb_build_display_upon (cb_tree x) 03407 { 03408 if (x == cb_error_node) { 03409 return cb_error_node; 03410 } 03411 03412 switch (CB_SYSTEM_NAME (cb_ref (x))->token) { 03413 case CB_DEVICE_CONSOLE: 03414 case CB_DEVICE_SYSOUT: 03415 return cb_int0; 03416 case CB_DEVICE_SYSERR: 03417 return cb_int1; 03418 default: 03419 cb_error_x (x, _("Invalid output stream")); 03420 return cb_error_node; 03421 } 03422 } 03423 03424 cb_tree 03425 cb_build_display_upon_direct (cb_tree x) 03426 { 03427 const char *name; 03428 cb_tree sys; 03429 03430 if (x == cb_error_node) { 03431 return cb_error_node; 03432 } 03433 name = CB_NAME (x); 03434 if (CB_REFERENCE (x)->word->count == 0) { 03435 sys = lookup_system_name (CB_NAME (x)); 03436 if (sys != cb_error_node) { 03437 switch (CB_SYSTEM_NAME (sys)->token) { 03438 case CB_DEVICE_CONSOLE: 03439 case CB_DEVICE_SYSOUT: 03440 cb_warning_x (x, _("'%s' undefined in SPECIAL-NAMES"), name); 03441 return cb_int0; 03442 case CB_DEVICE_SYSERR: 03443 cb_warning_x (x, _("'%s' undefined in SPECIAL-NAMES"), name); 03444 return cb_int1; 03445 default: 03446 break; 03447 } 03448 } 03449 } 03450 03451 cb_error_x (x, _("'%s' undefined in SPECIAL-NAMES"), name); 03452 return cb_error_node; 03453 } 03454 03455 /* 03456 * DIVIDE statement 03457 */ 03458 03459 void 03460 cb_emit_divide (cb_tree dividend, cb_tree divisor, cb_tree quotient, cb_tree remainder) 03461 { 03462 if (cb_validate_one (dividend)) { 03463 return; 03464 } 03465 if (cb_validate_one (divisor)) { 03466 return; 03467 } 03468 CB_VALUE (quotient) = cb_check_numeric_edited_name (CB_VALUE (quotient)); 03469 CB_VALUE (remainder) = cb_check_numeric_edited_name (CB_VALUE (remainder)); 03470 03471 if (cb_validate_one (CB_VALUE (quotient))) { 03472 return; 03473 } 03474 if (cb_validate_one (CB_VALUE (remainder))) { 03475 return; 03476 } 03477 03478 cb_emit (cb_build_funcall_4 ("cob_div_quotient", dividend, divisor, 03479 CB_VALUE (quotient), 03480 build_store_option (CB_VALUE (quotient), CB_PURPOSE (quotient)))); 03481 cb_emit (cb_build_funcall_2 ("cob_div_remainder", CB_VALUE (remainder), 03482 build_store_option (CB_VALUE (remainder), cb_int0))); 03483 } 03484 03485 /* 03486 * EVALUATE statement 03487 */ 03488 03489 static cb_tree 03490 evaluate_test (cb_tree s, cb_tree o) 03491 { 03492 int flag; 03493 cb_tree x, y; 03494 cb_tree t; 03495 03496 /* ANY is always true */ 03497 if (o == cb_any) { 03498 return cb_true; 03499 } 03500 03501 /* object TRUE or FALSE */ 03502 if (o == cb_true) { 03503 return s; 03504 } 03505 if (o == cb_false) { 03506 return cb_build_negation (s); 03507 } 03508 03509 flag = CB_PURPOSE_INT (o); 03510 x = CB_PAIR_X (CB_VALUE (o)); 03511 y = CB_PAIR_Y (CB_VALUE (o)); 03512 03513 /* subject TRUE or FALSE */ 03514 if (s == cb_true) { 03515 return flag ? cb_build_negation (x) : x; 03516 } 03517 if (s == cb_false) { 03518 return flag ? x : cb_build_negation (x); 03519 } 03520 03521 /* x THRU y */ 03522 if (y) { 03523 t = cb_build_binary_op (cb_build_binary_op (x, '[', s), 03524 '&', 03525 cb_build_binary_op (s, '[', y)); 03526 03527 return flag ? cb_build_negation (t) : t; 03528 } 03529 03530 if (CB_REFERENCE_P(x) && CB_FIELD_P(CB_REFERENCE(x)->value) && 03531 CB_FIELD(CB_REFERENCE(x)->value)->level == 88) { 03532 cb_error_x (CB_TREE (current_statement), 03533 _("Invalid use of 88 level in WHEN expression")); 03534 return NULL; 03535 } 03536 03537 /* regular comparison */ 03538 if (flag) { 03539 return cb_build_binary_op (s, '~', x); 03540 } else { 03541 return cb_build_binary_op (s, '=', x); 03542 } 03543 } 03544 03545 static cb_tree 03546 build_evaluate (cb_tree subject_list, cb_tree case_list) 03547 { 03548 cb_tree c1 = NULL; 03549 cb_tree c2; 03550 cb_tree c3; 03551 cb_tree subjs; 03552 cb_tree whens; 03553 cb_tree objs; 03554 cb_tree stmt; 03555 03556 if (case_list == NULL) { 03557 return NULL; 03558 } 03559 03560 whens = CB_VALUE (case_list); 03561 stmt = CB_VALUE (whens); 03562 whens = CB_CHAIN (whens); 03563 03564 /* for each WHEN sequence */ 03565 for (; whens; whens = CB_CHAIN (whens)) { 03566 c2 = NULL; 03567 /* single WHEN test */ 03568 for (subjs = subject_list, objs = CB_VALUE (whens); 03569 subjs && objs; subjs = CB_CHAIN (subjs), objs = CB_CHAIN (objs)) { 03570 c3 = evaluate_test (CB_VALUE (subjs), CB_VALUE (objs)); 03571 if (c3 == NULL) { 03572 return NULL; 03573 } 03574 03575 if (c2 == NULL) { 03576 c2 = c3; 03577 } else { 03578 c2 = cb_build_binary_op (c2, '&', c3); 03579 } 03580 } 03581 if (subjs || objs) { 03582 cb_error (_("Wrong number of WHEN parameters")); 03583 } 03584 /* connect multiple WHEN's */ 03585 if (c1 == NULL) { 03586 c1 = c2; 03587 } else { 03588 c1 = cb_build_binary_op (c1, '|', c2); 03589 } 03590 } 03591 03592 if (c1 == NULL) { 03593 return stmt; 03594 } else { 03595 return cb_build_if (cb_build_cond (c1), stmt, 03596 build_evaluate (subject_list, CB_CHAIN (case_list))); 03597 } 03598 } 03599 03600 void 03601 cb_emit_evaluate (cb_tree subject_list, cb_tree case_list) 03602 { 03603 cb_emit (build_evaluate (subject_list, case_list)); 03604 } 03605 03606 /* 03607 * FREE statement 03608 */ 03609 03610 void 03611 cb_emit_free (cb_tree vars) 03612 { 03613 cb_tree l; 03614 struct cb_field *f; 03615 int i; 03616 03617 if (cb_validate_list (vars)) { 03618 return; 03619 } 03620 for (l = vars, i = 1; l; l = CB_CHAIN (l), i++) { 03621 if (CB_TREE_CLASS (CB_VALUE (l)) == CB_CLASS_POINTER) { 03622 if (CB_CAST_P (CB_VALUE (l))) { 03623 f = cb_field (CB_CAST (CB_VALUE(l))->val); 03624 if (!f->flag_item_based) { 03625 cb_error_x (CB_TREE (current_statement), 03626 _("Target %d of FREE, a data address identifier, must address a BASED data item"), i); 03627 } 03628 cb_emit (cb_build_funcall_2 ("cob_free_alloc", 03629 cb_build_cast_address (CB_VALUE (l)), NULL)); 03630 } else { 03631 cb_emit (cb_build_funcall_2 ("cob_free_alloc", 03632 NULL, cb_build_cast_address (CB_VALUE (l)))); 03633 } 03634 } else if (CB_REF_OR_FIELD_P (CB_VALUE (l))) { 03635 f = cb_field (CB_VALUE (l)); 03636 if (!f->flag_item_based) { 03637 cb_error_x (CB_TREE (current_statement), 03638 _("Target %d of FREE, a data address identifier, must address a BASED data item"), i); 03639 } 03640 cb_emit (cb_build_funcall_2 ("cob_free_alloc", 03641 cb_build_cast_addr_of_addr (CB_VALUE (l)), NULL)); 03642 } else { 03643 cb_error_x (CB_TREE (current_statement), 03644 _("Target %d of FREE must be a data pointer"), i); 03645 } 03646 } 03647 } 03648 03649 /* 03650 * GO TO statement 03651 */ 03652 03653 void 03654 cb_emit_goto (cb_tree target, cb_tree depending) 03655 { 03656 if (target == cb_error_node) { 03657 return; 03658 } 03659 if (depending) { 03660 /* GO TO procedure-name ... DEPENDING ON identifier */ 03661 cb_emit (cb_build_goto (target, depending)); 03662 } else { 03663 /* GO TO procedure-name */ 03664 if (target == NULL) { 03665 cb_verify (cb_goto_statement_without_name, "GO TO without procedure-name"); 03666 } else if (CB_CHAIN (target)) { 03667 cb_error (_("GO TO with multiple procedure-names")); 03668 } else { 03669 cb_emit (cb_build_goto (CB_VALUE (target), NULL)); 03670 } 03671 } 03672 } 03673 03674 void 03675 cb_emit_exit (size_t goback) 03676 { 03677 if (goback) { 03678 cb_emit (cb_build_goto (cb_int1, NULL)); 03679 } else { 03680 cb_emit (cb_build_goto (NULL, NULL)); 03681 } 03682 } 03683 03684 /* 03685 * IF statement 03686 */ 03687 03688 void 03689 cb_emit_if (cb_tree cond, cb_tree stmt1, cb_tree stmt2) 03690 { 03691 cb_emit (cb_build_if (cond, stmt1, stmt2)); 03692 } 03693 03694 /* 03695 * INITIALIZE statement 03696 */ 03697 03698 void 03699 cb_emit_initialize (cb_tree vars, cb_tree fillinit, cb_tree value, cb_tree replacing, cb_tree def) 03700 { 03701 cb_tree l; 03702 int fill_init = 1; 03703 03704 if (cb_validate_list (vars)) { 03705 return; 03706 } 03707 if (value == NULL && replacing == NULL) { 03708 def = cb_true; 03709 } 03710 if (fillinit == cb_true) { 03711 fill_init = 0; 03712 } 03713 for (l = vars; l; l = CB_CHAIN (l)) { 03714 cb_emit (cb_build_initialize (CB_VALUE (l), value, replacing, def, fill_init)); 03715 } 03716 } 03717 03718 /* 03719 * INSPECT statement 03720 */ 03721 03722 void 03723 cb_emit_inspect (cb_tree var, cb_tree body, cb_tree replacing, int replconv) 03724 { 03725 switch (CB_TREE_TAG(var)) { 03726 case CB_TAG_REFERENCE: 03727 break; 03728 case CB_TAG_INTRINSIC: 03729 switch (CB_TREE_CATEGORY(var)) { 03730 case CB_CATEGORY_ALPHABETIC: 03731 case CB_CATEGORY_ALPHANUMERIC: 03732 case CB_CATEGORY_NATIONAL: 03733 break; 03734 default: 03735 cb_error (_("Invalid target for INSPECT")); 03736 return; 03737 } 03738 break; 03739 case CB_TAG_LITERAL: 03740 break; 03741 default: 03742 cb_error (_("Invalid target for REPLACING/CONVERTING")); 03743 return; 03744 } 03745 if (replconv && sending_id) { 03746 cb_error (_("Invalid target for REPLACING/CONVERTING")); 03747 } 03748 cb_emit (cb_build_funcall_2 ("cob_inspect_init", var, replacing)); 03749 cb_emit_list (body); 03750 cb_emit (cb_build_funcall_0 ("cob_inspect_finish")); 03751 } 03752 03753 void 03754 cb_init_tarrying (void) 03755 { 03756 inspect_func = NULL; 03757 inspect_data = NULL; 03758 } 03759 03760 cb_tree 03761 cb_build_tarrying_data (cb_tree x) 03762 { 03763 inspect_data = x; 03764 return NULL; 03765 } 03766 03767 cb_tree 03768 cb_build_tarrying_characters (cb_tree l) 03769 { 03770 if (inspect_data == NULL) { 03771 cb_error (_("Data name expected before CHARACTERS")); 03772 } 03773 inspect_func = NULL; 03774 return cb_list_add (l, cb_build_funcall_1 ("cob_inspect_characters", inspect_data)); 03775 } 03776 03777 cb_tree 03778 cb_build_tarrying_all (void) 03779 { 03780 if (inspect_data == NULL) { 03781 cb_error (_("Data name expected before ALL")); 03782 } 03783 inspect_func = "cob_inspect_all"; 03784 return NULL; 03785 } 03786 03787 cb_tree 03788 cb_build_tarrying_leading (void) 03789 { 03790 if (inspect_data == NULL) { 03791 cb_error (_("Data name expected before LEADING")); 03792 } 03793 inspect_func = "cob_inspect_leading"; 03794 return NULL; 03795 } 03796 03797 cb_tree 03798 cb_build_tarrying_trailing (void) 03799 { 03800 if (inspect_data == NULL) { 03801 cb_error (_("Data name expected before TRAILING")); 03802 } 03803 inspect_func = "cob_inspect_trailing"; 03804 return NULL; 03805 } 03806 03807 cb_tree 03808 cb_build_tarrying_value (cb_tree x, cb_tree l) 03809 { 03810 if (inspect_func == NULL) { 03811 cb_error_x (x, _("ALL, LEADING or TRAILING expected before '%s'"), cb_name (x)); 03812 } 03813 return cb_list_add (l, cb_build_funcall_2 (inspect_func, inspect_data, x)); 03814 } 03815 03816 cb_tree 03817 cb_build_replacing_characters (cb_tree x, cb_tree l) 03818 { 03819 return cb_list_add (l, cb_build_funcall_1 ("cob_inspect_characters", x)); 03820 } 03821 03822 cb_tree 03823 cb_build_replacing_all (cb_tree x, cb_tree y, cb_tree l) 03824 { 03825 return cb_list_add (l, cb_build_funcall_2 ("cob_inspect_all", y, x)); 03826 } 03827 03828 cb_tree 03829 cb_build_replacing_leading (cb_tree x, cb_tree y, cb_tree l) 03830 { 03831 return cb_list_add (l, cb_build_funcall_2 ("cob_inspect_leading", y, x)); 03832 } 03833 03834 cb_tree 03835 cb_build_replacing_first (cb_tree x, cb_tree y, cb_tree l) 03836 { 03837 return cb_list_add (l, cb_build_funcall_2 ("cob_inspect_first", y, x)); 03838 } 03839 03840 cb_tree 03841 cb_build_replacing_trailing (cb_tree x, cb_tree y, cb_tree l) 03842 { 03843 return cb_list_add (l, cb_build_funcall_2 ("cob_inspect_trailing", y, x)); 03844 } 03845 03846 cb_tree 03847 cb_build_converting (cb_tree x, cb_tree y, cb_tree l) 03848 { 03849 return cb_list_add (l, cb_build_funcall_2 ("cob_inspect_converting", x, y)); 03850 } 03851 03852 cb_tree 03853 cb_build_inspect_region_start (void) 03854 { 03855 return cb_list_init (cb_build_funcall_0 ("cob_inspect_start")); 03856 } 03857 03858 cb_tree 03859 cb_build_inspect_region (cb_tree l, cb_tree pos, cb_tree x) 03860 { 03861 if (pos == CB_BEFORE) { 03862 return cb_list_add (l, cb_build_funcall_1 ("cob_inspect_before", x)); 03863 } else { 03864 return cb_list_add (l, cb_build_funcall_1 ("cob_inspect_after", x)); 03865 } 03866 } 03867 03868 /* 03869 * MOVE statement 03870 */ 03871 03872 static void 03873 warning_destination (cb_tree x) 03874 { 03875 struct cb_reference *r; 03876 struct cb_field *f; 03877 cb_tree loc; 03878 03879 r = CB_REFERENCE (x); 03880 f = CB_FIELD (r->value); 03881 loc = CB_TREE (f); 03882 03883 if (r->offset) { 03884 return; 03885 } 03886 03887 if (!strcmp (f->name, "RETURN-CODE") || 03888 !strcmp (f->name, "SORT-RETURN") || 03889 !strcmp (f->name, "NUMBER-OF-CALL-PARAMETERS")) { 03890 cb_warning (_("Internal register '%s' defined as BINARY-LONG"), f->name); 03891 } else if (f->pic) { 03892 cb_warning_x (loc, _("'%s' defined here as PIC %s"), f->name, f->pic->orig); 03893 } else { 03894 cb_warning_x (loc, _("'%s' defined here as a group of length %d"), f->name, f->size); 03895 } 03896 } 03897 03898 static int 03899 move_error (cb_tree src, cb_tree dst, const size_t value_flag, const int flag, 03900 const int src_flag, const char *msg) 03901 { 03902 cb_tree loc; 03903 03904 if (suppress_warn) { 03905 return 0; 03906 } 03907 loc = src->source_line ? src : dst; 03908 if (value_flag) { 03909 /* VALUE clause */ 03910 cb_warning_x (loc, msg); 03911 } else { 03912 /* MOVE statement */ 03913 if (flag) { 03914 cb_warning_x (loc, msg); 03915 if (src_flag) { 03916 warning_destination (src); 03917 } 03918 warning_destination (dst); 03919 } 03920 } 03921 03922 return 0; 03923 } 03924 03925 /* count the number of free places in an alphanumeric edited field */ 03926 static int 03927 count_pic_alphanumeric_edited (struct cb_field *field) 03928 { 03929 int count; 03930 int repeat; 03931 unsigned char *p; 03932 03933 count = 0; 03934 for (p = (unsigned char *)(field->pic->str); *p; p += 5) { 03935 if (*p == '9' || *p == 'A' || *p == 'X') { 03936 memcpy ((unsigned char *)&repeat, p + 1, sizeof(int)); 03937 count += repeat; 03938 } 03939 } 03940 return count; 03941 } 03942 03943 int 03944 validate_move (cb_tree src, cb_tree dst, size_t is_value) 03945 { 03946 struct cb_field *f; 03947 struct cb_literal *l; 03948 unsigned char *p; 03949 cb_tree loc; 03950 long long val; 03951 size_t i; 03952 size_t is_numeric_edited = 0; 03953 int src_scale_mod; 03954 int dst_scale_mod; 03955 int dst_size_mod; 03956 int size; 03957 int most_significant; 03958 int least_significant; 03959 03960 loc = src->source_line ? src : dst; 03961 if (CB_REFERENCE_P(dst) && CB_ALPHABET_NAME_P(CB_REFERENCE(dst)->value)) { 03962 goto invalid; 03963 } 03964 if (CB_REFERENCE_P(dst) && CB_FILE_P(CB_REFERENCE(dst)->value)) { 03965 goto invalid; 03966 } 03967 if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_BOOLEAN) { 03968 cb_error_x (loc, _("Invalid destination for MOVE")); 03969 return -1; 03970 } 03971 03972 if (CB_TREE_CLASS (dst) == CB_CLASS_POINTER) { 03973 if (CB_TREE_CLASS (src) == CB_CLASS_POINTER) { 03974 return 0; 03975 } else { 03976 goto invalid; 03977 } 03978 } 03979 03980 f = cb_field (dst); 03981 switch (CB_TREE_TAG (src)) { 03982 case CB_TAG_CONST: 03983 if (src == cb_space) { 03984 if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_NUMERIC 03985 || (CB_TREE_CATEGORY (dst) == CB_CATEGORY_NUMERIC_EDITED && !is_value)) { 03986 goto invalid; 03987 } 03988 } else if (src == cb_zero) { 03989 if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_ALPHABETIC) { 03990 goto invalid; 03991 } 03992 } 03993 break; 03994 case CB_TAG_LITERAL: 03995 /* TODO: ALL literal */ 03996 03997 l = CB_LITERAL (src); 03998 if (CB_TREE_CLASS (src) == CB_CLASS_NUMERIC) { 03999 /* Numeric literal */ 04000 if (l->all) { 04001 goto invalid; 04002 } 04003 most_significant = -999; 04004 least_significant = 999; 04005 04006 /* compute the most significant figure place */ 04007 for (i = 0; i < l->size; i++) { 04008 if (l->data[i] != '0') { 04009 break; 04010 } 04011 } 04012 if (i != l->size) { 04013 most_significant = (int) (l->size - l->scale - i - 1); 04014 } 04015 04016 /* compute the least significant figure place */ 04017 for (i = 0; i < l->size; i++) { 04018 if (l->data[l->size - i - 1] != '0') { 04019 break; 04020 } 04021 } 04022 if (i != l->size) { 04023 least_significant = (int) (-l->scale + i); 04024 } 04025 04026 /* value check */ 04027 switch (CB_TREE_CATEGORY (dst)) { 04028 case CB_CATEGORY_ALPHANUMERIC: 04029 case CB_CATEGORY_ALPHANUMERIC_EDITED: 04030 if (is_value) { 04031 goto expect_alphanumeric; 04032 } 04033 04034 if (l->scale == 0) { 04035 goto expect_alphanumeric; 04036 } else { 04037 goto invalid; 04038 } 04039 case CB_CATEGORY_NUMERIC: 04040 if (f->pic->scale < 0) { 04041 /* check for PIC 9(n)P(m) */ 04042 if (least_significant < -f->pic->scale) { 04043 goto value_mismatch; 04044 } 04045 } else if (f->pic->scale > f->pic->size) { 04046 /* check for PIC P(n)9(m) */ 04047 if (most_significant >= f->pic->size - f->pic->scale) { 04048 goto value_mismatch; 04049 } 04050 } 04051 break; 04052 case CB_CATEGORY_NUMERIC_EDITED: 04053 if (is_value) { 04054 goto expect_alphanumeric; 04055 } 04056 04057 /* TODO */ 04058 break; 04059 default: 04060 if (is_value) { 04061 goto expect_alphanumeric; 04062 } 04063 goto invalid; 04064 } 04065 04066 /* sign check */ 04067 if (l->sign != 0 && !f->pic->have_sign) { 04068 if (is_value) { 04069 cb_error_x (loc, _("Data item not signed")); 04070 return -1; 04071 } 04072 if (cb_warn_constant) { 04073 cb_warning_x (loc, _("Ignoring negative sign")); 04074 } 04075 } 04076 04077 /* size check */ 04078 if (f->flag_real_binary || 04079 ((f->usage == CB_USAGE_COMP_5 || 04080 f->usage == CB_USAGE_COMP_X || 04081 f->usage == CB_USAGE_BINARY) && 04082 f->pic->scale == 0)) { 04083 p = l->data; 04084 for (i = 0; i < l->size; i++) { 04085 if (l->data[i] != '0') { 04086 p = &l->data[i]; 04087 break; 04088 } 04089 } 04090 i = l->size - i; 04091 switch (f->size) { 04092 case 1: 04093 if (i > 18) { 04094 goto numlit_overflow; 04095 } 04096 val = cb_get_long_long (src); 04097 if (f->pic->have_sign) { 04098 if (val < -128LL || 04099 val > 127LL) { 04100 goto numlit_overflow; 04101 } 04102 } else { 04103 if (val > 255LL) { 04104 goto numlit_overflow; 04105 } 04106 } 04107 break; 04108 case 2: 04109 if (i > 18) { 04110 goto numlit_overflow; 04111 } 04112 val = cb_get_long_long (src); 04113 if (f->pic->have_sign) { 04114 if (val < -32768LL || 04115 val > 32767LL) { 04116 goto numlit_overflow; 04117 } 04118 } else { 04119 if (val > 65535LL) { 04120 goto numlit_overflow; 04121 } 04122 } 04123 break; 04124 case 3: 04125 if (i > 18) { 04126 goto numlit_overflow; 04127 } 04128 val = cb_get_long_long (src); 04129 if (f->pic->have_sign) { 04130 if (val < -8388608LL || 04131 val > 8388607LL) { 04132 goto numlit_overflow; 04133 } 04134 } else { 04135 if (val > 16777215LL) { 04136 goto numlit_overflow; 04137 } 04138 } 04139 break; 04140 case 4: 04141 if (i > 18) { 04142 goto numlit_overflow; 04143 } 04144 val = cb_get_long_long (src); 04145 if (f->pic->have_sign) { 04146 if (val < -2147483648LL || 04147 val > 2147483647LL) { 04148 goto numlit_overflow; 04149 } 04150 } else { 04151 if (val > 4294967295LL) { 04152 goto numlit_overflow; 04153 } 04154 } 04155 break; 04156 case 5: 04157 if (i > 18) { 04158 goto numlit_overflow; 04159 } 04160 val = cb_get_long_long (src); 04161 if (f->pic->have_sign) { 04162 if (val < -549755813888LL || 04163 val > 549755813887LL) { 04164 goto numlit_overflow; 04165 } 04166 } else { 04167 if (val > 1099511627775LL) { 04168 goto numlit_overflow; 04169 } 04170 } 04171 break; 04172 case 6: 04173 if (i > 18) { 04174 goto numlit_overflow; 04175 } 04176 val = cb_get_long_long (src); 04177 if (f->pic->have_sign) { 04178 if (val < -140737488355328LL || 04179 val > 140737488355327LL) { 04180 goto numlit_overflow; 04181 } 04182 } else { 04183 if (val > 281474976710655LL) { 04184 goto numlit_overflow; 04185 } 04186 } 04187 break; 04188 case 7: 04189 if (i > 18) { 04190 goto numlit_overflow; 04191 } 04192 val = cb_get_long_long (src); 04193 if (f->pic->have_sign) { 04194 if (val < -36028797018963968LL || 04195 val > 36028797018963967LL) { 04196 goto numlit_overflow; 04197 } 04198 } else { 04199 if (val > 72057594037927935LL) { 04200 goto numlit_overflow; 04201 } 04202 } 04203 break; 04204 default: 04205 if (f->pic->have_sign) { 04206 if (i < 19) { 04207 break; 04208 } 04209 if (i > 19) { 04210 goto numlit_overflow; 04211 } 04212 if (memcmp (p, "9223372036854775807", 19) > 0) { 04213 goto numlit_overflow; 04214 } 04215 } else { 04216 if (i < 20) { 04217 break; 04218 } 04219 if (i > 20) { 04220 goto numlit_overflow; 04221 } 04222 if (memcmp (p, "18446744073709551615", 20) > 0) { 04223 goto numlit_overflow; 04224 } 04225 } 04226 break; 04227 } 04228 return 0; 04229 } 04230 if (least_significant < -f->pic->scale) { 04231 goto size_overflow; 04232 } 04233 if (f->pic->scale > 0) { 04234 size = f->pic->digits - f->pic->scale; 04235 } else { 04236 size = f->pic->digits; 04237 } 04238 if (most_significant >= size) { 04239 goto size_overflow; 04240 } 04241 } else { 04242 /* Alphanumeric literal */ 04243 04244 /* value check */ 04245 switch (CB_TREE_CATEGORY (dst)) { 04246 case CB_CATEGORY_ALPHABETIC: 04247 for (i = 0; i < l->size; i++) { 04248 if (!isalpha (l->data[i]) && !isspace (l->data[i])) { 04249 goto value_mismatch; 04250 } 04251 } 04252 break; 04253 case CB_CATEGORY_NUMERIC: 04254 goto expect_numeric; 04255 case CB_CATEGORY_NUMERIC_EDITED: 04256 if (!is_value) { 04257 goto expect_numeric; 04258 } 04259 04260 /* TODO: validate the value */ 04261 break; 04262 default: 04263 break; 04264 } 04265 04266 /* size check */ 04267 size = cb_field_size (dst); 04268 if (size >= 0 && (int)l->size > size) { 04269 goto size_overflow; 04270 } 04271 } 04272 break; 04273 case CB_TAG_FIELD: 04274 case CB_TAG_REFERENCE: 04275 if (CB_REFERENCE_P(src) && 04276 CB_ALPHABET_NAME_P(CB_REFERENCE(src)->value)) { 04277 break; 04278 } 04279 if (CB_REFERENCE_P(src) && 04280 CB_FILE_P(CB_REFERENCE(src)->value)) { 04281 goto invalid; 04282 } 04283 size = cb_field_size (src); 04284 if (size < 0) { 04285 size = cb_field (src)->size; 04286 } 04287 /* non-elementary move */ 04288 if (cb_field (src)->children || cb_field (dst)->children) { 04289 if (size > cb_field (dst)->size) { 04290 goto size_overflow_1; 04291 } 04292 break; 04293 } 04294 04295 /* elementary move */ 04296 switch (CB_TREE_CATEGORY (src)) { 04297 case CB_CATEGORY_ALPHANUMERIC: 04298 switch (CB_TREE_CATEGORY (dst)) { 04299 case CB_CATEGORY_NUMERIC: 04300 case CB_CATEGORY_NUMERIC_EDITED: 04301 if (size > cb_field (dst)->pic->digits) { 04302 goto size_overflow_2; 04303 } 04304 break; 04305 case CB_CATEGORY_ALPHANUMERIC_EDITED: 04306 if (size > 04307 count_pic_alphanumeric_edited (cb_field (dst))) { 04308 goto size_overflow_1; 04309 } 04310 break; 04311 default: 04312 if (size > cb_field (dst)->size) { 04313 goto size_overflow_1; 04314 } 04315 break; 04316 } 04317 break; 04318 case CB_CATEGORY_ALPHABETIC: 04319 case CB_CATEGORY_ALPHANUMERIC_EDITED: 04320 switch (CB_TREE_CATEGORY (dst)) { 04321 case CB_CATEGORY_NUMERIC: 04322 case CB_CATEGORY_NUMERIC_EDITED: 04323 goto invalid; 04324 case CB_CATEGORY_ALPHANUMERIC_EDITED: 04325 if (size > 04326 count_pic_alphanumeric_edited(cb_field (dst))) { 04327 goto size_overflow_1; 04328 } 04329 break; 04330 default: 04331 if (size > cb_field (dst)->size) { 04332 goto size_overflow_1; 04333 } 04334 break; 04335 } 04336 break; 04337 case CB_CATEGORY_NUMERIC: 04338 case CB_CATEGORY_NUMERIC_EDITED: 04339 switch (CB_TREE_CATEGORY (dst)) { 04340 case CB_CATEGORY_ALPHABETIC: 04341 goto invalid; 04342 case CB_CATEGORY_ALPHANUMERIC_EDITED: 04343 is_numeric_edited = 1; 04344 /* Drop through */ 04345 case CB_CATEGORY_ALPHANUMERIC: 04346 if (is_numeric_edited) { 04347 dst_size_mod = count_pic_alphanumeric_edited (cb_field (dst)); 04348 } else { 04349 dst_size_mod = cb_field (dst)->size; 04350 } 04351 if (CB_TREE_CATEGORY (src) == CB_CATEGORY_NUMERIC 04352 && cb_field (src)->pic->scale > 0) { 04353 if (cb_move_noninteger_to_alphanumeric == CB_ERROR) { 04354 goto invalid; 04355 } 04356 cb_warning_x (loc, _("Move non-integer to alphanumeric")); 04357 break; 04358 } 04359 if (CB_TREE_CATEGORY (src) == CB_CATEGORY_NUMERIC 04360 && cb_field (src)->pic->digits > dst_size_mod) { 04361 goto size_overflow_2; 04362 } 04363 if (CB_TREE_CATEGORY (src) == CB_CATEGORY_NUMERIC_EDITED 04364 && cb_field (src)->size > dst_size_mod) { 04365 goto size_overflow_1; 04366 } 04367 break; 04368 default: 04369 src_scale_mod = cb_field (src)->pic->scale < 0 ? 04370 0 : cb_field (src)->pic->scale; 04371 dst_scale_mod = cb_field (dst)->pic->scale < 0 ? 04372 0 : cb_field (dst)->pic->scale; 04373 if (cb_field (src)->pic->digits - src_scale_mod > 04374 cb_field (dst)->pic->digits - dst_scale_mod || 04375 src_scale_mod > dst_scale_mod) { 04376 goto size_overflow_2; 04377 } 04378 break; 04379 } 04380 break; 04381 default: 04382 cb_error_x (loc, _("Invalid source for MOVE")); 04383 return -1; 04384 } 04385 break; 04386 case CB_TAG_INTEGER: 04387 case CB_TAG_BINARY_OP: 04388 case CB_TAG_INTRINSIC: 04389 /* TODO: check this */ 04390 break; 04391 default: 04392 fprintf (stderr, "Invalid tree tag %d\n", CB_TREE_TAG (src)); 04393 ABORT (); 04394 } 04395 return 0; 04396 04397 invalid: 04398 if (is_value) { 04399 cb_error_x (loc, _("Invalid VALUE clause")); 04400 } else { 04401 cb_error_x (loc, _("Invalid MOVE statement")); 04402 } 04403 return -1; 04404 04405 numlit_overflow: 04406 if (is_value) { 04407 cb_error_x (loc, _("Invalid VALUE clause - literal exceeds data size")); 04408 return -1; 04409 } 04410 if (cb_warn_constant) { 04411 cb_warning_x (loc, _("Numeric literal exceeds data size")); 04412 } 04413 return 0; 04414 04415 expect_numeric: 04416 return move_error (src, dst, is_value, cb_warn_strict_typing, 0, 04417 _("Numeric value is expected")); 04418 04419 expect_alphanumeric: 04420 return move_error (src, dst, is_value, cb_warn_strict_typing, 0, 04421 _("Alphanumeric value is expected")); 04422 04423 value_mismatch: 04424 return move_error (src, dst, is_value, cb_warn_constant, 0, 04425 _("Value does not fit the picture string")); 04426 04427 size_overflow: 04428 return move_error (src, dst, is_value, cb_warn_constant, 0, 04429 _("Value size exceeds data size")); 04430 04431 size_overflow_1: 04432 return move_error (src, dst, is_value, cb_warn_truncate, 1, 04433 _("Sending field larger than receiving field")); 04434 04435 size_overflow_2: 04436 return move_error (src, dst, is_value, cb_warn_truncate, 1, 04437 _("Some digits may be truncated")); 04438 } 04439 04440 static cb_tree 04441 cb_build_memset (cb_tree x, int c) 04442 { 04443 int size = cb_field_size (x); 04444 04445 if (size == 1) { 04446 return cb_build_funcall_2 ("$E", x, cb_int (c)); 04447 } else { 04448 return cb_build_funcall_3 ("memset", 04449 cb_build_cast_address (x), 04450 cb_int (c), cb_build_cast_length (x)); 04451 } 04452 } 04453 04454 static cb_tree 04455 cb_build_move_copy (cb_tree src, cb_tree dst) 04456 { 04457 int size = cb_field_size (dst); 04458 04459 if (size == 1) { 04460 return cb_build_funcall_2 ("$F", dst, src); 04461 } else { 04462 return cb_build_funcall_3 ("memcpy", 04463 cb_build_cast_address (dst), 04464 cb_build_cast_address (src), cb_build_cast_length (dst)); 04465 } 04466 } 04467 04468 static cb_tree 04469 cb_build_move_call (cb_tree src, cb_tree dst) 04470 { 04471 return cb_build_funcall_2 ("cob_move", src, dst); 04472 } 04473 04474 static cb_tree 04475 cb_build_move_num_zero (cb_tree x) 04476 { 04477 struct cb_field *f; 04478 04479 f = cb_field (x); 04480 switch (f->usage) { 04481 case CB_USAGE_BINARY: 04482 case CB_USAGE_COMP_5: 04483 case CB_USAGE_COMP_X: 04484 if (f->flag_binary_swap) { 04485 return cb_build_memset (x, 0); 04486 } 04487 switch (f->size) { 04488 #ifdef COB_NON_ALIGNED 04489 case 1: 04490 return cb_build_assign (x, cb_int0); 04491 case 2: 04492 #ifdef COB_SHORT_BORK 04493 if (f->storage != CB_STORAGE_LINKAGE && f->indexes == 0 && 04494 (f->offset % 4 == 0)) { 04495 return cb_build_assign (x, cb_int0); 04496 } 04497 break; 04498 #endif 04499 case 4: 04500 case 8: 04501 if (f->storage != CB_STORAGE_LINKAGE && f->indexes == 0 && 04502 (f->offset % f->size == 0)) { 04503 return cb_build_assign (x, cb_int0); 04504 } 04505 break; 04506 #else 04507 case 1: 04508 case 2: 04509 case 4: 04510 case 8: 04511 return cb_build_assign (x, cb_int0); 04512 #endif 04513 } 04514 return cb_build_memset (x, 0); 04515 case CB_USAGE_DISPLAY: 04516 return cb_build_memset (x, '0'); 04517 case CB_USAGE_PACKED: 04518 return cb_build_funcall_1 ("cob_set_packed_zero", x); 04519 default: 04520 return cb_build_move_call (cb_zero, x); 04521 } 04522 } 04523 04524 static cb_tree 04525 cb_build_move_space (cb_tree x) 04526 { 04527 switch (CB_TREE_CATEGORY (x)) { 04528 case CB_CATEGORY_NUMERIC: 04529 case CB_CATEGORY_ALPHABETIC: 04530 case CB_CATEGORY_ALPHANUMERIC: 04531 return cb_build_memset (x, ' '); 04532 default: 04533 return cb_build_move_call (cb_space, x); 04534 } 04535 } 04536 04537 static cb_tree 04538 cb_build_move_zero (cb_tree x) 04539 { 04540 switch (CB_TREE_CATEGORY (x)) { 04541 case CB_CATEGORY_NUMERIC: 04542 if (cb_field (x)->flag_blank_zero) { 04543 return cb_build_move_space (x); 04544 } else { 04545 return cb_build_move_num_zero (x); 04546 } 04547 case CB_CATEGORY_ALPHABETIC: 04548 case CB_CATEGORY_ALPHANUMERIC: 04549 return cb_build_memset (x, '0'); 04550 default: 04551 return cb_build_move_call (cb_zero, x); 04552 } 04553 } 04554 04555 static cb_tree 04556 cb_build_move_high (cb_tree x) 04557 { 04558 switch (CB_TREE_CATEGORY (x)) { 04559 case CB_CATEGORY_NUMERIC: 04560 case CB_CATEGORY_ALPHABETIC: 04561 case CB_CATEGORY_ALPHANUMERIC: 04562 if (cb_high == cb_norm_high) { 04563 return cb_build_memset (x, 255); 04564 } else { 04565 return cb_build_move_call (cb_high, x); 04566 } 04567 default: 04568 return cb_build_move_call (cb_high, x); 04569 } 04570 } 04571 04572 static cb_tree 04573 cb_build_move_low (cb_tree x) 04574 { 04575 switch (CB_TREE_CATEGORY (x)) { 04576 case CB_CATEGORY_NUMERIC: 04577 case CB_CATEGORY_ALPHABETIC: 04578 case CB_CATEGORY_ALPHANUMERIC: 04579 if (cb_low == cb_norm_low) { 04580 return cb_build_memset (x, 0); 04581 } else { 04582 return cb_build_move_call (cb_low, x); 04583 } 04584 default: 04585 return cb_build_move_call (cb_low, x); 04586 } 04587 } 04588 04589 static cb_tree 04590 cb_build_move_quote (cb_tree x) 04591 { 04592 switch (CB_TREE_CATEGORY (x)) { 04593 case CB_CATEGORY_NUMERIC: 04594 case CB_CATEGORY_ALPHABETIC: 04595 case CB_CATEGORY_ALPHANUMERIC: 04596 return cb_build_memset (x, '"'); 04597 default: 04598 return cb_build_move_call (cb_quote, x); 04599 } 04600 } 04601 04602 #ifdef COB_EBCDIC_MACHINE 04603 static void 04604 cob_put_sign_ascii (unsigned char *p) 04605 { 04606 switch (*p) { 04607 case '0': 04608 *p = (unsigned char)'p'; 04609 return; 04610 case '1': 04611 *p = (unsigned char)'q'; 04612 return; 04613 case '2': 04614 *p = (unsigned char)'r'; 04615 return; 04616 case '3': 04617 *p = (unsigned char)'s'; 04618 return; 04619 case '4': 04620 *p = (unsigned char)'t'; 04621 return; 04622 case '5': 04623 *p = (unsigned char)'u'; 04624 return; 04625 case '6': 04626 *p = (unsigned char)'v'; 04627 return; 04628 case '7': 04629 *p = (unsigned char)'w'; 04630 return; 04631 case '8': 04632 *p = (unsigned char)'x'; 04633 return; 04634 case '9': 04635 *p = (unsigned char)'y'; 04636 return; 04637 } 04638 } 04639 #endif 04640 04641 static void 04642 cob_put_sign_ebcdic (unsigned char *p, const int sign) 04643 { 04644 if (sign < 0) { 04645 switch (*p) { 04646 case '0': 04647 *p = (unsigned char)'}'; 04648 return; 04649 case '1': 04650 *p = (unsigned char)'J'; 04651 return; 04652 case '2': 04653 *p = (unsigned char)'K'; 04654 return; 04655 case '3': 04656 *p = (unsigned char)'L'; 04657 return; 04658 case '4': 04659 *p = (unsigned char)'M'; 04660 return; 04661 case '5': 04662 *p = (unsigned char)'N'; 04663 return; 04664 case '6': 04665 *p = (unsigned char)'O'; 04666 return; 04667 case '7': 04668 *p = (unsigned char)'P'; 04669 return; 04670 case '8': 04671 *p = (unsigned char)'Q'; 04672 return; 04673 case '9': 04674 *p = (unsigned char)'R'; 04675 return; 04676 default: 04677 /* What to do here */ 04678 *p = (unsigned char)'}'; 04679 return; 04680 } 04681 } 04682 switch (*p) { 04683 case '0': 04684 *p = (unsigned char)'{'; 04685 return; 04686 case '1': 04687 *p = (unsigned char)'A'; 04688 return; 04689 case '2': 04690 *p = (unsigned char)'B'; 04691 return; 04692 case '3': 04693 *p = (unsigned char)'C'; 04694 return; 04695 case '4': 04696 *p = (unsigned char)'D'; 04697 return; 04698 case '5': 04699 *p = (unsigned char)'E'; 04700 return; 04701 case '6': 04702 *p = (unsigned char)'F'; 04703 return; 04704 case '7': 04705 *p = (unsigned char)'G'; 04706 return; 04707 case '8': 04708 *p = (unsigned char)'H'; 04709 return; 04710 case '9': 04711 *p = (unsigned char)'I'; 04712 return; 04713 default: 04714 /* What to do here */ 04715 *p = (unsigned char)'{'; 04716 return; 04717 } 04718 /* NOT REACHED */ 04719 } 04720 04721 static cb_tree 04722 cb_build_move_literal (cb_tree src, cb_tree dst) 04723 { 04724 struct cb_literal *l; 04725 struct cb_field *f; 04726 unsigned char *buff; 04727 unsigned char *p; 04728 enum cb_category cat; 04729 int i; 04730 int diff; 04731 int val; 04732 int n; 04733 unsigned char bbyte; 04734 04735 l = CB_LITERAL (src); 04736 f = cb_field (dst); 04737 cat = CB_TREE_CATEGORY (dst); 04738 04739 if (l->all) { 04740 if (cat == CB_CATEGORY_NUMERIC || cat == CB_CATEGORY_NUMERIC_EDITED) { 04741 return cb_build_move_call (src, dst); 04742 } 04743 if (l->size == 1) { 04744 return cb_build_funcall_3 ("memset", 04745 cb_build_cast_address (dst), 04746 cb_int (l->data[0]), cb_build_cast_length (dst)); 04747 } 04748 bbyte = l->data[0]; 04749 for (i = 0; i < (int)l->size; i++) { 04750 if (bbyte != l->data[i]) { 04751 break; 04752 } 04753 bbyte = l->data[i]; 04754 } 04755 if (i == (int)l->size) { 04756 return cb_build_funcall_3 ("memset", 04757 cb_build_cast_address (dst), 04758 cb_int (l->data[0]), cb_build_cast_length (dst)); 04759 } 04760 if (f->size > 128) { 04761 return cb_build_move_call (src, dst); 04762 } 04763 buff = cobc_malloc ((size_t)f->size); 04764 for (i = 0; i < f->size; i++) { 04765 buff[i] = l->data[i % l->size]; 04766 } 04767 return cb_build_funcall_3 ("memcpy", 04768 cb_build_cast_address (dst), 04769 cb_build_string (buff, f->size), cb_build_cast_length (dst)); 04770 } else if ((cat == CB_CATEGORY_NUMERIC 04771 && f->usage == CB_USAGE_DISPLAY 04772 && f->pic->scale == l->scale && !f->flag_sign_leading && !f->flag_sign_separate) 04773 || ((cat == CB_CATEGORY_ALPHABETIC || cat == CB_CATEGORY_ALPHANUMERIC) 04774 && f->size < (int) (l->size + 16) && !cb_field_variable_size (f))) { 04775 buff = cobc_malloc ((size_t)f->size); 04776 diff = (int) (f->size - l->size); 04777 if (cat == CB_CATEGORY_NUMERIC) { 04778 if (diff <= 0) { 04779 memcpy (buff, l->data - diff, (size_t)f->size); 04780 } else { 04781 memset (buff, '0', (size_t)diff); 04782 memcpy (buff + diff, l->data, (size_t)l->size); 04783 } 04784 if (f->pic->have_sign) { 04785 p = &buff[f->size - 1]; 04786 if (cb_display_sign) { 04787 cob_put_sign_ebcdic (p, l->sign); 04788 } else if (l->sign < 0) { 04789 #ifdef COB_EBCDIC_MACHINE 04790 cob_put_sign_ascii (p); 04791 #else 04792 *p += 0x40; 04793 #endif 04794 } 04795 } 04796 } else { 04797 if (f->flag_justified) { 04798 if (diff <= 0) { 04799 memcpy (buff, l->data - diff, (size_t)f->size); 04800 } else { 04801 memset (buff, ' ', (size_t)diff); 04802 memcpy (buff + diff, l->data, (size_t)l->size); 04803 } 04804 } else { 04805 if (diff <= 0) { 04806 memcpy (buff, l->data, (size_t)f->size); 04807 } else { 04808 memcpy (buff, l->data, (size_t)l->size); 04809 memset (buff + l->size, ' ', (size_t)diff); 04810 } 04811 } 04812 } 04813 bbyte = *buff; 04814 if (f->size == 1) { 04815 free (buff); 04816 return cb_build_funcall_2 ("$E", dst, cb_int (bbyte)); 04817 } 04818 for (i = 0; i < f->size; i++) { 04819 if (bbyte != buff[i]) { 04820 break; 04821 } 04822 } 04823 if (i == f->size) { 04824 free (buff); 04825 return cb_build_funcall_3 ("memset", 04826 cb_build_cast_address (dst), 04827 cb_int (bbyte), cb_build_cast_length (dst)); 04828 } 04829 return cb_build_funcall_3 ("memcpy", 04830 cb_build_cast_address (dst), 04831 cb_build_string (buff, f->size), 04832 cb_build_cast_length (dst)); 04833 } else if (cb_fits_int (src) && f->size <= 8 && 04834 (f->usage == CB_USAGE_BINARY || f->usage == CB_USAGE_COMP_5 || 04835 f->usage == CB_USAGE_COMP_X)) { 04836 val = cb_get_int (src); 04837 n = f->pic->scale - l->scale; 04838 if ((l->size + n) > 9) { 04839 return cb_build_move_call (src, dst); 04840 } 04841 for (; n > 0; n--) { 04842 val *= 10; 04843 } 04844 for (; n < 0; n++) { 04845 val /= 10; 04846 } 04847 if (val == 0) { 04848 return cb_build_move_num_zero (dst); 04849 } 04850 if (f->size == 1) { 04851 return cb_build_assign (dst, cb_int (val)); 04852 } 04853 if (f->flag_binary_swap) { 04854 i = (f->size - 1) + (8 * (f->pic->have_sign ? 1 : 0)); 04855 return cb_build_funcall_2 (bin_set_funcs[i], 04856 cb_build_cast_address (dst), 04857 cb_int (val)); 04858 } 04859 switch (f->size) { 04860 case 2: 04861 #ifdef COB_SHORT_BORK 04862 if (f->storage != CB_STORAGE_LINKAGE && f->indexes == 0 && 04863 (f->offset % 4 == 0)) { 04864 return cb_build_assign (dst, cb_int (val)); 04865 } 04866 break; 04867 #endif 04868 case 4: 04869 case 8: 04870 #ifdef COB_NON_ALIGNED 04871 if (f->storage != CB_STORAGE_LINKAGE && f->indexes == 0 && 04872 (f->offset % f->size == 0)) { 04873 return cb_build_assign (dst, cb_int (val)); 04874 } 04875 break; 04876 #else 04877 return cb_build_assign (dst, cb_int (val)); 04878 #endif 04879 } 04880 return cb_build_move_call (src, dst); 04881 } else if (cb_fits_int (src) && f->usage == CB_USAGE_PACKED) { 04882 if (f->pic->scale < 0) { 04883 return cb_build_move_call (src, dst); 04884 } 04885 val = cb_get_int (src); 04886 n = f->pic->scale - l->scale; 04887 if ((l->size + n) > 9) { 04888 return cb_build_move_call (src, dst); 04889 } 04890 for (; n > 0; n--) { 04891 val *= 10; 04892 } 04893 for (; n < 0; n++) { 04894 val /= 10; 04895 } 04896 if (val == 0) { 04897 return cb_build_move_num_zero (dst); 04898 } 04899 return cb_build_funcall_2 ("cob_set_packed_int", dst, cb_int (val)); 04900 } else { 04901 return cb_build_move_call (src, dst); 04902 } 04903 } 04904 04905 static cb_tree 04906 cb_build_move_field (cb_tree src, cb_tree dst) 04907 { 04908 struct cb_field *src_f; 04909 struct cb_field *dst_f; 04910 int src_size; 04911 int dst_size; 04912 04913 src_f = cb_field (src); 04914 src_size = cb_field_size (src); 04915 dst_f = cb_field (dst); 04916 dst_size = cb_field_size (dst); 04917 04918 if ((src_size > 0 && dst_size > 0 && src_size >= dst_size) 04919 && (!cb_field_variable_size (src_f) && !cb_field_variable_size (dst_f))) { 04920 switch (CB_TREE_CATEGORY (src)) { 04921 case CB_CATEGORY_ALPHABETIC: 04922 if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_ALPHABETIC 04923 || CB_TREE_CATEGORY (dst) == CB_CATEGORY_ALPHANUMERIC) { 04924 if (dst_f->flag_justified == 0) { 04925 return cb_build_move_copy (src, dst); 04926 } 04927 } 04928 break; 04929 case CB_CATEGORY_ALPHANUMERIC: 04930 if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_ALPHANUMERIC) { 04931 if (dst_f->flag_justified == 0) { 04932 return cb_build_move_copy (src, dst); 04933 } 04934 } 04935 break; 04936 case CB_CATEGORY_NUMERIC: 04937 if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_NUMERIC 04938 && src_f->usage == dst_f->usage 04939 && src_f->pic->size == dst_f->pic->size 04940 && src_f->pic->digits == dst_f->pic->digits 04941 && src_f->pic->scale == dst_f->pic->scale 04942 && src_f->pic->have_sign == dst_f->pic->have_sign 04943 && src_f->flag_binary_swap == dst_f->flag_binary_swap 04944 && src_f->flag_sign_leading == dst_f->flag_sign_leading 04945 && src_f->flag_sign_separate == dst_f->flag_sign_separate) { 04946 return cb_build_move_copy (src, dst); 04947 } else if (CB_TREE_CATEGORY (dst) == CB_CATEGORY_ALPHANUMERIC 04948 && src_f->usage == CB_USAGE_DISPLAY 04949 && src_f->pic->have_sign == 0 04950 && !src_f->flag_sign_leading 04951 && !src_f->flag_sign_separate) { 04952 return cb_build_move_copy (src, dst); 04953 } 04954 break; 04955 default: 04956 break; 04957 } 04958 } 04959 04960 return cb_build_move_call (src, dst); 04961 } 04962 04963 cb_tree 04964 cb_build_move (cb_tree src, cb_tree dst) 04965 { 04966 struct cb_field *f; 04967 struct cb_field *p; 04968 04969 if (src == cb_error_node || dst == cb_error_node) { 04970 return cb_error_node; 04971 } 04972 04973 if (validate_move (src, dst, 0) < 0) { 04974 return cb_error_node; 04975 } 04976 04977 if (CB_REFERENCE_P (src)) { 04978 CB_REFERENCE (src)->type = CB_SENDING_OPERAND; 04979 } 04980 if (CB_REFERENCE_P (dst)) { 04981 CB_REFERENCE (dst)->type = CB_RECEIVING_OPERAND; 04982 } 04983 04984 if (CB_TREE_CLASS (dst) == CB_CLASS_POINTER) { 04985 return cb_build_assign (dst, src); 04986 } 04987 04988 if (CB_REFERENCE_P (src) && CB_ALPHABET_NAME_P(CB_REFERENCE(src)->value)) { 04989 return cb_build_move_call (src, dst); 04990 } 04991 if (CB_INDEX_P (dst)) { 04992 if (src == cb_null) { 04993 return cb_build_assign (dst, cb_zero); 04994 } 04995 return cb_build_assign (dst, src); 04996 } 04997 04998 if (CB_INDEX_P (src)) { 04999 return cb_build_funcall_2 ("cob_set_int", dst, cb_build_cast_integer (src)); 05000 } 05001 05002 if (CB_INTRINSIC_P (src) || CB_INTRINSIC_P (dst)) { 05003 return cb_build_move_call (src, dst); 05004 } 05005 05006 f = cb_field (dst); 05007 05008 if (CB_EXCEPTION_ENABLE (COB_EC_BOUND_SUBSCRIPT)) { 05009 for (p = f; p; p = p->parent) { 05010 if (p->flag_occurs) { 05011 return cb_build_move_call (src, dst); 05012 } 05013 } 05014 if (CB_REF_OR_FIELD_P (src)) { 05015 for (p = cb_field (src); p; p = p->parent) { 05016 if (p->flag_occurs) { 05017 return cb_build_move_call (src, dst); 05018 } 05019 } 05020 } 05021 } 05022 05023 /* output optimal code */ 05024 if (src == cb_zero) { 05025 return cb_build_move_zero (dst); 05026 } else if (src == cb_space) { 05027 return cb_build_move_space (dst); 05028 } else if (src == cb_high) { 05029 return cb_build_move_high (dst); 05030 } else if (src == cb_low) { 05031 return cb_build_move_low (dst); 05032 } else if (src == cb_quote) { 05033 return cb_build_move_quote (dst); 05034 } else if (CB_LITERAL_P (src)) { 05035 return cb_build_move_literal (src, dst); 05036 } 05037 return cb_build_move_field (src, dst); 05038 } 05039 05040 void 05041 cb_emit_move (cb_tree src, cb_tree dsts) 05042 { 05043 cb_tree l; 05044 05045 if (cb_validate_one (src)) { 05046 return; 05047 } 05048 if (cb_validate_list (dsts)) { 05049 return; 05050 } 05051 05052 for (l = dsts; l; l = CB_CHAIN (l)) { 05053 cb_emit (cb_build_move (src, CB_VALUE (l))); 05054 } 05055 } 05056 05057 /* 05058 * OPEN statement 05059 */ 05060 05061 void 05062 cb_emit_open (cb_tree file, cb_tree mode, cb_tree sharing) 05063 { 05064 if (file == cb_error_node) { 05065 return; 05066 } 05067 file = cb_ref (file); 05068 if (file == cb_error_node) { 05069 return; 05070 } 05071 current_statement->file = file; 05072 05073 if (CB_FILE (file)->organization == COB_ORG_SORT) { 05074 cb_error_x (CB_TREE (current_statement), 05075 _("Operation not allowed on SORT files")); 05076 } 05077 if (sharing == NULL) { 05078 sharing = CB_FILE (file)->sharing ? CB_FILE (file)->sharing : cb_int0; 05079 } 05080 05081 /* READ ONLY */ 05082 if (sharing == cb_int0 && CB_INTEGER (mode)->val != COB_OPEN_INPUT) { 05083 sharing = cb_int1; 05084 } 05085 05086 cb_emit (cb_build_funcall_4 ("cob_open", file, mode, 05087 sharing, CB_FILE(file)->file_status)); 05088 } 05089 05090 /* 05091 * PERFORM statement 05092 */ 05093 05094 void 05095 cb_emit_perform (cb_tree perform, cb_tree body) 05096 { 05097 if (perform == cb_error_node) { 05098 return; 05099 } 05100 CB_PERFORM (perform)->body = body; 05101 cb_emit (perform); 05102 } 05103 05104 cb_tree 05105 cb_build_perform_once (cb_tree body) 05106 { 05107 cb_tree x; 05108 05109 if (body == cb_error_node) { 05110 return cb_error_node; 05111 } 05112 x = cb_build_perform (CB_PERFORM_ONCE); 05113 CB_PERFORM (x)->body = body; 05114 return x; 05115 } 05116 05117 cb_tree 05118 cb_build_perform_times (cb_tree times) 05119 { 05120 cb_tree x; 05121 05122 if (cb_check_integer_value (times) == cb_error_node) { 05123 return cb_error_node; 05124 } 05125 05126 x = cb_build_perform (CB_PERFORM_TIMES); 05127 CB_PERFORM (x)->data = times; 05128 return x; 05129 } 05130 05131 cb_tree 05132 cb_build_perform_until (cb_tree condition, cb_tree varying) 05133 { 05134 cb_tree x; 05135 05136 x = cb_build_perform (CB_PERFORM_UNTIL); 05137 CB_PERFORM (x)->test = condition; 05138 CB_PERFORM (x)->varying = varying; 05139 return x; 05140 } 05141 05142 cb_tree 05143 cb_build_perform_forever (cb_tree body) 05144 { 05145 cb_tree x; 05146 05147 if (body == cb_error_node) { 05148 return cb_error_node; 05149 } 05150 x = cb_build_perform (CB_PERFORM_FOREVER); 05151 CB_PERFORM (x)->body = body; 05152 return x; 05153 } 05154 05155 cb_tree 05156 cb_build_perform_exit (struct cb_label *label) 05157 { 05158 cb_tree x; 05159 05160 x = cb_build_perform (CB_PERFORM_EXIT); 05161 CB_PERFORM (x)->data = CB_TREE (label); 05162 return x; 05163 } 05164 05165 /* 05166 * READ statement 05167 */ 05168 05169 void 05170 cb_emit_read (cb_tree ref, cb_tree next, cb_tree into, cb_tree key, cb_tree lock_opts) 05171 { 05172 int read_opts = 0; 05173 cb_tree file; 05174 cb_tree rec; 05175 05176 if (lock_opts == cb_int1) { 05177 read_opts = COB_READ_LOCK; 05178 } else if (lock_opts == cb_int2) { 05179 read_opts = COB_READ_NO_LOCK; 05180 } else if (lock_opts == cb_int3) { 05181 read_opts = COB_READ_IGNORE_LOCK; 05182 } else if (lock_opts == cb_int4) { 05183 read_opts = COB_READ_WAIT_LOCK; 05184 } 05185 if (ref == cb_error_node) { 05186 return; 05187 } 05188 file = cb_ref (ref); 05189 if (file == cb_error_node) { 05190 return; 05191 } 05192 rec = cb_build_field_reference (CB_FILE (file)->record, ref); 05193 if (CB_FILE (file)->organization == COB_ORG_SORT) { 05194 cb_error_x (CB_TREE (current_statement), 05195 _("Operation not allowed on SORT files")); 05196 } 05197 if (next == cb_int1 || next == cb_int2 || 05198 CB_FILE (file)->access_mode == COB_ACCESS_SEQUENTIAL) { 05199 /* READ NEXT/PREVIOUS */ 05200 if (next == cb_int2) { 05201 if (CB_FILE (file)->organization != COB_ORG_INDEXED) { 05202 cb_error_x (CB_TREE (current_statement), 05203 _("READ PREVIOUS only allowed for INDEXED SEQUENTIAL files")); 05204 } 05205 read_opts |= COB_READ_PREVIOUS; 05206 } else { 05207 read_opts |= COB_READ_NEXT; 05208 } 05209 if (key) { 05210 cb_warning (_("KEY ignored with sequential READ")); 05211 } 05212 cb_emit (cb_build_funcall_4 ("cob_read", file, cb_int0, 05213 CB_FILE(file)->file_status, 05214 cb_int (read_opts))); 05215 } else { 05216 /* READ */ 05217 cb_emit (cb_build_funcall_4 ("cob_read", 05218 file, key ? key : CB_FILE (file)->key, 05219 CB_FILE(file)->file_status, cb_int (read_opts))); 05220 } 05221 if (into) { 05222 current_statement->handler3 = cb_build_move (rec, into); 05223 } 05224 current_statement->file = file; 05225 } 05226 05227 /* 05228 * REWRITE statement 05229 */ 05230 05231 void 05232 cb_emit_rewrite (cb_tree record, cb_tree from, cb_tree lockopt) 05233 { 05234 cb_tree file; 05235 int opts = 0; 05236 05237 if (record == cb_error_node || cb_ref (record) == cb_error_node) { 05238 return; 05239 } 05240 if (!CB_REF_OR_FIELD_P (cb_ref (record))) { 05241 cb_error_x (CB_TREE (current_statement), 05242 _("REWRITE requires a record name as subject")); 05243 return; 05244 } 05245 if (cb_field (record)->storage != CB_STORAGE_FILE) { 05246 cb_error_x (CB_TREE (current_statement), 05247 _("REWRITE subject does not refer to a record name")); 05248 return; 05249 } 05250 file = CB_TREE (CB_FIELD (cb_ref (record))->file); 05251 current_statement->file = file; 05252 if (CB_FILE (file)->organization == COB_ORG_SORT) { 05253 cb_error_x (CB_TREE (current_statement), 05254 _("Operation not allowed on SORT files")); 05255 } else if (current_statement->handler_id == COB_EC_I_O_INVALID_KEY && 05256 (CB_FILE(file)->organization != COB_ORG_RELATIVE && 05257 CB_FILE(file)->organization != COB_ORG_INDEXED)) { 05258 cb_error_x (CB_TREE(current_statement), 05259 _("INVALID KEY clause invalid with this file type")); 05260 } else if ((CB_FILE (file)->lock_mode & COB_LOCK_AUTOMATIC) && lockopt) { 05261 cb_error_x (CB_TREE (current_statement), 05262 _("LOCK clause invalid with file LOCK AUTOMATIC")); 05263 } else if (lockopt == cb_int1) { 05264 opts = COB_WRITE_LOCK; 05265 } 05266 if (from) { 05267 cb_emit (cb_build_move (from, record)); 05268 } 05269 cb_emit (cb_build_funcall_4 ("cob_rewrite", file, record, 05270 cb_int (opts), CB_FILE(file)->file_status)); 05271 } 05272 05273 /* 05274 * RELEASE statement 05275 */ 05276 05277 void 05278 cb_emit_release (cb_tree record, cb_tree from) 05279 { 05280 struct cb_field *f; 05281 cb_tree file; 05282 05283 if (record == cb_error_node) { 05284 return; 05285 } 05286 if (from == cb_error_node) { 05287 return; 05288 } 05289 if (cb_ref (record) == cb_error_node) { 05290 return; 05291 } 05292 if (!CB_REF_OR_FIELD_P (cb_ref (record))) { 05293 cb_error_x (CB_TREE (current_statement), 05294 _("RELEASE requires a record name as subject")); 05295 return; 05296 } 05297 if (cb_field (record)->storage != CB_STORAGE_FILE) { 05298 cb_error_x (CB_TREE (current_statement), 05299 _("RELEASE subject does not refer to a record name")); 05300 return; 05301 } 05302 f = CB_FIELD (cb_ref (record)); 05303 file = CB_TREE (f->file); 05304 if (CB_FILE (file)->organization != COB_ORG_SORT) { 05305 cb_error_x (CB_TREE (current_statement), 05306 _("RELEASE not allowed on this record item")); 05307 return; 05308 } 05309 current_statement->file = file; 05310 if (from) { 05311 cb_emit (cb_build_move (from, record)); 05312 } 05313 cb_emit (cb_build_funcall_1 ("cob_file_release", file)); 05314 } 05315 05316 /* 05317 * RETURN statement 05318 */ 05319 05320 void 05321 cb_emit_return (cb_tree ref, cb_tree into) 05322 { 05323 cb_tree file; 05324 cb_tree rec; 05325 05326 if (ref == cb_error_node) { 05327 return; 05328 } 05329 if (into == cb_error_node) { 05330 return; 05331 } 05332 file = cb_ref (ref); 05333 if (file == cb_error_node) { 05334 return; 05335 } 05336 rec = cb_build_field_reference (CB_FILE (file)->record, ref); 05337 cb_emit (cb_build_funcall_1 ("cob_file_return", file)); 05338 if (into) { 05339 current_statement->handler3 = cb_build_move (rec, into); 05340 } 05341 current_statement->file = file; 05342 } 05343 05344 /* 05345 * ROLLBACK statement 05346 */ 05347 05348 void 05349 cb_emit_rollback (void) 05350 { 05351 cb_emit (cb_build_funcall_0 ("cob_rollback")); 05352 } 05353 05354 /* 05355 * SEARCH statement 05356 */ 05357 05358 static void 05359 search_set_keys (struct cb_field *f, cb_tree x) 05360 { 05361 struct cb_binary_op *p; 05362 int i; 05363 05364 if (CB_REFERENCE_P (x)) { 05365 x = build_cond_88 (x); 05366 } 05367 05368 p = CB_BINARY_OP (x); 05369 switch (p->op) { 05370 case '&': 05371 search_set_keys (f, p->x); 05372 search_set_keys (f, p->y); 05373 break; 05374 case '=': 05375 for (i = 0; i < f->nkeys; i++) { 05376 if (cb_field (p->x) == cb_field (f->keys[i].key)) { 05377 f->keys[i].ref = p->x; 05378 f->keys[i].val = p->y; 05379 break; 05380 } 05381 } 05382 if (i == f->nkeys) { 05383 cb_error_x (x, _("Undeclared key '%s'"), cb_field (p->x)->name); 05384 } 05385 break; 05386 default: 05387 cb_error_x (x, _("Invalid SEARCH ALL condition")); 05388 break; 05389 } 05390 } 05391 05392 static cb_tree 05393 cb_build_search_all (cb_tree table, cb_tree cond) 05394 { 05395 cb_tree c1 = NULL; 05396 cb_tree c2; 05397 struct cb_field *f; 05398 int i; 05399 05400 f = cb_field (table); 05401 /* set keys */ 05402 for (i = 0; i < f->nkeys; i++) { 05403 f->keys[i].ref = NULL; 05404 } 05405 search_set_keys (f, cond); 05406 05407 /* build condition */ 05408 for (i = 0; i < f->nkeys; i++) { 05409 if (f->keys[i].ref) { 05410 if (f->keys[i].dir == COB_ASCENDING) { 05411 c2 = cb_build_binary_op (f->keys[i].ref, '=', f->keys[i].val); 05412 } else { 05413 c2 = cb_build_binary_op (f->keys[i].val, '=', f->keys[i].ref); 05414 } 05415 if (c1 == NULL) { 05416 c1 = c2; 05417 } else { 05418 c1 = cb_build_binary_op (c1, '&', c2); 05419 } 05420 } 05421 } 05422 05423 return cb_build_cond (c1); 05424 } 05425 05426 void 05427 cb_emit_search (cb_tree table, cb_tree varying, cb_tree at_end, cb_tree whens) 05428 { 05429 if (cb_validate_one (table)) { 05430 return; 05431 } 05432 if (cb_validate_one (varying)) { 05433 return; 05434 } 05435 if (table == cb_error_node) { 05436 return; 05437 } 05438 cb_emit (cb_build_search (0, table, varying, at_end, whens)); 05439 } 05440 05441 void 05442 cb_emit_search_all (cb_tree table, cb_tree at_end, cb_tree when, cb_tree stmts) 05443 { 05444 if (cb_validate_one (table)) { 05445 return; 05446 } 05447 if (table == cb_error_node) { 05448 return; 05449 } 05450 cb_emit (cb_build_search (1, table, NULL, at_end, 05451 cb_build_if (cb_build_search_all (table, when), stmts, NULL))); 05452 } 05453 05454 /* 05455 * SET statement 05456 */ 05457 05458 void 05459 cb_emit_setenv (cb_tree x, cb_tree y) 05460 { 05461 cb_emit (cb_build_funcall_2 ("cob_set_environment", x, y)); 05462 } 05463 05464 void 05465 cb_emit_set_to (cb_tree vars, cb_tree x) 05466 { 05467 cb_tree l; 05468 cb_tree v; 05469 struct cb_cast *p; 05470 #if 0 05471 enum cb_class class = CB_CLASS_UNKNOWN; 05472 #endif 05473 05474 if (cb_validate_one (x)) { 05475 return; 05476 } 05477 if (cb_validate_list (vars)) { 05478 return; 05479 } 05480 05481 #if 0 05482 /* determine the class of targets */ 05483 for (l = vars; l; l = CB_CHAIN (l)) { 05484 if (CB_TREE_CLASS (CB_VALUE (l)) != CB_CLASS_UNKNOWN) { 05485 if (class == CB_CLASS_UNKNOWN) { 05486 class = CB_TREE_CLASS (CB_VALUE (l)); 05487 } else if (class != CB_TREE_CLASS (CB_VALUE (l))) { 05488 break; 05489 } 05490 } 05491 } 05492 if (l || (class != CB_CLASS_INDEX && class != CB_CLASS_POINTER)) { 05493 cb_error_x (CB_TREE (current_statement), 05494 _("The targets of SET must be either indexes or pointers")); 05495 return; 05496 } 05497 #endif 05498 05499 if (CB_CAST_P (x)) { 05500 p = CB_CAST (x); 05501 if (p->type == CB_CAST_PROGRAM_POINTER) { 05502 for (l = vars; l; l = CB_CHAIN (l)) { 05503 v = CB_VALUE (l); 05504 if (!CB_REFERENCE_P (v)) { 05505 cb_error_x (CB_TREE (current_statement), 05506 _("SET targets must be PROGRAM-POINTER")); 05507 CB_VALUE (l) = cb_error_node; 05508 } else if (CB_FIELD(cb_ref(v))->usage != CB_USAGE_PROGRAM_POINTER) { 05509 cb_error_x (CB_TREE (current_statement), 05510 _("SET targets must be PROGRAM-POINTER")); 05511 CB_VALUE (l) = cb_error_node; 05512 } 05513 } 05514 } 05515 } 05516 /* validate the targets */ 05517 for (l = vars; l; l = CB_CHAIN (l)) { 05518 v = CB_VALUE (l); 05519 if (CB_CAST_P (v)) { 05520 p = CB_CAST (v); 05521 if (p->type == CB_CAST_ADDRESS 05522 && !CB_FIELD (cb_ref (p->val))->flag_item_based 05523 && CB_FIELD (cb_ref (p->val))->storage != CB_STORAGE_LINKAGE) { 05524 cb_error_x (p->val, _("The address of '%s' cannot be changed"), 05525 cb_name (p->val)); 05526 CB_VALUE (l) = cb_error_node; 05527 } 05528 } 05529 } 05530 if (cb_validate_list (vars)) { 05531 return; 05532 } 05533 05534 for (l = vars; l; l = CB_CHAIN (l)) { 05535 cb_emit (cb_build_move (x, CB_VALUE (l))); 05536 } 05537 } 05538 05539 void 05540 cb_emit_set_up_down (cb_tree l, cb_tree flag, cb_tree x) 05541 { 05542 if (cb_validate_one (x)) { 05543 return; 05544 } 05545 if (cb_validate_list (l)) { 05546 return; 05547 } 05548 for (; l; l = CB_CHAIN (l)) { 05549 if (flag == cb_int0) { 05550 cb_emit (cb_build_add (CB_VALUE (l), x, cb_int0)); 05551 } else { 05552 cb_emit (cb_build_sub (CB_VALUE (l), x, cb_int0)); 05553 } 05554 } 05555 } 05556 05557 void 05558 cb_emit_set_on_off (cb_tree l, cb_tree flag) 05559 { 05560 struct cb_system_name *s; 05561 05562 if (cb_validate_list (l)) { 05563 return; 05564 } 05565 for (; l; l = CB_CHAIN (l)) { 05566 s = CB_SYSTEM_NAME (cb_ref (CB_VALUE (l))); 05567 cb_emit (cb_build_funcall_2 ("cob_set_switch", cb_int (s->token), flag)); 05568 } 05569 } 05570 05571 void 05572 cb_emit_set_true (cb_tree l) 05573 { 05574 cb_tree x; 05575 struct cb_field *f; 05576 cb_tree ref; 05577 cb_tree val; 05578 05579 for (; l; l = CB_CHAIN (l)) { 05580 x = CB_VALUE (l); 05581 if (x == cb_error_node) { 05582 return; 05583 } 05584 if (!(CB_REFERENCE_P (x) && CB_FIELD_P(CB_REFERENCE(x)->value)) 05585 && !CB_FIELD_P (x)) { 05586 cb_error_x (x, _("Invalid SET statement")); 05587 return; 05588 } 05589 f = cb_field (x); 05590 if (f->level != 88) { 05591 cb_error_x (x, _("Invalid SET statement")); 05592 return; 05593 } 05594 ref = cb_build_field_reference (f->parent, x); 05595 val = CB_VALUE (f->values); 05596 if (CB_PAIR_P (val)) { 05597 val = CB_PAIR_X (val); 05598 } 05599 cb_emit (cb_build_move (val, ref)); 05600 } 05601 } 05602 05603 void 05604 cb_emit_set_false (cb_tree l) 05605 { 05606 cb_tree x; 05607 struct cb_field *f; 05608 cb_tree ref; 05609 cb_tree val; 05610 05611 for (; l; l = CB_CHAIN (l)) { 05612 x = CB_VALUE (l); 05613 if (x == cb_error_node) { 05614 return; 05615 } 05616 if (!(CB_REFERENCE_P (x) && CB_FIELD_P(CB_REFERENCE(x)->value)) 05617 && !CB_FIELD_P (x)) { 05618 cb_error_x (x, _("Invalid SET statement")); 05619 return; 05620 } 05621 f = cb_field (x); 05622 if (f->level != 88) { 05623 cb_error_x (x, _("Invalid SET statement")); 05624 return; 05625 } 05626 if (!f->false_88) { 05627 cb_error_x (x, _("Field does not have FALSE clause")); 05628 return; 05629 } 05630 ref = cb_build_field_reference (f->parent, x); 05631 val = CB_VALUE (f->false_88); 05632 if (CB_PAIR_P (val)) { 05633 val = CB_PAIR_X (val); 05634 } 05635 cb_emit (cb_build_move (val, ref)); 05636 } 05637 } 05638 05639 /* 05640 * SORT statement 05641 */ 05642 05643 void 05644 cb_emit_sort_init (cb_tree name, cb_tree keys, cb_tree col) 05645 { 05646 cb_tree l; 05647 struct cb_field *f; 05648 05649 if (cb_validate_list (keys)) { 05650 return; 05651 } 05652 for (l = keys; l; l = CB_CHAIN (l)) { 05653 if (CB_VALUE (l) == NULL) { 05654 CB_VALUE (l) = name; 05655 } 05656 cb_ref (CB_VALUE (l)); 05657 } 05658 05659 if (CB_FILE_P (cb_ref (name))) { 05660 if (CB_FILE (cb_ref (name))->organization != COB_ORG_SORT) { 05661 cb_error_x (name, _("Invalid SORT filename")); 05662 } 05663 cb_field (current_program->cb_sort_return)->count++; 05664 cb_emit (cb_build_funcall_5 ("cob_file_sort_init", cb_ref (name), 05665 cb_int (cb_list_length (keys)), col, 05666 cb_build_cast_address (current_program->cb_sort_return), 05667 CB_FILE(cb_ref (name))->file_status)); 05668 for (l = keys; l; l = CB_CHAIN (l)) { 05669 cb_emit (cb_build_funcall_4 ("cob_file_sort_init_key", cb_ref (name), 05670 CB_PURPOSE (l), 05671 CB_VALUE (l), 05672 cb_int (cb_field (CB_VALUE(l))->offset))); 05673 } 05674 } else { 05675 f = CB_FIELD (cb_ref (name)); 05676 if (keys == NULL) { 05677 cb_error_x (name, _("Table sort without keys not implemented yet")); 05678 } 05679 cb_emit (cb_build_funcall_2 ("cob_table_sort_init", cb_int (cb_list_length (keys)), col)); 05680 for (l = keys; l; l = CB_CHAIN (l)) { 05681 cb_emit (cb_build_funcall_3 ("cob_table_sort_init_key", 05682 CB_PURPOSE (l), 05683 CB_VALUE (l), 05684 cb_int (cb_field (CB_VALUE(l))->offset))); 05685 } 05686 cb_emit (cb_build_funcall_2 ("cob_table_sort", name, 05687 (f->occurs_depending 05688 ? cb_build_cast_integer (f->occurs_depending) 05689 : cb_int (f->occurs_max)))); 05690 } 05691 } 05692 05693 void 05694 cb_emit_sort_using (cb_tree file, cb_tree l) 05695 { 05696 if (cb_validate_list (l)) { 05697 return; 05698 } 05699 for (; l; l = CB_CHAIN (l)) { 05700 if (CB_FILE (cb_ref(CB_VALUE(l)))->organization == COB_ORG_SORT) { 05701 cb_error (_("Invalid SORT USING parameter")); 05702 } 05703 cb_emit (cb_build_funcall_2 ("cob_file_sort_using", 05704 cb_ref (file), cb_ref (CB_VALUE (l)))); 05705 } 05706 } 05707 05708 void 05709 cb_emit_sort_input (cb_tree proc) 05710 { 05711 cb_emit (cb_build_perform_once (proc)); 05712 } 05713 05714 void 05715 cb_emit_sort_giving (cb_tree file, cb_tree l) 05716 { 05717 cb_tree p; 05718 int listlen; 05719 05720 if (cb_validate_list (l)) { 05721 return; 05722 } 05723 for (p = l; p; p = CB_CHAIN (p)) { 05724 if (CB_FILE (cb_ref(CB_VALUE(p)))->organization == COB_ORG_SORT) { 05725 cb_error (_("Invalid SORT GIVING parameter")); 05726 } 05727 } 05728 listlen = cb_list_length (l); 05729 p = cb_build_funcall_2 ("cob_file_sort_giving", cb_ref (file), l); 05730 CB_FUNCALL(p)->varcnt = listlen; 05731 cb_emit (p); 05732 } 05733 05734 void 05735 cb_emit_sort_output (cb_tree proc) 05736 { 05737 cb_emit (cb_build_perform_once (proc)); 05738 } 05739 05740 void 05741 cb_emit_sort_finish (cb_tree file) 05742 { 05743 if (CB_FILE_P (cb_ref (file))) { 05744 cb_emit (cb_build_funcall_1 ("cob_file_sort_close", cb_ref (file))); 05745 } 05746 } 05747 05748 /* 05749 * START statement 05750 */ 05751 05752 void 05753 cb_emit_start (cb_tree file, cb_tree op, cb_tree key) 05754 { 05755 if (cb_validate_one (key)) { 05756 return; 05757 } 05758 if (file != cb_error_node) { 05759 current_statement->file = cb_ref (file); 05760 cb_emit (cb_build_funcall_4 ("cob_start", cb_ref (file), op, 05761 key ? key : CB_FILE (cb_ref (file))->key, 05762 CB_FILE(cb_ref(file))->file_status)); 05763 } 05764 } 05765 05766 /* 05767 * STOP statement 05768 */ 05769 05770 void 05771 cb_emit_stop_run (cb_tree x) 05772 { 05773 cb_emit (cb_build_funcall_1 ("cob_stop_run", cb_build_cast_integer (x))); 05774 } 05775 05776 /* 05777 * STRING statement 05778 */ 05779 05780 void 05781 cb_emit_string (cb_tree items, cb_tree into, cb_tree pointer) 05782 { 05783 cb_tree start; 05784 cb_tree l; 05785 cb_tree end; 05786 cb_tree dlm; 05787 05788 if (cb_validate_one (into)) { 05789 return; 05790 } 05791 if (cb_validate_one (pointer)) { 05792 return; 05793 } 05794 start = items; 05795 cb_emit (cb_build_funcall_2 ("cob_string_init", into, pointer)); 05796 while (start) { 05797 05798 /* find DELIMITED item */ 05799 for (end = start; end; end = CB_CHAIN (end)) { 05800 if (CB_PAIR_P (CB_VALUE (end))) { 05801 break; 05802 } 05803 } 05804 05805 /* cob_string_delimited */ 05806 dlm = end ? CB_PAIR_X (CB_VALUE (end)) : cb_int0; 05807 cb_emit (cb_build_funcall_1 ("cob_string_delimited", dlm)); 05808 05809 /* cob_string_append */ 05810 for (l = start; l != end; l = CB_CHAIN (l)) { 05811 cb_emit (cb_build_funcall_1 ("cob_string_append", CB_VALUE (l))); 05812 } 05813 05814 start = end ? CB_CHAIN (end) : NULL; 05815 } 05816 cb_emit (cb_build_funcall_0 ("cob_string_finish")); 05817 } 05818 05819 /* 05820 * UNLOCK statement 05821 */ 05822 05823 void 05824 cb_emit_unlock (cb_tree ref) 05825 { 05826 cb_tree file; 05827 05828 if (ref != cb_error_node) { 05829 file = cb_ref (ref); 05830 cb_emit (cb_build_funcall_2 ("cob_unlock_file", 05831 file, CB_FILE(file)->file_status)); 05832 current_statement->file = file; 05833 } 05834 } 05835 05836 /* 05837 * UNSTRING statement 05838 */ 05839 05840 void 05841 cb_emit_unstring (cb_tree name, cb_tree delimited, cb_tree into, cb_tree pointer, cb_tree tallying) 05842 { 05843 if (cb_validate_one (name)) { 05844 return; 05845 } 05846 if (cb_validate_one (tallying)) { 05847 return; 05848 } 05849 if (cb_validate_list (delimited)) { 05850 return; 05851 } 05852 if (cb_validate_list (into)) { 05853 return; 05854 } 05855 cb_emit (cb_build_funcall_3 ("cob_unstring_init", name, pointer, 05856 cb_int (cb_list_length (delimited)))); 05857 cb_emit_list (delimited); 05858 cb_emit_list (into); 05859 if (tallying) { 05860 cb_emit (cb_build_funcall_1 ("cob_unstring_tallying", tallying)); 05861 } 05862 cb_emit (cb_build_funcall_0 ("cob_unstring_finish")); 05863 } 05864 05865 cb_tree 05866 cb_build_unstring_delimited (cb_tree all, cb_tree value) 05867 { 05868 if (cb_validate_one (value)) { 05869 return cb_error_node; 05870 } 05871 return cb_build_funcall_2 ("cob_unstring_delimited", value, all); 05872 } 05873 05874 cb_tree 05875 cb_build_unstring_into (cb_tree name, cb_tree delimiter, cb_tree count) 05876 { 05877 if (cb_validate_one (name)) { 05878 return cb_error_node; 05879 } 05880 if (delimiter == NULL) { 05881 delimiter = cb_int0; 05882 } 05883 if (count == NULL) { 05884 count = cb_int0; 05885 } 05886 return cb_build_funcall_3 ("cob_unstring_into", name, delimiter, count); 05887 } 05888 05889 /* 05890 * WRITE statement 05891 */ 05892 05893 void 05894 cb_emit_write (cb_tree record, cb_tree from, cb_tree opt, cb_tree lockopt) 05895 { 05896 cb_tree file; 05897 int val; 05898 05899 if (record != cb_error_node && cb_ref (record) != cb_error_node) { 05900 if (!CB_REF_OR_FIELD_P (cb_ref (record))) { 05901 cb_error_x (CB_TREE (current_statement), 05902 _("WRITE requires a record name as subject")); 05903 return; 05904 } 05905 if (cb_field (record)->storage != CB_STORAGE_FILE) { 05906 cb_error_x (CB_TREE (current_statement), 05907 _("WRITE subject does not refer to a record name")); 05908 return; 05909 } 05910 file = CB_TREE (CB_FIELD (cb_ref (record))->file); 05911 current_statement->file = file; 05912 if (CB_FILE (file)->organization == COB_ORG_SORT) { 05913 cb_error_x (CB_TREE (current_statement), 05914 _("Operation not allowed on SORT files")); 05915 } else if (current_statement->handler_id == COB_EC_I_O_INVALID_KEY && 05916 (CB_FILE(file)->organization != COB_ORG_RELATIVE && 05917 CB_FILE(file)->organization != COB_ORG_INDEXED)) { 05918 cb_error_x (CB_TREE(current_statement), 05919 _("INVALID KEY clause invalid with this file type")); 05920 } else if (lockopt) { 05921 if ((CB_FILE (file)->lock_mode & COB_LOCK_AUTOMATIC)) { 05922 cb_error_x (CB_TREE (current_statement), 05923 _("LOCK clause invalid with file LOCK AUTOMATIC")); 05924 } else if (opt != cb_int0) { 05925 cb_error_x (CB_TREE (current_statement), 05926 _("LOCK clause invalid here")); 05927 } else if (lockopt == cb_int1) { 05928 opt = cb_int (COB_WRITE_LOCK); 05929 } 05930 } 05931 if (from) { 05932 cb_emit (cb_build_move (from, record)); 05933 } 05934 if (CB_FILE (file)->organization == COB_ORG_LINE_SEQUENTIAL && 05935 opt == cb_int0) { 05936 opt = cb_int (COB_WRITE_BEFORE | COB_WRITE_LINES | 1); 05937 } 05938 /* RXW - This is horrible */ 05939 if (current_statement->handler_id == COB_EC_I_O_EOP && 05940 current_statement->handler1) { 05941 if (CB_CAST_P(opt)) { 05942 val = CB_INTEGER(CB_BINARY_OP(CB_CAST(opt)->val)->x)->val; 05943 val |= COB_WRITE_EOP; 05944 CB_BINARY_OP(CB_CAST(opt)->val)->x = cb_int (val); 05945 } else { 05946 val = CB_INTEGER(opt)->val; 05947 val |= COB_WRITE_EOP; 05948 opt = cb_int (val); 05949 } 05950 } 05951 cb_emit (cb_build_funcall_4 ("cob_write", file, record, opt, 05952 CB_FILE(file)->file_status)); 05953 } 05954 } 05955 05956 cb_tree 05957 cb_build_write_advancing_lines (cb_tree pos, cb_tree lines) 05958 { 05959 cb_tree e; 05960 int opt; 05961 05962 opt = (pos == CB_BEFORE) ? COB_WRITE_BEFORE : COB_WRITE_AFTER; 05963 e = cb_build_binary_op (cb_int (opt | COB_WRITE_LINES), '+', lines); 05964 return cb_build_cast_integer (e); 05965 } 05966 05967 cb_tree 05968 cb_build_write_advancing_mnemonic (cb_tree pos, cb_tree mnemonic) 05969 { 05970 int opt; 05971 int token; 05972 05973 token = CB_SYSTEM_NAME (cb_ref (mnemonic))->token; 05974 switch (token) { 05975 case CB_FEATURE_FORMFEED: 05976 opt = (pos == CB_BEFORE) ? COB_WRITE_BEFORE : COB_WRITE_AFTER; 05977 return cb_int (opt | COB_WRITE_PAGE); 05978 case CB_FEATURE_C01: 05979 case CB_FEATURE_C02: 05980 case CB_FEATURE_C03: 05981 case CB_FEATURE_C04: 05982 case CB_FEATURE_C05: 05983 case CB_FEATURE_C06: 05984 case CB_FEATURE_C07: 05985 case CB_FEATURE_C08: 05986 case CB_FEATURE_C09: 05987 case CB_FEATURE_C10: 05988 case CB_FEATURE_C11: 05989 case CB_FEATURE_C12: 05990 opt = (pos == CB_BEFORE) ? COB_WRITE_BEFORE : COB_WRITE_AFTER; 05991 return cb_int (opt | COB_WRITE_CHANNEL | COB_WRITE_PAGE | token); 05992 default: 05993 cb_error_x (mnemonic, _("Invalid mnemonic name")); 05994 return cb_error_node; 05995 } 05996 } 05997 05998 cb_tree 05999 cb_build_write_advancing_page (cb_tree pos) 06000 { 06001 int opt = (pos == CB_BEFORE) ? COB_WRITE_BEFORE : COB_WRITE_AFTER; 06002 06003 return cb_int (opt | COB_WRITE_PAGE); 06004 }