GnuCOBOL  2.0
A free COBOL compiler
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
call.c File Reference
#include "config.h"
#include "defaults.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ltdl.h>
#include "libcob.h"
#include "coblocal.h"
#include "system.def"
Include dependency graph for call.c:

Data Structures

struct  call_hash
 
struct  struct_handle
 
struct  system_table
 

Macros

#define _GNU_SOURCE   1
 
#define COB_LIB_EXPIMP
 
#define COB_MAX_COBCALL_PARMS   16
 
#define CALL_BUFF_SIZE   256U
 
#define CALL_BUFF_MAX   (CALL_BUFF_SIZE - 1U)
 
#define HASH_SIZE   131U
 
#define COB_SYSTEM_GEN(x, y, z)   { x, {(void *(*)(void *))z} },
 

Functions

static void set_resolve_error (const char *msg, const char *entry)
 
static void cob_set_library_path (const char *path)
 
static void do_cancel_module (struct call_hash *p, struct call_hash **base_hash, struct call_hash *prev)
 
static void * cob_get_buff (const size_t buffsize)
 
static void cache_dynload (const char *path, lt_dlhandle handle)
 
static size_t cache_preload (const char *path)
 
static COB_INLINE unsigned int hash (const unsigned char *s)
 
static void insert (const char *name, void *func, lt_dlhandle handle, cob_module *module, const char *path, const unsigned int nocanc)
 
static void * lookup (const char *name)
 
static void * cob_resolve_internal (const char *name, const char *dirent, const int fold_case)
 
static const char * cob_chk_dirp (const char *name)
 
static char * cob_chk_call_path (const char *name, char **dirent)
 
const char * cob_resolve_error (void)
 
void cob_call_error (void)
 
void cob_set_cancel (cob_module *m)
 
void * cob_resolve (const char *name)
 
void * cob_resolve_cobol (const char *name, const int fold_case, const int errind)
 
void * cob_resolve_func (const char *name)
 
void * cob_call_field (const cob_field *f, const struct cob_call_struct *cs, const unsigned int errind, const int fold_case)
 
void cob_cancel (const char *name)
 
void cob_cancel_field (const cob_field *f, const struct cob_call_struct *cs)
 
int cob_call (const char *name, const int argc, void **argv)
 
int cob_func (const char *name, const int argc, void **argv)
 
void * cob_savenv (struct cobjmp_buf *jbuf)
 
void * cob_savenv2 (struct cobjmp_buf *jbuf, const int jsize)
 
void cob_longjmp (struct cobjmp_buf *jbuf)
 
void cob_exit_call (void)
 
void cob_init_call (cob_global *lptr, runtime_env *runtimeptr)
 

Variables

static struct call_hash ** call_table
 
static struct struct_handlebase_preload_ptr
 
static char * cob_preload_env
 
static char * cob_preload_resolved
 
static struct struct_handlebase_dynload_ptr
 
static cob_globalcobglobptr
 
static char ** resolve_path
 
static char * cob_library_path_env
 
static char * resolve_error
 
static char * resolve_alloc
 
static char * resolve_error_buff
 
static void * call_buffer
 
static char * call_filename_buff
 
static char * call_entry_buff
 
static unsigned char * call_entry2_buff
 
static lt_dlhandle mainhandle
 
static size_t call_lastsize
 
static size_t resolve_size
 
static unsigned int name_convert
 
static char * name_convert_env
 
static unsigned int cob_jmp_primed
 
static unsigned int physical_cancel
 
static char * physical_cancel_env
 
static struct system_table system_tab []
 
static const unsigned char hexval [] = "0123456789ABCDEF"
 
static unsigned char valid_char [256]
 
static const unsigned char pvalid_char []
 

Macro Definition Documentation

#define _GNU_SOURCE   1
#define CALL_BUFF_MAX   (CALL_BUFF_SIZE - 1U)

Referenced by set_resolve_error().

#define CALL_BUFF_SIZE   256U

Referenced by cob_init_call().

#define COB_LIB_EXPIMP
#define COB_MAX_COBCALL_PARMS   16
#define COB_SYSTEM_GEN (   x,
  y,
 
)    { x, {(void *(*)(void *))z} },
#define HASH_SIZE   131U

Referenced by cob_exit_call(), cob_init_call(), and hash().

Function Documentation

static void cache_dynload ( const char *  path,
lt_dlhandle  handle 
)
static

References base_dynload_ptr, cob_malloc(), cob_strdup(), struct_handle::handle, struct_handle::next, and struct_handle::path.

Referenced by cob_resolve_internal().

439 {
440  struct struct_handle *dynptr;
441 
442  for (dynptr = base_dynload_ptr; dynptr; dynptr = dynptr->next) {
443  if (!strcmp (path, dynptr->path)) {
444  if (!dynptr->handle) {
445  dynptr->handle = handle;
446  return;
447  }
448  }
449  }
450  dynptr = cob_malloc (sizeof (struct struct_handle));
451  dynptr->path = cob_strdup (path);
452  dynptr->handle = handle;
453  dynptr->next = base_dynload_ptr;
454  base_dynload_ptr = dynptr;
455 }
static size_t cache_preload ( const char *  path)
static

References base_preload_ptr, cob_malloc(), cob_strcat(), cob_strdup(), struct_handle::handle, struct_handle::next, NULL, struct_handle::path, PATHSEPS, and R_OK.

Referenced by cob_init_call().

459 {
460  struct struct_handle *preptr;
461  lt_dlhandle libhandle;
462 
463 #if defined(_WIN32) || defined(__CYGWIN__)
464  struct struct_handle *last_elem;
465  last_elem = NULL;
466 #endif
467 
468  /* Check for duplicate */
469  for (preptr = base_preload_ptr; preptr; preptr = preptr->next) {
470  if (!strcmp (path, preptr->path)) {
471  return 1;
472  }
473 #if defined(_WIN32) || defined(__CYGWIN__)
474  /* Save last element of preload list */
475  if (!preptr->next) last_elem = preptr;
476 #endif
477  }
478 
479  if (access (path, R_OK) != 0) {
480  return 0;
481  }
482 
483  libhandle = lt_dlopen (path);
484  if (!libhandle) {
485  return 0;
486  }
487 
488  preptr = cob_malloc (sizeof (struct struct_handle));
489  preptr->path = cob_strdup (path);
490  preptr->handle = libhandle;
491 
492 #if defined(_WIN32) || defined(__CYGWIN__)
493  /*
494  * Observation: dlopen (POSIX) and lt_dlopen (UNIX) are overloading
495  * symbols with equal name. So if we load two libraries with equal
496  * named symbols, the last one wins and is loaded.
497  * LoadLibrary (Win32) ignores any equal named symbol
498  * if another library with this symbol was already loaded.
499  *
500  * In Windows (including MinGW/CYGWIN) we need to load modules
501  * in the same order as we save them to COB_PRE_LOAD due to issues
502  * if we have got two modules with equal entry points.
503  */
504  if(last_elem) {
505  last_elem->next = preptr;
506  }
507  else {
508  preptr->next = NULL;
509  base_preload_ptr = preptr;
510  }
511 #else
512  preptr->next = base_preload_ptr;
513  base_preload_ptr = preptr;
514 #endif
515 
516 
517  if(!cob_preload_resolved) {
519  }
520  else {
523  }
524 
525  return 1;
526 }
int cob_call ( const char *  name,
const int  argc,
void **  argv 
)

References _, __cob_global::cob_call_params, cob_fatal_error(), COB_FERROR_INITIALIZED, cob_free(), cob_malloc(), COB_MAX_FIELD_PARAMS, cob_resolve_cobol(), cob_runtime_error(), cob_stop_run(), cob_call_union::funcint, cob_call_union::funcvoid, and unlikely.

Referenced by cob_func().

1088 {
1089  void **pargv;
1090  cob_call_union unifunc;
1091  int i;
1092 
1093  if (unlikely(!cobglobptr)) {
1094  cob_fatal_error (COB_FERROR_INITIALIZED);
1095  }
1096  if (argc < 0 || argc > COB_MAX_FIELD_PARAMS) {
1097  cob_runtime_error (_("Invalid number of arguments to 'cob_call'"));
1098  cob_stop_run (1);
1099  }
1100  if (unlikely(!name)) {
1101  cob_runtime_error (_("NULL name parameter passed to 'cob_call'"));
1102  cob_stop_run (1);
1103  }
1104  unifunc.funcvoid = cob_resolve_cobol (name, 0, 1);
1105  pargv = cob_malloc (COB_MAX_FIELD_PARAMS * sizeof(void *));
1106  /* Set number of parameters */
1107  cobglobptr->cob_call_params = argc;
1108  for (i = 0; i < argc; ++i) {
1109  pargv[i] = argv[i];
1110  }
1111  i = unifunc.funcint (pargv[0], pargv[1], pargv[2], pargv[3],
1112  pargv[4], pargv[5], pargv[6], pargv[7],
1113  pargv[8], pargv[9], pargv[10], pargv[11],
1114 #if COB_MAX_FIELD_PARAMS == 16
1115  pargv[12], pargv[13], pargv[14], pargv[15]);
1116 #elif COB_MAX_FIELD_PARAMS == 36
1117  pargv[12], pargv[13], pargv[14], pargv[15],
1118  pargv[16], pargv[17], pargv[18], pargv[19],
1119  pargv[20], pargv[21], pargv[22], pargv[23],
1120  pargv[24], pargv[25], pargv[26], pargv[27],
1121  pargv[28], pargv[29], pargv[30], pargv[31],
1122  pargv[32], pargv[33], pargv[34], pargv[35]);
1123 #else
1124 #error "Invalid COB_MAX_FIELD_PARAMS value"
1125 #endif
1126  cob_free (pargv);
1127  return i;
1128 }
void cob_call_error ( void  )
void* cob_call_field ( const cob_field f,
const struct cob_call_struct cs,
const unsigned int  errind,
const int  fold_case 
)

References cob_call_error(), cob_chk_call_path(), cob_call_struct::cob_cstr_call, cob_call_struct::cob_cstr_name, cob_fatal_error(), COB_FERROR_INITIALIZED, cob_field_to_string(), cob_free(), cob_get_buff(), cob_resolve_internal(), cob_set_exception(), cob_call_union::funcvoid, NULL, p, cob_field::size, system_table::syst_call, system_table::syst_name, and unlikely.

966 {
967  void *p;
968  const struct cob_call_struct *s;
969  const struct system_table *psyst;
970  char *buff;
971  char *entry;
972  char *dirent;
973 
974  if (unlikely(!cobglobptr)) {
975  cob_fatal_error (COB_FERROR_INITIALIZED);
976  }
977 
978  buff = cob_get_buff (f->size + 1);
979  cob_field_to_string (f, buff, f->size);
980 
981  entry = cob_chk_call_path (buff, &dirent);
982 
983  /* Check if system routine */
984  for (psyst = system_tab; psyst->syst_name; ++psyst) {
985  if (!strcmp (entry, psyst->syst_name)) {
986  if (dirent) {
987  cob_free (dirent);
988  }
989  return psyst->syst_call.funcvoid;
990  }
991  }
992 
993 
994  /* Check if contained program */
995  for (s = cs; s && s->cob_cstr_name; s++) {
996  if (!strcmp (entry, s->cob_cstr_name)) {
997  if (dirent) {
998  cob_free (dirent);
999  }
1000  return s->cob_cstr_call.funcvoid;
1001  }
1002  }
1003 
1004  p = cob_resolve_internal (entry, dirent, fold_case);
1005  if (dirent) {
1006  cob_free (dirent);
1007  }
1008  if (unlikely(!p)) {
1009  if (errind) {
1010  cob_call_error ();
1011  } else {
1012  cob_set_exception (COB_EC_PROGRAM_NOT_FOUND);
1013  return NULL;
1014  }
1015  }
1016  return p;
1017 }
void cob_cancel ( const char *  name)

References _, call_table, cob_chk_dirp(), cob_fatal_error(), COB_FERROR_INITIALIZED, cob_runtime_error(), cob_stop_run(), do_cancel_module(), hash(), call_hash::name, call_hash::next, NULL, p, and unlikely.

Referenced by cob_cancel_field(), and cob_func().

1021 {
1022  const char *entry;
1023  struct call_hash *p;
1024  struct call_hash **q;
1025  struct call_hash *r;
1026 
1027  if (unlikely(!cobglobptr)) {
1028  cob_fatal_error (COB_FERROR_INITIALIZED);
1029  }
1030  if (unlikely(!name)) {
1031  cob_runtime_error (_("NULL parameter passed to 'cob_cancel'"));
1032  cob_stop_run (1);
1033  }
1034  entry = cob_chk_dirp (name);
1035 
1036 #ifdef COB_ALT_HASH
1037  q = &call_table;
1038  p = *q;
1039 #else
1040  q = &call_table[hash ((const unsigned char *)entry)];
1041  p = *q;
1042 #endif
1043  r = NULL;
1044  for (; p; p = p->next) {
1045  if (strcmp (entry, p->name) == 0) {
1046  do_cancel_module (p, q, r);
1047  return;
1048  }
1049  r = p;
1050  }
1051 }
void cob_cancel_field ( const cob_field f,
const struct cob_call_struct cs 
)

References cob_cancel(), cob_chk_dirp(), cob_call_struct::cob_cstr_cancel, cob_call_struct::cob_cstr_name, cob_fatal_error(), COB_FERROR_INITIALIZED, cob_field_to_string(), cob_get_buff(), cob_call_union::funcint, cob_call_union::funcvoid, call_hash::name, NULL, cob_field::size, and unlikely.

1055 {
1056  char *name;
1057  const char *entry;
1058  const struct cob_call_struct *s;
1059 
1060  int (*cancel_func)(const int, void *, void *, void *, void *);
1061 
1062  if (unlikely(!cobglobptr)) {
1063  cob_fatal_error (COB_FERROR_INITIALIZED);
1064  }
1065  if (!f || f->size == 0) {
1066  return;
1067  }
1068  name = cob_get_buff (f->size + 1);
1069  cob_field_to_string (f, name, f->size);
1070  entry = cob_chk_dirp (name);
1071 
1072  /* Check if contained program */
1073  for (s = cs; s && s->cob_cstr_name; s++) {
1074  if (!strcmp (entry, s->cob_cstr_name)) {
1075  if (s->cob_cstr_cancel.funcvoid) {
1076  cancel_func = s->cob_cstr_cancel.funcint;
1077  (void)cancel_func (-1, NULL, NULL, NULL,
1078  NULL);
1079  }
1080  return;
1081  }
1082  }
1083  cob_cancel (entry);
1084 }
static char* cob_chk_call_path ( const char *  name,
char **  dirent 
)
static

References cob_strdup(), NULL, and p.

Referenced by cob_call_field(), cob_resolve(), and cob_resolve_cobol().

833 {
834  char *p;
835  char *q;
836  size_t size1;
837  size_t size2;
838 
839  *dirent = NULL;
840  q = NULL;
841  size2 = 0;
842  for (p = (char *)name, size1 = 0; *p; p++, size1++) {
843  if (*p == '/' || *p == '\\') {
844  q = p + 1;
845  size2 = size1 + 1;
846  }
847  }
848  if (q) {
849  p = cob_strdup (name);
850  p[size2] = 0;
851  *dirent = p;
852  for (; *p; p++) {
853 #ifdef _WIN32
854  if (*p == '/') {
855  *p = '\\';
856  }
857 #else
858  if (*p == '\\') {
859  *p = '/';
860  }
861 #endif
862  }
863  return q;
864  }
865  return (char *)name;
866 }
static const char* cob_chk_dirp ( const char *  name)
static

References NULL, and p.

Referenced by cob_cancel(), and cob_cancel_field().

815 {
816  const char *p;
817  const char *q;
818 
819  q = NULL;
820  for (p = name; *p; p++) {
821  if (*p == '/' || *p == '\\') {
822  q = p + 1;
823  }
824  }
825  if (q) {
826  return q;
827  }
828  return name;
829 }
void cob_exit_call ( void  )

References call_table, cob_free(), struct_handle::handle, HASH_SIZE, call_hash::name, call_hash::next, struct_handle::next, NULL, p, call_hash::path, and struct_handle::path.

Referenced by cob_terminate_routines().

1186 {
1187  struct call_hash *p;
1188  struct call_hash *q;
1189  struct struct_handle *h;
1190  struct struct_handle *j;
1191 
1192 #ifndef COB_ALT_HASH
1193  size_t i;
1194 #endif
1195 
1196  if (call_filename_buff) {
1199  }
1200  if (call_entry_buff) {
1203  }
1204  if (call_entry2_buff) {
1207  }
1208  if (call_buffer) {
1210  call_buffer = NULL;
1211  }
1212  if (resolve_error_buff) {
1215  }
1216  if (resolve_alloc) {
1218  resolve_alloc = NULL;
1219  }
1220  if (resolve_path) {
1222  resolve_path = NULL;
1223  }
1224 
1225 #ifndef COB_ALT_HASH
1226  for (i = 0; i < HASH_SIZE; ++i) {
1227  p = call_table[i];
1228 #else
1229  p = call_table;
1230 #endif
1231  for (; p;) {
1232  q = p;
1233  p = p->next;
1234  if (q->name) {
1235  cob_free ((void *)q->name);
1236  }
1237  if (q->path) {
1238  cob_free ((void *)q->path);
1239  }
1240  cob_free (q);
1241  }
1242 #ifndef COB_ALT_HASH
1243  }
1244  if (call_table) {
1245  cob_free (call_table);
1246  }
1247  call_table = NULL;
1248 #endif
1249 
1250  for (h = base_preload_ptr; h;) {
1251  j = h;
1252  if (h->path) {
1253  cob_free ((void *)h->path);
1254  }
1255  if (h->handle) {
1256  lt_dlclose (h->handle);
1257  }
1258  h = h->next;
1259  cob_free (j);
1260  }
1262  for (h = base_dynload_ptr; h;) {
1263  j = h;
1264  if (h->path) {
1265  cob_free ((void *)h->path);
1266  }
1267  if (h->handle) {
1268  lt_dlclose (h->handle);
1269  }
1270  h = h->next;
1271  cob_free (j);
1272  }
1274 
1275 #if !defined(_WIN32) && !defined(USE_LIBDL)
1276  lt_dlexit ();
1277 #if 0 /* RXWRXW - ltdl leak */
1278  /* Weird - ltdl leaks mainhandle - This appears to work but .. */
1279  cob_free (mainhandle);
1280 #endif
1281 #endif
1282 
1283 }
int cob_func ( const char *  name,
const int  argc,
void **  argv 
)

References cob_call(), and cob_cancel().

1132 {
1133  int ret;
1134 
1135  ret = cob_call (name, argc, argv);
1136  cob_cancel (name);
1137  return ret;
1138 }
static void* cob_get_buff ( const size_t  buffsize)
static

References call_buffer, cob_fast_malloc(), and cob_free().

Referenced by cob_call_field(), and cob_cancel_field().

428 {
429  if (buffsize > call_lastsize) {
430  call_lastsize = buffsize;
432  call_buffer = cob_fast_malloc (buffsize);
433  }
434  return call_buffer;
435 }
void cob_init_call ( cob_global lptr,
runtime_env runtimeptr 
)

References cache_preload(), CALL_BUFF_SIZE, cob_fast_malloc(), cob_free(), COB_LIBRARY_PATH, cob_library_path_env, runtime_env::cob_library_path_env, cob_malloc(), COB_MEDIUM_BUFF, COB_MEDIUM_MAX, COB_MODULE_EXT, COB_NORMAL_BUFF, cob_preload_env, runtime_env::cob_preload_env, runtime_env::cob_preload_resolved, cob_save_env_value(), cob_set_library_path(), COB_SMALL_BUFF, cob_strdup(), HASH_SIZE, name_convert, runtime_env::name_convert, name_convert_env, runtime_env::name_convert_env, NULL, p, PATHSEPS, physical_cancel, runtime_env::physical_cancel, physical_cancel_env, runtime_env::physical_cancel_env, resolve_path, runtime_env::resolve_path, resolve_size, runtime_env::resolve_size, and SLASH_STR.

Referenced by cob_init().

1287 {
1288  char *buff;
1289  char *s;
1290  char *p;
1291  size_t i;
1292 #ifndef HAVE_DESIGNATED_INITS
1293  const unsigned char *pv;
1294 #endif
1295 #ifdef __OS400__
1296  char *t;
1297 #endif
1298 
1299  cobglobptr = lptr;
1300 
1303  resolve_path = NULL;
1304  resolve_alloc = NULL;
1305  resolve_error = NULL;
1307  mainhandle = NULL;
1308  call_buffer = NULL;
1312  call_table = NULL;
1313  call_lastsize = 0;
1314  resolve_size = 0;
1315  name_convert = 0;
1316  cob_jmp_primed = 0;
1317  physical_cancel = 0;
1318 
1319 #ifndef HAVE_DESIGNATED_INITS
1320  memset (valid_char, 0, sizeof(valid_char));
1321  for (pv = pvalid_char; *pv; ++pv) {
1322  valid_char[*pv] = 1;
1323  }
1324 #endif
1325 
1326  /* Big enough for anything from libdl/libltdl */
1328 
1329 #ifndef COB_ALT_HASH
1330  call_table = cob_malloc (sizeof (struct call_hash *) * HASH_SIZE);
1331 #endif
1332 
1333  call_filename_buff = cob_malloc ((size_t)COB_NORMAL_BUFF);
1334  call_entry_buff = cob_malloc ((size_t)COB_SMALL_BUFF);
1335 
1336  s = getenv ("COB_PHYSICAL_CANCEL");
1337  if (s) {
1339 
1340  if (*s == 'Y' || *s == 'y' || *s == '1') {
1341  physical_cancel = 1;
1342  }
1343  } else {
1344  s = getenv ("default_cancel_mode");
1345  if (s) {
1346  if (*s == '0') {
1347  physical_cancel = 1;
1348  }
1349  }
1350  }
1351 
1352  s = getenv ("COB_LOAD_CASE");
1353  if (s != NULL) {
1355 
1356  if (strcasecmp (s, "LOWER") == 0) {
1357  name_convert = 1;
1358  } else if (strcasecmp (s, "UPPER") == 0) {
1359  name_convert = 2;
1360  }
1361  }
1362 
1363  buff = cob_fast_malloc ((size_t)COB_MEDIUM_BUFF);
1364  s = getenv ("COB_LIBRARY_PATH");
1365  if (s == NULL) {
1366  snprintf (buff, (size_t)COB_MEDIUM_MAX, ".%s%s",
1367  PATHSEPS, COB_LIBRARY_PATH);
1368  } else {
1370 
1371  snprintf (buff, (size_t)COB_MEDIUM_MAX, "%s%s.%s%s",
1372  s, PATHSEPS, PATHSEPS, COB_LIBRARY_PATH);
1373  }
1374  cob_set_library_path (buff);
1375 
1376  lt_dlinit ();
1377 
1378 #ifndef COB_BORKED_DLOPEN
1379  mainhandle = lt_dlopen (NULL);
1380 #endif
1381 
1382  s = getenv ("COB_PRE_LOAD");
1383  if (s != NULL) {
1385 
1386  p = cob_strdup (s);
1387  s = strtok (p, PATHSEPS);
1388  for (; s; s = strtok (NULL, PATHSEPS)) {
1389 #ifdef __OS400__
1390  for (t = s; *t; ++t) {
1391  *t = toupper (*t);
1392  }
1393  cache_preload (t);
1394 #else
1395  for (i = 0; i < resolve_size; ++i) {
1396  buff[COB_MEDIUM_MAX] = 0;
1397  snprintf (buff, (size_t)COB_MEDIUM_MAX,
1398  "%s%s%s.%s",
1399  resolve_path[i], SLASH_STR, s, COB_MODULE_EXT);
1400  if (cache_preload (buff)) {
1401  break;
1402  }
1403  }
1404  /* If not found, try just using the name */
1405  if (i == resolve_size) {
1406  (void)cache_preload (s);
1407  }
1408 #endif
1409  }
1410  cob_free (p);
1411  }
1412  cob_free (buff);
1415 
1416  runtimeptr->physical_cancel = &physical_cancel;
1418  runtimeptr->name_convert = &name_convert;
1419  runtimeptr->name_convert_env = name_convert_env;
1420  runtimeptr->resolve_path = resolve_path;
1421  runtimeptr->resolve_size = &resolve_size;
1424  runtimeptr->cob_preload_env = cob_preload_env;
1425 }
void cob_longjmp ( struct cobjmp_buf jbuf)

References _, cobjmp_buf::cbj_jmp_buf, cob_fatal_error(), COB_FERROR_INITIALIZED, cob_runtime_error(), cob_stop_run(), and unlikely.

1168 {
1169  if (unlikely(!cobglobptr)) {
1170  cob_fatal_error (COB_FERROR_INITIALIZED);
1171  }
1172  if (unlikely(!jbuf)) {
1173  cob_runtime_error (_("NULL parameter passed to 'cob_longjmp'"));
1174  cob_stop_run (1);
1175  }
1176  if (!cob_jmp_primed) {
1177  cob_runtime_error (_("Call to 'cob_longjmp' with no prior 'cob_setjmp'"));
1178  cob_stop_run (1);
1179  }
1180  cob_jmp_primed = 0;
1181  longjmp (jbuf->cbj_jmp_buf, 1);
1182 }
void* cob_resolve ( const char *  name)

References cob_chk_call_path(), cob_free(), cob_resolve_internal(), and p.

Referenced by main().

916 {
917  void *p;
918  char *entry;
919  char *dirent;
920 
921  entry = cob_chk_call_path (name, &dirent);
922  p = cob_resolve_internal (entry, dirent, 0);
923  if (dirent) {
924  cob_free (dirent);
925  }
926  return p;
927 }
void* cob_resolve_cobol ( const char *  name,
const int  fold_case,
const int  errind 
)

References cob_call_error(), cob_chk_call_path(), cob_free(), cob_resolve_internal(), cob_set_exception(), p, and unlikely.

Referenced by cob_call().

931 {
932  void *p;
933  char *entry;
934  char *dirent;
935 
936  entry = cob_chk_call_path (name, &dirent);
937  p = cob_resolve_internal (entry, dirent, fold_case);
938  if (dirent) {
939  cob_free (dirent);
940  }
941  if (unlikely(!p)) {
942  if (errind) {
943  cob_call_error ();
944  }
945  cob_set_exception (COB_EC_PROGRAM_NOT_FOUND);
946  }
947  return p;
948 }
const char* cob_resolve_error ( void  )

References _, NULL, p, and resolve_error.

Referenced by cob_call_error().

872 {
873  const char *p;
874 
875  if (!resolve_error) {
876  p = _("Indeterminable error");
877  } else {
878  p = resolve_error;
880  }
881  return p;
882 }
void* cob_resolve_func ( const char *  name)

References _, cob_resolve_internal(), cob_runtime_error(), cob_stop_run(), NULL, p, and unlikely.

952 {
953  void *p;
954 
955  p = cob_resolve_internal (name, NULL, 0);
956  if (unlikely(!p)) {
957  cob_runtime_error (_("User function '%s' not found"), name);
958  cob_stop_run (1);
959  }
960  return p;
961 }
static void* cob_resolve_internal ( const char *  name,
const char *  dirent,
const int  fold_case 
)
static

References _, cache_dynload(), call_entry2_buff, call_entry_buff, cob_fatal_error(), COB_FERROR_INITIALIZED, __cob_global::cob_first_init, COB_FOLD_LOWER, COB_FOLD_UPPER, cob_malloc(), COB_MODULE_EXT, COB_NORMAL_MAX, cob_set_exception(), COB_SMALL_BUFF, cob_u8_t, call_hash::func, struct_handle::handle, insert(), likely, lookup(), struct_handle::next, NULL, p, struct_handle::path, R_OK, resolve_size, set_resolve_error(), SLASH_STR, and unlikely.

Referenced by cob_call_field(), cob_resolve(), cob_resolve_cobol(), and cob_resolve_func().

608 {
609  unsigned char *p;
610  const unsigned char *s;
611  void *func;
612  struct struct_handle *preptr;
613  lt_dlhandle handle;
614  size_t i;
615 
616  if (unlikely(!cobglobptr)) {
617  cob_fatal_error (COB_FERROR_INITIALIZED);
618  }
619  cob_set_exception (0);
620 
621  /* Search the cache */
622  func = lookup (name);
623  if (func) {
624  return func;
625  }
626 
627  /* Encode program name */
628  p = (unsigned char *)call_entry_buff;
629  s = (const unsigned char *)name;
630  if (unlikely(*s <= (unsigned char)'9' && *s >= (unsigned char)'0')) {
631  *p++ = (unsigned char)'_';
632  }
633  for (; *s; ++s) {
634  if (likely(valid_char[*s])) {
635  *p++ = *s;
636  } else {
637  *p++ = (unsigned char)'_';
638  if (*s == (unsigned char)'-') {
639  *p++ = (unsigned char)'_';
640  } else {
641  *p++ = hexval[*s / 16U];
642  *p++ = hexval[*s % 16U];
643  }
644  }
645  }
646  *p = 0;
647 
648  /* Check case folding */
649  switch (fold_case) {
650  case COB_FOLD_UPPER:
651  for (p = (unsigned char *)call_entry_buff; *p; p++) {
652  if (islower (*p)) {
653  *p = (cob_u8_t)toupper (*p);
654  }
655  }
656  break;
657  case COB_FOLD_LOWER:
658  for (p = (unsigned char *)call_entry_buff; *p; p++) {
659  if (isupper (*p)) {
660  *p = (cob_u8_t)tolower (*p);
661  }
662  }
663  break;
664  default:
665  break;
666  }
667 
668  /* Search the main program */
669  if (mainhandle != NULL) {
670  func = lt_dlsym (mainhandle, call_entry_buff);
671  if (func != NULL) {
672  insert (name, func, mainhandle, NULL, NULL, 1);
675  return func;
676  }
677  }
678 
679  /* Search preloaded modules */
680  for (preptr = base_preload_ptr; preptr; preptr = preptr->next) {
681  func = lt_dlsym (preptr->handle, call_entry_buff);
682  if (func != NULL) {
683  insert (name, func, preptr->handle, NULL, preptr->path, 1);
685  return func;
686  }
687  }
688 
689  /* Search dynamic modules */
690  for (preptr = base_dynload_ptr; preptr; preptr = preptr->next) {
691  if (!preptr->handle) {
692  continue;
693  }
694  func = lt_dlsym (preptr->handle, call_entry_buff);
695  if (func != NULL) {
696  insert (name, func, preptr->handle,
697  NULL, preptr->path, 1);
699  return func;
700  }
701  }
702 
703 #if 0 /* RXWRXW RTLD */
704 #if defined(USE_LIBDL) && defined (RTLD_DEFAULT)
705  func = lt_dlsym (RTLD_DEFAULT, call_entry_buff);
706  if (func != NULL) {
707  insert (name, func, NULL, NULL, NULL, 1);
709  return func;
710  }
711 #endif
712 #endif
713 
714  s = (const unsigned char *)name;
715 
716  /* Check if name needs conversion */
717  if (unlikely(name_convert != 0)) {
718  if (!call_entry2_buff) {
719  call_entry2_buff = cob_malloc ((size_t)COB_SMALL_BUFF);
720  }
721  p = call_entry2_buff;
722  for (; *s; ++s, ++p) {
723  if (name_convert == 1 && isupper (*s)) {
724  *p = (cob_u8_t) tolower (*s);
725  } else if (name_convert == 2 && islower (*s)) {
726  *p = (cob_u8_t) toupper (*s);
727  } else {
728  *p = *s;
729  }
730  }
731  *p = 0;
732  s = (const unsigned char *)call_entry2_buff;
733  }
734 
735  /* Search external modules */
736 #ifdef __OS400__
737  strcpy (call_filename_buff, s);
738  for(p = call_filename_buff; *p; ++p) {
739  *p = (cob_u8_t)toupper(*p);
740  }
741  handle = lt_dlopen (call_filename_buff);
742  if (handle != NULL) {
743  /* Candidate for future calls */
745  func = lt_dlsym (handle, call_entry_buff);
746  if (func != NULL) {
747  insert (name, func, handle, NULL, call_filename_buff, 0);
749  return func;
750  }
751  }
752 #else
753  if (dirent) {
755  snprintf (call_filename_buff, (size_t)COB_NORMAL_MAX,
756  "%s%s.%s", dirent, (char *)s, COB_MODULE_EXT);
757  if (access (call_filename_buff, R_OK) != 0) {
758  set_resolve_error (_("Cannot find module"), name);
759  return NULL;
760  }
761  handle = lt_dlopen (call_filename_buff);
762  if (handle != NULL) {
763  /* Candidate for future calls */
765  func = lt_dlsym (handle, call_entry_buff);
766  if (func != NULL) {
767  insert (name, func, handle, NULL,
768  call_filename_buff, 0);
770  return func;
771  }
772  }
773  set_resolve_error (_("Cannot find entry point"),
774  (const char *)s);
775  return NULL;
776  }
777  for (i = 0; i < resolve_size; ++i) {
778  call_filename_buff[COB_NORMAL_MAX] = 0;
779  if (resolve_path[i] == NULL) {
780  snprintf (call_filename_buff, (size_t)COB_NORMAL_MAX,
781  "%s.%s", (char *)s, COB_MODULE_EXT);
782  } else {
783  snprintf (call_filename_buff, (size_t)COB_NORMAL_MAX,
784  "%s%s%s.%s", resolve_path[i],
785  SLASH_STR,
786  (char *)s,
788  }
789  if (access (call_filename_buff, R_OK) == 0) {
790  handle = lt_dlopen (call_filename_buff);
791  if (handle != NULL) {
792  /* Candidate for future calls */
794  func = lt_dlsym (handle, call_entry_buff);
795  if (func != NULL) {
796  insert (name, func, handle, NULL,
797  call_filename_buff, 0);
799  return func;
800  }
801  }
802  set_resolve_error (_("Cannot find entry point"),
803  (const char *)s);
804  return NULL;
805  }
806  }
807 #endif
808 
809  set_resolve_error (_("Cannot find module"), name);
810  return NULL;
811 }
void* cob_savenv ( struct cobjmp_buf jbuf)

References _, cobjmp_buf::cbj_jmp_buf, cob_fatal_error(), COB_FERROR_INITIALIZED, cob_runtime_error(), cob_stop_run(), and unlikely.

Referenced by cob_savenv2().

1142 {
1143  if (unlikely(!cobglobptr)) {
1144  cob_fatal_error (COB_FERROR_INITIALIZED);
1145  }
1146  if (unlikely(!jbuf)) {
1147  cob_runtime_error (_("NULL parameter passed to 'cob_savenv'"));
1148  cob_stop_run (1);
1149  }
1150  if (cob_jmp_primed) {
1151  cob_runtime_error (_("Multiple call to 'cob_setjmp'"));
1152  cob_stop_run (1);
1153  }
1154  cob_jmp_primed = 1;
1155  return jbuf->cbj_jmp_buf;
1156 }
void* cob_savenv2 ( struct cobjmp_buf jbuf,
const int  jsize 
)

References cob_savenv(), and COB_UNUSED.

1160 {
1161  COB_UNUSED (jsize);
1162 
1163  return cob_savenv (jbuf);
1164 }
void cob_set_cancel ( cob_module m)

References call_table, cob_call_union::funcvoid, hash(), insert(), call_hash::module, __cob_module::module_entry, __cob_module::module_name, __cob_module::module_path, call_hash::name, call_hash::next, NULL, p, and call_hash::path.

893 {
894  struct call_hash *p;
895 
896 #ifdef COB_ALT_HASH
897  p = call_table;
898 #else
899  p = call_table[hash ((const unsigned char *)(m->module_name))];
900 #endif
901  for (; p; p = p->next) {
902  if (strcmp (m->module_name, p->name) == 0) {
903  p->module = m;
904  /* Set path in program module structure */
905  if (p->path && m->module_path && !*(m->module_path)) {
906  *(m->module_path) = p->path;
907  }
908  return;
909  }
910  }
911  insert (m->module_name, m->module_entry.funcvoid, NULL, m, NULL, 1);
912 }
static void cob_set_library_path ( const char *  path)
static

References cob_free(), cob_malloc(), NULL, p, PATHSEPC, PATHSEPS, resolve_alloc, and resolve_size.

Referenced by cob_init_call().

287 {
288  char *p;
289  char *pstr;
290  size_t i;
291  size_t size;
292  struct stat st;
293 
294  int flag;
295 
296  /* Clear the previous path */
297  if (resolve_path) {
300  }
301 
302  /* Count the number of separators */
303  i = 1;
304  size = 0;
305  for (p = (char *)path; *p; p++, size++) {
306  if (*p == PATHSEPC) {
307  i++;
308  }
309  }
310 
311  /* Build path array */
312  size++;
313  resolve_alloc = cob_malloc (size);
314  pstr = resolve_alloc;
315  for (p = (char *)path; *p; p++, pstr++) {
316 #ifdef _WIN32
317  if (*p == (unsigned char)'/') {
318  *pstr = (unsigned char)'\\';
319  continue;
320  }
321 #else
322  if (*p == (unsigned char)'\\') {
323  *pstr = (unsigned char)'/';
324  continue;
325  }
326 #endif
327  *pstr = *p;
328  }
329 
330  resolve_path = cob_malloc (sizeof (char *) * i);
331  resolve_size = 0;
332  pstr = resolve_alloc;
333  for (; ; ) {
334  p = strtok (pstr, PATHSEPS);
335  if (!p) {
336  break;
337  }
338  pstr = NULL;
339  if (stat (p, &st) || !(S_ISDIR (st.st_mode))) {
340  continue;
341  }
342 
343  /*
344  * look if we already have this path
345  */
346  flag = 0;
347  for (i = 0; i < resolve_size; i++) {
348  if(strcmp(resolve_path[i], p) == 0) {
349  flag = 1;
350  break;
351  }
352  }
353 
354  if (!flag) {
355  resolve_path[resolve_size++] = p;
356  }
357  }
358 }
static void do_cancel_module ( struct call_hash p,
struct call_hash **  base_hash,
struct call_hash prev 
)
static

References base_dynload_ptr, cob_free(), __cob_module::flag_no_phys_canc, cob_call_union::funcint, cob_call_union::funcvoid, call_hash::handle, struct_handle::handle, call_hash::module, __cob_module::module_active, __cob_module::module_cancel, __cob_module::module_ref_count, call_hash::name, call_hash::next, struct_handle::next, call_hash::no_phys_cancel, NULL, and call_hash::path.

Referenced by cob_cancel().

363 {
364  struct struct_handle *dynptr;
365  int (*cancel_func)(const int, void *, void *, void *, void *);
366  int nocancel;
367  nocancel = 0;
368 
369  if (!p->module) {
370  return;
371  }
372  if (!p->module->module_cancel.funcvoid) {
373  return;
374  }
375  if (p->module->flag_no_phys_canc) {
376  nocancel = 1;
377  }
378  /* This should be impossible */
379  if (p->module->module_active) {
380  nocancel = 1;
381  }
382  if (p->module->module_ref_count &&
383  *(p->module->module_ref_count)) {
384  nocancel = 1;
385  }
386  cancel_func = p->module->module_cancel.funcint;
387  (void)cancel_func (-1, NULL, NULL, NULL, NULL);
388  p->module = NULL;
389 
390  if (nocancel) {
391  return;
392  }
393  if (!physical_cancel) {
394  return;
395  }
396  if (p->no_phys_cancel) {
397  return;
398  }
399  if (!p->handle) {
400  return;
401  }
402 
403  lt_dlclose (p->handle);
404 
405  dynptr = base_dynload_ptr;
406  for (; dynptr; dynptr = dynptr->next) {
407  if (dynptr->handle == p->handle) {
408  dynptr->handle = NULL;
409  }
410  }
411 
412  if (!prev) {
413  *base_hash = p->next;
414  } else {
415  prev->next = p->next;
416  }
417  if (p->name) {
418  cob_free ((void *)(p->name));
419  }
420  if (p->path) {
421  cob_free ((void *)(p->path));
422  }
423  cob_free (p);
424 }
static COB_INLINE unsigned int hash ( const unsigned char *  s)
static

References HASH_SIZE.

Referenced by cob_cancel(), cob_set_cancel(), insert(), and lookup().

531 {
532  unsigned int val = 0;
533 
534  while (*s) {
535  val += *s++;
536  }
537  return val % HASH_SIZE;
538 }
static void insert ( const char *  name,
void *  func,
lt_dlhandle  handle,
cob_module module,
const char *  path,
const unsigned int  nocanc 
)
static

References call_table, cob_free(), cob_malloc(), COB_NORMAL_BUFF, cob_strdup(), call_hash::func, call_hash::handle, hash(), call_hash::module, call_hash::name, call_hash::next, call_hash::no_phys_cancel, NULL, p, and call_hash::path.

Referenced by cob_resolve_internal(), and cob_set_cancel().

545 {
546  struct call_hash *p;
547 #ifndef COB_ALT_HASH
548  unsigned int val;
549 #endif
550 
551  p = cob_malloc (sizeof (struct call_hash));
552  p->name = cob_strdup (name);
553  p->func = func;
554  p->handle = handle;
555  p->module = module;
556  if (path) {
557 #ifdef _WIN32
558  /* Malloced path or NULL */
559  p->path = _fullpath (NULL, path, 1);
560 #elif defined(HAVE_CANONICALIZE_FILE_NAME)
561  /* Malloced path or NULL */
562  p->path = canonicalize_file_name (path);
563 #elif defined(HAVE_REALPATH)
564  char *s;
565 
566  s = cob_malloc ((size_t)COB_NORMAL_BUFF);
567  if (realpath (path, s) != NULL) {
568  p->path = cob_strdup (s);
569  }
570  cob_free (s);
571 #endif
572  if (!p->path) {
573  p->path = cob_strdup (path);
574  }
575  }
576  p->no_phys_cancel = nocanc;
577 #ifdef COB_ALT_HASH
578  p->next = call_table;
579  call_table = p;
580 #else
581  val = hash ((const unsigned char *)name);
582  p->next = call_table[val];
583  call_table[val] = p;
584 #endif
585 }
static void* lookup ( const char *  name)
static

References call_table, call_hash::func, hash(), call_hash::name, call_hash::next, NULL, and p.

Referenced by cob_resolve_internal().

589 {
590  struct call_hash *p;
591 
592 #ifdef COB_ALT_HASH
593  p = call_table;
594 #else
595  p = call_table[hash ((const unsigned char *)name)];
596 #endif
597  for (; p; p = p->next) {
598  if (strcmp (name, p->name) == 0) {
599  return p->func;
600  }
601  }
602  return NULL;
603 }
static void set_resolve_error ( const char *  msg,
const char *  entry 
)
static

References CALL_BUFF_MAX, __cob_global::cob_first_init, cob_set_exception(), and resolve_error_buff.

Referenced by cob_resolve_internal().

276 {
278  snprintf (resolve_error_buff, (size_t)CALL_BUFF_MAX,
279  "%s '%s'", msg, entry);
281  cob_set_exception (COB_EC_PROGRAM_NOT_FOUND);
283 }

Variable Documentation

struct struct_handle* base_dynload_ptr
static

Referenced by cache_dynload(), and do_cancel_module().

struct struct_handle* base_preload_ptr
static

Referenced by cache_preload().

void* call_buffer
static

Referenced by cob_get_buff().

unsigned char* call_entry2_buff
static

Referenced by cob_resolve_internal().

char* call_entry_buff
static

Referenced by cob_resolve_internal().

char* call_filename_buff
static
size_t call_lastsize
static
struct call_hash** call_table
static
unsigned int cob_jmp_primed
static
char* cob_library_path_env
static

Referenced by cob_init_call().

char* cob_preload_env
static

Referenced by cob_init_call().

char* cob_preload_resolved
static
cob_global* cobglobptr
static
const unsigned char hexval[] = "0123456789ABCDEF"
static
lt_dlhandle mainhandle
static
unsigned int name_convert
static

Referenced by cob_init_call().

char* name_convert_env
static

Referenced by cob_init_call().

unsigned int physical_cancel
static

Referenced by cob_init_call().

char* physical_cancel_env
static

Referenced by cob_init_call().

const unsigned char pvalid_char[]
static
Initial value:
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
char* resolve_alloc
static

Referenced by cob_set_library_path().

char* resolve_error
static

Referenced by cob_resolve_error().

char* resolve_error_buff
static

Referenced by set_resolve_error().

char** resolve_path
static

Referenced by cob_init_call().

size_t resolve_size
static
struct system_table system_tab[]
static
unsigned char valid_char[256]
static