aboutsummaryrefslogtreecommitdiff
path: root/libgcobol/libgcobol.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libgcobol/libgcobol.cc')
-rw-r--r--libgcobol/libgcobol.cc241
1 files changed, 190 insertions, 51 deletions
diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc
index 81b5b7a..c3d78d4 100644
--- a/libgcobol/libgcobol.cc
+++ b/libgcobol/libgcobol.cc
@@ -10132,49 +10132,45 @@ __gg__classify( classify_t type,
return retval;
}
-extern "C"
+static
int
-__gg__accept_envar( cblc_field_t *tgt,
- size_t tgt_offset,
- size_t tgt_length,
- cblc_field_t *name,
- size_t name_offset,
- size_t name_length)
+accept_envar( cblc_field_t *tgt,
+ size_t tgt_offset,
+ size_t tgt_length,
+ const char *psz_name)
{
- int retval;
- tgt_length = tgt_length ? tgt_length : tgt->capacity;
- name_length = name_length ? name_length : name->capacity;
-
- // Pick up the environment variable name, which is in teh internal codeset
- static char *env = NULL;
- static size_t env_length = 0;
- if( env_length < name_length+1 )
+ int retval = 1; // 1 means we couldn't find it
+ if( psz_name )
{
- env_length = name_length+1;
- env = static_cast<char *>(realloc(env, env_length));
- }
- memcpy(env, name->data + name_offset, name_length);
- env[name_length] = '\0';
+ tgt_length = tgt_length ? tgt_length : tgt->capacity;
- // Get rid of leading and trailing internal_space characters:
- char *trimmed_env = brute_force_trim(env);
+ // Pick up the environment variable name, which is in the internal codeset
+ char *env = strdup(psz_name);
+ massert(env);
- // Convert the name to the console codeset:
- __gg__internal_to_console_in_place(trimmed_env, strlen(trimmed_env));
+ // Get rid of leading and trailing internal_space characters:
+ char *trimmed_env = brute_force_trim(env);
- // Pick up the environment variable, and convert it to the internal codeset
- const char *p = getenv(trimmed_env);
- if(p)
- {
- char *pp = strdup(p);
- console_to_internal(pp, strlen(pp));
- retval = 0; // Okay
- move_string(tgt, tgt_offset, tgt_length, pp);
- free(pp);
+ // Convert the name to the console codeset:
+ __gg__internal_to_console_in_place(trimmed_env, strlen(trimmed_env));
+
+ // Pick up the environment variable, and convert it to the internal codeset
+ const char *p = getenv(trimmed_env);
+ if(p)
+ {
+ char *pp = strdup(p);
+ massert(pp);
+ console_to_internal(pp, strlen(pp));
+ retval = 0; // Okay
+ move_string(tgt, tgt_offset, tgt_length, pp);
+ free(pp);
+ }
+ free(env);
}
- else
+
+ if( retval == 1 )
{
- retval = 1; // Could't find it
+ // Could't find it
exception_raise(ec_argument_imp_environment_e);
}
@@ -10182,6 +10178,28 @@ __gg__accept_envar( cblc_field_t *tgt,
}
extern "C"
+int
+__gg__accept_envar( cblc_field_t *tgt,
+ size_t tgt_offset,
+ size_t tgt_length,
+ const cblc_field_t *name,
+ size_t name_offset,
+ size_t name_length)
+ {
+ // We need the name to be nul-terminated:
+ char *p = static_cast<char *>(malloc(name_length + 1));
+ massert(p);
+ memcpy(p, name->data+name_offset, name_length);
+ p[name_length] = '\0';
+ int retval = accept_envar(tgt,
+ tgt_offset,
+ tgt_length,
+ p);
+ free(p);
+ return retval;
+ }
+
+extern "C"
bool
__gg__set_envar(cblc_field_t *name,
size_t name_offset,
@@ -11247,35 +11265,42 @@ match_declarative( bool enabled,
return matches;
}
-/*
- * The default exception handler is called if:
- * 1. The EC is enabled and was not handled by a Declarative, or
- * 2. The EC is EC-I-O and was not handled by a Format-1 Declarative, or
- * 3. The EC is EC-I-O, associated with a file, and is not OPEN or CLOSE.
- */
-static void
-default_exception_handler( ec_type_t ec )
+static
+void open_syslog(int option, int facility)
{
+ static bool first_time = true;
+ if( first_time ) {
#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
/* Declared in errno.h, when available. */
- static const char * const ident = program_invocation_short_name;
+ static const char * const ident = program_invocation_short_name;
#elif defined (HAVE_GETPROGNAME)
/* Declared in stdlib.h. */
- static const char * const ident = getprogname();
+ static const char * const ident = getprogname();
#else
/* Avoid a NULL entry. */
- static const char * const ident = "unnamed_COBOL_program";
+ static const char * const ident = "unnamed_COBOL_program";
#endif
- static bool first_time = true;
- static const int priority = LOG_INFO, option = LOG_PERROR, facility = LOG_USER;
- ec_disposition_t disposition = ec_category_fatal_e;
-
- if( first_time ) {
// TODO: Program to set option in library via command-line and/or environment.
// Library listens to program, not to the environment.
openlog(ident, option, facility);
first_time = false;
}
+}
+
+/*
+ * The default exception handler is called if:
+ * 1. The EC is enabled and was not handled by a Declarative, or
+ * 2. The EC is EC-I-O and was not handled by a Format-1 Declarative, or
+ * 3. The EC is EC-I-O, associated with a file, and is not OPEN or CLOSE.
+ */
+static void
+default_exception_handler( ec_type_t ec )
+{
+ static const int priority = LOG_INFO, option = LOG_PERROR, facility = LOG_USER;
+ open_syslog(option, facility);
+
+ ec_disposition_t disposition = ec_category_fatal_e;
+
if( ec != ec_none_e ) {
auto pec = std::find_if( __gg__exception_table, __gg__exception_table_end,
@@ -13149,6 +13174,7 @@ operator<<( std::vector<cbl_declarative_t>& dcls,
}
// The first element of each array is the number of elements that follow
+// The first element of each array is the number of elements that follow
extern "C"
void
__gg__set_exception_environment( uint64_t *ecs, uint64_t *dcls )
@@ -13207,6 +13233,7 @@ __gg__set_env_name( const cblc_field_t *var,
size_t offset,
size_t length )
{
+ // implements DISPLAY UPON ENVIRONMENT-NAME
free(sv_envname);
sv_envname = static_cast<char *>(malloc(length+1));
massert(sv_envname);
@@ -13214,12 +13241,41 @@ __gg__set_env_name( const cblc_field_t *var,
sv_envname[length] = '\0';
}
+
+extern "C"
+void
+__gg__get_env_name( cblc_field_t *dest,
+ size_t dest_offset,
+ size_t dest_length)
+ {
+ // Implements ACCEPT FROM ENVIRONMENT-NAME
+ // It returns the value previously established by __gg__set_env_name.
+ if( sv_envname )
+ {
+ sv_envname = strdup("");
+ }
+ move_string(dest, dest_offset, dest_length, sv_envname);
+ }
+
+extern "C"
+int
+__gg__get_env_value(cblc_field_t *dest,
+ size_t dest_offset,
+ size_t dest_length)
+ {
+ return accept_envar(dest,
+ dest_offset,
+ dest_length,
+ sv_envname);
+ }
+
extern "C"
void
__gg__set_env_value(const cblc_field_t *value,
size_t offset,
size_t length )
{
+ // implements DISPLAY UPON ENVIRONMENT-VALUE
size_t name_length = strlen(sv_envname);
size_t value_length = length;
@@ -13261,6 +13317,11 @@ __gg__set_env_value(const cblc_field_t *value,
extern "C"
void
__gg__fprintf_stderr(const char *format_string, ...)
+ __attribute__ ((__format__ (__printf__, 1, 2)));
+
+extern "C"
+void
+__gg__fprintf_stderr(const char *format_string, ...)
{
/* This routine allows the compiler to send stuff to stderr in a way
that is straightforward to use.. */
@@ -13270,3 +13331,81 @@ __gg__fprintf_stderr(const char *format_string, ...)
va_end(ap);
}
+
+static int sv_argument_number = 0;
+
+extern "C"
+void
+__gg__set_arg_num( const cblc_field_t *index,
+ size_t index_offset,
+ size_t index_size )
+ {
+ // Implements DISPLAY UPON ARGUMENT-NUMBER.
+ int rdigits;
+ __int128 N = get_binary_value_local(&rdigits,
+ index,
+ index->data + index_offset,
+ index_size);
+ // If he gives us fractional digits, just truncate
+ N /= __gg__power_of_ten(rdigits);
+
+ // N is 1-based, per normal COBOL. We have to decrement it here:
+ N -= 1;
+ sv_argument_number = static_cast<int>(N);
+ }
+
+extern "C"
+int
+__gg__accept_arg_value( cblc_field_t *dest,
+ size_t dest_offset,
+ size_t dest_length)
+ {
+ // Implements ACCEPT FROM ARGUMENT-VALUE
+ int retcode;
+ command_line_plan_b();
+ if( sv_argument_number >= stashed_argc || sv_argument_number < 0 )
+ {
+ exception_raise(ec_argument_imp_command_e);
+ retcode = 1; // Error
+ }
+ else
+ {
+ char *retval = strdup(stashed_argv[sv_argument_number]);
+ console_to_internal(retval, strlen(retval));
+ move_string(dest, dest_offset, dest_length, retval);
+ free(retval);
+ retcode = 0; // Okay
+
+ // The Fujitsu spec says bump this value by one.
+ sv_argument_number += 1;
+ }
+ return retcode;
+ }
+
+extern "C"
+int
+__gg__get_file_descriptor(const char *device)
+ {
+ int retval = open(device, O_WRONLY);
+
+ if( retval == -1 )
+ {
+ char *msg;
+ int ec = asprintf(&msg,
+ "Trying to open %s. Got error %s",
+ device,
+ strerror(errno));
+ if( ec != -1 )
+ {
+ static const int priority = LOG_INFO,
+ option = LOG_PERROR,
+ facility = LOG_USER;
+ open_syslog(option, facility);
+ syslog(priority, "%s", msg);
+ }
+
+ // Open a new handle to /dev/stdout, since our caller will be closing it
+ retval = open("/dev/stdout", O_WRONLY);
+ }
+ return retval;
+ }