OpenCOBOL 1.1pre-rel
tree.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 
00028 #include "cobc.h"
00029 #include "tree.h"
00030 
00031 #define PIC_ALPHABETIC          0x01
00032 #define PIC_NUMERIC             0x02
00033 #define PIC_NATIONAL            0x04
00034 #define PIC_EDITED              0x08
00035 #define PIC_ALPHANUMERIC        (PIC_ALPHABETIC | PIC_NUMERIC)
00036 #define PIC_ALPHABETIC_EDITED   (PIC_ALPHABETIC | PIC_EDITED)
00037 #define PIC_ALPHANUMERIC_EDITED (PIC_ALPHANUMERIC | PIC_EDITED)
00038 #define PIC_NUMERIC_EDITED      (PIC_NUMERIC | PIC_EDITED)
00039 #define PIC_NATIONAL_EDITED     (PIC_NATIONAL | PIC_EDITED)
00040 
00041 /* Local variables */
00042 
00043 static const enum cb_class category_to_class_table[] = {
00044         CB_CLASS_UNKNOWN,       /* CB_CATEGORY_UNKNOWN */
00045         CB_CLASS_ALPHABETIC,    /* CB_CATEGORY_ALPHABETIC */
00046         CB_CLASS_ALPHANUMERIC,  /* CB_CATEGORY_ALPHANUMERIC */
00047         CB_CLASS_ALPHANUMERIC,  /* CB_CATEGORY_ALPHANUMERIC_EDITED */
00048         CB_CLASS_BOOLEAN,       /* CB_CATEGORY_BOOLEAN */
00049         CB_CLASS_INDEX,         /* CB_CATEGORY_INDEX */
00050         CB_CLASS_NATIONAL,      /* CB_CATEGORY_NATIONAL */
00051         CB_CLASS_NATIONAL,      /* CB_CATEGORY_NATIONAL_EDITED */
00052         CB_CLASS_NUMERIC,       /* CB_CATEGORY_NUMERIC */
00053         CB_CLASS_ALPHANUMERIC,  /* CB_CATEGORY_NUMERIC_EDITED */
00054         CB_CLASS_OBJECT,        /* CB_CATEGORY_OBJECT_REFERENCE */
00055         CB_CLASS_POINTER,       /* CB_CATEGORY_DATA_POINTER */
00056         CB_CLASS_POINTER,       /* CB_CATEGORY_PROGRAM_POINTER */
00057 };
00058 
00059 static struct int_node {
00060         struct int_node *next;
00061         cb_tree         node;
00062         int             n;
00063 } *int_node_table = NULL;
00064 
00065 static char     *treenamebuff = NULL;
00066 static int      filler_id = 1;
00067 
00068 /* Global variables */
00069 
00070 /*
00071  * Constants
00072  */
00073 
00074 cb_tree cb_any;
00075 cb_tree cb_true;
00076 cb_tree cb_false;
00077 cb_tree cb_null;
00078 cb_tree cb_zero;
00079 cb_tree cb_one;
00080 cb_tree cb_space;
00081 cb_tree cb_low;
00082 cb_tree cb_high;
00083 cb_tree cb_norm_low;
00084 cb_tree cb_norm_high;
00085 cb_tree cb_quote;
00086 cb_tree cb_int0;
00087 cb_tree cb_int1;
00088 cb_tree cb_int2;
00089 cb_tree cb_int3;
00090 cb_tree cb_int4;
00091 cb_tree cb_int5;
00092 cb_tree cb_i[8];
00093 cb_tree cb_error_node;
00094 
00095 cb_tree cb_intr_whencomp;
00096 cb_tree cb_intr_pi;
00097 cb_tree cb_intr_e;
00098 
00099 cb_tree cb_standard_error_handler;
00100 
00101 size_t  gen_screen_ptr = 0;
00102 
00103 /* Local functions */
00104 
00105 static char *
00106 to_cname (const char *s)
00107 {
00108         char            *copy;
00109         unsigned char   *p;
00110 
00111         copy = strdup (s);
00112         for (p = (unsigned char *)copy; *p; p++) {
00113                 *p = (*p == '-') ? '_' : toupper (*p);
00114         }
00115         return copy;
00116 }
00117 
00118 static size_t
00119 hash (const unsigned char *s)
00120 {
00121         size_t val = 0;
00122 
00123         for (; *s; s++) {
00124                 val += toupper (*s);
00125         }
00126         return val % CB_WORD_HASH_SIZE;
00127 }
00128 
00129 static struct cb_word *
00130 lookup_word (const char *name)
00131 {
00132         struct cb_word  *p;
00133         size_t          val;
00134 
00135         val = hash ((const unsigned char *)name);
00136         /* find the existing word */
00137         if (current_program) {
00138                 for (p = current_program->word_table[val]; p; p = p->next) {
00139                         if (strcasecmp (p->name, name) == 0) {
00140                                 return p;
00141                         }
00142                 }
00143         }
00144 
00145         /* create new word */
00146         p = cobc_malloc (sizeof (struct cb_word));
00147         p->name = strdup (name);
00148 
00149         /* insert it into the table */
00150         if (current_program) {
00151                 p->next = current_program->word_table[val];
00152                 current_program->word_table[val] = p;
00153         }
00154 
00155         return p;
00156 }
00157 
00158 static void
00159 file_error (cb_tree name, const char *clause)
00160 {
00161         cb_error_x (name, _("%s clause is required for file '%s'"), clause,
00162                     CB_NAME (name));
00163 }
00164 
00165 /*
00166  * Tree
00167  */
00168 
00169 static void *
00170 make_tree (int tag, enum cb_category category, size_t size)
00171 {
00172         cb_tree x;
00173 
00174         x = cobc_malloc (size);
00175         x->tag = tag;
00176         x->category = category;
00177         return x;
00178 }
00179 
00180 static cb_tree
00181 make_constant (enum cb_category category, const char *val)
00182 {
00183         struct cb_const *p;
00184 
00185         p = make_tree (CB_TAG_CONST, category, sizeof (struct cb_const));
00186         p->val = val;
00187         return CB_TREE (p);
00188 }
00189 
00190 static cb_tree
00191 make_constant_label (const char *name)
00192 {
00193         struct cb_label *p;
00194 
00195         p = CB_LABEL (cb_build_label (cb_build_reference (name), NULL));
00196         p->need_begin = 1;
00197         return CB_TREE (p);
00198 }
00199 
00200 static int
00201 cb_name_1 (char *s, cb_tree x)
00202 {
00203         char                    *orig;
00204         struct cb_funcall       *cbip;
00205         struct cb_binary_op     *cbop;
00206         struct cb_reference     *p;
00207         struct cb_intrinsic     *cbit;
00208         cb_tree                 l;
00209         int                     i;
00210 
00211         orig = s;
00212         switch (CB_TREE_TAG (x)) {
00213         case CB_TAG_CONST:
00214                 if (x == cb_any) {
00215                         strcpy (s, "ANY");
00216                 } else if (x == cb_true) {
00217                         strcpy (s, "TRUE");
00218                 } else if (x == cb_false) {
00219                         strcpy (s, "FALSE");
00220                 } else if (x == cb_null) {
00221                         strcpy (s, "NULL");
00222                 } else if (x == cb_zero) {
00223                         strcpy (s, "ZERO");
00224                 } else if (x == cb_space) {
00225                         strcpy (s, "SPACE");
00226                 } else if (x == cb_low || x == cb_norm_low) {
00227                         strcpy (s, "LOW-VALUE");
00228                 } else if (x == cb_high || x == cb_norm_high) {
00229                         strcpy (s, "HIGH-VALUE");
00230                 } else if (x == cb_quote) {
00231                         strcpy (s, "QUOTE");
00232                 } else if (x == cb_error_node) {
00233                         strcpy (s, "Internal error node");
00234                 } else {
00235                         strcpy (s, "#<unknown constant>");
00236                 }
00237                 break;
00238 
00239         case CB_TAG_LITERAL:
00240                 if (CB_TREE_CLASS (x) == CB_CLASS_NUMERIC) {
00241                         strcpy (s, (char *)CB_LITERAL (x)->data);
00242                 } else {
00243                         sprintf (s, "\"%s\"", CB_LITERAL (x)->data);
00244                 }
00245                 break;
00246 
00247         case CB_TAG_FIELD:
00248                 strcpy (s, CB_FIELD (x)->name);
00249                 break;
00250 
00251         case CB_TAG_REFERENCE:
00252                 p = CB_REFERENCE (x);
00253                 s += sprintf (s, "%s", p->word->name);
00254                 if (p->subs) {
00255                         l = p->subs = cb_list_reverse (p->subs);
00256                         s += sprintf (s, " (");
00257                         for (; l; l = CB_CHAIN (l)) {
00258                                 s += cb_name_1 (s, CB_VALUE (l));
00259                                 s += sprintf (s, CB_CHAIN (l) ? ", " : ")");
00260                         }
00261                         p->subs = cb_list_reverse (p->subs);
00262                 }
00263                 if (p->offset) {
00264                         s += sprintf (s, " (");
00265                         s += cb_name_1 (s, p->offset);
00266                         s += sprintf (s, ":");
00267                         if (p->length) {
00268                                 s += cb_name_1 (s, p->length);
00269                         }
00270                         strcpy (s, ")");
00271                 }
00272                 if (p->chain) {
00273                         s += sprintf (s, " in ");
00274                         s += cb_name_1 (s, p->chain);
00275                 }
00276                 break;
00277 
00278         case CB_TAG_LABEL:
00279                 sprintf (s, "%s", CB_LABEL (x)->name);
00280                 break;
00281 
00282         case CB_TAG_ALPHABET_NAME:
00283                 sprintf (s, "%s", CB_ALPHABET_NAME (x)->name);
00284                 break;
00285 
00286         case CB_TAG_CLASS_NAME:
00287                 sprintf (s, "%s", CB_CLASS_NAME (x)->name);
00288                 break;
00289 
00290         case CB_TAG_LOCALE_NAME:
00291                 sprintf (s, "%s", CB_LOCALE_NAME (x)->name);
00292                 break;
00293 
00294         case CB_TAG_BINARY_OP:
00295                 cbop = CB_BINARY_OP (x);
00296                 if (cbop->op == '@') {
00297                         s += sprintf (s, "(");
00298                         s += cb_name_1 (s, cbop->x);
00299                         s += sprintf (s, ")");
00300                 } else if (cbop->op == '!') {
00301                         s += sprintf (s, "!");
00302                         s += cb_name_1 (s, cbop->x);
00303                 } else {
00304                         s += sprintf (s, "(");
00305                         s += cb_name_1 (s, cbop->x);
00306                         s += sprintf (s, " %c ", cbop->op);
00307                         s += cb_name_1 (s, cbop->y);
00308                         strcpy (s, ")");
00309                 }
00310                 break;
00311 
00312         case CB_TAG_FUNCALL:
00313                 cbip = CB_FUNCALL (x);
00314                 s += sprintf (s, "%s", cbip->name);
00315                 for (i = 0; i < cbip->argc; i++) {
00316                         s += sprintf (s, (i == 0) ? "(" : ", ");
00317                         s += cb_name_1 (s, cbip->argv[i]);
00318                 }
00319                 s += sprintf (s, ")");
00320                 break;
00321 
00322         case CB_TAG_INTRINSIC:
00323                 cbit = CB_INTRINSIC (x);
00324                 sprintf (s, "FUNCTION %s", cbit->intr_tab->name);
00325                 break;
00326         default:
00327                 sprintf (s, "#<unknown %d %p>", CB_TREE_TAG (x), x);
00328         }
00329 
00330         return strlen (orig);
00331 }
00332 
00333 static cb_tree
00334 make_intrinsic (cb_tree name, struct cb_intrinsic_table *cbp, cb_tree args,
00335                 cb_tree field, cb_tree refmod)
00336 {
00337         struct cb_intrinsic *x;
00338 
00339 /* Leave in, we may need this
00340         cb_tree                 l;
00341         for (l = args; l; l = CB_CHAIN(l)) {
00342                 switch (CB_TREE_TAG (CB_VALUE(l))) {
00343                 case CB_TAG_CONST:
00344                 case CB_TAG_INTEGER:
00345                 case CB_TAG_LITERAL:
00346                 case CB_TAG_DECIMAL:
00347                 case CB_TAG_FIELD:
00348                 case CB_TAG_REFERENCE:
00349                 case CB_TAG_INTRINSIC:
00350                         break;
00351                 default:
00352                         cb_error (_("FUNCTION %s has invalid/not supported arguments - Tag %d"),
00353                                 cbp->name, CB_TREE_TAG(l));
00354                         return cb_error_node;
00355 
00356                 }
00357         }
00358 */
00359         x = make_tree (CB_TAG_INTRINSIC, cbp->category, sizeof (struct cb_intrinsic));
00360         x->name = name;
00361         x->args = args;
00362         x->intr_tab = cbp;
00363         x->intr_field = field;
00364         if (refmod) {
00365                 x->offset = CB_PAIR_X (refmod);
00366                 x->length = CB_PAIR_Y (refmod);
00367         }
00368         return CB_TREE (x);
00369 }
00370 
00371 static cb_tree
00372 global_check (struct cb_reference *r, cb_tree items, size_t *ambiguous)
00373 {
00374         cb_tree                 candidate = NULL;
00375         struct cb_field         *p;
00376         cb_tree                 v;
00377         cb_tree                 c;
00378 
00379         for (; items; items = CB_CHAIN (items)) {
00380                 /* find a candidate value by resolving qualification */
00381                 v = CB_VALUE (items);
00382                 c = r->chain;
00383                 if (CB_FIELD_P (v)) {
00384                         if (!CB_FIELD (v)->flag_is_global) {
00385                                 continue;
00386                         }
00387                         /* in case the value is a field, it might be qualified
00388                            by its parent names and a file name */
00389                         if (CB_FIELD (v)->flag_indexed_by) {
00390                                 p = CB_FIELD (v)->index_qual;
00391                         } else {
00392                                 p = CB_FIELD (v)->parent;
00393                         }
00394                         /* resolve by parents */
00395                         for (; p; p = p->parent) {
00396                                 if (c && strcasecmp (CB_NAME (c), p->name) == 0) {
00397                                         c = CB_REFERENCE (c)->chain;
00398                                 }
00399                         }
00400 
00401                         /* resolve by file */
00402                         if (c && CB_REFERENCE (c)->chain == NULL) {
00403                                 if (CB_REFERENCE (c)->word->count == 1 && CB_FILE_P (cb_ref (c))
00404                                     && (CB_FILE (cb_ref (c)) == cb_field_founder (CB_FIELD (v))->file)) {
00405                                         c = CB_REFERENCE (c)->chain;
00406                                 }
00407                         }
00408                 }
00409                 /* a well qualified value is a good candidate */
00410                 if (c == NULL) {
00411                         if (candidate == NULL) {
00412                                 /* keep the first candidate */
00413                                 candidate = v;
00414                         } else {
00415                                 /* multiple candidates and possibly ambiguous */
00416                                 *ambiguous = 1;
00417                         }
00418                 }
00419         }
00420         return candidate;
00421 }
00422 
00423 /* Global functions */
00424 
00425 struct cb_literal *
00426 build_literal (enum cb_category category, const unsigned char *data, size_t size)
00427 {
00428         struct cb_literal *p;
00429 
00430         p = make_tree (CB_TAG_LITERAL, category, sizeof (struct cb_literal));
00431         p->data = cobc_malloc ((size_t) (size + 1));
00432         p->size = size;
00433         memcpy (p->data, data, (size_t) size);
00434         /* RXW - malloc zeroes
00435         p->data[size] = 0;
00436         */
00437         return p;
00438 }
00439 
00440 char *
00441 cb_name (cb_tree x)
00442 {
00443         if (!treenamebuff) {
00444                 treenamebuff = cobc_malloc (COB_NORMAL_BUFF);
00445         }
00446         cb_name_1 (treenamebuff, x);
00447         return treenamebuff;
00448 }
00449 
00450 enum cb_class
00451 cb_tree_class (cb_tree x)
00452 {
00453 
00454         return category_to_class_table[CB_TREE_CATEGORY (x)];
00455 }
00456 
00457 enum cb_category
00458 cb_tree_category (cb_tree x)
00459 {
00460         struct cb_cast          *p;
00461         struct cb_reference     *r;
00462         struct cb_field         *f;
00463 
00464         if (x == cb_error_node) {
00465                 return 0;
00466         }
00467         if (x->category != CB_CATEGORY_UNKNOWN) {
00468                 return x->category;
00469         }
00470 
00471         switch (CB_TREE_TAG (x)) {
00472         case CB_TAG_CAST:
00473                 p = CB_CAST (x);
00474                 switch (p->type) {
00475                 case CB_CAST_ADDRESS:
00476                 case CB_CAST_ADDR_OF_ADDR:
00477                         x->category = CB_CATEGORY_DATA_POINTER;
00478                         break;
00479                 case CB_CAST_PROGRAM_POINTER:
00480                         x->category = CB_CATEGORY_PROGRAM_POINTER;
00481                         break;
00482                 default:
00483                         fprintf (stderr, "Unexpected cast type -> %d\n", p->type);
00484                         ABORT ();
00485                 }
00486                 break;
00487         case CB_TAG_REFERENCE:
00488                 r = CB_REFERENCE (x);
00489                 if (r->offset) {
00490                         x->category = CB_CATEGORY_ALPHANUMERIC;
00491                 } else {
00492                         x->category = cb_tree_category (r->value);
00493                 }
00494                 break;
00495         case CB_TAG_FIELD:
00496                 f = CB_FIELD (x);
00497                 if (f->children) {
00498                         x->category = CB_CATEGORY_ALPHANUMERIC;
00499                 } else if (f->usage == CB_USAGE_POINTER && f->level != 88) {
00500                         x->category = CB_CATEGORY_DATA_POINTER;
00501                 } else if (f->usage == CB_USAGE_PROGRAM_POINTER && f->level != 88) {
00502                         x->category = CB_CATEGORY_PROGRAM_POINTER;
00503                 } else {
00504                         switch (f->level) {
00505                         case 66:
00506                                 if (f->rename_thru) {
00507                                         x->category = CB_CATEGORY_ALPHANUMERIC;
00508                                 } else {
00509                                         x->category = cb_tree_category (CB_TREE (f->redefines));
00510                                 }
00511                                 break;
00512                         case 88:
00513                                 x->category = CB_CATEGORY_BOOLEAN;
00514                                 break;
00515                         default:
00516                                 x->category = f->pic->category;
00517                                 break;
00518                         }
00519                 }
00520                 break;
00521         case CB_TAG_ALPHABET_NAME:
00522         case CB_TAG_LOCALE_NAME:
00523                 x->category = CB_CATEGORY_ALPHANUMERIC;
00524                 break;
00525         case CB_TAG_BINARY_OP:
00526                 x->category = CB_CATEGORY_BOOLEAN;
00527                 break;
00528         default:
00529                 fprintf (stderr, "Unknown tree tag %d Category %d\n", CB_TREE_TAG (x), x->category);
00530                 ABORT ();
00531         }
00532 
00533         return x->category;
00534 }
00535 
00536 int
00537 cb_tree_type (cb_tree x)
00538 {
00539         struct cb_field *f;
00540 
00541         f = cb_field (x);
00542         if (f->children) {
00543                 return COB_TYPE_GROUP;
00544         }
00545 
00546         switch (CB_TREE_CATEGORY (x)) {
00547         case CB_CATEGORY_ALPHABETIC:
00548         case CB_CATEGORY_ALPHANUMERIC:
00549                 return COB_TYPE_ALPHANUMERIC;
00550         case CB_CATEGORY_ALPHANUMERIC_EDITED:
00551                 return COB_TYPE_ALPHANUMERIC_EDITED;
00552         case CB_CATEGORY_NUMERIC:
00553                 switch (f->usage) {
00554                 case CB_USAGE_DISPLAY:
00555                         return COB_TYPE_NUMERIC_DISPLAY;
00556                 case CB_USAGE_BINARY:
00557                 case CB_USAGE_COMP_5:
00558                 case CB_USAGE_COMP_X:
00559                 case CB_USAGE_INDEX:
00560                 case CB_USAGE_LENGTH:
00561                         return COB_TYPE_NUMERIC_BINARY;
00562                 case CB_USAGE_FLOAT:
00563                         return COB_TYPE_NUMERIC_FLOAT;
00564                 case CB_USAGE_DOUBLE:
00565                         return COB_TYPE_NUMERIC_DOUBLE;
00566                 case CB_USAGE_PACKED:
00567                         return COB_TYPE_NUMERIC_PACKED;
00568                 default:
00569                         fprintf (stderr, "Unexpected numeric usage -> %d\n", f->usage);
00570                         ABORT ();
00571                 }
00572         case CB_CATEGORY_NUMERIC_EDITED:
00573                 return COB_TYPE_NUMERIC_EDITED;
00574         case CB_CATEGORY_OBJECT_REFERENCE:
00575         case CB_CATEGORY_DATA_POINTER:
00576         case CB_CATEGORY_PROGRAM_POINTER:
00577                 return COB_TYPE_NUMERIC_BINARY;
00578         default:
00579                 fprintf (stderr, "Unexpected category -> %d\n", CB_TREE_CATEGORY (x));
00580                 ABORT ();
00581         }
00582 /* NOT REACHED */
00583         return 0;
00584 }
00585 
00586 int
00587 cb_fits_int (cb_tree x)
00588 {
00589         struct cb_literal       *l;
00590         struct cb_field         *f;
00591 
00592         switch (CB_TREE_TAG (x)) {
00593         case CB_TAG_LITERAL:
00594                 l = CB_LITERAL (x);
00595                 if (l->scale <= 0 && l->size < 10) {
00596                         return 1;
00597                 }
00598                 return 0;
00599         case CB_TAG_FIELD:
00600                 f = CB_FIELD (x);
00601                 switch (f->usage) {
00602                 case CB_USAGE_INDEX:
00603                 case CB_USAGE_LENGTH:
00604                         return 1;
00605                 case CB_USAGE_BINARY:
00606                 case CB_USAGE_COMP_5:
00607                 case CB_USAGE_COMP_X:
00608                         if (f->pic->scale <= 0 && f->size <= (int)sizeof (int)) {
00609                                 return 1;
00610                         }
00611                         return 0;
00612                 case CB_USAGE_DISPLAY:
00613                         if (f->size < 10) {
00614                                 if (!f->pic || f->pic->scale <= 0) {
00615                                         return 1;
00616                                 }
00617                         }
00618                         return 0;
00619                 case CB_USAGE_PACKED:
00620                         if (f->pic->scale <= 0 && f->pic->digits < 10) {
00621                                 return 1;
00622                         }
00623                         return 0;
00624                 default:
00625                         return 0;
00626                 }
00627         case CB_TAG_REFERENCE:
00628                 return cb_fits_int (CB_REFERENCE (x)->value);
00629         default:
00630                 return 0;
00631         }
00632 }
00633 
00634 int
00635 cb_fits_long_long (cb_tree x)
00636 {
00637         struct cb_literal       *l;
00638         struct cb_field         *f;
00639 
00640         switch (CB_TREE_TAG (x)) {
00641         case CB_TAG_LITERAL:
00642                 l = CB_LITERAL (x);
00643                 if (l->scale <= 0 && l->size < 19) {
00644                         return 1;
00645                 }
00646                 return 0;
00647         case CB_TAG_FIELD:
00648                 f = CB_FIELD (x);
00649                 switch (f->usage) {
00650                 case CB_USAGE_INDEX:
00651                 case CB_USAGE_LENGTH:
00652                         return 1;
00653                 case CB_USAGE_BINARY:
00654                 case CB_USAGE_COMP_5:
00655                 case CB_USAGE_COMP_X:
00656                         if (f->pic->scale <= 0 && f->size <= (int)sizeof (long long)) {
00657                                 return 1;
00658                         }
00659                         return 0;
00660                 case CB_USAGE_DISPLAY:
00661                         if (f->pic->scale <= 0 && f->size < 19) {
00662                                 return 1;
00663                         }
00664                         return 0;
00665                 default:
00666                         return 0;
00667                 }
00668         case CB_TAG_REFERENCE:
00669                 return cb_fits_long_long (CB_REFERENCE (x)->value);
00670         default:
00671                 return 0;
00672         }
00673 }
00674 
00675 int
00676 cb_get_int (cb_tree x)
00677 {
00678         struct cb_literal       *l;
00679         size_t                  i;
00680         int                     val = 0;
00681 
00682         l = CB_LITERAL (x);
00683         for (i = 0; i < l->size; i++) {
00684                 if (l->data[i] != '0') {
00685                         break;
00686                 }
00687         }
00688 
00689 /* RXWRXW
00690         if (l->size - i >= 10) {
00691                 ABORT ();
00692         }
00693 */
00694 
00695         for (; i < l->size; i++) {
00696                 val = val * 10 + l->data[i] - '0';
00697         }
00698         if (l->sign < 0) {
00699                 val = -val;
00700         }
00701         return val;
00702 }
00703 
00704 long long
00705 cb_get_long_long (cb_tree x)
00706 {
00707         struct cb_literal       *l;
00708         size_t                  i;
00709         long long               val = 0;
00710 
00711         l = CB_LITERAL (x);
00712         for (i = 0; i < l->size; i++) {
00713                 if (l->data[i] != '0') {
00714                         break;
00715                 }
00716         }
00717 
00718         if (l->size - i >= 19) {
00719                 ABORT ();
00720         }
00721 
00722         for (; i < l->size; i++) {
00723                 val = val * 10 + l->data[i] - '0';
00724         }
00725         if (l->sign < 0) {
00726                 val = -val;
00727         }
00728         return val;
00729 }
00730 
00731 void
00732 cb_init_constants (void)
00733 {
00734         char    *s;
00735         int     i;
00736 
00737         cb_error_node = make_constant (CB_CATEGORY_UNKNOWN, NULL);
00738         cb_any = make_constant (CB_CATEGORY_UNKNOWN, NULL);
00739         cb_true = make_constant (CB_CATEGORY_BOOLEAN, "1");
00740         cb_false = make_constant (CB_CATEGORY_BOOLEAN, "0");
00741         cb_null = make_constant (CB_CATEGORY_DATA_POINTER, "0");
00742         cb_zero = make_constant (CB_CATEGORY_NUMERIC, "&cob_zero");
00743         cb_one = make_constant (CB_CATEGORY_NUMERIC, "&cob_one");
00744         cb_space = make_constant (CB_CATEGORY_ALPHANUMERIC, "&cob_space");
00745         cb_low = make_constant (CB_CATEGORY_ALPHANUMERIC, "&cob_low");
00746         cb_norm_low = cb_low;
00747         cb_high = make_constant (CB_CATEGORY_ALPHANUMERIC, "&cob_high");
00748         cb_norm_high = cb_high;
00749         cb_quote = make_constant (CB_CATEGORY_ALPHANUMERIC, "&cob_quote");
00750         cb_int0 = cb_int (0);
00751         cb_int1 = cb_int (1);
00752         cb_int2 = cb_int (2);
00753         cb_int3 = cb_int (3);
00754         cb_int4 = cb_int (4);
00755         cb_int5 = cb_int (5);
00756         for (i = 1; i < 8; i++) {
00757                 s = cobc_malloc (4);
00758                 sprintf (s, "i%d", i);
00759                 cb_i[i] = make_constant (CB_CATEGORY_NUMERIC, s);
00760         }
00761         cb_standard_error_handler = make_constant_label ("Default Error Handler");
00762 }
00763 
00764 /*
00765  * List
00766  */
00767 
00768 cb_tree
00769 cb_build_list (cb_tree purpose, cb_tree value, cb_tree rest)
00770 {
00771         struct cb_list *p;
00772 
00773         p = make_tree (CB_TAG_LIST, CB_CATEGORY_UNKNOWN, sizeof (struct cb_list));
00774         p->purpose = purpose;
00775         p->value = value;
00776         p->chain = rest;
00777         return CB_TREE (p);
00778 }
00779 
00780 cb_tree
00781 cb_list_append (cb_tree l1, cb_tree l2)
00782 {
00783         cb_tree l;
00784 
00785         if (l1 == NULL) {
00786                 return l2;
00787         } else {
00788                 l = l1;
00789                 while (CB_CHAIN (l)) {
00790                         l = CB_CHAIN (l);
00791                 }
00792                 CB_CHAIN (l) = l2;
00793                 return l1;
00794         }
00795 }
00796 
00797 cb_tree
00798 cb_list_add (cb_tree l, cb_tree x)
00799 {
00800         return cb_list_append (l, cb_list_init (x));
00801 }
00802 
00803 cb_tree
00804 cb_list_reverse (cb_tree l)
00805 {
00806         cb_tree next;
00807         cb_tree last = NULL;
00808 
00809         for (; l; l = next) {
00810                 next = CB_CHAIN (l);
00811                 CB_CHAIN (l) = last;
00812                 last = l;
00813         }
00814         return last;
00815 }
00816 
00817 int
00818 cb_list_length (cb_tree l)
00819 {
00820         int n = 0;
00821 
00822         for (; l; l = CB_CHAIN (l)) {
00823                 n++;
00824         }
00825         return n;
00826 }
00827 
00828 void
00829 cb_list_map (cb_tree (*func) (cb_tree x), cb_tree l)
00830 {
00831         for (; l; l = CB_CHAIN (l)) {
00832                 CB_VALUE (l) = func (CB_VALUE (l));
00833         }
00834 }
00835 
00836 /*
00837  * Program
00838  */
00839 
00840 struct cb_program *
00841 cb_build_program (struct cb_program *last_program, int nest_level)
00842 {
00843         struct cb_program *p;
00844 
00845         cb_reset_78 ();
00846         cb_reset_in_procedure ();
00847         cb_clear_real_field ();
00848         p = cobc_malloc (sizeof (struct cb_program));
00849         p->next_program = last_program;
00850         p->nested_level = nest_level;
00851         p->decimal_point = '.';
00852         p->currency_symbol = '$';
00853         p->numeric_separator = ',';
00854         if (nest_level) {
00855                 p->global_file_list = last_program->global_file_list;
00856                 p->collating_sequence = last_program->collating_sequence;
00857                 p->function_spec_list = last_program->function_spec_list;
00858                 p->class_spec_list = last_program->class_spec_list;
00859                 p->interface_spec_list = last_program->interface_spec_list;
00860                 p->program_spec_list = last_program->program_spec_list;
00861                 p->property_spec_list = last_program->property_spec_list;
00862                 p->alphabet_name_list = last_program->alphabet_name_list;
00863                 p->class_name_list = last_program->class_name_list;
00864                 p->locale_list = last_program->locale_list;
00865                 p->symbolic_list = last_program->symbolic_list;
00866                 p->decimal_point = last_program->decimal_point;
00867                 p->numeric_separator = last_program->numeric_separator;
00868                 p->currency_symbol = last_program->currency_symbol;
00869                 p->cb_return_code = last_program->cb_return_code;
00870         } else {
00871                 functions_are_all = cb_flag_functions_all;
00872         }
00873         return p;
00874 }
00875 
00876 /*
00877  * Integer
00878  */
00879 
00880 cb_tree
00881 cb_int (int n)
00882 {
00883         struct cb_integer       *x;
00884         struct int_node         *p;
00885 
00886         for (p = int_node_table; p; p = p->next) {
00887                 if (p->n == n) {
00888                         return p->node;
00889                 }
00890         }
00891 
00892         x = make_tree (CB_TAG_INTEGER, CB_CATEGORY_NUMERIC, sizeof (struct cb_integer));
00893         x->val = n;
00894 
00895         p = cobc_malloc (sizeof (struct int_node));
00896         p->n = n;
00897         p->node = CB_TREE (x);
00898         p->next = int_node_table;
00899         int_node_table = p;
00900         return p->node;
00901 }
00902 
00903 /*
00904  * String
00905  */
00906 
00907 cb_tree
00908 cb_build_string (const unsigned char *data, size_t size)
00909 {
00910         struct cb_string *p;
00911 
00912         p = make_tree (CB_TAG_STRING, CB_CATEGORY_ALPHANUMERIC, sizeof (struct cb_string));
00913         p->size = size;
00914         p->data = data;
00915         return CB_TREE (p);
00916 }
00917 
00918 /*
00919  * Alphabet-name
00920  */
00921 
00922 cb_tree
00923 cb_build_alphabet_name (cb_tree name, enum cb_alphabet_name_type type)
00924 {
00925         struct cb_alphabet_name *p;
00926 
00927         p = make_tree (CB_TAG_ALPHABET_NAME, CB_CATEGORY_UNKNOWN, sizeof (struct cb_alphabet_name));
00928         p->name = cb_define (name, CB_TREE (p));
00929         p->cname = to_cname (p->name);
00930         p->type = type;
00931         return CB_TREE (p);
00932 }
00933 
00934 /*
00935  * Class-name
00936  */
00937 
00938 cb_tree
00939 cb_build_class_name (cb_tree name, cb_tree list)
00940 {
00941         struct cb_class_name    *p;
00942         char                    buff[COB_MINI_BUFF];
00943 
00944         p = make_tree (CB_TAG_CLASS_NAME, CB_CATEGORY_BOOLEAN, sizeof (struct cb_class_name));
00945         p->name = cb_define (name, CB_TREE (p));
00946         snprintf (buff, COB_MINI_MAX, "is_%s", to_cname (p->name));
00947         p->cname = strdup (buff);
00948         p->list = list;
00949         return CB_TREE (p);
00950 }
00951 
00952 /*
00953  * Locale-name
00954  */
00955 
00956 cb_tree
00957 cb_build_locale_name (cb_tree name, cb_tree list)
00958 {
00959         struct cb_class_name    *p;
00960 
00961         p = make_tree (CB_TAG_LOCALE_NAME, CB_CATEGORY_UNKNOWN, sizeof (struct cb_locale_name));
00962         p->name = cb_define (name, CB_TREE (p));
00963         p->cname = to_cname (p->name);
00964         p->list = list;
00965         return CB_TREE (p);
00966 }
00967 
00968 /*
00969  * System-name
00970  */
00971 
00972 cb_tree
00973 cb_build_system_name (enum cb_system_name_category category, int token)
00974 {
00975         struct cb_system_name *p;
00976 
00977         p = make_tree (CB_TAG_SYSTEM_NAME, CB_CATEGORY_UNKNOWN, sizeof (struct cb_system_name));
00978         p->category = category;
00979         p->token = token;
00980         return CB_TREE (p);
00981 }
00982 
00983 /*
00984  * Literal
00985  */
00986 
00987 cb_tree
00988 cb_build_numeric_literal (int sign, const unsigned char *data, int scale)
00989 {
00990         struct cb_literal *p;
00991 
00992         p = build_literal (CB_CATEGORY_NUMERIC, data, strlen ((char *)data));
00993         p->sign = (char)sign;
00994         p->scale = (char)scale;
00995         return CB_TREE (p);
00996 }
00997 
00998 cb_tree
00999 cb_build_alphanumeric_literal (const unsigned char *data, size_t size)
01000 {
01001         return CB_TREE (build_literal (CB_CATEGORY_ALPHANUMERIC, data, size));
01002 }
01003 
01004 cb_tree
01005 cb_concat_literals (cb_tree x1, cb_tree x2)
01006 {
01007         unsigned char           *buff;
01008         cb_tree                 x;
01009         unsigned char           *data1;
01010         unsigned char           *data2;
01011         size_t                  size1;
01012         size_t                  size2;
01013 
01014         if (x1 == cb_error_node || x2 == cb_error_node) {
01015                 return cb_error_node;
01016         }
01017         if (CB_LITERAL_P (x1)) {
01018                 data1 = CB_LITERAL (x1)->data;
01019                 size1 = CB_LITERAL (x1)->size;
01020         } else if (CB_CONST_P (x1)) {
01021                 size1 = 1;
01022                 if (x1 == cb_space) {
01023                         data1 = (unsigned char *)" ";
01024                 } else if (x1 == cb_zero) {
01025                         data1 = (unsigned char *)"0";
01026                 } else if (x1 == cb_quote) {
01027                         data1 = (unsigned char *)"\"";
01028                 } else if (x1 == cb_norm_low) {
01029                         data1 = (unsigned char *)"\0";
01030                 } else if (x1 == cb_norm_high) {
01031                         data1 = (unsigned char *)"\255";
01032                 } else if (x1 == cb_null) {
01033                         data1 = (unsigned char *)"\0";
01034                 } else {
01035                         return cb_error_node;
01036                 }
01037         } else {
01038                 return cb_error_node;
01039         }
01040         if (CB_LITERAL_P (x2)) {
01041                 data2 = CB_LITERAL (x2)->data;
01042                 size2 = CB_LITERAL (x2)->size;
01043         } else if (CB_CONST_P (x2)) {
01044                 size2 = 1;
01045                 if (x2 == cb_space) {
01046                         data2 = (unsigned char *)" ";
01047                 } else if (x2 == cb_zero) {
01048                         data2 = (unsigned char *)"0";
01049                 } else if (x2 == cb_quote) {
01050                         data2 = (unsigned char *)"\"";
01051                 } else if (x2 == cb_norm_low) {
01052                         data2 = (unsigned char *)"\0";
01053                 } else if (x2 == cb_norm_high) {
01054                         data2 = (unsigned char *)"\255";
01055                 } else if (x2 == cb_null) {
01056                         data2 = (unsigned char *)"\0";
01057                 } else {
01058                         return cb_error_node;
01059                 }
01060         } else {
01061                 return cb_error_node;
01062         }
01063         buff = cobc_malloc (size1 + size2 + 3);
01064         memcpy (buff, data1, size1);
01065         memcpy (buff + size1, data2, size2);
01066         x = cb_build_alphanumeric_literal (buff, size1 + size2);
01067         free (buff);
01068         return x;
01069 }
01070 
01071 /*
01072  * Decimal
01073  */
01074 
01075 cb_tree
01076 cb_build_decimal (int id)
01077 {
01078         struct cb_decimal *p;
01079 
01080         p = make_tree (CB_TAG_DECIMAL, CB_CATEGORY_NUMERIC, sizeof (struct cb_decimal));
01081         p->id = id;
01082         return CB_TREE (p);
01083 }
01084 
01085 /*
01086  * Picture
01087  */
01088 
01089 cb_tree
01090 cb_build_picture (const char *str)
01091 {
01092         struct cb_picture       *pic;
01093         const char              *p;
01094         size_t                  idx = 0;
01095         size_t                  buffcnt = 0;
01096         size_t                  at_beginning;
01097         size_t                  at_end;
01098         size_t                  p_char_seen;
01099         size_t                  s_char_seen;
01100         int                     category = 0;
01101         int                     size = 0;
01102         int                     allocated = 0;
01103         int                     digits = 0;
01104         int                     scale = 0;
01105         int                     s_count = 0;
01106         int                     v_count = 0;
01107         int                     i;
01108         int                     n;
01109         unsigned char           c;
01110         unsigned char           lastonechar = 0;
01111         unsigned char           lasttwochar = 0;
01112         unsigned char           buff[COB_SMALL_BUFF];
01113 
01114         pic = make_tree (CB_TAG_PICTURE, CB_CATEGORY_UNKNOWN, sizeof (struct cb_picture));
01115         if (strlen (str) > 50) {
01116                 goto error;
01117         }
01118         memset (buff, 0, sizeof (buff));
01119         p_char_seen = 0;
01120         s_char_seen = 0;
01121         for (p = str; *p; p++) {
01122                 n = 1;
01123                 c = *p;
01124 repeat:
01125                 /* count the number of repeated chars */
01126                 while (p[1] == c) {
01127                         p++, n++;
01128                 }
01129 
01130                 /* add parenthesized numbers */
01131                 if (p[1] == '(') {
01132                         i = 0;
01133                         p += 2;
01134                         for (; *p == '0'; p++) {
01135                                 ;
01136                         }
01137                         for (; *p != ')'; p++) {
01138                                 if (!isdigit (*p)) {
01139                                         goto error;
01140                                 } else {
01141                                         allocated++;
01142                                         if (allocated > 9) {
01143                                                 goto error;
01144                                         }
01145                                         i = i * 10 + (*p - '0');
01146                                 }
01147                         }
01148                         if (i == 0) {
01149                                 goto error;
01150                         }
01151                         n += i - 1;
01152                         goto repeat;
01153                 }
01154 
01155                 /* check grammar and category */
01156                 /* FIXME: need more error check */
01157                 switch (c) {
01158                 case 'A':
01159                         if (s_char_seen || p_char_seen) {
01160                                 goto error;
01161                         }
01162                         category |= PIC_ALPHABETIC;
01163                         break;
01164 
01165                 case 'X':
01166                         if (s_char_seen || p_char_seen) {
01167                                 goto error;
01168                         }
01169                         category |= PIC_ALPHANUMERIC;
01170                         break;
01171 
01172                 case '9':
01173                         category |= PIC_NUMERIC;
01174                         digits += n;
01175                         if (v_count) {
01176                                 scale += n;
01177                         }
01178                         break;
01179 
01180                 case 'N':
01181                         if (s_char_seen || p_char_seen) {
01182                                 goto error;
01183                         }
01184                         category |= PIC_NATIONAL;
01185                         break;
01186 
01187                 case 'S':
01188                         category |= PIC_NUMERIC;
01189                         if (category & PIC_ALPHABETIC) {
01190                                 goto error;
01191                         }
01192                         s_count += n;
01193                         if (s_count > 1 || idx != 0) {
01194                                 goto error;
01195                         }
01196                         s_char_seen = 1;
01197                         continue;
01198 
01199                 case ',':
01200                 case '.':
01201                         category |= PIC_NUMERIC_EDITED;
01202                         if (s_char_seen || p_char_seen) {
01203                                 goto error;
01204                         }
01205                         if (c != current_program->decimal_point) {
01206                                 break;
01207                         }
01208                         /* fall through */
01209                 case 'V':
01210                         category |= PIC_NUMERIC;
01211                         if (category & PIC_ALPHABETIC) {
01212                                 goto error;
01213                         }
01214                         v_count += n;
01215                         if (v_count > 1) {
01216                                 goto error;
01217                         }
01218                         break;
01219 
01220                 case 'P':
01221                         category |= PIC_NUMERIC;
01222                         if (category & PIC_ALPHABETIC) {
01223                                 goto error;
01224                         }
01225                         if (p_char_seen) {
01226                                 goto error;
01227                         }
01228                         at_beginning = 0;
01229                         at_end = 0;
01230                         switch (buffcnt) {
01231                         case 0:
01232                                 /* P..... */
01233                                 at_beginning = 1;
01234                                 break;
01235                         case 1:
01236                                 /* VP.... */
01237                                 /* SP.... */
01238                                 if (lastonechar == 'V' || lastonechar == 'S') {
01239                                         at_beginning = 1;
01240                                 }
01241                                 break;
01242                         case 2:
01243                                 /* SVP... */
01244                                 if (lasttwochar == 'S' && lastonechar == 'V') {
01245                                         at_beginning = 1;
01246                                 }
01247                                 break;
01248                         }
01249                         if (p[1] == 0 || (p[1] == 'V' && p[2] == 0)) {
01250                                 /* .....P */
01251                                 /* ....PV */
01252                                 at_end = 1;
01253                         }
01254                         if (!at_beginning && !at_end) {
01255                                 goto error;
01256                         }
01257                         p_char_seen = 1;
01258                         if (at_beginning) {
01259                                 v_count++;      /* implicit V */
01260                         }
01261                         digits += n;
01262                         if (v_count) {
01263                                 scale += n;
01264                         } else {
01265                                 scale -= n;
01266                         }
01267                         break;
01268 
01269                 case '0':
01270                 case 'B':
01271                 case '/':
01272                         category |= PIC_EDITED;
01273                         if (s_char_seen || p_char_seen) {
01274                                 goto error;
01275                         }
01276                         break;
01277 
01278                 case '*':
01279                 case 'Z':
01280                         category |= PIC_NUMERIC_EDITED;
01281                         if (category & PIC_ALPHABETIC) {
01282                                 goto error;
01283                         }
01284                         if (s_char_seen || p_char_seen) {
01285                                 goto error;
01286                         }
01287                         digits += n;
01288                         if (v_count) {
01289                                 scale += n;
01290                         }
01291                         break;
01292 
01293                 case '+':
01294                 case '-':
01295                         category |= PIC_NUMERIC_EDITED;
01296                         if (category & PIC_ALPHABETIC) {
01297                                 goto error;
01298                         }
01299                         if (s_char_seen || p_char_seen) {
01300                                 goto error;
01301                         }
01302                         digits += n - 1;
01303                         s_count++;
01304                         /* FIXME: need more check */
01305                         break;
01306 
01307                 case 'C':
01308                         category |= PIC_NUMERIC_EDITED;
01309                         if (!(p[1] == 'R' && p[2] == 0)) {
01310                                 goto error;
01311                         }
01312                         if (s_char_seen || p_char_seen) {
01313                                 goto error;
01314                         }
01315                         p++;
01316                         s_count++;
01317                         break;
01318 
01319                 case 'D':
01320                         category |= PIC_NUMERIC_EDITED;
01321                         if (!(p[1] == 'B' && p[2] == 0)) {
01322                                 goto error;
01323                         }
01324                         if (s_char_seen || p_char_seen) {
01325                                 goto error;
01326                         }
01327                         p++;
01328                         s_count++;
01329                         break;
01330 
01331                 default:
01332                         if (c == current_program->currency_symbol) {
01333                                 category |= PIC_NUMERIC_EDITED;
01334                                 digits += n - 1;
01335                                 /* FIXME: need more check */
01336                                 break;
01337                         }
01338 
01339                         goto error;
01340                 }
01341 
01342                 /* calculate size */
01343                 if (c != 'V' && c != 'P') {
01344                         size += n;
01345                 }
01346                 if (c == 'C' || c == 'D' || c == 'N') {
01347                         size += n;
01348                 }
01349 
01350                 /* store in the buffer */
01351                 buff[idx++] = c;
01352                 lasttwochar = lastonechar;
01353                 lastonechar = c;
01354                 memcpy (&buff[idx], (unsigned char *)&n, sizeof(int));
01355                 idx += sizeof(int);
01356                 ++buffcnt;
01357         }
01358         buff[idx] = 0;
01359 
01360         if (size == 0 && v_count) {
01361                 goto error;
01362         }
01363         /* set picture */
01364         pic->orig = strdup (str);
01365         pic->size = size;
01366         pic->digits = (unsigned char)digits;
01367         pic->scale = (signed char)scale;
01368         pic->have_sign = (unsigned char)s_count;
01369 
01370         /* set picture category */
01371         switch (category) {
01372         case PIC_ALPHABETIC:
01373                 pic->category = CB_CATEGORY_ALPHABETIC;
01374                 break;
01375         case PIC_NUMERIC:
01376                 pic->category = CB_CATEGORY_NUMERIC;
01377                 if (digits > 36) {
01378                         cb_error (_("Numeric field cannot be larger than 36 digits"));
01379                 }
01380                 break;
01381         case PIC_ALPHANUMERIC:
01382         case PIC_NATIONAL:
01383                 pic->category = CB_CATEGORY_ALPHANUMERIC;
01384                 break;
01385         case PIC_NUMERIC_EDITED:
01386                 pic->str = cobc_malloc (idx + 1);
01387                 memcpy (pic->str, buff, idx);
01388                 pic->category = CB_CATEGORY_NUMERIC_EDITED;
01389                 pic->lenstr = idx;
01390                 break;
01391         case PIC_EDITED:
01392         case PIC_ALPHABETIC_EDITED:
01393         case PIC_ALPHANUMERIC_EDITED:
01394         case PIC_NATIONAL_EDITED:
01395                 pic->str = cobc_malloc (idx + 1);
01396                 memcpy (pic->str, buff, idx);
01397                 pic->category = CB_CATEGORY_ALPHANUMERIC_EDITED;
01398                 pic->lenstr = idx;
01399                 break;
01400         default:
01401                 goto error;
01402         }
01403         goto end;
01404 
01405 error:
01406         cb_error (_("Invalid picture string - '%s'"), str);
01407 
01408 end:
01409         return CB_TREE (pic);
01410 }
01411 
01412 /*
01413  * Field
01414  */
01415 
01416 cb_tree
01417 cb_build_field (cb_tree name)
01418 {
01419         struct cb_field *p;
01420 
01421         p = make_tree (CB_TAG_FIELD, CB_CATEGORY_UNKNOWN, sizeof (struct cb_field));
01422         p->id = cb_field_id++;
01423         p->name = cb_define (name, CB_TREE (p));
01424         p->ename = NULL;
01425         p->usage = CB_USAGE_DISPLAY;
01426         p->storage = CB_STORAGE_WORKING;
01427         p->occurs_max = 1;
01428         return CB_TREE (p);
01429 }
01430 
01431 cb_tree
01432 cb_build_implicit_field (cb_tree name, int len)
01433 {
01434         cb_tree x;
01435         char    pic[32];
01436 
01437         x = cb_build_field (name);
01438         memset (pic, 0, sizeof(pic));
01439         sprintf (pic, "X(%d)", len);
01440         CB_FIELD (x)->pic = CB_PICTURE (cb_build_picture (pic));
01441         cb_validate_field (CB_FIELD (x));
01442         return x;
01443 }
01444 
01445 cb_tree
01446 cb_build_constant (cb_tree name, cb_tree value)
01447 {
01448         cb_tree x;
01449 
01450         x = cb_build_field (name);
01451         x->category = cb_tree_category (value);
01452         CB_FIELD (x)->storage = CB_STORAGE_CONSTANT;
01453         CB_FIELD (x)->values = cb_list_init (value);
01454         return x;
01455 }
01456 
01457 struct cb_field *
01458 cb_field (cb_tree x)
01459 {
01460         if (CB_REFERENCE_P (x)) {
01461                 return CB_FIELD (cb_ref (x));
01462         } else {
01463                 return CB_FIELD (x);
01464         }
01465 }
01466 
01467 struct cb_field *
01468 cb_field_add (struct cb_field *f, struct cb_field *p)
01469 {
01470         struct cb_field *t;
01471 
01472         if (f == NULL) {
01473                 return p;
01474         }
01475         for (t = f; t->sister; t = t->sister) {
01476                 ;
01477         }
01478         t->sister = p;
01479         return f;
01480 }
01481 
01482 int
01483 cb_field_size (cb_tree x)
01484 {
01485         struct cb_reference     *r;
01486         struct cb_field         *f;
01487 
01488         switch (CB_TREE_TAG (x)) {
01489         case CB_TAG_LITERAL:
01490                 return CB_LITERAL (x)->size;
01491         case CB_TAG_FIELD:
01492                 return CB_FIELD (x)->size;
01493         case CB_TAG_REFERENCE:
01494                 r = CB_REFERENCE (x);
01495                 f = CB_FIELD (r->value);
01496 
01497                 if (r->length) {
01498                         if (CB_LITERAL_P (r->length)) {
01499                                 return cb_get_int (r->length);
01500                         } else {
01501                                 return -1;
01502                         }
01503                 } else if (r->offset) {
01504                         if (CB_LITERAL_P (r->offset)) {
01505                                 return f->size - cb_get_int (r->offset) + 1;
01506                         } else {
01507                                 return -1;
01508                         }
01509                 } else {
01510                         return f->size;
01511                 }
01512         default:
01513                 fprintf (stderr, "Unexpected tree tag %d\n", CB_TREE_TAG (x));
01514                 ABORT ();
01515         }
01516 /* NOT REACHED */
01517         return 0;
01518 }
01519 
01520 struct cb_field *
01521 cb_field_founder (struct cb_field *f)
01522 {
01523         while (f->parent) {
01524                 f = f->parent;
01525         }
01526         return f;
01527 }
01528 
01529 struct cb_field *
01530 cb_field_variable_size (struct cb_field *f)
01531 {
01532         struct cb_field *p;
01533 
01534         for (f = f->children; f; f = f->sister) {
01535                 if (f->occurs_depending) {
01536                         return f;
01537                 } else if ((p = cb_field_variable_size (f)) != NULL) {
01538                         return p;
01539                 }
01540         }
01541         return NULL;
01542 }
01543 
01544 struct cb_field *
01545 cb_field_variable_address (struct cb_field *f)
01546 {
01547         struct cb_field *p;
01548 
01549         for (p = f->parent; p; f = f->parent, p = f->parent) {
01550                 for (p = p->children; p != f; p = p->sister) {
01551                         if (p->occurs_depending || cb_field_variable_size (p)) {
01552                                 return p;
01553                         }
01554                 }
01555         }
01556         return NULL;
01557 }
01558 
01559 /* Return 1 if P is subordinate to F */
01560 
01561 int
01562 cb_field_subordinate (struct cb_field *p, struct cb_field *f)
01563 {
01564         for (p = p->parent; p; p = p->parent) {
01565                 if (p == f) {
01566                         return 1;
01567                 }
01568         }
01569         return 0;
01570 }
01571 
01572 /*
01573  * File
01574  */
01575 
01576 struct cb_file *
01577 build_file (cb_tree name)
01578 {
01579         struct cb_file *p;
01580 
01581         p = make_tree (CB_TAG_FILE, CB_CATEGORY_UNKNOWN, sizeof (struct cb_file));
01582         p->name = cb_define (name, CB_TREE (p));
01583         p->cname = to_cname (p->name);
01584 
01585         p->organization = COB_ORG_SEQUENTIAL;
01586         p->access_mode = COB_ACCESS_SEQUENTIAL;
01587         p->handler = CB_LABEL (cb_standard_error_handler);
01588         p->handler_prog = current_program;
01589         return p;
01590 }
01591 
01592 void
01593 validate_file (struct cb_file *f, cb_tree name)
01594 {
01595         /* check RECORD/RELATIVE KEY clause */
01596         switch (f->organization) {
01597         case COB_ORG_INDEXED:
01598                 if (f->key == NULL) {
01599                         file_error (name, "RECORD KEY");
01600                 }
01601                 break;
01602         case COB_ORG_RELATIVE:
01603                 if (f->key == NULL && f->access_mode != COB_ACCESS_SEQUENTIAL) {
01604                         file_error (name, "RELATIVE KEY");
01605                 }
01606                 break;
01607         }
01608 }
01609 
01610 void
01611 finalize_file (struct cb_file *f, struct cb_field *records)
01612 {
01613         struct cb_field *p;
01614         struct cb_field *v;
01615         cb_tree         l;
01616         cb_tree         x;
01617         char            buff[COB_MINI_BUFF];
01618 
01619         if (f->special) {
01620                 f->organization = COB_ORG_LINE_SEQUENTIAL;
01621         }
01622         if (f->fileid_assign && !f->assign) {
01623                 f->assign = cb_build_alphanumeric_literal ((unsigned char *)f->name,
01624                                                             strlen (f->name));
01625         }
01626 
01627         /* check the record size if it is limited */
01628         for (p = records; p; p = p->sister) {
01629                 if (f->record_min > 0) {
01630                         if (p->size < f->record_min) {
01631                                 cb_error (_("Record size too small '%s'"), p->name);
01632                         }
01633                 }
01634                 if (f->record_max > 0) {
01635                         if (p->size > f->record_max) {
01636                                 cb_error (_("Record size too large '%s' (%d)"),
01637                                              p->name, p->size);
01638                         }
01639                 }
01640         }
01641 
01642         /* compute the record size */
01643         if (f->record_min == 0) {
01644                 if (records) {
01645                         f->record_min = records->size;
01646                 } else {
01647                         f->record_min = 0;
01648                 }
01649         }
01650         for (p = records; p; p = p->sister) {
01651                 v = cb_field_variable_size (p);
01652                 if (v && v->offset + v->size * v->occurs_min < f->record_min) {
01653                         f->record_min = v->offset + v->size * v->occurs_min;
01654                 }
01655                 if (p->size < f->record_min) {
01656                         f->record_min = p->size;
01657                 }
01658                 if (p->size > f->record_max) {
01659                         f->record_max = p->size;
01660                 }
01661         }
01662 
01663         if (f->same_clause) {
01664                 for (l = current_program->file_list; l; l = CB_CHAIN (l)) {
01665                         if (CB_FILE (CB_VALUE (l))->same_clause == f->same_clause) {
01666                                 if (CB_FILE (CB_VALUE (l))->finalized) {
01667                                         if (f->record_max > CB_FILE (CB_VALUE (l))->record->memory_size) {
01668                                                 CB_FILE (CB_VALUE (l))->record->memory_size =
01669                                                     f->record_max;
01670                                         }
01671                                         f->record = CB_FILE (CB_VALUE (l))->record;
01672                                         for (p = records; p; p = p->sister) {
01673                                                 p->file = f;
01674                                                 p->redefines = f->record;
01675                                         }
01676                                         for (p = f->record->sister; p; p = p->sister) {
01677                                                 if (!p->sister) {
01678                                                         p->sister = records;
01679                                                         break;
01680                                                 }
01681                                         }
01682                                         f->finalized = 1;
01683                                         return;
01684                                 }
01685                         }
01686                 }
01687         }
01688         /* create record */
01689         snprintf (buff, COB_MINI_MAX, "%s_record", f->name);
01690         if (f->record_max == 0) {
01691                 f->record_max = 32;
01692                 f->record_min = 32;
01693         }
01694         if (f->organization == COB_ORG_LINE_SEQUENTIAL) {
01695                 f->record_min = 0;
01696         }
01697         f->record = CB_FIELD (cb_build_implicit_field (cb_build_reference (buff),
01698                                 f->record_max));
01699         f->record->sister = records;
01700         f->record->count++;
01701         if (f->external) {
01702                 has_external = 1;
01703                 f->record->flag_external = 1;
01704         }
01705 
01706         for (p = records; p; p = p->sister) {
01707                 p->file = f;
01708                 p->redefines = f->record;
01709         }
01710         f->finalized = 1;
01711         if (f->linage) {
01712                 snprintf (buff, COB_MINI_MAX, "LC_%s", f->name);
01713                 x = cb_build_field (cb_build_reference (buff));
01714                 CB_FIELD (x)->pic = CB_PICTURE (cb_build_picture ("9(9)"));
01715                 CB_FIELD (x)->usage = CB_USAGE_COMP_5;
01716                 CB_FIELD (x)->values = cb_list_init (cb_zero);
01717                 CB_FIELD (x)->count++;
01718                 cb_validate_field (CB_FIELD (x));
01719                 f->linage_ctr = cb_build_field_reference (CB_FIELD (x), NULL);
01720                 current_program->working_storage =
01721                     cb_field_add (current_program->working_storage, CB_FIELD (x));
01722         }
01723 }
01724 
01725 /*
01726  * Reference
01727  */
01728 
01729 cb_tree
01730 cb_build_reference (const char *name)
01731 {
01732         struct cb_reference *p;
01733 
01734         p = make_tree (CB_TAG_REFERENCE, CB_CATEGORY_UNKNOWN, sizeof (struct cb_reference));
01735         p->word = lookup_word (name);
01736         return CB_TREE (p);
01737 }
01738 
01739 cb_tree
01740 cb_build_filler (void)
01741 {
01742         cb_tree         x;
01743         char            name[16];
01744 
01745         sprintf (name, "WORK$%d", filler_id++);
01746         x = cb_build_reference (name);
01747         x->source_line = cb_source_line;
01748         return x;
01749 }
01750 
01751 cb_tree
01752 cb_build_field_reference (struct cb_field *f, cb_tree ref)
01753 {
01754         cb_tree         x;
01755         struct cb_word  *word;
01756 
01757         x = cb_build_reference (f->name);
01758         word = CB_REFERENCE (x)->word;
01759         if (ref) {
01760                 memcpy (x, ref, sizeof (struct cb_reference));
01761         }
01762         x->category = CB_CATEGORY_UNKNOWN;
01763         CB_REFERENCE (x)->word = word;
01764         CB_REFERENCE (x)->value = CB_TREE (f);
01765         return x;
01766 }
01767 
01768 const char *
01769 cb_define (cb_tree name, cb_tree val)
01770 {
01771         struct cb_word *w;
01772 
01773         w = CB_REFERENCE (name)->word;
01774         w->items = cb_list_add (w->items, val);
01775         w->count++;
01776         val->source_file = name->source_file;
01777         val->source_line = name->source_line;
01778         CB_REFERENCE (name)->value = val;
01779         return w->name;
01780 }
01781 
01782 void
01783 cb_define_system_name (const char *name)
01784 {
01785         cb_tree x;
01786 
01787         x = cb_build_reference (name);
01788         if (CB_REFERENCE (x)->word->count == 0) {
01789                 cb_define (x, lookup_system_name (name));
01790         }
01791 }
01792 
01793 cb_tree
01794 cb_ref (cb_tree x)
01795 {
01796         struct cb_reference     *r;
01797         struct cb_field         *p;
01798         struct cb_label         *s;
01799         cb_tree                 candidate = NULL;
01800         cb_tree                 items;
01801         cb_tree                 cb1;
01802         cb_tree                 cb2;
01803         cb_tree                 v;
01804         cb_tree                 c;
01805         struct cb_program       *prog;
01806         struct cb_word          *w;
01807         size_t                  val;
01808         size_t                  ambiguous = 0;
01809 
01810         r = CB_REFERENCE (x);
01811         /* if this reference has already been resolved (and the value
01812            has been cached), then just return the value */
01813         if (r->value) {
01814                 return r->value;
01815         }
01816         /* resolve the value */
01817 
01818         items = r->word->items;
01819         for (; items; items = CB_CHAIN (items)) {
01820                 /* find a candidate value by resolving qualification */
01821                 v = CB_VALUE (items);
01822                 c = r->chain;
01823                 switch (CB_TREE_TAG (v)) {
01824                 case CB_TAG_FIELD:
01825                         /* in case the value is a field, it might be qualified
01826                            by its parent names and a file name */
01827                         if (CB_FIELD (v)->flag_indexed_by) {
01828                                 p = CB_FIELD (v)->index_qual;
01829                         } else {
01830                                 p = CB_FIELD (v)->parent;
01831                         }
01832                         /* resolve by parents */
01833                         for (; p; p = p->parent) {
01834                                 if (c && strcasecmp (CB_NAME (c), p->name) == 0) {
01835                                         c = CB_REFERENCE (c)->chain;
01836                                 }
01837                         }
01838 
01839                         /* resolve by file */
01840                         if (c && CB_REFERENCE (c)->chain == NULL) {
01841                                 if (CB_REFERENCE (c)->word->count == 1 && CB_FILE_P (cb_ref (c))
01842                                     && (CB_FILE (cb_ref (c)) == cb_field_founder (CB_FIELD (v))->file)) {
01843                                         c = CB_REFERENCE (c)->chain;
01844                                 }
01845                         }
01846 
01847                         break;
01848                 case CB_TAG_LABEL:
01849                         /* in case the value is a label, it might be qualified
01850                            by its section name */
01851                         s = CB_LABEL (v)->section;
01852 
01853                         /* unqualified paragraph name referenced within the section
01854                            is resolved without ambiguity check if not duplicated */
01855                         if (c == NULL && r->offset && s == CB_LABEL (r->offset)) {
01856                                 for (cb1 = CB_CHAIN (items); cb1; cb1 = CB_CHAIN (cb1)) {
01857                                         cb2 = CB_VALUE (cb1);
01858                                         if (s == CB_LABEL (cb2)->section) {
01859                                                 ambiguous_error (x);
01860                                                 goto error;
01861                                         }
01862                                 }
01863                                 candidate = v;
01864                                 goto end;
01865                         }
01866 
01867                         /* resolve by section name */
01868                         if (c && s && strcasecmp (CB_NAME (c), (char *)s->name) == 0) {
01869                                 c = CB_REFERENCE (c)->chain;
01870                         }
01871 
01872                         break;
01873                 default:
01874                         /* other values cannot be qualified */
01875                         break;
01876                 }
01877 
01878                 /* a well qualified value is a good candidate */
01879                 if (c == NULL) {
01880                         if (candidate == NULL) {
01881                                 /* keep the first candidate */
01882                                 candidate = v;
01883                         } else {
01884                                 /* multiple candidates and possibly ambiguous */
01885                                 ambiguous = 1;
01886                                 /* continue search because the reference might not
01887                                    be ambiguous and exit loop by "goto end" later */
01888                         }
01889                 }
01890         }
01891 
01892         /* there is no candidate */
01893         if (candidate == NULL) {
01894                 if (current_program->nested_level > 0) {
01895                         /* Nested program - check parents for GLOBAL candidate */
01896                         ambiguous = 0;
01897                         val = hash ((const unsigned char *)r->word->name);
01898                         prog = current_program->next_program;
01899                         for (; prog; prog = prog->next_program) {
01900                                 if (prog->nested_level >= current_program->nested_level) {
01901                                         continue;
01902                                 }
01903                                 for (w = prog->word_table[val]; w; w = w->next) {
01904                                         if (strcasecmp (r->word->name, w->name) == 0) {
01905                                                 candidate = global_check (r, w->items, &ambiguous);
01906                                                 if (candidate) {
01907                                                         if (ambiguous) {
01908                                                                 ambiguous_error (x);
01909                                                                 goto error;
01910                                                         }
01911                                                         if (CB_FILE_P(candidate)) {
01912                                                                 current_program->gen_file_error = 1;
01913                                                         }
01914                                                         goto end;
01915                                                 }
01916                                         }
01917                                 }
01918                                 if (prog->nested_level == 0) {
01919                                         break;
01920                                 }
01921                         }
01922                 }
01923                 undefined_error (x);
01924                 goto error;
01925         }
01926 
01927         /* the reference is ambiguous */
01928         if (ambiguous) {
01929                 ambiguous_error (x);
01930                 goto error;
01931         }
01932 
01933 end:
01934         if (CB_FIELD_P (candidate)) {
01935                 CB_FIELD (candidate)->count++;
01936                 if (CB_FIELD (candidate)->flag_invalid) {
01937                         goto error;
01938                 }
01939         }
01940 
01941         r->value = candidate;
01942         return r->value;
01943 
01944 error:
01945         r->value = cb_error_node;
01946         return cb_error_node;
01947 }
01948 
01949 /*
01950  * Expression
01951  */
01952 
01953 cb_tree
01954 cb_build_binary_op (cb_tree x, int op, cb_tree y)
01955 {
01956         struct cb_binary_op     *p;
01957         enum cb_category        category = CB_CATEGORY_UNKNOWN;
01958 
01959         switch (op) {
01960         case '+':
01961         case '-':
01962         case '*':
01963         case '/':
01964         case '^':
01965                 /* arithmetic operators */
01966                 if (CB_TREE_CLASS (x) == CB_CLASS_POINTER ||
01967                     CB_TREE_CLASS (y) == CB_CLASS_POINTER) {
01968                         category = CB_CATEGORY_DATA_POINTER;
01969                         break;
01970                 }
01971                 x = cb_check_numeric_value (x);
01972                 y = cb_check_numeric_value (y);
01973                 if (x == cb_error_node || y == cb_error_node) {
01974                         return cb_error_node;
01975                 }
01976                 category = CB_CATEGORY_NUMERIC;
01977                 break;
01978 
01979         case '=':
01980         case '~':
01981         case '<':
01982         case '>':
01983         case '[':
01984         case ']':
01985                 /* relational operators */
01986                 category = CB_CATEGORY_BOOLEAN;
01987                 break;
01988 
01989         case '!':
01990         case '&':
01991         case '|':
01992                 /* logical operators */
01993                 if (CB_TREE_CLASS (x) != CB_CLASS_BOOLEAN ||
01994                     (y && CB_TREE_CLASS (y) != CB_CLASS_BOOLEAN)) {
01995                         cb_error (_("Invalid expression"));
01996                         return cb_error_node;
01997                 }
01998                 category = CB_CATEGORY_BOOLEAN;
01999                 break;
02000 
02001         case '@':
02002                 /* parentheses */
02003                 category = CB_TREE_CATEGORY (x);
02004                 break;
02005 
02006         default:
02007                 fprintf (stderr, "Unexpected operator -> %d\n", op);
02008                 ABORT ();
02009         }
02010 
02011         p = make_tree (CB_TAG_BINARY_OP, category, sizeof (struct cb_binary_op));
02012         p->op = op;
02013         p->x = x;
02014         p->y = y;
02015         return CB_TREE (p);
02016 }
02017 
02018 cb_tree
02019 cb_build_binary_list (cb_tree l, int op)
02020 {
02021         cb_tree e;
02022 
02023         e = CB_VALUE (l);
02024         for (l = CB_CHAIN (l); l; l = CB_CHAIN (l)) {
02025                 e = cb_build_binary_op (e, op, CB_VALUE (l));
02026         }
02027         return e;
02028 }
02029 
02030 /*
02031  * Function call
02032  */
02033 
02034 cb_tree
02035 cb_build_funcall (const char *name, int argc, cb_tree a1, cb_tree a2, cb_tree a3,
02036                   cb_tree a4, cb_tree a5, cb_tree a6, cb_tree a7)
02037 {
02038         struct cb_funcall *p;
02039 
02040         p = make_tree (CB_TAG_FUNCALL, CB_CATEGORY_BOOLEAN, sizeof (struct cb_funcall));
02041         p->name = name;
02042         p->argc = argc;
02043         p->varcnt = 0;
02044         p->screenptr = gen_screen_ptr;
02045         p->argv[0] = a1;
02046         p->argv[1] = a2;
02047         p->argv[2] = a3;
02048         p->argv[3] = a4;
02049         p->argv[4] = a5;
02050         p->argv[5] = a6;
02051         p->argv[6] = a7;
02052         return CB_TREE (p);
02053 }
02054 
02055 /*
02056  * Type cast
02057  */
02058 
02059 cb_tree
02060 cb_build_cast (enum cb_cast_type type, cb_tree val)
02061 {
02062         struct cb_cast          *p;
02063         enum cb_category        category;
02064 
02065         if (type == CB_CAST_INTEGER) {
02066                 category = CB_CATEGORY_NUMERIC;
02067         } else {
02068                 category = CB_CATEGORY_UNKNOWN;
02069         }
02070         p = make_tree (CB_TAG_CAST, category, sizeof (struct cb_cast));
02071         p->type = type;
02072         p->val = val;
02073         return CB_TREE (p);
02074 }
02075 
02076 /*
02077  * Label
02078  */
02079 
02080 cb_tree
02081 cb_build_label (cb_tree name, struct cb_label *section)
02082 {
02083         struct cb_label *p;
02084 
02085         p = make_tree (CB_TAG_LABEL, CB_CATEGORY_UNKNOWN, sizeof (struct cb_label));
02086         p->id = cb_id++;
02087         p->name = (const unsigned char *)cb_define (name, CB_TREE (p));
02088         p->orig_name = p->name;
02089         p->section = section;
02090         return CB_TREE (p);
02091 }
02092 
02093 /*
02094  * Assign
02095  */
02096 
02097 cb_tree
02098 cb_build_assign (cb_tree var, cb_tree val)
02099 {
02100         struct cb_assign *p;
02101 
02102         p = make_tree (CB_TAG_ASSIGN, CB_CATEGORY_UNKNOWN, sizeof (struct cb_assign));
02103         p->var = var;
02104         p->val = val;
02105         return CB_TREE (p);
02106 }
02107 
02108 /*
02109  * INITIALIZE
02110  */
02111 
02112 cb_tree
02113 cb_build_initialize (cb_tree var, cb_tree val, cb_tree rep, cb_tree def, int flag)
02114 {
02115         struct cb_initialize *p;
02116 
02117         p = make_tree (CB_TAG_INITIALIZE, CB_CATEGORY_UNKNOWN, sizeof (struct cb_initialize));
02118         p->var = var;
02119         p->val = val;
02120         p->rep = rep;
02121         p->def = def;
02122         p->flag_statement = flag;
02123         return CB_TREE (p);
02124 }
02125 
02126 /*
02127  * SEARCH
02128  */
02129 
02130 cb_tree
02131 cb_build_search (int flag_all, cb_tree table, cb_tree var, cb_tree end_stmt, cb_tree whens)
02132 {
02133         struct cb_search *p;
02134 
02135         p = make_tree (CB_TAG_SEARCH, CB_CATEGORY_UNKNOWN, sizeof (struct cb_search));
02136         p->flag_all = flag_all;
02137         p->table = table;
02138         p->var = var;
02139         p->end_stmt = end_stmt;
02140         p->whens = whens;
02141         return CB_TREE (p);
02142 }
02143 
02144 /*
02145  * CALL
02146  */
02147 
02148 cb_tree
02149 cb_build_call (cb_tree name, cb_tree args, cb_tree stmt1, cb_tree stmt2, cb_tree returning, int is_system_call)
02150 {
02151         struct cb_call *p;
02152 
02153         p = make_tree (CB_TAG_CALL, CB_CATEGORY_UNKNOWN, sizeof (struct cb_call));
02154         p->name = name;
02155         p->args = args;
02156         p->stmt1 = stmt1;
02157         p->stmt2 = stmt2;
02158         p->returning = returning;
02159         p->is_system = is_system_call;
02160         return CB_TREE (p);
02161 }
02162 
02163 /*
02164  * GO TO
02165  */
02166 
02167 cb_tree
02168 cb_build_goto (cb_tree target, cb_tree depending)
02169 {
02170         struct cb_goto *p;
02171 
02172         p = make_tree (CB_TAG_GOTO, CB_CATEGORY_UNKNOWN, sizeof (struct cb_goto));
02173         p->target = target;
02174         p->depending = depending;
02175         return CB_TREE (p);
02176 }
02177 
02178 /*
02179  * IF
02180  */
02181 
02182 cb_tree
02183 cb_build_if (cb_tree test, cb_tree stmt1, cb_tree stmt2)
02184 {
02185         struct cb_if *p;
02186 
02187         p = make_tree (CB_TAG_IF, CB_CATEGORY_UNKNOWN, sizeof (struct cb_if));
02188         p->test = test;
02189         p->stmt1 = stmt1;
02190         p->stmt2 = stmt2;
02191         return CB_TREE (p);
02192 }
02193 
02194 /*
02195  * PERFORM
02196  */
02197 
02198 cb_tree
02199 cb_build_perform (int type)
02200 {
02201         struct cb_perform *p;
02202 
02203         p = make_tree (CB_TAG_PERFORM, CB_CATEGORY_UNKNOWN, sizeof (struct cb_perform));
02204         p->type = type;
02205         return CB_TREE (p);
02206 }
02207 
02208 cb_tree
02209 cb_build_perform_varying (cb_tree name, cb_tree from, cb_tree by, cb_tree until)
02210 {
02211         struct cb_perform_varying *p;
02212 
02213         p = make_tree (CB_TAG_PERFORM_VARYING, CB_CATEGORY_UNKNOWN, sizeof (struct cb_perform_varying));
02214         p->name = name;
02215         p->from = from;
02216         p->step = name ? cb_build_add (name, by, cb_high) : NULL;
02217         p->until = until;
02218         return CB_TREE (p);
02219 }
02220 
02221 /*
02222  * Statement
02223  */
02224 
02225 struct cb_statement *
02226 cb_build_statement (const char *name)
02227 {
02228         struct cb_statement *p;
02229 
02230         p = make_tree (CB_TAG_STATEMENT, CB_CATEGORY_UNKNOWN, sizeof (struct cb_statement));
02231         p->name = name;
02232         return p;
02233 }
02234 
02235 /*
02236  * CONTINUE
02237  */
02238 
02239 cb_tree
02240 cb_build_continue (void)
02241 {
02242         struct cb_continue *p;
02243 
02244         p = make_tree (CB_TAG_CONTINUE, CB_CATEGORY_UNKNOWN, sizeof (struct cb_continue));
02245         return CB_TREE (p);
02246 }
02247 
02248 /*
02249  * FUNCTION
02250  */
02251 
02252 cb_tree
02253 cb_build_any_intrinsic (cb_tree args)
02254 {
02255         struct cb_intrinsic_table       *cbp;
02256 
02257         cbp = lookup_intrinsic ("LENGTH", 0);
02258         return make_intrinsic (NULL, cbp, args, NULL, NULL);
02259 }
02260 
02261 cb_tree
02262 cb_build_intrinsic (cb_tree name, cb_tree args, cb_tree refmod)
02263 {
02264         struct cb_intrinsic_table       *cbp;
02265         cb_tree                         x;
02266         int                             numargs;
02267 
02268         numargs = cb_list_length (args);
02269 
02270         cbp = lookup_intrinsic (CB_NAME (name), 0);
02271         if (cbp) {
02272                 if ((cbp->args != -1 && numargs != cbp->args) ||
02273                     (cbp->args == -1 && cbp->intr_enum != CB_INTR_RANDOM && numargs < 1)) {
02274                         cb_error_x (name, _("FUNCTION %s has wrong number of arguments"), cbp->name);
02275                         return cb_error_node;
02276                 }
02277                 if (refmod) {
02278                         if (!cbp->refmod) {
02279                                 cb_error_x (name, _("FUNCTION %s can not have reference modification"), cbp->name);
02280                                 return cb_error_node;
02281                         }
02282                         if (CB_LITERAL_P(CB_PAIR_X(refmod)) &&
02283                             cb_get_int (CB_PAIR_X(refmod))< 1) {
02284                                 cb_error_x (name, _("FUNCTION %s has invalid reference modification"), cbp->name);
02285                                 return cb_error_node;
02286                         }
02287                         if (CB_PAIR_Y(refmod) && CB_LITERAL_P(CB_PAIR_Y(refmod)) &&
02288                             cb_get_int (CB_PAIR_Y(refmod))< 1) {
02289                                 cb_error_x (name, _("FUNCTION %s has invalid reference modification"), cbp->name);
02290                                 return cb_error_node;
02291                         }
02292                 }
02293                 /* cb_tree      x; */
02294                 switch (cbp->intr_enum) {
02295                 case CB_INTR_LENGTH:
02296                 case CB_INTR_BYTE_LENGTH:
02297                         x = CB_VALUE (args);
02298                         if (CB_INTRINSIC_P (x)) {
02299                                 return make_intrinsic (name, cbp, args, NULL, NULL);
02300                         } else if ((CB_FIELD_P (x) || CB_REFERENCE_P (x)) &&
02301                                     cb_field(x)->flag_any_length) {
02302                                 return make_intrinsic (name, cbp, args, NULL, NULL);
02303                         } else {
02304                                 return cb_build_length (CB_VALUE (args));
02305                         }
02306 
02307                 case CB_INTR_WHEN_COMPILED:
02308                         if (refmod) {
02309                                 return make_intrinsic (name, cbp,
02310                                         cb_list_init (cb_intr_whencomp), NULL, refmod);
02311                         } else {
02312                                 return cb_intr_whencomp;
02313                         }
02314                 case CB_INTR_PI:
02315                         return cb_intr_pi;
02316                 case CB_INTR_E:
02317                         return cb_intr_e;
02318 
02319                 case CB_INTR_LOWER_CASE:
02320                 case CB_INTR_UPPER_CASE:
02321                 case CB_INTR_REVERSE:
02322 /* RXW Why did I do this ? - still do not know
02323                         if (CB_INTRINSIC_P (CB_VALUE (args))) {
02324                                 return make_intrinsic (name, cbp, args, cb_int0);
02325                         } else {
02326                                 return make_intrinsic (name, cbp, args,
02327                                                        cb_build_length (CB_VALUE (args)));
02328                         }
02329 RXW */
02330 
02331                 case CB_INTR_ABS:
02332                 case CB_INTR_ACOS:
02333                 case CB_INTR_ANNUITY:
02334                 case CB_INTR_ASIN:
02335                 case CB_INTR_ATAN:
02336                 case CB_INTR_CHAR:
02337                 case CB_INTR_COMBINED_DATETIME:
02338                 case CB_INTR_COS:
02339                 case CB_INTR_CURRENT_DATE:
02340                 case CB_INTR_DATE_OF_INTEGER:
02341                 case CB_INTR_DAY_OF_INTEGER:
02342                 case CB_INTR_EXCEPTION_FILE:
02343                 case CB_INTR_EXCEPTION_LOCATION:
02344                 case CB_INTR_EXCEPTION_STATUS:
02345                 case CB_INTR_EXCEPTION_STATEMENT:
02346                 case CB_INTR_EXP:
02347                 case CB_INTR_EXP10:
02348                 case CB_INTR_FACTORIAL:
02349                 case CB_INTR_FRACTION_PART:
02350                 case CB_INTR_INTEGER:
02351                 case CB_INTR_INTEGER_OF_DATE:
02352                 case CB_INTR_INTEGER_OF_DAY:
02353                 case CB_INTR_INTEGER_PART:
02354                 case CB_INTR_LOCALE_DATE:
02355                 case CB_INTR_LOCALE_TIME:
02356                 case CB_INTR_LOCALE_TIME_FROM_SECS:
02357                 case CB_INTR_LOG:
02358                 case CB_INTR_LOG10:
02359                 case CB_INTR_MOD:
02360                 case CB_INTR_NUMVAL:
02361                 case CB_INTR_NUMVAL_C:
02362                 case CB_INTR_ORD:
02363                 case CB_INTR_REM:
02364                 case CB_INTR_SECONDS_FROM_FORMATTED_TIME:
02365                 case CB_INTR_SECONDS_PAST_MIDNIGHT:
02366                 case CB_INTR_SIGN:
02367                 case CB_INTR_SIN:
02368                 case CB_INTR_SQRT:
02369                 case CB_INTR_STORED_CHAR_LENGTH:
02370                 case CB_INTR_TAN:
02371                 case CB_INTR_TEST_DATE_YYYYMMDD:
02372                 case CB_INTR_TEST_DAY_YYYYDDD:
02373                 case CB_INTR_TRIM:
02374                         return make_intrinsic (name, cbp, args, NULL, refmod);
02375 
02376                 case CB_INTR_CONCATENATE:
02377                         return make_intrinsic (name, cbp, args, cb_int1, refmod);
02378                 case CB_INTR_DATE_TO_YYYYMMDD:
02379                 case CB_INTR_DAY_TO_YYYYDDD:
02380                 case CB_INTR_MAX:
02381                 case CB_INTR_MEAN:
02382                 case CB_INTR_MEDIAN:
02383                 case CB_INTR_MIDRANGE:
02384                 case CB_INTR_MIN:
02385                 case CB_INTR_ORD_MAX:
02386                 case CB_INTR_ORD_MIN:
02387                 case CB_INTR_PRESENT_VALUE:
02388                 case CB_INTR_RANDOM:
02389                 case CB_INTR_RANGE:
02390                 case CB_INTR_STANDARD_DEVIATION:
02391                 case CB_INTR_SUM:
02392                 case CB_INTR_VARIANCE:
02393                 case CB_INTR_YEAR_TO_YYYY:
02394                         return make_intrinsic (name, cbp, args, cb_int1, NULL);
02395                 case CB_INTR_SUBSTITUTE:
02396                 case CB_INTR_SUBSTITUTE_CASE:
02397                         if (numargs < 3 || (numargs % 2) == 0) {
02398                                 cb_error_x (name, _("FUNCTION %s has wrong number of arguments"), cbp->name);
02399                                 return cb_error_node;
02400                         }
02401                         return make_intrinsic (name, cbp, args, cb_int1, refmod);
02402 
02403                 default:
02404                         break;
02405                 }
02406         }
02407         cb_error_x (name, _("FUNCTION %s not implemented"), CB_NAME (name));
02408         return cb_error_node;
02409 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines