/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 2003-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* sort uniq summary discipline
*/
static const char usage[] =
"[-1lp0s5P?\n@(#)$Id: sum (AT&T Research) 2011-08-23 $\n]"
"[+PLUGIN?sum - sort uniq summary discipline]"
"[+DESCRIPTION?The \bsum\b \bsort\b(1) discipline applies "
"summarization operations to selected fields in records that compare "
"equal. The discipline sets the \bsort\b \b--unique\b option. Summary "
"fields in non-unique records are modified according to the operations "
"specified in the \bop\b discipline option.]"
"[l:library?Load the \bdss\b(1) type library \alibrary\a. Types are used "
"by the \bop\b option. The \bnum_t\b library is loaded by default. \vdss "
"--plugin=man\v lists the information on all \bdss\b libraries and \vdss "
"--plugin=man\v \aname\a lists the information for the \aname\a "
"library.]:[library]"
"[o:op?A field summary operation. \aarg\a is a \bdss\b(1) type name for "
"all but the \bset\b \aop\a, either from the \bnum_t\b library or from a "
"library loaded by the \blibrary\b option. \atype\a may also contain one "
"or more \b:\b separated attributes. \akey\a is a \bsort\b(1) \b-k\b "
"style field specification. \aop\a\b:\b\aarg\a may be specified multiple "
"times; \aop\a and \aarg\a are inherited across \akey\a values from left "
"to right. The default type is native character set \binteger\b; some "
"operations may ignore the type. Spaces may be used in place of the "
"\b:\b. \aop\a may be one of:]:[op::[arg...]]::key[...]]]"
"{"
"[+max (M)?maximum value]"
"[+min (m)?minimum value]"
"[+average (a)?average value]"
"[+sum (s)?sum]"
"[+count (c)?multiply subsequent field values and increment the "
"total count by this value]"
"[+set (s)?set all field field bytes to the first character of "
"\aarg\a, which may be a C-style escape sequence]"
"}"
"[r:regress?Massage output for regression testing.]"
"[d:debug?List the field operations on the standard error.]"
"[+EXAMPLES]"
"{"
"[+sort -k.2.1 -lsum,op=sum::integer::.6.2?Sorts on the 1 byte "
"fixed width field starting at byte position 2 (counting from 1) "
"and computes the sum of the integers in the 2 byte fixed width "
"field starting at byte position 6.]"
"[+dlls --base dss | grep '_t$'?Lists the \bdss\b(1) type "
"library names.]"
"[+dss --plugin=man num_t?Lists the \bdss\b(1) \bnum_t\b type "
"library description in the \b--man\b style.]"
"}"
"[+SEE ALSO?\bdss\b(1), \bsort\b(1)]"
"\n\n--library=sum[,option[=value]...]\n\n"
;
#include <ast.h>
#include <ctype.h>
#include <ccode.h>
#include <dss.h>
#include <error.h>
#include <recsort.h>
#include <recfmt.h>
#include <vmalloc.h>
struct Library_s
{
};
typedef struct Position_s
{
short field;
short index;
} Position_t;
struct Summary_s
{
unsigned char* map;
unsigned char* pam;
int op;
int set;
int fixed;
int width;
};
typedef struct Buffer_s
{
unsigned char* buf;
} Buffer_t;
typedef struct State_s
{
unsigned char* tab;
int alt;
int regress;
} State_t;
static int
{
if (b->siz < z)
{
{
return -1;
}
}
return 0;
}
static int
{
register unsigned char* s;
register unsigned char* e;
register unsigned char* a;
register unsigned char* z;
register unsigned char* del;
register const unsigned char* map;
unsigned char* x;
unsigned char* tab;
int beg;
int end;
int t;
int c;
size_t w;
size_t y;
ssize_t n;
Cxoperand_t v;
s = r->data;
count = 1;
t = *tab++;
if (!*tab)
tab = 0;
{
{
tab1:
while (s < e)
if (del[*s++])
{
if (tab)
{
for (c = 0; (s + c) < e; c++)
if (!tab[c])
{
s += c;
break;
}
else if (tab[c] != s[c])
goto tab1;
}
else if (t == ' ')
while (s < e && del[*s])
s++;
break;
}
}
{
{
tab2:
while (s < e)
if (del[*s++])
{
if (tab)
{
for (c = 0; (s + c) < e; c++)
if (!tab[c])
{
s += c;
break;
}
else if (tab[c] != s[c])
goto tab2;
}
else if (t == ' ')
while (s < e && del[*s])
s++;
break;
}
end++;
}
{
tab3:
while (s < e)
if (del[*s++])
{
if (tab)
{
for (c = 0; (s + c) < e; c++)
if (!tab[c])
break;
else if (tab[c] != s[c])
goto tab3;
}
else if (t == ' ')
while (s < e && del[*s])
s++;
s--;
break;
}
z = s;
}
else
z = a;
}
else
a = z = s;
w = z - a;
sum->format.width = RECTYPE(state->fmt) == REC_fixed ? w : (!(sum->format.flags & CX_FLOAT) || sum->end.index || w >= 8) ? 0 : 8;
{
a -= w;
}
else
x = a;
if (sum->op == 'v' || (*sum->type->internalf)(cx, sum->type, NiL, &sum->format, &v, (char*)x, w, cx->rm, cx->disc) < 0)
{
n /= 10;
}
if (op < 0)
{
}
else
{
if (count != 1)
{
case 'a':
break;
case 'c':
continue;
case 'M':
break;
case 'm':
break;
case 's':
break;
}
if (op > 0)
{
{
case 'a':
break;
case 'v':
while (a < z)
continue;
}
for (;;)
{
y = n + 1;
if ((n = (*sum->type->externalf)(cx, sum->type, NiL, &sum->format, &v.value, (char*)state->tmp.buf, y, cx->disc)) < 0)
{
error(2, "%s value %I*g conversion error", sum->type->name, sizeof(v.value.number), v.value.number);
return -1;
}
if (n < y)
break;
}
if (n > w)
{
{
error(2, "%s value %I*g width exceeds %d", sum->type->name, sizeof(v.value.number), v.value.number, w);
return -1;
}
r->datalen += n - w;
}
if (map)
{
if (n < w)
{
while (n++ < w)
*a++ = c;
}
}
else
{
if (n < w)
{
while (n++ < w)
*a++ = c;
}
}
}
}
}
return 0;
}
static int
{
register Rsobj_t* r;
register Rsobj_t* q;
switch (op)
{
case RS_POP:
break;
case RS_SUMMARY:
return -1;
return -1;
break;
default:
return -1;
}
return 0;
}
{
char* s;
char* t;
char* b;
char* loc;
int tok;
int n;
int debug;
char chr;
return 0;
goto drop;
debug = 0;
if (options)
{
for (;;)
{
{
case 0:
break;
case 'd':
debug = 1;
continue;
case 'l':
goto drop;
continue;
case 'o':
def = 0;
for (;;)
{
while (*s == ':' || isspace(*s))
s++;
if (!*s)
break;
if (def)
{
}
else
b = s;
tok = 0;
/*UNDENT...*/
for (;;)
{
if (*s == '.' || isdigit(*s))
{
pos = 0;
while (*s == '.' || isdigit(*s))
{
if (!pos)
{
loc = "begin";
}
{
loc = "end";
}
else
{
goto drop;
}
if (*s == '.')
n = 1;
else
for (n = 0; *s >= '0' && *s <= '9'; n = n * 10 + (*s++ - '0'));
{
goto drop;
}
switch (*s)
{
case '.':
for (n = 0; *++s >= '0' && *s <= '9'; n = n * 10 + (*s - '0'));
{
goto drop;
}
if (*s == '.')
{
n = 0;
for (n = 0; *++s >= '0' && *s <= '9'; n = n * 10 + (*s - '0'));
if (n <= 0)
{
goto drop;
}
}
break;
case 'C':
s++;
switch (*s++)
{
case 'a':
n = CC_ASCII;
break;
case 'e':
n = CC_EBCDIC_E;
break;
case 'i':
n = CC_EBCDIC_I;
break;
case 'o':
n = CC_EBCDIC_O;
break;
case 'n':
n = CC_NATIVE;
break;
default:
goto drop;
}
switch (*s++)
{
case 'a':
break;
case 'e':
n = CCOP(n, CC_EBCDIC_E);
break;
case 'i':
n = CCOP(n, CC_EBCDIC_I);
break;
case 'o':
n = CCOP(n, CC_EBCDIC_O);
break;
case 'n':
break;
default:
s--;
break;
}
break;
default:
if (isalpha(*s))
{
goto drop;
}
break;
}
}
break;
}
switch (tok)
{
case 0:
{
case 'a':
case 'c':
break;
case 'M':
if (*s == 'I')
break;
case 'm':
if (*s == 'a')
break;
case 's':
if (*s != 'e')
break;
/*FALLTHROUGH*/
case 'v':
t = s - 1;
while (isalnum(*s))
s++;
if (*s != ':' || !*++s)
{
goto drop;
}
break;
default:
goto drop;
}
while (isalnum(*s))
s++;
tok++;
break;
case 1:
{
s = t;
tok++;
break;
}
/*FALLTHROUGH*/
default:
goto drop;
}
while (*s == ':' || isspace(*s))
s++;
if (!*s)
break;
}
/*...INDENT*/
{
goto drop;
}
if (sum->beg.field < cur->beg.field || sum->beg.field == cur->beg.field && sum->end.field < cur->end.field)
break;
if (prv)
else
}
continue;
case 'r':
continue;
case '?':
goto drop;
case ':':
goto drop;
}
break;
}
}
{
if (isspace(n))
}
else
{
{
else
}
{
}
}
{
else
sfprintf(sfstderr, "%d.%d,%d.%d", sum->beg.field + 1, sum->beg.index + 1, sum->end.field + 1, sum->end.index);
else
{
}
else
}
drop:
return 0;
}