summaryrefslogtreecommitdiff
path: root/support/vvcode/vvencode.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/vvcode/vvencode.c
Initial commit
Diffstat (limited to 'support/vvcode/vvencode.c')
-rw-r--r--support/vvcode/vvencode.c2349
1 files changed, 2349 insertions, 0 deletions
diff --git a/support/vvcode/vvencode.c b/support/vvcode/vvencode.c
new file mode 100644
index 0000000000..99b8827879
--- /dev/null
+++ b/support/vvcode/vvencode.c
@@ -0,0 +1,2349 @@
+/*-
+******************************************************************************
+******************************************************************************
+**
+** ARCHIVE HEADER INFORMATION
+**
+** @C-file{
+** FILENAME = "vvencode.c",
+** VERSION = "1.00",
+** DATE = "",
+** TIME = "",
+**
+** AUTHOR = "Niel Kempson",
+** ADDRESS = "25 Whitethorn Drive, Cheltenham, GL52 5LL, England",
+** TELEPHONE = "+44-242 579105",
+** EMAIL = "kempson@tex.ac.uk (Internet)",
+**
+** SUPPORTED = "yes",
+** ARCHIVED = "tex.ac.uk, ftp.tex.ac.uk",
+** KEYWORDS = "VVcode",
+**
+** CODETABLE = "ISO/ASCII",
+** CHECKSUM = "51492 1481 5732 57976",
+**
+** DOCSTRING = { This file is part of VVcode.
+** }
+** }
+**
+**
+** MODULE CONTENTS
+**
+**
+** COPYRIGHT
+**
+** Copyright (c) 1991-1993 by Niel Kempson <kempson@tex.ac.uk>
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License as
+** published by the Free Software Foundation; either version 1, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** In other words, you are welcome to use, share and improve this
+** program. You are forbidden to forbid anyone else to use, share
+** and improve what you give them. Help stamp out software-hoarding!
+**
+** CHANGE LOG
+**
+******************************************************************************
+******************************************************************************
+*/
+static char rcsid[] = "$Id$";
+
+
+#define VVENCODE 1
+#define VVCODE_MAIN 1
+
+/*-
+**----------------------------------------------------------------------------
+** Standard include files
+**----------------------------------------------------------------------------
+*/
+#include <stdio.h>
+
+
+/*-
+**----------------------------------------------------------------------------
+** Include the machine specific definitions
+**----------------------------------------------------------------------------
+*/
+#include "checkos.h"
+#include "machine.h"
+#include "local.h"
+#include "globals.h"
+#include "specific.h"
+#include "vvutils.h"
+
+
+/*-
+**----------------------------------------------------------------------------
+** Forward declarations of functions in this file
+**----------------------------------------------------------------------------
+*/
+int main ARGS ((CONST int argc,
+ CONST char *argv[]));
+Int32 enc_line ARGS ((CONST char *ip_buffer,
+ CONST Int32 num_bytes,
+ char *op_buffer));
+void encode ARGS ((void));
+void initialize ARGS ((void));
+void open_ip_file ARGS ((CONST Qualifier_Struct *ip_qualifier,
+ File_Info *ip_file));
+void open_op_file ARGS ((CONST Qualifier_Struct *op_qualifier,
+ CONST char *def_file_name,
+ CONST Int16 overwrite_flag,
+ File_Info *op_file));
+void set_enc_tbl ARGS ((CONST Qualifier_Struct *enc_qualifier,
+ CONST Int16 enc_tbl_len,
+ char *encode_table));
+void set_format ARGS ((CONST Qualifier_Struct *fmt_qualifier,
+ CONST File_Info *ex_file,
+ CONST char *fmt_str_array[],
+ File_Info *ip_file));
+void set_hdr_file_spec ARGS ((CONST Qualifier_Struct *hdr_qualifier,
+ CONST File_Info *ip_file,
+ char **hdr_file_spec));
+void set_ip_filespec ARGS ((CONST Qualifier_Struct *ip_qualifier,
+ File_Info *ip_file));
+void set_mode ARGS ((CONST Qualifier_Struct *mode_qualifier,
+ CONST File_Info *ex_file,
+ CONST char *mode_str_array[],
+ File_Info *ip_file));
+void set_record_len ARGS ((CONST Qualifier_Struct *rec_qualifer,
+ CONST File_Info *ex_file,
+ File_Info *ip_file));
+void set_split_size ARGS ((CONST File_Info *op_file,
+ Qualifier_Struct *split_qualifier,
+ Int32 *split_size));
+void set_timestamp ARGS ((CONST Qualifier_Struct *time_qualifier,
+ CONST File_Info *ex_file,
+ File_Info *ip_file));
+void start_next_op_file ARGS ((CONST Int16 overwrite_flag,
+ File_Info *op_file,
+ Int16 *op_part_no));
+void terminate ARGS ((void));
+void usage_error ARGS ((CONST char *reason));
+void wr_headers ARGS ((CONST Int16 part_no));
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** encode
+**
+** DESCRIPTION
+**
+** Encode the bytes from the input file and write them to the output
+** file.
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void encode (void)
+#else /* NOT (ANSI_SYNTAX) */
+ void encode ()
+#endif /* (ANSI_SYNTAX) */
+{
+ char *ip_buffer;
+ char *buf_ptr;
+ Int32 buffer_size;
+ Int32 bytes_left;
+ Int32 bytes_read;
+ Int32 bytes_to_encode;
+ Int16 encode_state;
+ SIZE_T idx;
+ char tmp_buffer[MAX_ENCODED_BYTES + 2];
+ char vv_buffer[2 * MAX_ENCODED_BYTES];
+ Int32 vve_line_bytes;
+ Int32 vve_room_needed;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** If the input file has variable length format records, then allocate
+ ** a buffer to hold the largest possible record. For fixed or stream
+ ** format files, allocate a smaller buffer of IO_BUFFER_SIZE bytes.
+ **------------------------------------------------------------------------
+ */
+ if (G_ip_file.format == FMT_VARIABLE)
+ {
+ buffer_size = (Int32) MAX_VARIABLE_RECORD_LEN;
+ }
+ else
+ {
+ buffer_size = (Int32) IO_BUFFER_SIZE;
+ }
+ ip_buffer = allocate_buffer ((SIZE_T) buffer_size, "ip_buffer");
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ for (;;)
+ {
+
+ /*-
+ **--------------------------------------------------------------------
+ **
+ **--------------------------------------------------------------------
+ */
+ if (G_ip_file.format == FMT_VARIABLE)
+ {
+ bytes_read = read_record (MAX_VARIABLE_RECORD_LEN, ip_buffer,
+ &G_ip_file);
+ if (bytes_read < 0L)
+ {
+ break;
+ }
+ G_ip_file.bytecount += bytes_read;
+ DEBUG_2 ("encode: record length = %5ld, total bytes read = %10ld",
+ bytes_read, G_ip_file.bytecount);
+ encode_state = ENCODE_REC_LEN;
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ **
+ **--------------------------------------------------------------------
+ */
+ else
+ {
+ bytes_read = read_bytes ((Int32) MAX_ENCODED_BYTES, ip_buffer,
+ &G_ip_file);
+ if (bytes_read <= 0L)
+ {
+ break;
+ }
+ G_ip_file.bytecount += (long) bytes_read;
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ ** If the /TRANSLATE command qualifier was specified, translate the
+ ** bytes read to the destination character set.
+ **--------------------------------------------------------------------
+ */
+ if (Q_TRANSLATE)
+ {
+ for (idx = 0; idx < (SIZE_T) bytes_read; idx++)
+ {
+ ip_buffer[idx] =
+ (char) G_xlt_table.xlt_tbl[(Byte) ip_buffer[idx]];
+ }
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ ** Compute the CRC of the bytes to be encoded in the VVE file.
+ **--------------------------------------------------------------------
+ */
+ for (idx = 0; idx < (SIZE_T) bytes_read; idx++)
+ {
+ UPDATE_CRC32 (G_ip_file.crc32, ip_buffer[idx]);
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ ** Write the remaining bytes in chunks of MAX_ENCODED_BYTES. If the
+ ** file is in variable length format, each record is likely to have a
+ ** shorter last line.
+ **--------------------------------------------------------------------
+ */
+ bytes_left = bytes_read;
+ buf_ptr = ip_buffer;
+
+ /*-
+ **--------------------------------------------------------------------
+ **
+ **--------------------------------------------------------------------
+ */
+ while (bytes_left > 0L)
+ {
+
+ /*-
+ **----------------------------------------------------------------
+ **
+ **----------------------------------------------------------------
+ */
+ if ((G_ip_file.format == FMT_VARIABLE)
+ && (encode_state == ENCODE_REC_LEN))
+ {
+ bytes_to_encode = MINIMUM (bytes_left, MAX_ENCODED_BYTES - 2);
+ tmp_buffer[0] = (char) (bytes_read / 256);
+ tmp_buffer[1] = (char) (bytes_read % 256);
+
+ for (idx = 0; idx < (SIZE_T) bytes_to_encode; idx++)
+ {
+ tmp_buffer[2 + idx] = ip_buffer[idx];
+ }
+ vve_line_bytes = enc_line (tmp_buffer, bytes_to_encode + 2,
+ vv_buffer);
+ bytes_left -= bytes_to_encode;
+ buf_ptr += (SIZE_T) bytes_to_encode;
+ encode_state = ENCODE_DATA;
+ }
+ /*-
+ **----------------------------------------------------------------
+ **
+ **----------------------------------------------------------------
+ */
+ else
+ {
+ bytes_to_encode = MINIMUM (bytes_left, MAX_ENCODED_BYTES);
+ vve_line_bytes = enc_line (buf_ptr, bytes_to_encode,
+ vv_buffer);
+ bytes_left -= bytes_to_encode;
+ buf_ptr += (SIZE_T) bytes_to_encode;
+ }
+
+ /*-
+ **----------------------------------------------------------------
+ ** If a maximum VVE output file size has been specified, check
+ ** whether this encoded line will cause that maximum size to be
+ ** exceeded.
+ **----------------------------------------------------------------
+ */
+ if (Q_SPLIT)
+ {
+ vve_room_needed = vve_line_bytes + TEXT_LINE_OVERHEAD
+ + VV_POSTAMBLE_LEN;
+
+ if ((G_oppart_bytes + vve_room_needed) >= G_split_size)
+ {
+ start_next_op_file (G_overwrite_flag, &G_op_file,
+ &G_oppt_no);
+ G_op_file.bytecount += G_oppart_bytes;
+ G_oppart_bytes = 0L;
+ wr_headers (G_oppt_no);
+ }
+ }
+
+ /*-
+ **----------------------------------------------------------------
+ ** Write the encoded line to the VVE file.
+ **----------------------------------------------------------------
+ */
+ VVEOUT (vv_buffer);
+ } /* while (bytes_left > 0L) */
+ } /* for (;;) */
+} /* encode */
+
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** initialize
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void initialize (void)
+#else /* NOT (ANSI_SYNTAX) */
+ void initialize ()
+#endif /* (ANSI_SYNTAX) */
+{
+ File_Info ex_file_info;
+ char *def_file_name;
+ File_Info xlt_file;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Set up the input file specification from the command line argument.
+ ** The 'pipe_flag' structure field is also set up.
+ **------------------------------------------------------------------------
+ */
+ set_ip_filespec (&G_cmd_ipfile, &G_ip_file);
+ def_file_name = allocate_buffer ((MAX_PATH + 1), "def_file_name");
+ (void) split_file_spec (G_ip_file.file_spec, NULL, def_file_name,
+ NULL, NULL);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (Q_OVERWRITE)
+ {
+ G_overwrite_flag = OVERWRITE_YES;
+ }
+ else
+ if (G_ip_file.pipe_flag == TRUE)
+ {
+ G_overwrite_flag = OVERWRITE_NO;
+ }
+ else
+ {
+ G_overwrite_flag = OVERWRITE_ASK;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** If the 'log' qualifier was specified, open the log file. On systems
+ ** which use 'STICKY_DEFAULTS', this must be done after the input file
+ ** specification is known.
+ **------------------------------------------------------------------------
+ */
+ open_log_file (&G_cmdqual[CMDQ_LOG], def_file_name, G_overwrite_flag,
+ &G_log_file);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_3 ("VVencode %s, %s release (%s)\n",
+ VV_VERSION_STR, VV_IMPLEMENTATION, VV_DATE);
+ LOGMSG_1 ("I/P file: %s", G_ip_file.file_spec);
+ LOGMSG_1 ("Overwrite existing files: %s",
+ (Q_OVERWRITE ? "yes" : "no"));
+ LOGMSG_1 ("Log file: %s", G_log_file.file_spec);
+ LOGMSG ("Encoding method: VVcode\n");
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Ensure that the local timezone offset from GMT is initialized.
+ **------------------------------------------------------------------------
+ */
+ (void) tz_offset (time ((TIME_T) NULL));
+
+ /*-
+ **------------------------------------------------------------------------
+ ** If we're not reading from standard input, attempt to determine the
+ ** the key file parameters by examining the file.
+ **------------------------------------------------------------------------
+ */
+ if (G_ip_file.pipe_flag != TRUE)
+ {
+ strcpy (ex_file_info.file_spec, G_ip_file.file_spec);
+ examine_file (&ex_file_info);
+
+ LOGMSG_1 ("I/P file mode: %s",
+ (ex_file_info.mode != INV_MODE) ?
+ (char *) G_mode_str[ex_file_info.mode] : "unknown");
+ LOGMSG_1 ("I/P file format: %s",
+ (ex_file_info.format != INV_FORMAT) ?
+ (char *) G_fmt_str[ex_file_info.format] : "unknown");
+
+ if (ex_file_info.lng_rec_len != INV_RECORD_LEN)
+ {
+ LOGMSG_1 ("I/P file longest record length: %ld",
+ ex_file_info.lng_rec_len);
+ }
+ else
+ {
+ LOGMSG ("I/P file longest record length: unknown");
+ }
+
+ if (ex_file_info.max_rec_len != INV_RECORD_LEN)
+ {
+ LOGMSG_1 ("I/P file maximum record length: %ld",
+ ex_file_info.max_rec_len);
+ }
+ else
+ {
+ LOGMSG ("I/P file maximum record length: unknown");
+ }
+
+ LOGMSG_1 ("I/P file timestamp: %s\n",
+ (ex_file_info.mod_time != INV_TIMESTAMP) ?
+ vv_timestamp (ex_file_info.mod_time) : "unknown");
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Set the key File_Info parameters, taking into account the file
+ ** parameters and the command line qualifier values.
+ **------------------------------------------------------------------------
+ */
+ set_mode (&G_cmdqual[CMDQ_MODE], &ex_file_info, G_mode_str, &G_ip_file);
+ set_format (&G_cmdqual[CMDQ_FORMAT], &ex_file_info, G_fmt_str, &G_ip_file);
+ set_record_len (&G_cmdqual[CMDQ_RECORDLEN], &ex_file_info, &G_ip_file);
+ set_timestamp (&G_cmdqual[CMDQ_TIMESTAMP], &ex_file_info, &G_ip_file);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Get and act upon the other command line qualifiers.
+ **------------------------------------------------------------------------
+ */
+ set_hdr_file_spec (&G_cmdqual[CMDQ_HDRFILE], &G_ip_file, &G_hdrf_spec);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ set_enc_tbl (&G_cmdqual[CMDQ_ENCODE], ENCODE_TABLE_LEN, G_encode_table);
+ set_dec_tbl (ENCODE_TABLE_LEN, G_encode_table,
+ DECODE_TABLE_LEN, G_decode_table);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (Q_TRANSLATE)
+ {
+ strcpy (xlt_file.file_spec, G_cmdqual[CMDQ_TRANSLATE].value);
+ set_xlt_tbl (&xlt_file, &G_xlt_table, G_xlthdr);
+
+ if (STRCMPI (VV_CHARACTERSET, G_xlt_table.xlt_from) != 0)
+ {
+ WARNMSG_2 ("translation file translates from `%s' to `%s'",
+ G_xlt_table.xlt_from, G_xlt_table.xlt_to);
+ INFOMSG_1 ("local character set is `%s'", VV_CHARACTERSET);
+ }
+ }
+ else
+ {
+ LOGMSG ("Translation performed: none");
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ open_ip_file (&G_cmd_ipfile, &G_ip_file);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ open_op_file (&G_cmd_opfile, def_file_name, G_overwrite_flag, &G_op_file);
+ set_split_size (&G_op_file, &G_cmdqual[CMDQ_SPLIT], &G_split_size);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Initialize global variables.
+ **------------------------------------------------------------------------
+ */
+ init_crc32_table (CRC32_TABLE_SIZE, CRC32_POLYNOMIAL, G_crc32_table);
+ G_ip_file.crc32 = CRC32_MASK;
+ G_ip_file.bytecount = 0L;
+ G_op_file.bytecount = 0L;
+ G_oppart_bytes = 0L;
+ G_oppt_no = 1;
+ free (def_file_name);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Write the VVE file header lines.
+ **------------------------------------------------------------------------
+ */
+ wr_headers (G_oppt_no);
+} /* initialize */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** open_ip_file
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void open_ip_file (CONST Qualifier_Struct *ip_qualifier,
+ File_Info *ip_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void open_ip_file (ip_qualifier, ip_file)
+ CONST Qualifier_Struct *ip_qualifier;
+ File_Info *ip_file;
+#endif /* (ANSI_SYNTAX) */
+{
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (ip_qualifier->present != TRUE)
+ {
+ INTERNAL_ERROR ("open_ip_file");
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (ip_file->pipe_flag == TRUE)
+ {
+ ip_file->file_ptr = stdin;
+ }
+ else
+ {
+ DEBUG_1 ("encode: opening input file `%s'", ip_file->file_spec);
+ ip_file->file_ptr = f_open_in (ip_file);
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (ip_file->file_ptr == (FILE *) NULL)
+ {
+ FATALMSG_1 ("error opening input file `%s'", ip_file->file_spec);
+ vv_exit ();
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if ((ip_file->pipe_flag == TRUE) || (is_a_file (ip_file) == FALSE))
+ {
+ DEBUG_1 ("open_ip_file: `%s' is not a regular file",
+ ip_file->file_spec);
+ ip_file->pipe_flag = TRUE;
+ set_pipe_mode (ip_file);
+ }
+} /* open_ip_file */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** open_op_file
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void open_op_file (CONST Qualifier_Struct *op_qualifier,
+ CONST char *def_file_name,
+ CONST Int16 overwrite_flag,
+ File_Info *op_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void open_op_file (op_qualifier, def_file_name,
+ overwrite_flag, op_file)
+ CONST Qualifier_Struct *op_qualifier;
+ CONST char *def_file_name;
+ CONST Int16 overwrite_flag;
+ File_Info *op_file;
+#endif /* (ANSI_SYNTAX) */
+{
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ op_file->file_ptr = (FILE *) NULL;
+ op_file->mode = MODE_TEXT;
+ op_file->format = DEF_TEXT_FMT;
+ op_file->max_rec_len = INV_RECORD_LEN;
+ op_file->lng_rec_len = INV_RECORD_LEN;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (op_qualifier->present == TRUE)
+ {
+
+ /*-
+ **--------------------------------------------------------------------
+ **
+ **--------------------------------------------------------------------
+ */
+#if (SUPPORT_PIPING)
+ if (STRCMP (op_qualifier->value, STDIO_SYMBOL) == 0)
+ {
+ op_file->pipe_flag = TRUE;
+ strcpy (op_file->file_spec, "stdout");
+ op_file->file_ptr = stdout;
+ op_file->format = FMT_STREAM;
+ }
+ else
+#endif /* (SUPPORT_PIPING) */
+
+ {
+ strcpy (op_file->file_spec, op_qualifier->value);
+
+ /*-
+ **----------------------------------------------------------------
+ ** The default file spec for the VVencoded file is the name of the
+ ** input file with the default extension for VVencoded files.
+ **----------------------------------------------------------------
+ */
+#if (STICKY_DEFAULTS)
+ apply_defaults (def_file_name, DEF_VV_EXT, op_file->file_spec);
+#endif /* (STICKY_DEFAULTS) */
+
+ DEBUG_1 ("open_op_file: opening output file `%s'",
+ op_file->file_spec);
+ op_file->file_ptr = f_open_out (overwrite_flag, op_file);
+ }
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ else
+ {
+
+#if (STDOUT_OUTPUT)
+ strcpy (op_file->file_spec, "stdout");
+ op_file->file_ptr = stdout;
+ op_file->pipe_flag = TRUE;
+
+#else /* NOT (STDOUT_OUTPUT) */
+
+ strcpy (op_file->file_spec, "");
+ make_file_spec (NULL, def_file_name, NULL, NULL, op_file->file_spec);
+ apply_defaults (NULL, DEF_VV_EXT, op_file->file_spec);
+ DEBUG_1 ("open_op_file: opening output file `%s'", op_file->file_spec);
+ op_file->file_ptr = f_open_out (overwrite_flag, op_file);
+
+#endif /* (STDOUT_OUTPUT) */
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (op_file->file_ptr == (FILE *) NULL)
+ {
+ FATALMSG_1 ("error opening output file `%s'", op_file->file_spec);
+ vv_exit ();
+ }
+ LOGMSG_1 ("\nVVE O/P file: %s", op_file->file_spec);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if ((op_file->pipe_flag == TRUE) || (is_a_file (op_file) == FALSE))
+ {
+ DEBUG_1 ("open_op_file: `%s' is not a regular file",
+ op_file->file_spec);
+ op_file->pipe_flag = TRUE;
+ set_pipe_mode (op_file);
+ }
+} /* open_op_file */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_enc_tbl
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_enc_tbl (CONST Qualifier_Struct *enc_qualifier,
+ CONST Int16 enc_tbl_len,
+ char *encode_table)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_enc_tbl (enc_qualifier, enc_tbl_len,
+ encode_table)
+ CONST Qualifier_Struct *enc_qualifier;
+ CONST Int16 enc_tbl_len;
+ char *encode_table;
+#endif /* (ANSI_SYNTAX) */
+{
+ File_Info enc_file;
+ int status;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (enc_qualifier->present == TRUE)
+ {
+ strcpy (enc_file.file_spec, enc_qualifier->value);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** If an extension has not been provided, use the default extension
+ ** for encoding table files.
+ **--------------------------------------------------------------------
+ */
+#if (STICKY_DEFAULTS)
+ apply_defaults (NULL, DEF_ENC_EXT, enc_file.file_spec);
+#endif /* (STICKY_DEFAULTS) */
+
+ status = rd_enc_tbl (&enc_file, enc_tbl_len, encode_table);
+
+ if (!status)
+ {
+ FATALMSG_1 ("error reading encoding table file `%s'",
+ enc_file.file_spec);
+ vv_exit ();
+ }
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ else
+ {
+ DEBUG ("encoding table not specified on the command line");
+ strcpy (enc_file.file_spec, "default VVCODE");
+ strcpy ((char *) encode_table, VV_ENCODE_TABLE);
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("\nEncoding table source: %s", enc_file.file_spec);
+ LOGMSG_1 ("Encoding table contents: %.32s", encode_table);
+ LOGMSG_1 (" %.32s", encode_table + 32);
+} /* set_enc_tbl */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_format
+**
+** DESCRIPTION
+**
+** Set the format (fixed/stream/variable) to use when reading and
+** encoding the input file. The format may be set from the command
+** line, examine_file() or the default specified in machine.h. The
+** logic used is:
+**
+** Cmd ExFile Pipe Result
+** ------------------------------
+** Y * * Cmd
+** N N N Def
+** N Y N ExF
+** N * Y Stm
+** ------------------------------
+**
+** NOTE: if the input file is standard input, examine_file() is not
+** called and stream format is used unless it is overrriden
+** from the command line.
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_format (CONST Qualifier_Struct *fmt_qualifier,
+ CONST File_Info *ex_file,
+ CONST char *fmt_str_array[],
+ File_Info *ip_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_format (fmt_qualifier, ex_file, fmt_str_array,
+ ip_file)
+ CONST Qualifier_Struct *fmt_qualifier;
+ CONST File_Info *ex_file;
+ CONST char *fmt_str_array[];
+ File_Info *ip_file;
+#endif /* (ANSI_SYNTAX) */
+{
+ Int16 cmd_format;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Get the format specified on the command line (if any). The number of
+ ** 'if' statements could be reduced by making the second expression more
+ ** complicated at a cost of less readable code.
+ **------------------------------------------------------------------------
+ */
+ cmd_format = getc_format (fmt_qualifier, fmt_str_array);
+
+ if (cmd_format != INV_FORMAT)
+ {
+ ip_file->format = cmd_format;
+ }
+ else
+ if (ip_file->pipe_flag == TRUE)
+ {
+ ip_file->format = FMT_STREAM;
+ }
+ else
+ if (ex_file->format != INV_FORMAT)
+ {
+ ip_file->format = ex_file->format;
+ }
+ else
+ {
+ if (ip_file->mode == MODE_BINARY)
+ {
+ ip_file->format = DEF_BINARY_FMT;
+ }
+ else
+ {
+ ip_file->format = DEF_TEXT_FMT;
+ }
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("VVE encoding format: %s",
+ (ip_file->format != INV_FORMAT) ?
+ (char *) fmt_str_array[ip_file->format] : "not recorded");
+} /* set_format */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_hdr_file_spec
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_hdr_file_spec (
+ CONST Qualifier_Struct *hdr_qualifier,
+ CONST File_Info *ip_file,
+ char **hdr_file_spec)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_hdr_file_spec (hdr_qualifier, ip_file,
+ hdr_file_spec)
+ CONST Qualifier_Struct *hdr_qualifier;
+ CONST File_Info *ip_file;
+ char **hdr_file_spec;
+#endif /* (ANSI_SYNTAX) */
+{
+ char file_name[MAX_NAME + 1];
+ char file_ext[MAX_EXT + 1];
+
+#if (UPPERCASE_FILESYSTEM)
+ char *tmp_ptr;
+#endif /* (UPPERCASE_FILESYSTEM) */
+
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ *hdr_file_spec = allocate_buffer ((MAX_IP_LINE_LEN + 1), "hdr_file_spec");
+ if (hdr_qualifier->present == TRUE)
+ {
+ strcpy (*hdr_file_spec, hdr_qualifier->value);
+ }
+ else
+ {
+ (void) split_file_spec (ip_file->file_spec, NULL, file_name,
+ file_ext, NULL);
+ make_file_spec (NULL, file_name, file_ext, NULL, *hdr_file_spec);
+
+#if (UPPERCASE_FILESYSTEM)
+ for (tmp_ptr = *hdr_file_spec; *tmp_ptr != '\0'; tmp_ptr++)
+ {
+ *tmp_ptr = (char) TOLOWER ((int) *tmp_ptr);
+ }
+#endif /* (UPPERCASE_FILESYSTEM) */
+
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("VVE header file spec: %s", *hdr_file_spec);
+} /* set_hdr_file_spec */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_ip_filespec
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_ip_filespec (
+ CONST Qualifier_Struct *ip_qualifier,
+ File_Info *ip_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_ip_filespec (ip_qualifier, ip_file)
+ CONST Qualifier_Struct *ip_qualifier;
+ File_Info *ip_file;
+#endif /* (ANSI_SYNTAX) */
+{
+ if (ip_qualifier->present != TRUE)
+ {
+ INTERNAL_ERROR ("set_ip_filespec");
+ }
+
+#if (SUPPORT_PIPING)
+
+ if (STRCMP (ip_qualifier->value, STDIO_SYMBOL) == 0)
+ {
+ strcpy (ip_file->file_spec, "stdin");
+ ip_file->pipe_flag = TRUE;
+ }
+ else
+ {
+ strcpy (ip_file->file_spec, ip_qualifier->value);
+ }
+
+#else /* NOT (SUPPORT_PIPING) */
+
+ strcpy (ip_file->file_spec, ip_qualifier->value);
+
+#endif /* (SUPPORT_PIPING) */
+
+} /* set_ip_filespec */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_mode
+**
+** DESCRIPTION
+**
+** Set the mode (text/binary) to use when reading and encoding the input
+** file. The mode may be set from the command line, examine_file() or
+** the default specified in machine.h. The logic used is:
+**
+** Cmd ExFile Pipe Result
+** ------------------------------
+** Y * * Cmd
+** N N N Def
+** N Y N ExF
+** N * Y Def
+** ------------------------------
+**
+** NOTE: if the input file is standard input, examine_file() is not
+** called and the default mode is used unless it is overrriden
+** from the command line.
+**
+** INPUT PARAMETERS
+**
+** ex_file_info - a File_Info structure containing the results of
+** the call to examine_file(). If the input file
+** was specified as standard input, this structure
+** will not be examined.
+**
+** OUTPUT PARAMETERS
+**
+** none
+**
+** RETURN VALUE
+**
+** none
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_mode (CONST Qualifier_Struct *mode_qualifier,
+ CONST File_Info *ex_file,
+ CONST char *mode_str_array[],
+ File_Info *ip_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_mode (mode_qualifier, ex_file, mode_str_array,
+ ip_file)
+ CONST Qualifier_Struct *mode_qualifier;
+ CONST File_Info *ex_file;
+ CONST char *mode_str_array[];
+ File_Info *ip_file;
+#endif /* (ANSI_SYNTAX) */
+{
+ Int16 cmd_mode;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Get the mode specified on the command line (if any). The number of
+ ** 'if' statements could be reduced by making the second expression more
+ ** complicated at a cost of less readable code.
+ **------------------------------------------------------------------------
+ */
+ cmd_mode = getc_mode (mode_qualifier, mode_str_array);
+
+ if (cmd_mode != INV_MODE)
+ {
+ ip_file->mode = cmd_mode;
+ }
+ else
+ if (ip_file->pipe_flag == TRUE)
+ {
+ ip_file->mode = DEF_MODE;
+ }
+ else
+ if (ex_file->mode != INV_MODE)
+ {
+ ip_file->mode = ex_file->mode;
+ }
+ else
+ {
+ ip_file->mode = DEF_MODE;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** One final check to make sure that the mode is valid. The mode can only
+ ** come from a validated command line value, examine_file() or the default
+ ** setting, so it should not be wrong.
+ **------------------------------------------------------------------------
+ */
+ switch (ip_file->mode)
+ {
+ case MODE_BINARY:
+ case MODE_TEXT:
+ break;
+ default:
+ FATALMSG_1 ("invalid file encoding mode set (%d)", ip_file->mode);
+ vv_exit ();
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("VVE encoding mode: %s",
+ mode_str_array[ip_file->mode]);
+} /* set_mode */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_record_len
+**
+** DESCRIPTION
+**
+** Set the maximum record length to use when reading and encoding the
+** input file. The record length may be set from the command line,
+** examine_file() or the default specified in machine.h. The logic used
+** is:
+**
+** Cmd ExFile Pipe Result
+** ------------------------------
+** Y * * Cmd
+** N N N Def
+** N Y N ExF
+** N * Y Def
+** ------------------------------
+**
+** NOTE: if the input file is standard input, examine_file() is not
+** called and the default record length is used unless it is
+** overrriden from the command line.
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_record_len (
+ CONST Qualifier_Struct *rec_qualifier,
+ CONST File_Info *ex_file,
+ File_Info *ip_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_record_len (rec_qualifier, ex_file, ip_file)
+ CONST Qualifier_Struct *rec_qualifier;
+ CONST File_Info *ex_file;
+ File_Info *ip_file;
+#endif /* (ANSI_SYNTAX) */
+{
+ Int32 cmd_reclen;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Get the record length specified on the command line (if any). The
+ ** number of 'if' statements could be reduced by making the second
+ ** expression more complicated at a cost of less readable code.
+ **------------------------------------------------------------------------
+ */
+ cmd_reclen = getc_reclen (rec_qualifier, ip_file);
+
+ if (cmd_reclen != INV_RECORD_LEN)
+ {
+ ip_file->max_rec_len = cmd_reclen;
+ ip_file->lng_rec_len = INV_RECORD_LEN;
+ }
+ else
+ if (ip_file->pipe_flag == TRUE)
+ {
+ ip_file->max_rec_len = INV_RECORD_LEN;
+ ip_file->lng_rec_len = INV_RECORD_LEN;
+ }
+ else
+ if (ex_file->max_rec_len != INV_RECORD_LEN)
+ {
+ ip_file->max_rec_len = ex_file->max_rec_len;
+ ip_file->lng_rec_len = ex_file->lng_rec_len;
+ }
+ else
+ {
+ ip_file->max_rec_len = INV_RECORD_LEN;
+ ip_file->lng_rec_len = INV_RECORD_LEN;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** One final check to make sure that the maximum record length is valid.
+ ** The longest record length can only come from examine_file() so it
+ ** should not be wrong. There is an exception: the default may be set to
+ ** INV_RECORD_LEN so that f_open_in() will use a default value.
+ **------------------------------------------------------------------------
+ */
+ if (ip_file->lng_rec_len == INV_RECORD_LEN)
+ {
+ LOGMSG ("VVE longest record length: not recorded");
+ }
+ else if (ip_file->format == FMT_VARIABLE)
+ {
+ if ((ip_file->lng_rec_len < MIN_VARIABLE_RECORD_LEN)
+ || (ip_file->lng_rec_len > MAX_VARIABLE_RECORD_LEN))
+ {
+ FATALMSG_1 ("invalid longest record length set (%ld)",
+ ip_file->lng_rec_len);
+ vv_exit ();
+ }
+ LOGMSG_1 ("VVE longest record length: %ld",
+ ip_file->lng_rec_len);
+ }
+ else if (ip_file->format == FMT_FIXED)
+ {
+ if ((ip_file->lng_rec_len < MIN_FIXED_RECORD_LEN)
+ || (ip_file->lng_rec_len > MAX_FIXED_RECORD_LEN))
+ {
+ FATALMSG_1 ("invalid longest record length set (%ld)",
+ ip_file->lng_rec_len);
+ vv_exit ();
+ }
+ LOGMSG_1 ("VVE longest record length: %ld",
+ ip_file->lng_rec_len);
+ }
+
+
+ /*-
+ **------------------------------------------------------------------------
+ ** One final check to make sure that the maximum record length is valid.
+ ** The record length can only come from a validated command line value,
+ ** examine_file() or the default setting, so it should not be wrong.
+ ** There is an exception: the default may be set to INV_RECORD_LEN so that
+ ** f_open_in() will use a default value.
+ **------------------------------------------------------------------------
+ */
+ if (ip_file->max_rec_len == INV_RECORD_LEN)
+ {
+ LOGMSG ("VVE maximum record length: not recorded");
+ }
+ else if (ip_file->format == FMT_VARIABLE)
+ {
+ if ((ip_file->max_rec_len < MIN_VARIABLE_RECORD_LEN)
+ || (ip_file->max_rec_len > MAX_VARIABLE_RECORD_LEN))
+ {
+ FATALMSG_1 ("invalid maximum record length set (%ld)",
+ ip_file->max_rec_len);
+ vv_exit ();
+ }
+ LOGMSG_1 ("VVE maximum record length: %ld",
+ ip_file->max_rec_len);
+ }
+ else if (ip_file->format == FMT_FIXED)
+ {
+ if ((ip_file->max_rec_len < MIN_FIXED_RECORD_LEN)
+ || (ip_file->max_rec_len > MAX_FIXED_RECORD_LEN))
+ {
+ FATALMSG_1 ("invalid maximum record length set (%ld)",
+ ip_file->max_rec_len);
+ vv_exit ();
+ }
+ LOGMSG_1 ("VVE maximum record length: %ld",
+ ip_file->max_rec_len);
+ }
+} /* set_record_len */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_split_size
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void set_split_size (CONST File_Info *op_file,
+ Qualifier_Struct *split_qualifier,
+ Int32 *split_size)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_split_size (op_file, split_qualifier,
+ split_size)
+ CONST File_Info *op_file;
+ Qualifier_Struct *split_qualifier;
+ Int32 *split_size;
+#endif /* (ANSI_SYNTAX) */
+{
+ Int32 tmp_split_size;
+ int status;
+
+ if (split_qualifier->present != TRUE)
+ {
+ DEBUG ("split size not specified on the command line");
+ LOGMSG ("VVE O/P file maximum size: no maximum");
+ return;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (op_file->pipe_flag == TRUE)
+ {
+ split_qualifier->present = FALSE;
+ WARNMSG ("not encoding to a file - file splitting disabled");
+ LOGMSG ("VVE O/P file maximum size: no maximum");
+ return;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ tmp_split_size = -1;
+ status = sscanf (split_qualifier->value, "%ld", &tmp_split_size);
+
+ if ((status != 1) || (tmp_split_size <= 0))
+ {
+ USAGE_1 ("invalid split size specified `%s'", split_qualifier->value);
+ }
+
+ if (tmp_split_size < (Int32) MIN_SPLIT_SIZE)
+ {
+ USAGE_1 ("split size must be at least %ld kB", (Int32) MIN_SPLIT_SIZE);
+ }
+ *split_size = tmp_split_size * 1024L;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("VVE O/P file maximum size: %ld kB", tmp_split_size);
+} /* set_split_size */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** set_timestamp
+**
+** DESCRIPTION
+**
+** Set the timestamp to record in the VVE file. The timestamp may be
+** set from the command line or by examine_file(). The logic used is:
+**
+** Cmd ExFile Pipe Result
+** ------------------------------
+** Y * * Cmd
+** N N N Inv
+** N Y N ExF
+** N * Y Inv
+** ------------------------------
+**
+** NOTE: if the input file is standard input, examine_file() is not
+** called and the timestamp is set to INV_TIMESTAMP unless it is
+** overrriden from the command line.
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+void set_timestamp (
+ CONST Qualifier_Struct *time_qualifier,
+ CONST File_Info *ex_file,
+ File_Info *ip_file)
+#else /* NOT (ANSI_SYNTAX) */
+ void set_timestamp (time_qualifier, ex_file, ip_file)
+ CONST Qualifier_Struct *time_qualifier;
+ CONST File_Info *ex_file;
+ File_Info *ip_file;
+#endif /* (ANSI_SYNTAX) */
+{
+ TIME_T cmd_timestamp;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Get the timestamp specified on the command line (if any). The number
+ ** of 'if' statements could be reduced by making the second expression
+ ** more complicated at a cost of less readable code.
+ **------------------------------------------------------------------------
+ */
+ cmd_timestamp = getc_timestamp (time_qualifier);
+
+ if (cmd_timestamp != INV_TIMESTAMP)
+ {
+ ip_file->mod_time = cmd_timestamp;
+ }
+ else
+ if (ip_file->pipe_flag == TRUE)
+ {
+ ip_file->mod_time = INV_TIMESTAMP;
+ }
+ else
+ if (ex_file->mod_time != INV_TIMESTAMP)
+ {
+ ip_file->mod_time = ex_file->mod_time;
+ }
+ else
+ {
+ ip_file->mod_time = INV_TIMESTAMP;
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("VVE file timestamp: %s",
+ (ip_file->mod_time != INV_TIMESTAMP) ?
+ vv_timestamp (ip_file->mod_time) : "not recorded");
+} /* set_timestamp */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** start_next_op_file
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void start_next_op_file (CONST Int16 overwrite_flag,
+ File_Info *op_file,
+ Int16 *op_part_no)
+#else /* NOT (ANSI_SYNTAX) */
+ void start_next_op_file (overwrite_flag, op_file,
+ op_part_no)
+ CONST Int16 overwrite_flag;
+ File_Info *op_file;
+ Int16 *op_part_no;
+#endif /* (ANSI_SYNTAX) */
+{
+ char next_file_ext[MAX_EXT + 1];
+ char tmp_buffer[32];
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (++(*op_part_no) > MAX_VV_PARTS)
+ {
+ FATALMSG_1 ("maximum number of parts reached (%d)", MAX_VV_PARTS);
+ vv_exit ();
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ (void) enc_line ("", 0L, tmp_buffer);
+ VVEOUT (tmp_buffer);
+
+ VVEOUT_2 ("%sskipto %d\n", VV_PREFIX, *op_part_no);
+ f_close (op_file);
+
+ LOGMSG_2 ("Part %3d bytes written: %ld",
+ (*op_part_no - 1), G_oppart_bytes);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ SPRINTF (next_file_ext, VV_EXT_FMT, *op_part_no);
+ force_file_ext (next_file_ext, op_file->file_spec);
+ op_file->file_ptr = f_open_out (overwrite_flag, op_file);
+
+ if (op_file->file_ptr == (FILE *) NULL)
+ {
+ FATALMSG_1 ("error opening output file `%s'", op_file->file_spec);
+ vv_exit ();
+ }
+} /* start_next_op_file */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** terminate
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void terminate (void)
+#else /* NOT (ANSI_SYNTAX) */
+ void terminate ()
+#endif /* (ANSI_SYNTAX) */
+{
+ char tmp_buffer[32];
+
+ G_ip_file.crc32 = G_ip_file.crc32 ^ CRC32_MASK;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Write the line of zero encoded bytes to signify the end of encoded
+ ** data.
+ **------------------------------------------------------------------------
+ */
+ (void) enc_line ("", 0L, tmp_buffer);
+ VVEOUT (tmp_buffer);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** End header.
+ **------------------------------------------------------------------------
+ */
+ VVEOUT_2 ("%s%s\n", VV_PREFIX, G_vvehdr[HDR_END].h_string);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Bytecount header.
+ **------------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %ld\n", VV_PREFIX,
+ G_vvehdr[HDR_BYTECOUNT].h_string, G_ip_file.bytecount);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Crc32 header.
+ **------------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %08lx\n", VV_PREFIX,
+ G_vvehdr[HDR_CRC32].h_string, G_ip_file.crc32);
+ G_op_file.bytecount += G_oppart_bytes;
+ LOGMSG_2 ("Part %3d bytes written: %ld",
+ G_oppt_no, G_oppart_bytes);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Close the input file if it's not connected to stdin.
+ **------------------------------------------------------------------------
+ */
+ if (G_ip_file.file_ptr != stdin)
+ {
+ f_close (&G_ip_file);
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Close the output file if it's not connected to stdout.
+ **------------------------------------------------------------------------
+ */
+ if (G_op_file.file_ptr != stdout)
+ {
+ f_close (&G_op_file);
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Finish off the log file, then close it if it's not connected to stderr.
+ **------------------------------------------------------------------------
+ */
+ LOGMSG_1 ("\nCRC-32: %08lx", G_ip_file.crc32);
+ LOGMSG_1 ("Total bytes read: %ld", G_ip_file.bytecount);
+ LOGMSG_1 ("Total bytes written: %ld", G_op_file.bytecount);
+ LOGMSG_1 ("Total O/P parts written: %d", G_oppt_no);
+
+ if (G_log_file.file_ptr != stderr)
+ {
+ f_close (&G_log_file);
+ }
+
+} /* terminate */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** usage_error
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void usage_error (CONST char *reason)
+#else /* NOT (ANSI_SYNTAX) */
+ void usage_error (reason)
+ CONST char *reason;
+#endif /* (ANSI_SYNTAX) */
+{
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Initial error message, followed by Unix style usage message.
+ **------------------------------------------------------------------------
+ */
+ FPRINTF (stderr, "\nVVencode %s, %s release (%s)\n\n",
+ VV_VERSION_STR, VV_IMPLEMENTATION, VV_DATE);
+ FPRINTF (stderr, "VVencode: %s\n\n", reason);
+ FPRINTF (stderr,
+ "Usage: VVencode [qualifiers] input_file [output_file]\n\n");
+ FPRINTF (stderr, " Valid qualifiers are:\n\n");
+
+ /*-
+ **------------------------------------------------------------------------
+ ** qualifier: 'debug' (if support compiled in)
+ **------------------------------------------------------------------------
+ */
+#if (VV_DEBUG_SUPPORT)
+ FPRINTF (stderr, " %.1s%s\n", QUAL_INTRO, G_cmdqual[CMDQ_DEBUG].q_string);
+#endif /* (VV_DEBUG_SUPPORT) */
+
+ /*-
+ **------------------------------------------------------------------------
+ ** qualifier: 'encoding_table'
+ **------------------------------------------------------------------------
+ */
+ FPRINTF (stderr, " %.1s%s%.1sfile-spec\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_ENCODE].q_string, QUAL_SEP);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** qualifier: 'format'
+ **------------------------------------------------------------------------
+ */
+ FPRINTF (stderr, " %.1s%s%.1sfile-format (formats supported:%s%s%s%s%s%s)\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_FORMAT].q_string, QUAL_SEP,
+
+#if (SUPPORT_FIXED_FMT)
+ " ", G_fmt_str[FMT_FIXED],
+#else /* NOT (SUPPORT_FIXED_FMT) */
+ "", "",
+#endif /* (SUPPORT_FIXED_FMT) */
+
+#if (SUPPORT_STREAM_FMT)
+ " ", G_fmt_str[FMT_STREAM],
+#else /* NOT (SUPPORT_STREAM_FMT) */
+ "", "",
+#endif /* (SUPPORT_STREAM_FMT) */
+
+#if (SUPPORT_VARIABLE_FMT)
+ " ", G_fmt_str[FMT_VARIABLE]);
+#else /* NOT (SUPPORT_VARIABLE_FMT) */
+ "", "");
+#endif /* (SUPPORT_VARIABLE_FMT) */
+
+ /*-
+ **------------------------------------------------------------------------
+ ** qualifiers: 'header_filespec', 'help', 'log', 'mode'
+ **------------------------------------------------------------------------
+ */
+ FPRINTF (stderr, " %.1s%s%.1sfile-spec\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_HDRFILE].q_string, QUAL_SEP);
+ FPRINTF (stderr, " %.1s%s\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_HELP].q_string);
+ FPRINTF (stderr, " %.1s%s[%.1sfile-spec]\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_LOG].q_string, QUAL_SEP);
+ FPRINTF (stderr, " %.1s%s%.1sfile-mode (modes supported: binary text)\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_MODE].q_string, QUAL_SEP);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** qualifiers: 'overwrite', 'record_length', 'split_size'
+ **------------------------------------------------------------------------
+ */
+ FPRINTF (stderr, " %.1s%s\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_OVERWRITE].q_string);
+ FPRINTF (stderr, " %.1s%s%.1sbytes\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_RECORDLEN].q_string, QUAL_SEP);
+ FPRINTF (stderr, " %.1s%s%.1skbytes\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_SPLIT].q_string, QUAL_SEP);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** qualifiers: 'timestamp', 'translation_file'
+ **------------------------------------------------------------------------
+ */
+ FPRINTF (stderr, " %.1s%s[%.1stime]\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_TIMESTAMP].q_string, QUAL_SEP);
+ FPRINTF (stderr, " %.1s%s%.1sfile-spec\n\n",
+ QUAL_INTRO, G_cmdqual[CMDQ_TRANSLATE].q_string, QUAL_SEP);
+
+ G_status = FATAL_STATUS;
+ vv_exit ();
+} /* usage_error */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** enc_line
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ Int32 enc_line (CONST char *ip_buffer,
+ CONST Int32 num_bytes,
+ char *op_buffer)
+#else /* NOT (ANSI_SYNTAX) */
+ Int32 enc_line (ip_buffer, num_bytes, op_buffer)
+ CONST char *ip_buffer;
+ CONST Int32 num_bytes;
+ char *op_buffer;
+#endif /* (ANSI_SYNTAX) */
+{
+ int c1;
+ int c2;
+ int c3;
+ int c4;
+ SIZE_T idx;
+ int offset;
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ strcpy (op_buffer, VV_PREFIX);
+ offset = strlen (op_buffer);
+ op_buffer[offset++] = ENCODE ((SIZE_T) num_bytes);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ for (idx = 0; idx < (SIZE_T) num_bytes; idx += 3)
+ {
+ c1 = (int) ip_buffer[idx] >> 2;
+ c2 = (int) ((ip_buffer[idx] << 4) & 0x30)
+ | ((ip_buffer[idx + 1] >> 4) & 0x0f);
+ c3 = (int) ((ip_buffer[idx + 1] << 2) & 0x3c)
+ | ((ip_buffer[idx + 2] >> 6) & 0x03);
+ c4 = (int) (ip_buffer[idx + 2] & 0x3f);
+
+ op_buffer[offset++] = ENCODE (c1);
+ op_buffer[offset++] = ENCODE (c2);
+ op_buffer[offset++] = ENCODE (c3);
+ op_buffer[offset++] = ENCODE (c4);
+ }
+ op_buffer[offset] = '\0';
+ strcat (op_buffer, VV_EOL_MARKER);
+ strcat (op_buffer, "\n");
+ return ((Int32) strlen (op_buffer));
+} /* enc_line */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** wr_headers
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ void wr_headers (CONST Int16 part_no)
+#else /* NOT (ANSI_SYNTAX) */
+ void wr_headers (part_no)
+ CONST Int16 part_no;
+#endif /* (ANSI_SYNTAX) */
+{
+ Int16 adv_line;
+
+ LOGMSG_2 ("\nPart %3d O/P file: %s",
+ G_oppt_no, G_op_file.file_spec);
+ LOGMSG_2 ("Part %3d started at I/P byte: %ld",
+ G_oppt_no, G_ip_file.bytecount);
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Write the VVcode advert text at the top of the VVE file.
+ **------------------------------------------------------------------------
+ */
+ for (adv_line = 0; G_vv_advert[adv_line] != NULL; adv_line++)
+ {
+ VVEOUT_1 ("%s\n", G_vv_advert[adv_line]);
+ }
+ VVEOUT_1 ("Written by VVencode %s,\n", VV_VERSION_STR);
+ VVEOUT_2 (" %s release (%s)\n", VV_IMPLEMENTATION, VV_DATE);
+ VVEOUT ("\n");
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (part_no == 1)
+ {
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'decodeversion'
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %d\n", VV_PREFIX,
+ G_vvehdr[HDR_DECODEVERSION].h_string, VV_MAJOR_VERSION_NO);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'operating system'
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_OPERATINGSYSTEM].h_string, VV_OPERATING_SYSTEM);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'characterset'
+ **
+ ** If the /TRANSLATE qualifier was used, add a 'comment' header
+ ** recording the original character set (even if it was the same as
+ ** the translated character set).
+ **--------------------------------------------------------------------
+ */
+ if (Q_TRANSLATE)
+ {
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_CHARACTERSET].h_string, G_xlt_table.xlt_to);
+ VVEOUT_3 ("%s%s Original file character set was %s\n",
+ VV_PREFIX, G_vvehdr[HDR_COMMENT].h_string,
+ VV_CHARACTERSET);
+ }
+ else
+ {
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_CHARACTERSET].h_string, VV_CHARACTERSET);
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'mode'
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_MODE].h_string, G_mode_str[G_ip_file.mode]);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'format'
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_FORMAT].h_string, G_fmt_str[G_ip_file.format]);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'recordlength'
+ **
+ ** This header is included only if a valid record length was
+ ** determined.
+ **--------------------------------------------------------------------
+ */
+ if (G_ip_file.max_rec_len != INV_RECORD_LEN)
+ {
+ if (G_ip_file.lng_rec_len != INV_RECORD_LEN)
+ {
+ VVEOUT_4 ("%s%s %ld %ld\n", VV_PREFIX,
+ G_vvehdr[HDR_RECORDLEN].h_string,
+ G_ip_file.max_rec_len, G_ip_file.lng_rec_len);
+ }
+ else
+ {
+ VVEOUT_3 ("%s%s %ld\n", VV_PREFIX,
+ G_vvehdr[HDR_RECORDLEN].h_string,
+ G_ip_file.max_rec_len);
+ }
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'timestamp'
+ **
+ ** This header is included only if a valid timestamp was determined.
+ **--------------------------------------------------------------------
+ */
+ if (G_ip_file.mod_time != INV_TIMESTAMP)
+ {
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_TIMESTAMP].h_string,
+ vv_timestamp (G_ip_file.mod_time));
+ }
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'table'
+ **
+ ** The 'table' header is followed by the encoding table.
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_2 ("%s%s\n", VV_PREFIX, G_vvehdr[HDR_TABLE].h_string);
+ VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table);
+ VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table + 32);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'begin'
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_3 ("%s%s %s\n", VV_PREFIX,
+ G_vvehdr[HDR_BEGIN].h_string, G_hdrf_spec);
+ }
+ else
+ {
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'table'
+ **
+ ** The 'table' header is followed by the encoding table.
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_2 ("%s%s\n", VV_PREFIX, G_vvehdr[HDR_TABLE].h_string);
+ VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table);
+ VVEOUT_2 ("%s%.32s\n", VV_PREFIX, G_encode_table + 32);
+
+ /*-
+ **--------------------------------------------------------------------
+ ** VVE header: 'skipfrom'
+ **--------------------------------------------------------------------
+ */
+ VVEOUT_4 ("%s%s %d %s\n", VV_PREFIX,
+ G_vvehdr[HDR_SKIPFROM].h_string, G_oppt_no, G_hdrf_spec);
+ }
+} /* wr_headers */
+
+
+
+/*-
+**============================================================================
+**
+** FUNCTION
+**
+** main
+**
+** DESCRIPTION
+**
+** [tbs]
+**
+** INPUT PARAMETERS
+**
+** [tbs]
+**
+** OUTPUT PARAMETERS
+**
+** [tbs]
+**
+** RETURN VALUE
+**
+** [tbs]
+**
+**============================================================================
+*/
+#if (ANSI_SYNTAX)
+ int main (CONST int argc, CONST char *argv[])
+#else /* NOT (ANSI_SYNTAX) */
+ int main (argc, argv)
+ CONST int argc;
+ CONST char *argv[];
+#endif /* (ANSI_SYNTAX) */
+{
+ SIZE_T bytes_reqd;
+
+ G_status = LOG_STATUS;
+ G_debugging = FALSE;
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Allocate the global message buffer manually since it is used by the
+ ** various MESSAGE_x and DEBUG_x macros.
+ **------------------------------------------------------------------------
+ */
+ bytes_reqd = sizeof (char) * (SIZE_T) MAX_MSG_LEN;
+ G_tmp_msg = (char *) malloc (bytes_reqd);
+
+ if (G_tmp_msg == NULL)
+ {
+ FPRINTF (stderr, "%s %ld bytes for the message buffer\n",
+ "FATAL: unable to allocate", bytes_reqd);
+
+ G_status = FATAL_STATUS;
+ vv_exit ();
+ }
+ DEBUG_2 ("main: allocated %ld bytes for buffer `%s'",
+ (Int32) bytes_reqd, "G_tmp_msg");
+
+ /*-
+ **------------------------------------------------------------------------
+ ** Allocate the other global buffers.
+ **------------------------------------------------------------------------
+ */
+ G_ip_buffer = allocate_buffer ((SIZE_T) IP_BUFFER_SIZE, "G_ip_buffer");
+ G_op_buffer = allocate_buffer ((SIZE_T) OP_BUFFER_SIZE, "G_op_buffer");
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ scan_cmd_line (argc, argv, QUAL_INTRO, QUAL_SEP, G_cmdqual,
+ &G_cmd_ipfile, &G_cmd_opfile);
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+#if (VV_DEBUG_SUPPORT)
+#else /* NOT (VV_DEBUG_SUPPORT) */
+ if (Q_DEBUG)
+ {
+ WARNMSG ("Debugging support was not compiled into VVencode");
+ }
+ G_debugging = FALSE;
+ G_cmdqual[CMDQ_DEBUG].present = FALSE;
+#endif /* (VV_DEBUG_SUPPORT) */
+
+ /*-
+ **------------------------------------------------------------------------
+ ** If the 'help' option was selected, call usage_error() and stop.
+ **------------------------------------------------------------------------
+ */
+ if (Q_HELP)
+ {
+ USAGE ("help requested");
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ ** If the 'debug' option was selected, ensure that the 'log' option is
+ ** selected.
+ **------------------------------------------------------------------------
+ */
+ if (Q_DEBUG)
+ {
+ G_debugging = TRUE;
+ if (!Q_LOG)
+ {
+ G_cmdqual[CMDQ_LOG].present = TRUE;
+ G_cmdqual[CMDQ_LOG].value = NULL;
+ }
+ }
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ if (!Q_INPUT_FILE)
+ {
+ USAGE ("input file must be specified");
+ }
+
+ initialize ();
+ encode ();
+ terminate ();
+
+ /*-
+ **------------------------------------------------------------------------
+ **
+ **------------------------------------------------------------------------
+ */
+ vv_exit ();
+ return (0);
+} /* main */