1783 lines
37 KiB
C
1783 lines
37 KiB
C
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
|
||
/* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
|
||
/* All Rights Reserved */
|
||
|
||
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
|
||
/* UNIX System Laboratories, Inc. */
|
||
/* The copyright notice above does not evidence any */
|
||
/* actual or intended publication of such source code. */
|
||
|
||
#ident "$Revision: 1.17 $"
|
||
/*
|
||
** convert and copy
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <signal.h>
|
||
#include <sys/param.h>
|
||
#include <sys/types.h>
|
||
#include <sys/sysmacros.h>
|
||
#include <sys/fcntl.h>
|
||
#include <sys/stat.h>
|
||
#include <unistd.h>
|
||
#include <stdlib.h>
|
||
#include <locale.h>
|
||
#include <pfmt.h>
|
||
#include <string.h>
|
||
#include <errno.h>
|
||
#include <sgi_nl.h>
|
||
#include <msgs/uxsgicore.h>
|
||
|
||
|
||
/* The BIG parameter is machine dependent. It should be a long integer */
|
||
/* constant that can be used by the number parser to check the validity */
|
||
/* of numeric parameters. On 16-bit machines, it should probably be */
|
||
/* the maximum unsigned integer, 0177777L. On 32-bit machines where */
|
||
/* longs are the same size as ints, the maximum signed integer is more */
|
||
/* appropriate. This value is 017777777777L. */
|
||
|
||
#ifdef __sgi
|
||
#define BIGLL 0x7FFFFFFFFFFFFFFFLL
|
||
#define DD_BSIZE 512 /* dd's default block size */
|
||
#endif /* __sgi */
|
||
#define BIG 017777777777L
|
||
|
||
/* Option parameters */
|
||
|
||
#define COPY 0 /* file copy, preserve input block size */
|
||
#define REBLOCK 1 /* file copy, change block size */
|
||
#define LCREBLOCK 2 /* file copy, convert to lower case */
|
||
#define UCREBLOCK 3 /* file copy, convert to upper case */
|
||
#define NBASCII 4 /* file copy, convert from EBCDIC to ASCII */
|
||
#define LCNBASCII 5 /* file copy, EBCDIC to lower case ASCII */
|
||
#define UCNBASCII 6 /* file copy, EBCDIC to upper case ASCII */
|
||
#define NBEBCDIC 7 /* file copy, convert from ASCII to EBCDIC */
|
||
#define LCNBEBCDIC 8 /* file copy, ASCII to lower case EBCDIC */
|
||
#define UCNBEBCDIC 9 /* file copy, ASCII to upper case EBCDIC */
|
||
#define NBIBM 10 /* file copy, convert from ASCII to IBM */
|
||
#define LCNBIBM 11 /* file copy, ASCII to lower case IBM */
|
||
#define UCNBIBM 12 /* file copy, ASCII to upper case IBM */
|
||
#define UNBLOCK 13 /* convert blocked ASCII to ASCII */
|
||
#define LCUNBLOCK 14 /* convert blocked ASCII to lower case ASCII */
|
||
#define UCUNBLOCK 15 /* convert blocked ASCII to upper case ASCII */
|
||
#define ASCII 16 /* convert blocked EBCDIC to ASCII */
|
||
#define LCASCII 17 /* convert blocked EBCDIC to lower case ASCII */
|
||
#define UCASCII 18 /* convert blocked EBCDIC to upper case ASCII */
|
||
#define BLOCK 19 /* convert ASCII to blocked ASCII */
|
||
#define LCBLOCK 20 /* convert ASCII to lower case blocked ASCII */
|
||
#define UCBLOCK 21 /* convert ASCII to upper case blocked ASCII */
|
||
#define EBCDIC 22 /* convert ASCII to blocked EBCDIC */
|
||
#define LCEBCDIC 23 /* convert ASCII to lower case blocked EBCDIC */
|
||
#define UCEBCDIC 24 /* convert ASCII to upper case blocked EBCDIC */
|
||
#define IBM 25 /* convert ASCII to blocked IBM */
|
||
#define LCIBM 26 /* convert ASCII to lower case blocked IBM */
|
||
#define UCIBM 27 /* convert ASCII to upper case blocked IBM */
|
||
#define LCASE 01 /* flag - convert to lower case */
|
||
#define UCASE 02 /* flag - convert to upper case */
|
||
#define SWAB 04 /* flag - swap bytes before conversion */
|
||
#define NERR 010 /* flag - proceed on input errors */
|
||
#define SYNC 020 /* flag - pad short input blocks with spaces */
|
||
#define NOTRUNC 040 /* flag - XXX */
|
||
#define IGNERR 0100 /* "ignore" (zero-fill output) errors */
|
||
|
||
#define BADLIMIT 5 /* give up if no progress after BADLIMIT tries */
|
||
|
||
int badlimit = BADLIMIT; /* no limit if conv=ignerr */
|
||
|
||
/* Global references */
|
||
|
||
/* Local routine declarations */
|
||
|
||
int match();
|
||
void term();
|
||
unsigned int number();
|
||
#ifdef __sgi
|
||
unsigned long long bignumber();
|
||
#endif /* __sgi */
|
||
unsigned char *flsh();
|
||
void stats();
|
||
|
||
/* Local data definitions */
|
||
|
||
static unsigned ibs; /* input buffer size */
|
||
static unsigned obs; /* output buffer size */
|
||
static unsigned bs; /* buffer size, overrules ibs and obs */
|
||
static unsigned cbs; /* conversion buffer size, used for block conversions */
|
||
static unsigned ibc; /* number of bytes still in the input buffer */
|
||
static unsigned obc; /* number of bytes in the output buffer */
|
||
static unsigned cbc; /* number of bytes in the conversion buffer */
|
||
|
||
static int ibf; /* input file descriptor */
|
||
static int obf; /* output file descriptor */
|
||
static int cflag; /* conversion option flags */
|
||
static int skipf; /* if skipf == 1, skip rest of input line */
|
||
static long long nifr; /* count of full input records */
|
||
static int nipr; /* count of partial input records */
|
||
static long long nofr; /* count of full output records */
|
||
static int nopr; /* count of partial output records */
|
||
static int ntrunc; /* count of truncated input lines */
|
||
static int nbad; /* count of bad records since last good one */
|
||
static int files; /* number of input files to concatenate (tape only) */
|
||
static int skip; /* number of input records to skip */
|
||
#ifdef __sgi
|
||
static long long iseekn; /* number of input records to seek past */
|
||
static long long oseekn; /* number of output records to seek past */
|
||
#else
|
||
static int iseekn; /* number of input records to seek past */
|
||
static int oseekn; /* number of output records to seek past */
|
||
#endif /* __sgi */
|
||
static int count; /* number of input records to copy (0 = all) */
|
||
|
||
static char *string; /* command arg pointer */
|
||
static char *ifile; /* input file name pointer */
|
||
static char *ofile; /* output file name pointer */
|
||
static unsigned char *ibuf; /* input buffer pointer */
|
||
static unsigned char *obuf; /* output buffer pointer */
|
||
|
||
/* This is an EBCDIC to ASCII conversion table */
|
||
/* from a proposed BTL standard April 16, 1979 */
|
||
|
||
static unsigned char etoa [] =
|
||
{
|
||
0000,0001,0002,0003,0234,0011,0206,0177,
|
||
0227,0215,0216,0013,0014,0015,0016,0017,
|
||
0020,0021,0022,0023,0235,0205,0010,0207,
|
||
0030,0031,0222,0217,0034,0035,0036,0037,
|
||
0200,0201,0202,0203,0204,0012,0027,0033,
|
||
0210,0211,0212,0213,0214,0005,0006,0007,
|
||
0220,0221,0026,0223,0224,0225,0226,0004,
|
||
0230,0231,0232,0233,0024,0025,0236,0032,
|
||
0040,0240,0241,0242,0243,0244,0245,0246,
|
||
0247,0250,0325,0056,0074,0050,0053,0174,
|
||
0046,0251,0252,0253,0254,0255,0256,0257,
|
||
0260,0261,0041,0044,0052,0051,0073,0176,
|
||
0055,0057,0262,0263,0264,0265,0266,0267,
|
||
0270,0271,0313,0054,0045,0137,0076,0077,
|
||
0272,0273,0274,0275,0276,0277,0300,0301,
|
||
0302,0140,0072,0043,0100,0047,0075,0042,
|
||
0303,0141,0142,0143,0144,0145,0146,0147,
|
||
0150,0151,0304,0305,0306,0307,0310,0311,
|
||
0312,0152,0153,0154,0155,0156,0157,0160,
|
||
0161,0162,0136,0314,0315,0316,0317,0320,
|
||
0321,0345,0163,0164,0165,0166,0167,0170,
|
||
0171,0172,0322,0323,0324,0133,0326,0327,
|
||
0330,0331,0332,0333,0334,0335,0336,0337,
|
||
0340,0341,0342,0343,0344,0135,0346,0347,
|
||
0173,0101,0102,0103,0104,0105,0106,0107,
|
||
0110,0111,0350,0351,0352,0353,0354,0355,
|
||
0175,0112,0113,0114,0115,0116,0117,0120,
|
||
0121,0122,0356,0357,0360,0361,0362,0363,
|
||
0134,0237,0123,0124,0125,0126,0127,0130,
|
||
0131,0132,0364,0365,0366,0367,0370,0371,
|
||
0060,0061,0062,0063,0064,0065,0066,0067,
|
||
0070,0071,0372,0373,0374,0375,0376,0377,
|
||
};
|
||
|
||
/* This is an ASCII to EBCDIC conversion table */
|
||
/* from a proposed BTL standard April 16, 1979 */
|
||
|
||
static unsigned char atoe [] =
|
||
{
|
||
0000,0001,0002,0003,0067,0055,0056,0057,
|
||
0026,0005,0045,0013,0014,0015,0016,0017,
|
||
0020,0021,0022,0023,0074,0075,0062,0046,
|
||
0030,0031,0077,0047,0034,0035,0036,0037,
|
||
0100,0132,0177,0173,0133,0154,0120,0175,
|
||
0115,0135,0134,0116,0153,0140,0113,0141,
|
||
0360,0361,0362,0363,0364,0365,0366,0367,
|
||
0370,0371,0172,0136,0114,0176,0156,0157,
|
||
0174,0301,0302,0303,0304,0305,0306,0307,
|
||
0310,0311,0321,0322,0323,0324,0325,0326,
|
||
0327,0330,0331,0342,0343,0344,0345,0346,
|
||
0347,0350,0351,0255,0340,0275,0232,0155,
|
||
0171,0201,0202,0203,0204,0205,0206,0207,
|
||
0210,0211,0221,0222,0223,0224,0225,0226,
|
||
0227,0230,0231,0242,0243,0244,0245,0246,
|
||
0247,0250,0251,0300,0117,0320,0137,0007,
|
||
0040,0041,0042,0043,0044,0025,0006,0027,
|
||
0050,0051,0052,0053,0054,0011,0012,0033,
|
||
0060,0061,0032,0063,0064,0065,0066,0010,
|
||
0070,0071,0072,0073,0004,0024,0076,0341,
|
||
0101,0102,0103,0104,0105,0106,0107,0110,
|
||
0111,0121,0122,0123,0124,0125,0126,0127,
|
||
0130,0131,0142,0143,0144,0145,0146,0147,
|
||
0150,0151,0160,0161,0162,0163,0164,0165,
|
||
0166,0167,0170,0200,0212,0213,0214,0215,
|
||
0216,0217,0220,0152,0233,0234,0235,0236,
|
||
0237,0240,0252,0253,0254,0112,0256,0257,
|
||
0260,0261,0262,0263,0264,0265,0266,0267,
|
||
0270,0271,0272,0273,0274,0241,0276,0277,
|
||
0312,0313,0314,0315,0316,0317,0332,0333,
|
||
0334,0335,0336,0337,0352,0353,0354,0355,
|
||
0356,0357,0372,0373,0374,0375,0376,0377,
|
||
};
|
||
|
||
/* Table for ASCII to IBM (alternate EBCDIC) code conversion */
|
||
|
||
static unsigned char atoibm[] =
|
||
{
|
||
0000,0001,0002,0003,0067,0055,0056,0057,
|
||
0026,0005,0045,0013,0014,0015,0016,0017,
|
||
0020,0021,0022,0023,0074,0075,0062,0046,
|
||
0030,0031,0077,0047,0034,0035,0036,0037,
|
||
0100,0132,0177,0173,0133,0154,0120,0175,
|
||
0115,0135,0134,0116,0153,0140,0113,0141,
|
||
0360,0361,0362,0363,0364,0365,0366,0367,
|
||
0370,0371,0172,0136,0114,0176,0156,0157,
|
||
0174,0301,0302,0303,0304,0305,0306,0307,
|
||
0310,0311,0321,0322,0323,0324,0325,0326,
|
||
0327,0330,0331,0342,0343,0344,0345,0346,
|
||
0347,0350,0351,0255,0340,0275,0137,0155,
|
||
0171,0201,0202,0203,0204,0205,0206,0207,
|
||
0210,0211,0221,0222,0223,0224,0225,0226,
|
||
0227,0230,0231,0242,0243,0244,0245,0246,
|
||
0247,0250,0251,0300,0117,0320,0241,0007,
|
||
0040,0041,0042,0043,0044,0025,0006,0027,
|
||
0050,0051,0052,0053,0054,0011,0012,0033,
|
||
0060,0061,0032,0063,0064,0065,0066,0010,
|
||
0070,0071,0072,0073,0004,0024,0076,0341,
|
||
0101,0102,0103,0104,0105,0106,0107,0110,
|
||
0111,0121,0122,0123,0124,0125,0126,0127,
|
||
0130,0131,0142,0143,0144,0145,0146,0147,
|
||
0150,0151,0160,0161,0162,0163,0164,0165,
|
||
0166,0167,0170,0200,0212,0213,0214,0215,
|
||
0216,0217,0220,0232,0233,0234,0235,0236,
|
||
0237,0240,0252,0253,0254,0255,0256,0257,
|
||
0260,0261,0262,0263,0264,0265,0266,0267,
|
||
0270,0271,0272,0273,0274,0275,0276,0277,
|
||
0312,0313,0314,0315,0316,0317,0332,0333,
|
||
0334,0335,0336,0337,0352,0353,0354,0355,
|
||
0356,0357,0372,0373,0374,0375,0376,0377,
|
||
};
|
||
|
||
/* Table for conversion of ASCII to lower case ASCII */
|
||
|
||
static unsigned char utol[] =
|
||
{
|
||
0000,0001,0002,0003,0004,0005,0006,0007,
|
||
0010,0011,0012,0013,0014,0015,0016,0017,
|
||
0020,0021,0022,0023,0024,0025,0026,0027,
|
||
0030,0031,0032,0033,0034,0035,0036,0037,
|
||
0040,0041,0042,0043,0044,0045,0046,0047,
|
||
0050,0051,0052,0053,0054,0055,0056,0057,
|
||
0060,0061,0062,0063,0064,0065,0066,0067,
|
||
0070,0071,0072,0073,0074,0075,0076,0077,
|
||
0100,0141,0142,0143,0144,0145,0146,0147,
|
||
0150,0151,0152,0153,0154,0155,0156,0157,
|
||
0160,0161,0162,0163,0164,0165,0166,0167,
|
||
0170,0171,0172,0133,0134,0135,0136,0137,
|
||
0140,0141,0142,0143,0144,0145,0146,0147,
|
||
0150,0151,0152,0153,0154,0155,0156,0157,
|
||
0160,0161,0162,0163,0164,0165,0166,0167,
|
||
0170,0171,0172,0173,0174,0175,0176,0177,
|
||
0200,0201,0202,0203,0204,0205,0206,0207,
|
||
0210,0211,0212,0213,0214,0215,0216,0217,
|
||
0220,0221,0222,0223,0224,0225,0226,0227,
|
||
0230,0231,0232,0233,0234,0235,0236,0237,
|
||
0240,0241,0242,0243,0244,0245,0246,0247,
|
||
0250,0251,0252,0253,0254,0255,0256,0257,
|
||
0260,0261,0262,0263,0264,0265,0266,0267,
|
||
0270,0271,0272,0273,0274,0275,0276,0277,
|
||
0300,0301,0302,0303,0304,0305,0306,0307,
|
||
0310,0311,0312,0313,0314,0315,0316,0317,
|
||
0320,0321,0322,0323,0324,0325,0326,0327,
|
||
0330,0331,0332,0333,0334,0335,0336,0337,
|
||
0340,0341,0342,0343,0344,0345,0346,0347,
|
||
0350,0351,0352,0353,0354,0355,0356,0357,
|
||
0360,0361,0362,0363,0364,0365,0366,0367,
|
||
0370,0371,0372,0373,0374,0375,0376,0377,
|
||
};
|
||
|
||
/* Table for conversion of ASCII to upper case ASCII */
|
||
|
||
static unsigned char ltou[] =
|
||
{
|
||
0000,0001,0002,0003,0004,0005,0006,0007,
|
||
0010,0011,0012,0013,0014,0015,0016,0017,
|
||
0020,0021,0022,0023,0024,0025,0026,0027,
|
||
0030,0031,0032,0033,0034,0035,0036,0037,
|
||
0040,0041,0042,0043,0044,0045,0046,0047,
|
||
0050,0051,0052,0053,0054,0055,0056,0057,
|
||
0060,0061,0062,0063,0064,0065,0066,0067,
|
||
0070,0071,0072,0073,0074,0075,0076,0077,
|
||
0100,0101,0102,0103,0104,0105,0106,0107,
|
||
0110,0111,0112,0113,0114,0115,0116,0117,
|
||
0120,0121,0122,0123,0124,0125,0126,0127,
|
||
0130,0131,0132,0133,0134,0135,0136,0137,
|
||
0140,0101,0102,0103,0104,0105,0106,0107,
|
||
0110,0111,0112,0113,0114,0115,0116,0117,
|
||
0120,0121,0122,0123,0124,0125,0126,0127,
|
||
0130,0131,0132,0173,0174,0175,0176,0177,
|
||
0200,0201,0202,0203,0204,0205,0206,0207,
|
||
0210,0211,0212,0213,0214,0215,0216,0217,
|
||
0220,0221,0222,0223,0224,0225,0226,0227,
|
||
0230,0231,0232,0233,0234,0235,0236,0237,
|
||
0240,0241,0242,0243,0244,0245,0246,0247,
|
||
0250,0251,0252,0253,0254,0255,0256,0257,
|
||
0260,0261,0262,0263,0264,0265,0266,0267,
|
||
0270,0271,0272,0273,0274,0275,0276,0277,
|
||
0300,0301,0302,0303,0304,0305,0306,0307,
|
||
0310,0311,0312,0313,0314,0315,0316,0317,
|
||
0320,0321,0322,0323,0324,0325,0326,0327,
|
||
0330,0331,0332,0333,0334,0335,0336,0337,
|
||
0340,0341,0342,0343,0344,0345,0346,0347,
|
||
0350,0351,0352,0353,0354,0355,0356,0357,
|
||
0360,0361,0362,0363,0364,0365,0366,0367,
|
||
0370,0371,0372,0373,0374,0375,0376,0377,
|
||
};
|
||
|
||
main(argc, argv)
|
||
int argc;
|
||
char **argv;
|
||
{
|
||
register unsigned char *ip, *op;/* input and output buffer pointers */
|
||
register int c; /* character counter */
|
||
register int ic; /* input character */
|
||
register int conv; /* conversion option code */
|
||
static char null_string[1]; /* "", but you can take its address */
|
||
|
||
(void)setlocale(LC_ALL, "");
|
||
(void)setcat("uxcore.abi");
|
||
#define CMD_LABEL "UX:dd"
|
||
(void)setlabel(CMD_LABEL);
|
||
|
||
/* Set option defaults */
|
||
|
||
#ifdef __sgi
|
||
ibs = DD_BSIZE;
|
||
obs = DD_BSIZE;
|
||
#else
|
||
ibs = BSIZE;
|
||
obs = BSIZE;
|
||
#endif /* __sgi */
|
||
files = 1;
|
||
conv = COPY;
|
||
|
||
/* Parse command options */
|
||
|
||
for (c = 1; c < argc; c++)
|
||
{
|
||
string = argv[c];
|
||
if (match("ibs="))
|
||
{
|
||
ibs = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("obs="))
|
||
{
|
||
obs = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("cbs="))
|
||
{
|
||
cbs = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("bs="))
|
||
{
|
||
bs = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("if="))
|
||
{
|
||
ifile = string;
|
||
continue;
|
||
}
|
||
if (match("of="))
|
||
{
|
||
ofile = string;
|
||
continue;
|
||
}
|
||
|
||
if (match("skip="))
|
||
{
|
||
skip = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("iseek="))
|
||
{
|
||
#ifdef __sgi
|
||
iseekn = bignumber(BIGLL);
|
||
#else
|
||
iseekn = number(BIG);
|
||
#endif /* __sgi */
|
||
continue;
|
||
}
|
||
if (match("oseek="))
|
||
{
|
||
#ifdef __sgi
|
||
oseekn = bignumber(BIGLL);
|
||
#else
|
||
oseekn = number(BIG);
|
||
#endif /* __sgi */
|
||
continue;
|
||
}
|
||
if (match("seek=")) /* retained for compatibility */
|
||
{
|
||
#ifdef __sgi
|
||
oseekn = bignumber(BIGLL);
|
||
#else
|
||
oseekn = number(BIG);
|
||
#endif /* __sgi */
|
||
continue;
|
||
}
|
||
if (match("count="))
|
||
{
|
||
count = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("files="))
|
||
{
|
||
files = number(BIG);
|
||
continue;
|
||
}
|
||
if (match("conv="))
|
||
{
|
||
for (;;)
|
||
{
|
||
if (match(","))
|
||
{
|
||
continue;
|
||
}
|
||
if (*string == '\0')
|
||
{
|
||
break;
|
||
}
|
||
if (match("block"))
|
||
{
|
||
conv = BLOCK;
|
||
continue;
|
||
}
|
||
if (match("unblock"))
|
||
{
|
||
conv = UNBLOCK;
|
||
continue;
|
||
}
|
||
|
||
if (match("ebcdic"))
|
||
{
|
||
conv = EBCDIC;
|
||
continue;
|
||
}
|
||
if (match("ibm"))
|
||
{
|
||
conv = IBM;
|
||
continue;
|
||
}
|
||
if (match("ascii"))
|
||
{
|
||
conv = ASCII;
|
||
continue;
|
||
}
|
||
if (match("lcase"))
|
||
{
|
||
cflag |= LCASE;
|
||
continue;
|
||
}
|
||
if (match("ucase"))
|
||
{
|
||
cflag |= UCASE;
|
||
continue;
|
||
}
|
||
if (match("swab"))
|
||
{
|
||
cflag |= SWAB;
|
||
continue;
|
||
}
|
||
if (match("noerror"))
|
||
{
|
||
cflag |= NERR;
|
||
continue;
|
||
}
|
||
if (match("ignerror"))
|
||
{
|
||
cflag |= IGNERR;
|
||
badlimit = 0;
|
||
continue;
|
||
}
|
||
if (match("sync"))
|
||
{
|
||
cflag |= SYNC;
|
||
continue;
|
||
}
|
||
if (match("notrunc"))
|
||
{
|
||
cflag |= NOTRUNC;
|
||
continue;
|
||
}
|
||
|
||
goto badarg;
|
||
}
|
||
continue;
|
||
}
|
||
badarg:
|
||
pfmt(stderr, MM_ERROR, ":145:Bad argument: \"%s\"\n", string);
|
||
exit(2);
|
||
}
|
||
|
||
/* Perform consistency checks on options, decode strange conventions */
|
||
|
||
if (bs)
|
||
{
|
||
ibs = obs = bs;
|
||
}
|
||
if ((ibs == 0) || (obs == 0))
|
||
{
|
||
pfmt(stderr, MM_ERROR, ":146:Buffer sizes cannot be zero\n");
|
||
exit(2);
|
||
}
|
||
if (conv == COPY)
|
||
{
|
||
if (cbs != 0)
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":147:cbs must be zero if no block conversion requested\n");
|
||
exit(2);
|
||
}
|
||
if ((bs == 0) || (cflag&(LCASE|UCASE)))
|
||
{
|
||
conv = REBLOCK;
|
||
}
|
||
}
|
||
if (cbs == 0)
|
||
{
|
||
switch (conv)
|
||
{
|
||
case BLOCK:
|
||
case UNBLOCK:
|
||
conv = REBLOCK;
|
||
break;
|
||
|
||
case ASCII:
|
||
conv = NBASCII;
|
||
break;
|
||
|
||
case EBCDIC:
|
||
conv = NBEBCDIC;
|
||
break;
|
||
|
||
case IBM:
|
||
conv = NBIBM;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Expand options into lower and upper case versions if necessary */
|
||
|
||
switch (conv)
|
||
{
|
||
case REBLOCK:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCREBLOCK;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCREBLOCK;
|
||
}
|
||
break;
|
||
|
||
case UNBLOCK:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCUNBLOCK;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCUNBLOCK;
|
||
}
|
||
break;
|
||
|
||
case BLOCK:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCBLOCK;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCBLOCK;
|
||
}
|
||
break;
|
||
|
||
case ASCII:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCASCII;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCASCII;
|
||
}
|
||
break;
|
||
|
||
case NBASCII:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCNBASCII;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCNBASCII;
|
||
}
|
||
break;
|
||
|
||
case EBCDIC:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCEBCDIC;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCEBCDIC;
|
||
}
|
||
break;
|
||
|
||
case NBEBCDIC:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCNBEBCDIC;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCNBEBCDIC;
|
||
}
|
||
break;
|
||
|
||
case IBM:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCIBM;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCIBM;
|
||
}
|
||
break;
|
||
|
||
case NBIBM:
|
||
if (cflag&LCASE)
|
||
{
|
||
conv = LCNBIBM;
|
||
}
|
||
else if (cflag&UCASE)
|
||
{
|
||
conv = UCNBIBM;
|
||
}
|
||
break;
|
||
}
|
||
|
||
/* Open the input file, or duplicate standard input */
|
||
|
||
ibf = -1;
|
||
if (ifile)
|
||
{
|
||
ibf = open(ifile, 0);
|
||
}
|
||
#ifndef STANDALONE
|
||
else
|
||
{
|
||
ifile = "";
|
||
ibf = dup(0);
|
||
}
|
||
#endif
|
||
if (ibf == -1)
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":4:Cannot open %s: %s\n", ifile,
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
|
||
/* Open the output file, or duplicate standard output */
|
||
|
||
obf = -1;
|
||
if (ofile)
|
||
{
|
||
obf = open(ofile,
|
||
O_WRONLY | O_CREAT | \
|
||
((oseekn || (cflag & NOTRUNC)) ? 0 : O_TRUNC),
|
||
(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH));
|
||
|
||
}
|
||
#ifndef STANDALONE
|
||
else
|
||
{
|
||
ofile = null_string;
|
||
obf = dup(1);
|
||
}
|
||
#endif
|
||
if (obf == -1)
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":148:Cannot create %s: %s\n", ofile,
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
|
||
/* Expand memory to get an input buffer */
|
||
|
||
ibuf = (unsigned char *)malloc(ibs + 10);
|
||
|
||
/* If no conversions, the input buffer is the output buffer */
|
||
|
||
if (conv == COPY)
|
||
{
|
||
obuf = ibuf;
|
||
}
|
||
|
||
/* Expand memory to get an output buffer. Leave enough room at the */
|
||
/* end to convert a logical record when doing block conversions. */
|
||
|
||
else
|
||
{
|
||
obuf = (unsigned char *)malloc(obs + cbs + 10);
|
||
}
|
||
if ((ibuf == (unsigned char *)NULL) || (obuf == (unsigned char *)NULL))
|
||
{
|
||
pfmt(stderr, MM_ERROR, ":149:Not enough memory: %s\n",
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
|
||
/* Enable a statistics message on SIGINT */
|
||
|
||
#ifndef STANDALONE
|
||
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
|
||
{
|
||
(void)signal(SIGINT, term);
|
||
}
|
||
#endif
|
||
|
||
/* Skip input blocks */
|
||
|
||
while (skip)
|
||
{
|
||
ibc = read(ibf, (char *)ibuf, ibs);
|
||
if (ibc == (unsigned)-1)
|
||
{
|
||
if (badlimit && ++nbad > badlimit)
|
||
{
|
||
pfmt(stderr, MM_ERROR, ":150:Skip failed: %s\n",
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
else
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":151:Read error during skip: %s\n",
|
||
strerror(errno));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (ibc == 0)
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":152:Cannot skip past end-of-file: %s\n",
|
||
strerror(errno));
|
||
exit(3);
|
||
}
|
||
else
|
||
{
|
||
nbad = 0;
|
||
}
|
||
}
|
||
skip--;
|
||
}
|
||
|
||
/* Seek past input blocks */
|
||
|
||
#ifdef __sgi
|
||
if (iseekn && lseek64(ibf, ((off64_t) iseekn) * ((off64_t) ibs), 1) == -1)
|
||
#else
|
||
if (iseekn && lseek(ibf, ((off_t) iseekn) * ((off_t) ibs), 1) == -1)
|
||
#endif /* __sgi */
|
||
{
|
||
pfmt(stderr, MM_ERROR, ":153:Input seek error: %s\n",
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
|
||
/* Seek past output blocks */
|
||
|
||
#ifdef __sgi
|
||
if (oseekn && lseek64(obf, ((off64_t) oseekn) * ((off64_t) obs), 1) == -1)
|
||
#else
|
||
if (oseekn && lseek(obf, ((off_t) oseekn) * ((off_t) obs), 1) == -1)
|
||
#endif /* __sgi */
|
||
{
|
||
pfmt(stderr, MM_ERROR, ":154:Output seek error: %s\n",
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
if (oseekn && (cflag & NOTRUNC) != NOTRUNC && ofile != null_string) {
|
||
#ifdef __sgi
|
||
if (ftruncate64(obf, ((off64_t) oseekn) * ((off64_t) obs))
|
||
== -1)
|
||
#else
|
||
if (ftruncate(obf, ((off_t) oseekn) * ((off_t) obs)) == -1)
|
||
#endif /* __sgi */
|
||
{
|
||
/*
|
||
* Ignore errors from devices which don't
|
||
* support truncatation.
|
||
*/
|
||
if (errno != EINVAL) {
|
||
(void)setcat("uxsgicore");
|
||
_sgi_nl_usage(SGINL_NOSYSERR,CMD_LABEL,
|
||
gettxt(_SGI_MMX_dd_trucat_err,
|
||
"Cannot truncate %s: %s"),
|
||
ofile,
|
||
strerror(errno));
|
||
exit(2);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Initialize all buffer pointers */
|
||
|
||
skipf = 0; /* not skipping an input line */
|
||
ibc = 0; /* no input characters yet */
|
||
obc = 0; /* no output characters yet */
|
||
cbc = 0; /* the conversion buffer is empty */
|
||
op = obuf; /* point to the output buffer */
|
||
|
||
/* Read and convert input blocks until end of file(s) */
|
||
|
||
for (;;)
|
||
{
|
||
if ((count == 0) || (nifr+nipr < count))
|
||
{
|
||
/* If proceed on error is enabled, zero the input buffer */
|
||
|
||
if (cflag&(IGNERR|NERR))
|
||
{
|
||
ip = ibuf + ibs;
|
||
c = ibs;
|
||
if (c & 1) /* if the size is odd, */
|
||
{
|
||
*--ip = 0; /* clear the odd byte */
|
||
}
|
||
if (c >>= 1) /* divide by two */
|
||
{
|
||
do { /* clear two at a time */
|
||
*--ip = 0;
|
||
*--ip = 0;
|
||
} while (--c);
|
||
}
|
||
}
|
||
|
||
/* Read the next input block */
|
||
|
||
ibc = read(ibf, (char *)ibuf, ibs);
|
||
|
||
/* Process input errors */
|
||
|
||
if (ibc == (unsigned)-1)
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":155:Read error: %s\n", strerror(errno));
|
||
if ( ((cflag&(IGNERR|NERR)) == 0)
|
||
|| (badlimit && ++nbad > badlimit) )
|
||
{
|
||
while (obc)
|
||
{
|
||
(void)flsh();
|
||
}
|
||
term(2);
|
||
}
|
||
else
|
||
{
|
||
stats();
|
||
if(cflag&IGNERR) {
|
||
/* try to lseek over the bad read; assumes something
|
||
* like a disk, where this makes sense... */
|
||
if(lseek64(ibf, ibs, SEEK_CUR) == -1)
|
||
perror("couldn't seek over failed read");
|
||
}
|
||
ibc = ibs; /* mark as a full block */
|
||
}
|
||
}
|
||
else
|
||
{
|
||
nbad = 0;
|
||
}
|
||
}
|
||
|
||
/* Record count satisfied, simulate end of file */
|
||
|
||
else
|
||
{
|
||
ibc = 0;
|
||
files = 1;
|
||
}
|
||
|
||
/* Process end of file */
|
||
|
||
if (ibc == 0)
|
||
{
|
||
switch (conv)
|
||
{
|
||
case UNBLOCK:
|
||
case LCUNBLOCK:
|
||
case UCUNBLOCK:
|
||
case ASCII:
|
||
case LCASCII:
|
||
case UCASCII:
|
||
|
||
/* Trim trailing blanks from the last line */
|
||
|
||
if ((c = cbc) != 0)
|
||
{
|
||
do {
|
||
if ((*--op) != ' ')
|
||
{
|
||
op++;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
*op++ = '\n';
|
||
obc -= cbc - c - 1;
|
||
cbc = 0;
|
||
|
||
/* Flush the output buffer if full */
|
||
|
||
while (obc >= obs)
|
||
{
|
||
op = flsh();
|
||
}
|
||
}
|
||
break;
|
||
|
||
case BLOCK:
|
||
case LCBLOCK:
|
||
case UCBLOCK:
|
||
case EBCDIC:
|
||
case LCEBCDIC:
|
||
case UCEBCDIC:
|
||
case IBM:
|
||
case LCIBM:
|
||
case UCIBM:
|
||
|
||
/* Pad trailing blanks if the last line is short */
|
||
|
||
if (cbc)
|
||
{
|
||
obc += c = cbs - cbc;
|
||
cbc = 0;
|
||
if (c > 0)
|
||
{
|
||
/* Use the right kind of blank */
|
||
|
||
switch (conv)
|
||
{
|
||
case BLOCK:
|
||
case LCBLOCK:
|
||
case UCBLOCK:
|
||
ic = ' ';
|
||
break;
|
||
|
||
case EBCDIC:
|
||
case LCEBCDIC:
|
||
case UCEBCDIC:
|
||
ic = atoe[' '];
|
||
break;
|
||
|
||
case IBM:
|
||
case LCIBM:
|
||
case UCIBM:
|
||
ic = atoibm[' '];
|
||
break;
|
||
}
|
||
|
||
/* Pad with trailing blanks */
|
||
|
||
do {
|
||
*op++ = ic;
|
||
} while (--c);
|
||
}
|
||
}
|
||
|
||
/* Flush the output buffer if full */
|
||
|
||
while (obc >= obs)
|
||
{
|
||
op = flsh();
|
||
}
|
||
break;
|
||
}
|
||
|
||
/* If no more files to read, flush the output buffer */
|
||
|
||
if (--files <= 0)
|
||
{
|
||
(void)flsh();
|
||
term(0); /* successful exit */
|
||
}
|
||
else
|
||
{
|
||
continue; /* read the next file */
|
||
}
|
||
}
|
||
|
||
/* Normal read, check for special cases */
|
||
|
||
else if (ibc == ibs)
|
||
{
|
||
nifr++; /* count another full input record */
|
||
}
|
||
else
|
||
{
|
||
nipr++; /* count a partial input record */
|
||
|
||
/* If `sync' enabled, pad nulls */
|
||
|
||
if ((cflag&SYNC) && ((cflag&(IGNERR|NERR)) == 0))
|
||
{
|
||
int pad_char = 0;
|
||
|
||
if(conv == BLOCK || conv == UNBLOCK)
|
||
pad_char = ' ';
|
||
|
||
c = ibs - ibc;
|
||
ip = ibuf + ibs;
|
||
do {
|
||
*--ip = pad_char;
|
||
} while (--c);
|
||
ibc = ibs;
|
||
}
|
||
}
|
||
|
||
/* Swap the bytes in the input buffer if necessary */
|
||
|
||
if (cflag&SWAB)
|
||
{
|
||
ip = ibuf;
|
||
if (ibc & 1) /* if the byte count is odd, */
|
||
{
|
||
ip[ibc] = 0; /* make it even, pad with zero */
|
||
}
|
||
c = (ibc + 1) >> 1; /* compute the pair count */
|
||
do {
|
||
ic = *ip++;
|
||
ip[-1] = *ip;
|
||
*ip++ = ic;
|
||
} while (--c); /* do two bytes at a time */
|
||
}
|
||
|
||
/* Select the appropriate conversion loop */
|
||
|
||
ip = ibuf;
|
||
switch (conv)
|
||
{
|
||
|
||
/* Simple copy: no conversion, preserve the input block size */
|
||
|
||
case COPY:
|
||
obc = ibc;
|
||
(void)flsh();
|
||
break;
|
||
|
||
/* Simple copy: pack all output into equal sized blocks */
|
||
|
||
case REBLOCK:
|
||
case LCREBLOCK:
|
||
case UCREBLOCK:
|
||
case NBASCII:
|
||
case LCNBASCII:
|
||
case UCNBASCII:
|
||
case NBEBCDIC:
|
||
case LCNBEBCDIC:
|
||
case UCNBEBCDIC:
|
||
case NBIBM:
|
||
case LCNBIBM:
|
||
case UCNBIBM:
|
||
while ((c = ibc) != 0)
|
||
{
|
||
if (c > (obs - obc))
|
||
{
|
||
c = obs - obc;
|
||
}
|
||
ibc -= c;
|
||
obc += c;
|
||
switch (conv)
|
||
{
|
||
case REBLOCK:
|
||
do {
|
||
*op++ = *ip++;
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCREBLOCK:
|
||
do {
|
||
*op++ = utol[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCREBLOCK:
|
||
do {
|
||
*op++ = ltou[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case NBASCII:
|
||
do {
|
||
*op++ = etoa[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCNBASCII:
|
||
do {
|
||
*op++ = utol[etoa[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCNBASCII:
|
||
do {
|
||
*op++ = ltou[etoa[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
|
||
case NBEBCDIC:
|
||
do {
|
||
*op++ = atoe[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCNBEBCDIC:
|
||
do {
|
||
*op++ = atoe[utol[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCNBEBCDIC:
|
||
do {
|
||
*op++ = atoe[ltou[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
|
||
case NBIBM:
|
||
do {
|
||
*op++ = atoibm[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCNBIBM:
|
||
do {
|
||
*op++ = atoibm[utol[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCNBIBM:
|
||
do {
|
||
*op++ = atoibm[ltou[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
}
|
||
if (obc >= obs)
|
||
{
|
||
op = flsh();
|
||
}
|
||
}
|
||
break;
|
||
|
||
/* Convert from blocked records to lines terminated by newline */
|
||
|
||
case UNBLOCK:
|
||
case LCUNBLOCK:
|
||
case UCUNBLOCK:
|
||
case ASCII:
|
||
case LCASCII:
|
||
case UCASCII:
|
||
while ((c = ibc) != 0)
|
||
{
|
||
if (c > (cbs - cbc)) /* if more than one record, */
|
||
{
|
||
c = cbs - cbc; /* only copy one record */
|
||
}
|
||
ibc -= c;
|
||
cbc += c;
|
||
obc += c;
|
||
switch (conv)
|
||
{
|
||
case UNBLOCK:
|
||
do {
|
||
*op++ = *ip++;
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCUNBLOCK:
|
||
do {
|
||
*op++ = utol[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCUNBLOCK:
|
||
do {
|
||
*op++ = ltou[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case ASCII:
|
||
do {
|
||
*op++ = etoa[*ip++];
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCASCII:
|
||
do {
|
||
*op++ = utol[etoa[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCASCII:
|
||
do {
|
||
*op++ = ltou[etoa[*ip++]];
|
||
} while (--c);
|
||
break;
|
||
}
|
||
|
||
/* Trim trailing blanks if the line is full */
|
||
|
||
if (cbc == cbs)
|
||
{
|
||
c = cbs; /* `do - while' is usually */
|
||
do { /* faster than `for' */
|
||
if ((*--op) != ' ')
|
||
{
|
||
op++;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
*op++ = '\n';
|
||
obc -= cbs - c - 1;
|
||
cbc = 0;
|
||
|
||
/* Flush the output buffer if full */
|
||
|
||
while (obc >= obs)
|
||
{
|
||
op = flsh();
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
/* Convert to blocked records */
|
||
|
||
case BLOCK:
|
||
case LCBLOCK:
|
||
case UCBLOCK:
|
||
case EBCDIC:
|
||
case LCEBCDIC:
|
||
case UCEBCDIC:
|
||
case IBM:
|
||
case LCIBM:
|
||
case UCIBM:
|
||
while ((c = ibc) != 0)
|
||
{
|
||
int nlflag = 0;
|
||
|
||
/* We may have to skip to the end of a long line */
|
||
|
||
if (skipf)
|
||
{
|
||
do {
|
||
if ((ic = *ip++) == '\n')
|
||
{
|
||
skipf = 0;
|
||
c--;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
if ((ibc = c) == 0)
|
||
{
|
||
continue; /* read another block */
|
||
}
|
||
}
|
||
|
||
/* If anything left, copy until newline */
|
||
|
||
if (c > (cbs - cbc + 1))
|
||
{
|
||
c = cbs - cbc + 1;
|
||
}
|
||
ibc -= c;
|
||
cbc += c;
|
||
obc += c;
|
||
|
||
switch (conv)
|
||
{
|
||
case BLOCK:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = ic;
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCBLOCK:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = utol[ic];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCBLOCK:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = ltou[ic];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case EBCDIC:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = atoe[ic];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCEBCDIC:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = atoe[utol[ic]];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCEBCDIC:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = atoe[ltou[ic]];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case IBM:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = atoibm[ic];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case LCIBM:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = atoibm[utol[ic]];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
|
||
case UCIBM:
|
||
do {
|
||
if ((ic = *ip++) != '\n')
|
||
{
|
||
*op++ = atoibm[ltou[ic]];
|
||
}
|
||
else
|
||
{
|
||
nlflag = 1;
|
||
break;
|
||
}
|
||
} while (--c);
|
||
break;
|
||
}
|
||
|
||
/* If newline found, update all the counters and */
|
||
/* pointers, pad with trailing blanks if necessary */
|
||
|
||
if (nlflag)
|
||
{
|
||
ibc += c - 1;
|
||
obc += cbs - cbc;
|
||
c += cbs - cbc;
|
||
cbc = 0;
|
||
if (c > 0)
|
||
{
|
||
/* Use the right kind of blank */
|
||
|
||
switch (conv)
|
||
{
|
||
case BLOCK:
|
||
case LCBLOCK:
|
||
case UCBLOCK:
|
||
ic = ' ';
|
||
break;
|
||
|
||
case EBCDIC:
|
||
case LCEBCDIC:
|
||
case UCEBCDIC:
|
||
ic = atoe[' '];
|
||
break;
|
||
|
||
case IBM:
|
||
case LCIBM:
|
||
case UCIBM:
|
||
ic = atoibm[' '];
|
||
break;
|
||
}
|
||
|
||
/* Pad with trailing blanks */
|
||
|
||
do {
|
||
*op++ = ic;
|
||
} while (--c);
|
||
}
|
||
}
|
||
|
||
/* If not end of line, this line may be too long */
|
||
|
||
else if (cbc > cbs)
|
||
{
|
||
skipf = 1; /* note skip in progress */
|
||
obc--;
|
||
op--;
|
||
cbc = 0;
|
||
ntrunc++; /* count another long line */
|
||
}
|
||
|
||
/* Flush the output buffer if full */
|
||
|
||
while (obc >= obs)
|
||
{
|
||
op = flsh();
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* match ************************************************************** */
|
||
/* */
|
||
/* Compare two text strings for equality */
|
||
/* */
|
||
/* Arg: s - pointer to string to match with a command arg */
|
||
/* Global arg: string - pointer to command arg */
|
||
/* */
|
||
/* Return: 1 if match, 0 if no match */
|
||
/* If match, also reset `string' to point to the text */
|
||
/* that follows the matching text. */
|
||
/* */
|
||
/* ******************************************************************** */
|
||
|
||
int match(s)
|
||
char *s;
|
||
{
|
||
register char *cs;
|
||
|
||
cs = string;
|
||
while (*cs++ == *s)
|
||
{
|
||
if (*s++ == '\0')
|
||
{
|
||
goto true;
|
||
}
|
||
}
|
||
if (*s != '\0')
|
||
{
|
||
return(0);
|
||
}
|
||
|
||
true:
|
||
cs--;
|
||
string = cs;
|
||
return(1);
|
||
}
|
||
|
||
#ifdef __sgi
|
||
/* bignumber ************************************************************* */
|
||
/* */
|
||
/* Convert a numeric arg to binary */
|
||
/* */
|
||
/* Arg: big - maximum valid input number */
|
||
/* Global arg: string - pointer to command arg */
|
||
/* */
|
||
/* Valid forms: 123 | 123k | 123w | 123b | 123*123 | 123x123 */
|
||
/* plus combinations such as 2b*3kw*4w */
|
||
/* */
|
||
/* Return: converted number */
|
||
/* */
|
||
/* ******************************************************************** */
|
||
|
||
unsigned long long bignumber(big)
|
||
long long big;
|
||
{
|
||
register char *cs;
|
||
long long n;
|
||
long long cut = BIGLL / 10; /* limit to avoid overflow */
|
||
|
||
cs = string;
|
||
n = 0;
|
||
while ((*cs >= '0') && (*cs <= '9') && (n <= cut))
|
||
{
|
||
n = n*10 + *cs++ - '0';
|
||
}
|
||
for (;;)
|
||
{
|
||
switch (*cs++)
|
||
{
|
||
|
||
case 'k':
|
||
n *= 1024;
|
||
continue;
|
||
|
||
case 'w':
|
||
n *= 2;
|
||
continue;
|
||
|
||
case 'b':
|
||
n *= DD_BSIZE;
|
||
continue;
|
||
|
||
case '*':
|
||
case 'x':
|
||
string = cs;
|
||
n *= bignumber(BIGLL);
|
||
|
||
/* Fall into exit test, recursion has read rest of string */
|
||
/* End of string, check for a valid number */
|
||
|
||
case '\0':
|
||
if ((n > cut) || (n < 0))
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":156:Argument out of range: \"%llu\"\n",
|
||
n);
|
||
exit(2);
|
||
}
|
||
return(n);
|
||
|
||
default:
|
||
pfmt(stderr, MM_ERROR,
|
||
":157:Bad numeric argument: \"%s\"\n", string);
|
||
exit(2);
|
||
}
|
||
} /* never gets here */
|
||
}
|
||
#endif /* __sgi */
|
||
/* number ************************************************************* */
|
||
/* */
|
||
/* Convert a numeric arg to binary */
|
||
/* */
|
||
/* Arg: big - maximum valid input number */
|
||
/* Global arg: string - pointer to command arg */
|
||
/* */
|
||
/* Valid forms: 123 | 123k | 123w | 123b | 123*123 | 123x123 */
|
||
/* plus combinations such as 2b*3kw*4w */
|
||
/* */
|
||
/* Return: converted number */
|
||
/* */
|
||
/* ******************************************************************** */
|
||
|
||
unsigned int number(big)
|
||
long big;
|
||
{
|
||
register char *cs;
|
||
long n;
|
||
long cut = BIG / 10; /* limit to avoid overflow */
|
||
|
||
cs = string;
|
||
n = 0;
|
||
while ((*cs >= '0') && (*cs <= '9') && (n <= cut))
|
||
{
|
||
n = n*10 + *cs++ - '0';
|
||
}
|
||
for (;;)
|
||
{
|
||
switch (*cs++)
|
||
{
|
||
|
||
case 'k':
|
||
n *= 1024;
|
||
continue;
|
||
|
||
case 'w':
|
||
n *= 2;
|
||
continue;
|
||
|
||
case 'b':
|
||
#ifdef __sgi
|
||
n *= DD_BSIZE;
|
||
#else
|
||
n *= BSIZE;
|
||
#endif /* __sgi */
|
||
continue;
|
||
|
||
case '*':
|
||
case 'x':
|
||
string = cs;
|
||
n *= number(BIG);
|
||
|
||
/* Fall into exit test, recursion has read rest of string */
|
||
|
||
/* End of string, check for a valid number */
|
||
|
||
case '\0':
|
||
if ((n > cut) || (n < 0))
|
||
{
|
||
pfmt(stderr, MM_ERROR,
|
||
":156:Argument out of range: \"%lu\"\n",
|
||
n);
|
||
exit(2);
|
||
}
|
||
return(n);
|
||
|
||
default:
|
||
pfmt(stderr, MM_ERROR,
|
||
":157:Bad numeric argument: \"%s\"\n", string);
|
||
exit(2);
|
||
}
|
||
} /* never gets here */
|
||
}
|
||
|
||
/* flsh *************************************************************** */
|
||
/* */
|
||
/* Flush the output buffer, move any excess bytes down to the beginning */
|
||
/* */
|
||
/* Arg: none */
|
||
/* Global args: obuf, obc, obs, nofr, nopr */
|
||
/* */
|
||
/* Return: Pointer to the first free byte in the output buffer. */
|
||
/* Also reset `obc' to account for moved bytes. */
|
||
/* */
|
||
/* ******************************************************************** */
|
||
|
||
unsigned char *flsh()
|
||
{
|
||
register unsigned char *op, *cp;
|
||
register unsigned int bc;
|
||
register unsigned int oc;
|
||
|
||
if (obc) /* don't flush if the buffer is empty */
|
||
{
|
||
if (obc >= obs)
|
||
{
|
||
oc = obs;
|
||
nofr++; /* count a full output buffer */
|
||
}
|
||
else
|
||
{
|
||
oc = obc;
|
||
nopr++; /* count a partial output buffer */
|
||
}
|
||
bc = write(obf, (char *)obuf, oc);
|
||
if (bc != oc)
|
||
{
|
||
pfmt(stderr, MM_ERROR, ":1:Write error: %s\n",
|
||
strerror(errno));
|
||
if (obc >= obs)
|
||
nofr--;
|
||
else
|
||
nopr--;
|
||
term(2);
|
||
}
|
||
obc -= oc;
|
||
op = obuf;
|
||
|
||
/* If any data in the conversion buffer, move it into the output buffer */
|
||
|
||
if (obc)
|
||
{
|
||
cp = obuf + obs;
|
||
bc = obc;
|
||
do {
|
||
*op++ = *cp++;
|
||
} while (--bc);
|
||
}
|
||
return(op);
|
||
}
|
||
return(obuf);
|
||
}
|
||
|
||
/* term *************************************************************** */
|
||
/* */
|
||
/* Write record statistics, then exit */
|
||
/* */
|
||
/* Arg: c - exit status code */
|
||
/* */
|
||
/* Return: no return, calls exit */
|
||
/* */
|
||
/* ******************************************************************** */
|
||
|
||
void
|
||
term(c)
|
||
int c;
|
||
{
|
||
stats();
|
||
exit(c);
|
||
}
|
||
|
||
/* stats ************************************************************** */
|
||
/* */
|
||
/* Write record statistics onto standard error */
|
||
/* */
|
||
/* Args: none */
|
||
/* Global args: nifr, nipr, nofr, nopr, ntrunc */
|
||
/* */
|
||
/* Return: void */
|
||
/* */
|
||
/* ******************************************************************** */
|
||
|
||
void stats()
|
||
{
|
||
pfmt(stderr, MM_NOSTD, ":158:%llu+%u records in\n", nifr, nipr);
|
||
pfmt(stderr, MM_NOSTD, ":159:%llu+%u records out\n", nofr, nopr);
|
||
if (ntrunc == 1)
|
||
pfmt(stderr, MM_NOSTD, ":160:1 truncated record\n");
|
||
else if (ntrunc > 1)
|
||
pfmt(stderr, MM_NOSTD, ":161:%u truncated records\n", ntrunc);
|
||
}
|