1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
# T_JOINLINES -- Join text files line by line.
procedure t_joinlines ()
int list # List of input files
int out # Output file descriptor
pointer delim # Delimiter string
pointer missing # Missing string
int maxchars # Maximum characters per line
bool shortest # Stop of shortest file?
bool verbose # Verbose warnings?
char c
pointer sp, fname, fds
int i, j, in
int nfiles, nlines, neof, nchars, ntruncate, nlong, ndelim, nmissing
int fntopnb(), clplen(), clgfil(), clgeti(), open(), strlen()
char getc()
bool clgetb()
begin
call smark (sp)
call salloc (fname, SZ_FNAME, TY_CHAR)
call salloc (delim, SZ_FNAME, TY_CHAR)
call salloc (missing, SZ_LINE, TY_CHAR)
# Task parameters
# This stuff is provided for backwards compatibility.
# It would be better to just use an "input" parameter.
call clgstr ("list1", Memc[fname], SZ_FNAME)
if (clgeti ("$nargs") == 2) {
call clgstr ("list2", Memc[delim], SZ_FNAME)
call strcat (",", Memc[fname], SZ_FNAME)
call strcat (Memc[delim], Memc[fname], SZ_FNAME)
}
list = fntopnb (Memc[fname], NO)
# list = clpopnu ("input")
call clgstr ("output", Memc[fname], SZ_FNAME)
call clgstr ("delim", Memc[delim], SZ_FNAME)
call clgstr ("missing", Memc[missing], SZ_LINE)
maxchars = clgeti ("maxchars") - 1
shortest = clgetb ("shortest")
verbose = clgetb ("verbose")
# Open files. Quit on an error.
out = open (Memc[fname], APPEND, TEXT_FILE)
nfiles = clplen (list)
call malloc (fds, nfiles, TY_INT)
do i = 1, nfiles {
j = clgfil (list, Memc[fname], SZ_FNAME)
Memi[fds+i-1] = open (Memc[fname], READ_ONLY, TEXT_FILE)
}
call clpcls (list)
# Join the input lines. First read a character from each file
# to determine if we are at the EOF and take appropriate action
# if one or more EOFs are found.
ndelim = strlen (Memc[delim])
nmissing = strlen (Memc[missing])
ntruncate = 0
nlong = 0
for (nlines = 1; ; nlines = nlines + 1) {
nchars = 0
neof = 0
do i = 1, nfiles {
in = Memi[fds+i-1]
if (getc (in, c) == EOF)
neof = neof + 1
else
call ungetc (in, c)
}
if (neof == nfiles || (shortest && neof > 0))
break
do i = 1, nfiles {
in = Memi[fds+i-1]
repeat {
if (getc (in, c) == EOF) {
do j = 1, nmissing {
if (nchars < maxchars)
call putc (out, Memc[missing+j-1])
nchars = nchars + 1
}
break
} else if (c == '\n')
break
if (nchars < maxchars)
call putc (out, c)
nchars = nchars + 1
}
# Add the delimiter and new line. Count the delimiter also.
if (i < nfiles) {
do j = 1, ndelim {
if (nchars < maxchars)
call putc (out, Memc[delim+j-1])
nchars = nchars + 1
}
} else {
call fprintf (out, "\n")
break
}
}
# Accumulate warnings about line lengths.
if (nchars > maxchars)
ntruncate = ntruncate + 1
if (min (nchars, maxchars + 1) > SZ_LINE)
nlong = nlong + 1
}
# Finish up.
if (verbose) {
if (ntruncate > 0) {
call eprintf ("WARNING: %d lines truncated at %d characters\n")
call pargi (ntruncate)
call pargi (maxchars + 1)
}
if (nlong > 0) {
call eprintf (
"WARNING: %d lines exceed IRAF limit of %d characters\n")
call pargi (nlong)
call pargi (SZ_LINE)
}
if (neof < nfiles) {
call eprintf ("WARNING: %d/%d files completed\n")
call pargi (neof)
call pargi (nfiles)
}
}
call close (out)
do i = 1, nfiles
call close (Memi[fds+i-1])
call sfree (sp)
end
|