OpenCOBOL 1.1pre-rel
typeck.c
Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines