// crm_file_io.c - Controllable Regex Mutilator, version v1.0
// Copyright 2001-2006 William S. Yerazunis, all rights reserved.
//
// This software is licensed to the public under the Free Software
// Foundation's GNU GPL, version 2. You may obtain a copy of the
// GPL by visiting the Free Software Foundations web site at
// www.fsf.org, and a copy is included in this distribution.
//
// Other licenses may be negotiated; contact the
// author for details.
//
// include some standard files
#include "crm114_sysincludes.h"
// include any local crm114 configuration file
#include "crm114_config.h"
// include the crm114 data structures file
#include "crm114_structs.h"
// and include the routine declarations file
#include "crm114.h"
// and for READLINE - only this file uses it (it may not be portable
// #define HAVE_READLINE
#ifdef HAVE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
// the command line argc, argv
extern int prog_argc;
extern char **prog_argv;
// the auxilliary input buffer (for WINDOW input)
extern char *newinputbuf;
// the globals used when we need a big buffer - allocated once, used
// wherever needed. These are sized to the same size as the data window.
extern char *inbuf;
extern char *outbuf;
extern char *tempbuf;
int crm_expr_input ( CSL_CELL *csl, ARGPARSE_BLOCK *apb )
{
// Allow input of text from stdin.
FILE *fp;
char temp_vars [MAX_PATTERN];
long tvlen;
char filename [MAX_FILE_NAME_LEN];
long fnlen;
char ifn [MAX_FILE_NAME_LEN];
char fileoffset [MAX_FILE_NAME_LEN];
long fileoffsetlen;
char fileiolen [MAX_FILE_NAME_LEN];
long fileiolenlen;
long offset, iolen;
long vstart;
long vlen;
long mc;
long done;
long till_eof;
long use_readline;
// a couple of vars to bash upon
long i, j;
if (user_trace)
fprintf (stderr, "executing an INPUT statement\n");
// set up the flags (if any)
//
till_eof = 1;
if (apb->sflags & CRM_BYLINE)
{
till_eof = 0;
if (user_trace)
fprintf (stderr, " reading one line mode\n ");
};
use_readline = 0;
if (apb->sflags & CRM_READLINE)
{
use_readline = 1;
if (user_trace)
fprintf (stderr, " Using READLINE input line editing\n ");
};
// get the list of variable names
//
crm_get_pgm_arg (temp_vars, MAX_PATTERN, apb->p1start, apb->p1len);
tvlen = crm_nexpandvar (temp_vars, apb->p1len, MAX_PATTERN);
// If you think INPUT should read to the data window, uncomment this.
//
if (tvlen == 0)
{
strcpy (temp_vars, ":_dw:");
tvlen = strlen (":_dw:");
};
if (internal_trace)
fprintf (stderr, " inputting to var: >>>%s<<<\n", temp_vars);
// and what file to get it from...
//
crm_get_pgm_arg (filename, MAX_FILE_NAME_LEN, apb->b1start,apb->b1len);
crm_nextword (filename, apb->b1len, 0, &i, &j);
memmove (ifn, &filename[i], j);
fnlen = crm_nexpandvar (ifn, j, MAX_FILE_NAME_LEN);
ifn[fnlen] = '\0';
if (user_trace)
fprintf (stderr, " from filename >>>%s<<<\n", ifn);
// and what offset we need to do before the I/O...
//
offset = 0;
crm_nextword (filename, apb->b1len, i+j, &i, &j);
memmove (fileoffset, &filename[i], j);
fileoffsetlen = crm_qexpandvar (fileoffset, j, MAX_FILE_NAME_LEN, NULL);
fileoffset [fileoffsetlen] = '\0';
sscanf (fileoffset, "%ld", &offset);
if (user_trace)
fprintf (stderr, " pre-IO seek to >>>%s<<< --> %ld \n",
fileoffset, offset);
// and how many bytes to read
//
iolen = 0;
crm_nextword (filename, apb->b1len, i+j, &i, &j);
memmove (fileiolen, &filename[i], j);
fileiolenlen = crm_qexpandvar (fileiolen, j, MAX_FILE_NAME_LEN, NULL);
fileiolen [fileiolenlen] = '\0';
sscanf (fileiolen, "%ld", &iolen);
if (fileiolenlen == 0 || iolen > data_window_size) iolen = data_window_size;
if (user_trace)
fprintf (stderr, " and maximum length IO of >>>%s<<< --> %ld\n",
fileiolen, iolen);
if (user_trace)
fprintf (stderr, "Opening file %s for file I/O (reading)\n", ifn);
fp = stdin;
if ( fnlen > 0 && strncmp ("stdin", ifn, 6) != 0)
{
fp = fopen (ifn, "rb");
if (fp == NULL)
{
fatalerror5 (
"For some reason, I was unable to read-open the file named ",
filename, CRM_ENGINE_HERE );
goto input_no_open_bailout;
};
};
done = 0;
mc = 0;
// get the variable name
crm_nextword( temp_vars, tvlen, 0, &vstart, &vlen);
if (vlen == 0)
{
done = 1;
}
else
{
// must make a copy of the varname.
//
char vname[MAX_VARNAME];
long ichar = 0;
memmove (vname, &(temp_vars[vstart]), vlen);
vname [vlen] = '\000';
// If we have a seek requested, do an fseek.
// (Annoying But True: fseek on stdin does NOT error, it's
// silently _ignored_. Who knew?
if (fp == stdin && offset != 0 )
{
nonfatalerror5 ("Hmmm, a file offset on stdin won't do much. ",
"I'll ignore it for now. ",
CRM_ENGINE_HERE );
}
else
if (offset != 0)
if (EBADF == fseek (fp, offset, SEEK_SET))
nonfatalerror5 ("Dang, seems that this file isn't fseek()able: ",
filename, CRM_ENGINE_HERE);
// are we supposed to use readline?
#ifdef HAVE_READLINE
if (use_readline)
{
char *chartemp;
chartemp = readline ("");
strncpy (inbuf, chartemp, data_window_size);
free (chartemp);
}
else
#endif
// Are we in <byline> mode? If so, read one char at a time.
if (! till_eof)
{
// grab characters in a loop, terminated by EOF or newline
ichar = 0;
if (feof (fp) ) clearerr (fp);
while (!feof (fp)
&& ichar < (data_window_size >> SYSCALL_WINDOW_RATIO)
&& ( till_eof || ( ichar == 0 || inbuf [ichar-1] != '\n'))
&& ichar <= iolen )
{
inbuf[ichar] = fgetc (fp);
ichar++;
};
if (ichar > 0) ichar-- ; // get rid of any present newline
inbuf[ichar] = '\000'; // and put a null on the end of it.
}
else
{
// Nope, we are in full-block mode, read the whole block in
// a single I/O if we can.
ichar = 0;
if (feof (fp)) clearerr (fp); // reset any EOF
ichar = fread (inbuf, 1, iolen, fp); // do a block I/O
inbuf[ichar] ='\000'; // null at the end
};
crm_set_temp_nvar (vname, inbuf, ichar);
};
// and close the input file if it's not stdin.
if (fp != stdin) fclose (fp);
input_no_open_bailout:
return (0);
};
//////////////////////////////////////////
//
// And here's where we do output
int crm_expr_output ( CSL_CELL *csl, ARGPARSE_BLOCK *apb)
{
long i, j;
// output a string, usually to stdout unless otherwise
// specified in the output statement.
//
// We do variable substitutions here....
// char outfile[MAX_VARNAME];
//long outfilelen;
//char ofn[MAX_VARNAME];
long outtextlen;
FILE *outf;
char filename [MAX_FILE_NAME_LEN];
char fnam [MAX_FILE_NAME_LEN];
long fnlen;
char fileoffset [MAX_FILE_NAME_LEN];
long fileoffsetlen;
char fileiolen [MAX_FILE_NAME_LEN];
long fileiolenlen;
long offset, iolen;
if (user_trace)
fprintf (stderr," Executing an OUTPUT statement\n");
// get the output file name
//
// What file name?
//
crm_get_pgm_arg (filename, MAX_FILE_NAME_LEN, apb->b1start,apb->b1len);
crm_nextword (filename, apb->b1len, 0, &i, &j);
memmove (fnam, &filename[i], j);
fnlen = crm_nexpandvar (fnam, j, MAX_FILE_NAME_LEN);
fnam[fnlen] = '\0';
if (user_trace)
fprintf (stderr, " filename >>>%s<<<\n", fnam);
// and what offset we need to do before the I/O...
//
offset = 0;
crm_nextword (filename, apb->b1len, i+j, &i, &j);
memmove (fileoffset, &filename[i], j);
fileoffsetlen = crm_qexpandvar (fileoffset, j, MAX_FILE_NAME_LEN, NULL);
fileoffset [fileoffsetlen] = '\0';
sscanf (fileoffset, "%ld", &offset);
if (user_trace)
fprintf (stderr, " pre-IO seek to >>>%s<<< --> %ld \n",
fileoffset, offset);
// and how many bytes to read
//
iolen = 0;
crm_nextword (filename, apb->b1len, i+j, &i, &j);
memmove (fileiolen, &filename[i], j);
fileiolenlen = crm_qexpandvar (fileiolen, j, MAX_FILE_NAME_LEN, NULL);
fileiolen [fileiolenlen] = '\0';
sscanf (fileiolen, "%ld", &iolen);
if (fileiolenlen == 0 || iolen > data_window_size) iolen = data_window_size;
if (user_trace)
fprintf (stderr, " and maximum length IO of >>>%s<<< --> %ld\n",
fileiolen, iolen);
outf = stdout;
if ( fnlen > 0)
{
if (user_trace)
fprintf (stderr, "Opening file %s for I/O (writing)\n", fnam);
if (strcmp(fnam,"stderr")==0)
{
outf = stderr;
}
else if (strcmp(fnam,"stdout")!=0)
{
if (apb->sflags & CRM_APPEND
|| fileoffsetlen > 0 )
{
outf = fopen (fnam, "r+b");
//
// If the file didn't exist already, that open would fail.
// so we retry with "w+".
if (!outf) outf = fopen (fnam, "w+b");
//
// And make sure the file pointer is at EOF.
if ( outf != 0 )
fseek (outf, 0, SEEK_END);
}
else
{
outf = fopen (fnam, "wb");
};
};
};
//
// could we open the file?
//
if ( outf == 0 )
{
fatalerror ("For some reason, I was unable to write-open the file named",
fnam);
}
else
{
// Yep, file is open, go for the writing.
//
crm_get_pgm_arg (outbuf, data_window_size,
apb->s1start, apb->s1len);
outtextlen = apb->s1len;
if (internal_trace)
fprintf (stderr, " outputting with pattern %s\n", outbuf);
// Do variable substitution on outbuf.
outtextlen = crm_nexpandvar (outbuf, outtextlen, data_window_size);
// Do the seek if necessary
//
if ( fileoffsetlen > 0)
{
// fprintf (stderr, "SEEKING to %ld\n", offset);
rewind (outf);
fseek (outf, offset, SEEK_SET);
};
// Write at most iolen bytes
//
if (fileiolenlen > 0)
if (iolen < outtextlen)
outtextlen = iolen;
// and send it to outf
//
fwrite (outbuf, outtextlen, 1, outf);
fflush (outf);
if (outf != stdout && outf != stderr ) fclose (outf);
};
return (0);
}
syntax highlighted by Code2HTML, v. 0.9.1