ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/lam.c
Revision: 1.27
Committed: Thu Feb 6 19:52:05 2025 UTC (6 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.26: +11 -8 lines
Log Message:
fix(rlam): Fixed processing of -in option

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: lam.c,v 1.26 2024/06/07 18:19:22 greg Exp $";
3 #endif
4 /*
5 * lam.c - simple program to laminate files.
6 *
7 * 7/14/88 Greg Ward
8 */
9
10 #include <ctype.h>
11
12 #include "rtio.h"
13 #include "platform.h"
14 #include "paths.h"
15
16 #define MAXLINE 262144 /* maximum input line */
17
18 struct instream { /* structure to hold input stream info */
19 FILE *input; /* input stream */
20 int bytsiz; /* bytes/component if binary */
21 char *tabc; /* data separation string */
22 } *rifile = NULL;
23
24 int nfiles = 0;
25
26 char buf[MAXLINE];
27
28 int
29 main(int argc, char *argv[])
30 {
31 long incnt = 0;
32 int unbuff = 0;
33 int binout = 0;
34 char *curtab = "\t";
35 int curbytes = 0;
36 int puteol;
37 int i;
38
39 rifile = (struct instream *)calloc(argc-1, sizeof(struct instream));
40 if (!rifile) {
41 fputs(argv[0], stderr);
42 fputs(": not enough memory\n", stderr);
43 return(1);
44 }
45 for (i = 1; i < argc; i++) {
46 if (argv[i][0] == '-') {
47 switch (argv[i][1]) {
48 case 't':
49 curtab = argv[i]+2;
50 if (!*curtab) curtab = "\n";
51 continue;
52 case 'u':
53 unbuff = !unbuff;
54 continue;
55 case 'i':
56 switch (argv[i][2]) {
57 case 'n':
58 incnt = atol(argv[++i]);
59 continue;
60 case 'f':
61 case 'F':
62 curbytes = sizeof(float);
63 break;
64 case 'd':
65 case 'D':
66 curbytes = sizeof(double);
67 break;
68 case 'i':
69 case 'I':
70 curbytes = sizeof(int);
71 break;
72 case 'w':
73 case 'W':
74 curbytes = 2;
75 break;
76 case 'b':
77 curbytes = 1;
78 break;
79 case 'a':
80 curbytes = argv[i][3] ? -1 : 0;
81 break;
82 default:
83 goto badopt;
84 }
85 if (isdigit(argv[i][3]))
86 curbytes *= atoi(argv[i]+3);
87 curbytes += (curbytes == -1);
88 if (curbytes > MAXLINE) {
89 fputs(argv[0], stderr);
90 fputs(": input size too big\n", stderr);
91 return(1);
92 }
93 if (curbytes > 0) {
94 curtab = "";
95 ++binout;
96 }
97 continue;
98 case '\0':
99 rifile[nfiles].tabc = curtab;
100 rifile[nfiles].input = stdin;
101 if (curbytes > 0)
102 SET_FILE_BINARY(rifile[nfiles].input);
103 rifile[nfiles++].bytsiz = curbytes;
104 continue;
105 badopt:;
106 default:
107 fputs(argv[0], stderr);
108 fputs(": unknown option '", stderr);
109 fputs(argv[i], stderr);
110 fputs("'\n", stderr);
111 return(1);
112 }
113 }
114 if (argv[i][0] == '!') {
115 rifile[nfiles].tabc = curtab;
116 if ((rifile[nfiles].input = popen(argv[i]+1, "r")) == NULL) {
117 fputs(argv[i], stderr);
118 fputs(": cannot start command\n", stderr);
119 return(1);
120 }
121 if (curbytes > 0)
122 SET_FILE_BINARY(rifile[nfiles].input);
123 rifile[nfiles++].bytsiz = curbytes;
124 } else {
125 rifile[nfiles].tabc = curtab;
126 if ((rifile[nfiles].input = fopen(argv[i], "r")) == NULL) {
127 fputs(argv[i], stderr);
128 fputs(": cannot open file\n", stderr);
129 return(1);
130 }
131 if (curbytes > 0)
132 SET_FILE_BINARY(rifile[nfiles].input);
133 rifile[nfiles++].bytsiz = curbytes;
134 }
135 }
136 if (!nfiles) {
137 fputs(argv[0], stderr);
138 fputs(": no input streams\n", stderr);
139 return(1);
140 } /* reduce array to size we need */
141 rifile = (struct instream *)realloc(rifile, nfiles*sizeof(struct instream));
142 if (!rifile) {
143 fputs(argv[0], stderr);
144 fputs(": realloc() failed!\n", stderr);
145 return(1);
146 }
147 if (binout) /* binary output? */
148 SET_FILE_BINARY(stdout);
149 #ifdef getc_unlocked /* avoid lock/unlock overhead */
150 for (i = nfiles; i--; )
151 flockfile(rifile[i].input);
152 flockfile(stdout);
153 #endif
154 puteol = 0; /* any ASCII output at all? */
155 for (i = nfiles; i--; )
156 puteol += (rifile[i].bytsiz <= 0);
157 do { /* main loop */
158 for (i = 0; i < nfiles; i++) {
159 if (rifile[i].bytsiz > 0) { /* binary input */
160 if (getbinary(buf, rifile[i].bytsiz, 1, rifile[i].input) < 1)
161 break;
162 if (putbinary(buf, rifile[i].bytsiz, 1, stdout) != 1)
163 break;
164 } else if (rifile[i].bytsiz < 0) { /* multi-line input */
165 int n = -rifile[i].bytsiz;
166 while (n--) {
167 if (fgets(buf, MAXLINE, rifile[i].input) == NULL)
168 break;
169 if ((i > 0) | (n < -rifile[i].bytsiz-1))
170 fputs(rifile[i].tabc, stdout);
171 buf[strlen(buf)-1] = '\0';
172 if (fputs(buf, stdout) == EOF)
173 break;
174 }
175 if (n >= 0) /* fell short? */
176 break;
177 } else { /* single-line input */
178 if (fgets(buf, MAXLINE, rifile[i].input) == NULL)
179 break;
180 if (i)
181 fputs(rifile[i].tabc, stdout);
182 buf[strlen(buf)-1] = '\0';
183 if (fputs(buf, stdout) == EOF)
184 break;
185 }
186 }
187 if (i < nfiles)
188 break;
189 if (puteol)
190 putchar('\n');
191 if (unbuff)
192 fflush(stdout);
193 } while (--incnt);
194 /* check ending */
195 if (fflush(stdout) == EOF) {
196 fputs(argv[0], stderr);
197 fputs(": write error on standard output\n", stderr);
198 return(1);
199 }
200 if (incnt > 0) {
201 fputs(argv[0], stderr);
202 fputs(": warning: premature EOD\n", stderr);
203 }
204 return(0);
205 }