home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast2.iso
/
awk
/
awk320sr.zip
/
AWKFILE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-22
|
14KB
|
575 lines
/*
* Awk file and command line processing
*
* Copyright (C) 1988, 1989, 1990, 1991 by Rob Duff
* All rights reserved
*/
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "awkfstr.h"
#include "awk.h"
extern long fatol(FSTR);
ELEMENT *allell(void);
short modfield = 0;
short modrecord = 0;
static ITEM argn[1] = { { ACTUAL, S_SHORT } };
static ITEM argp[1] = { { FORMAL, S_SIMPLE } };
static char argvbuf[66]; /* string form of getargv */
static void set_element(int, char*, ITEM*);
/*
* set an element of the ARGV array
*/
static void set_element(int argc, char *arg, ITEM *vp)
{
FSTR sp;
ELEMENT *ep;
ITEM ip[1];
ip->stype = S_SHORT;
ip->sclass = ACTUAL;
ip->svalue.ival = argc;
sp = getstr(tostring(ip));
buffer[0] = ZSTR;
fstrncpy(buffer+1, arg, MAXCODE-2);
ep = allell();
ep->aclass = ACTUAL;
ep->atype = S_STRING;
ep->astr = getstr(buffer);
ep->aindex = sp;
ep->anext = NULL;
add_element(ep, vp);
if (isnumber(arg)) {
ep->avalue.dval = todouble((ITEM*)ep);
ep->atype = S_NUMBER;
}
}
/*
* copy argv into ARGV
*/
void setargv(int n, char *arg0, char *argv[])
{
int argc;
clear_array(av);
set_element(0, arg0, av);
argc = 1;
while (n) {
set_element(argc, *argv, av);
n--; argc++; argv++;
}
free_item((ITEM*)ac);
ac->stype = S_SHORT;
ac->svalue.ival = argc;
argn->svalue.ival = 0;
argp->svalue.sptr = av;
}
/*
* check to see whether an argument is a
* command line assignment.
* returns pointer to string after "="
*/
FSTR isname(FSTR sp)
{
if (*sp > ' ' && (isalpha(*sp) || *sp == '_'))
sp++;
while (*sp > ' ' && (isalnum(*sp) || *sp == '_'))
sp++;
if (*sp != '=')
sp = NULL;
return sp;
}
/*
* check to see if a field can be fully
* represented as a number.
*/
int isnumber(FSTR sp)
{
int lag, lead, len, power, digit;
FSTR exp;
if (*sp == '\0')
return 0;
exp = "0"; len = 1;
lead = lag = digit = 0;
if (*sp == '+' || *sp == '-')
*sp++;
if (*sp > ' ' && isdigit(*sp))
digit++;
while (*sp == '0')
sp++;
while (*sp > ' ' && isdigit(*sp)) {
lead++;
sp++;
}
if (*sp == '.') {
sp++;
if (*sp > ' ' && isdigit(*sp))
digit++;
while (*sp == '0') {
lag++;
sp++;
}
while (*sp > ' ' && isdigit(*sp))
sp++;
}
if (*sp == 'e' || *sp == 'E') {
sp++;
exp = sp;
len = 0;
if (*sp == '+' || *sp == '-')
*sp++;
if (*sp < ' ' || !isdigit(*sp))
return 0;
while (*sp == '0')
sp++;
while (*sp > ' ' && isdigit(*sp)) {
len++;
sp++;
}
}
if (digit == 0)
return 0;
if (*sp != '\0')
return 0;
if (len > 3)
return 0;
power = (int)fatol(exp);
if (lead > 0)
power += lead;
else
power -= lag;
if (power > 307 || power < -305)
return 0;
return 1;
}
/*
* get next non null element of ARGV less than ARGC
* the user program may delete some of the arguments
* or set them to null to erase them.
*/
char *getargv()
{
int argc, n;
FSTR argv, argq;
IDENT *vp;
ITEM *sp;
ITEM item[1];
argc = tointeger(ac);
while (++(argn->svalue.ival) < argc) {
index(argp, argn, item);
argv = tostring(item);
argq = isname(argv + 1);
if (argq != NULL) {
n = (int)(argq - argv) - 1;
if (n > MAXCODE-1)
n = MAXCODE-1;
fstrncpy(buffer, argv + 1, n);
buffer[n] = '\0';
for (vp = ident; vp != NULL; vp = vp->vnext) {
if (fstrcmp(buffer, vp->vname) == 0) {
sp = vp->vitem;
if (sp != nul) {
buffer[0] = ZSTR;
fstrncpy(buffer + 1, argq + 1, MAXCODE-2);
free_item(sp);
sp->stype = S_STRING;
sp->sstr = getstr(buffer);
if (isnumber(buffer+1)) {
sp->svalue.dval = todouble(sp);
sp->stype = S_NUMBER;
}
}
break;
}
}
}
else if (argv[1] != '\0') {
fstrncpy(argvbuf, argv+1, 64);
return argvbuf;
}
}
return NULL;
}
/*
* get a list of var=text elements and process them
*/
void getargs(NAME *list)
{
int n;
FSTR var, text;
IDENT *vp;
ITEM *sp;
while (list != NULL) {
var = list->name;
text = isname(var);
if (text != NULL) {
n = (int)(text - var);
if (n > MAXCODE-1)
n = MAXCODE-1;
fstrncpy(buffer, var, n);
buffer[n] = '\0';
for (vp = ident; vp != NULL; vp = vp->vnext) {
if (strcmp(buffer, vp->vname) == 0) {
sp = vp->vitem;
if (sp != nul) {
buffer[0] = ZSTR;
fstrncpy(buffer + 1, text + 1, MAXCODE-2);
free_item(sp);
sp->stype = S_STRING;
sp->sstr = getstr(buffer);
if (isnumber(buffer+1)) {
sp->svalue.dval = todouble(sp);
sp->stype = S_NUMBER;
}
}
break;
}
}
}
else
error("invalid -v var=text syntax %s", list->name);
list = list->next;
}
}
/*
* set the filename variable to name
* and clear FNR to 0
*/
void setfile(FSTR name)
{
free_item(fn);
fn->stype = S_STRING;
fn->sstr = name;
free_item(fnr);
fnr->stype = S_SHORT;
fnr->svalue.ival = 0;
}
/*
* read the next input record to $0
*/
int getrecord()
{
kbhit();
return getline(files + 1, (ITEM*)fieldtab);
}
/*
* read the input until an end of record character
* is read or until the end of input.
*/
int getline(FYLE *fp, ITEM *ip)
{
int ch, och, lrs;
char *lp, *ep;
FSTR dp;
double lnr;
if (fp->ffyle == NULL) {
return -1;
}
if (ip == (ITEM*)fieldtab) {
lp = linebuf;
ep = linebuf + sizeof(linebuf) - 1;
*lp++ = TSTR;
}
else {
lp = buffer;
ep = buffer + sizeof(buffer) - 1;
*lp++ = ZSTR;
}
*lp = '\0';
if (feof(fp->ffyle))
return 0;
dp = tostring(rs);
lrs = dp[1];
ch = fgetc(fp->ffyle);
if (ch == EOF)
return 0;
if (lrs == 0) {
och = '\0';
while (ch != EOF && lp < ep) {
if (ch == '\n' && och == '\n')
break;
*lp++ = och = ch;
ch = fgetc(fp->ffyle);
}
}
else {
while (ch != EOF && ch != lrs && lp < ep) {
*lp++ = ch;
ch = fgetc(fp->ffyle);
}
}
if (ch != EOF && lp == ep)
ungetc(ch, fp->ffyle);
*lp = '\0';
if (ip == (ITEM*)fieldtab) {
modrecord = 1;
modfield = 0;
free_item(ip);
ip->stype = S_STRING;
ip->sstr = linebuf;
if (ch == EOF && lp == linebuf+1)
return 0;
}
else {
if (ip != (ITEM*)nul) {
free_item(ip);
ip->stype = S_STRING;
ip->sstr = getstr(buffer);
}
if (ch == EOF && lp == buffer+1)
return 0;
}
if (fp == (files + 1)) {
lnr = todouble((ITEM*)fnr);
if (fnr->stype != S_DOUBLE) {
free_item((ITEM*)fnr);
fnr->stype = S_DOUBLE;
}
fnr->svalue.dval = lnr + 1;
lnr = todouble((ITEM*)nr);
if (nr->stype != S_DOUBLE) {
free_item((ITEM*)nr);
nr->stype = S_DOUBLE;
}
nr->svalue.dval = lnr + 1;
}
return 1;
}
/*
* free all the fields to prepare for the
* next input record.
*/
void deparse()
{
int i;
for (i = 0; i < MAXFIELD; i++)
free_item(fieldtab + i);
fieldtab->stype = S_STRING;
fieldtab->sstr = linebuf;
linebuf[0] = TSTR;
linebuf[1] = 0;
free_item((ITEM*)nf);
nf->stype = S_SHORT;
nf->svalue.ival = 0;
modfield = 0;
modrecord = 0;
}
/*
* parse the input record into fields
*/
void parse()
{
FSTR dst, mat, beg, src;
int lnf, i;
ITEM *ip;
if (modrecord) {
for (i = 1; i < MAXFIELD; i++)
free_item(fieldtab + i);
lnf = 0;
dst = fieldbuf;
src = onestring(fieldtab)+1;
beg = src;
mat = NULL;
ip = fieldtab+1;
if (awkfre == blankre) {
i = *src++;
while (i != '\0' && lnf < MAXFIELD-1) {
while (i > '\0' && isspace(i))
i = *src++;
if (i != '\0') {
ip->stype = S_STRING;
ip->sstr = dst;
*dst++ = TSTR;
while (i != '\0' && (i < 0 || !isspace(i))) {
*dst++ = i;
i = *src++;
}
*dst++ = '\0';
if (isnumber(ip->sstr+1)) {
ip->svalue.dval = todouble(ip);
ip->stype = S_NUMBER;
}
lnf++;
ip++;
}
}
}
else {
while (*src != '\0' && lnf < MAXFIELD-1) {
ip->stype = S_STRING;
ip->sstr = dst;
*dst++ = TSTR;
while (*src != '\0' &&
(mat = matchp(beg, src, awkfre)) == NULL && *src != '\n')
*dst++ = *src++;
if (src == mat)
*dst++ = *mat++;
if (mat != NULL) {
if (*src != '\0') {
if(mat > src)
src = mat;
else {
mat = NULL;
if (dst == fieldbuf + 1)
*dst++ = *src++;
}
}
}
else if (*src == '\n') {
src++;
mat = NULL;
}
*dst++ = '\0';
if (isnumber(ip->sstr+1)) {
ip->svalue.dval = todouble(ip);
ip->stype = S_NUMBER;
}
lnf++;
ip++;
}
if (mat != NULL) {
ip->stype = S_STRING;
ip->sstr = nullstr;
lnf++;
}
}
free_item((ITEM*)nf);
nf->stype = S_SHORT;
nf->svalue.ival = lnf;
modfield = 0;
modrecord = 0;
}
}
/*
* convert the fields back into the input record
* this is done whenever $0 is referenced after
* any field is modified.
*/
void unparse()
{
int i, lnf;
char *dp;
FSTR sp, fp;
if (modfield) {
free_item(fieldtab);
fieldtab->stype = S_STRING;
fieldtab->sstr = linebuf;
dp = linebuf;
*dp++ = TSTR;
fp = tostring((ITEM*)ofs);
lnf = tointeger((ITEM*)nf);
for (i = 1; i <= lnf; i++) {
if (i > 1) {
sp = fp+1;
while (*sp != '\0')
*dp++ = *sp++;
}
sp = tostring(fieldtab + i)+1;
while (*sp != '\0')
*dp++ = *sp++;
}
*dp = '\0';
for (i = lnf + 1; i < MAXFIELD; i++)
free_item(fieldtab + i);
modfield = 0;
modrecord = 0;
}
}
/*
* convert an item into a file number
* the item is converted to a string
* and this string is used as the filename
* mp is a pointer to a string that is the
* open mode of the file "w" or "a"
*/
FYLE *getfile(ITEM *a, int p)
{
FSTR sp;
FYLE *fp;
sp = tostring(a);
for (fp = files + 2; fp < nextfile; fp++) {
if (fstrcmp(fp->fname+1, sp+1) == 0)
break;
}
if (p == P_CLOSE) {
if (fp < nextfile && fp->ffyle != NULL) {
fclose(fp->ffyle);
fp->ffyle = NULL;
}
fp = NULL;
}
else {
if (fp >= nextfile) {
if (nextfile >= files + MAXFILE) {
for (fp = files; fp < nextfile; fp++) {
if (fp->ffyle == NULL)
break;
}
}
else
fp = nextfile++;
if (fp >= files + MAXFILE)
error("too many files open \"%s\"", sp+1);
}
if (fp->ffyle == NULL) {
switch (p) {
case P_OPEN:
fp->fmode = "r";
break;
case P_CREATE:
fp->fmode = "w";
break;
case P_APPEND:
fp->fmode = "a";
break;
}
fp->fname = newstr(sp);
fp->ffyle = NULL;
}
}
return fp;
}
/*
* close all of the files used by the AWK program
*/
void awkclose()
{
FYLE *fp;
for (fp = files + 2; fp < nextfile; fp++)
if (fp->ffyle != NULL)
fclose(fp->ffyle);
}