Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/sort/sfopen.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1996-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* Phong Vo <[email protected]> *
19
* Doug McIlroy <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
24
/*
25
* sfopen file suffix match intercept
26
* export SFOPEN_INTERCEPT with one or more suffix map entries
27
*
28
* option<del>[no]verbose<del>
29
* program<del><pattern><del>
30
* input<del><pattern><del>command<del>
31
* output<del><pattern><del>command<del>
32
* ...
33
*
34
* space between entries ignored
35
* program patterns matched against error_info.id
36
* io patterns matched against the file path
37
* (literal) \0 in command expands to the file path
38
* (literal) \<n> in command expands to the <n>th subexpression in the file path pattern match
39
*/
40
41
#define sfopen _sfopen
42
43
#include <ast.h>
44
#include <ctype.h>
45
#include <error.h>
46
47
#undef sfopen
48
49
struct Io_s; typedef struct Io_s Io_t;
50
struct Match_s; typedef struct Match_s Match_t;
51
52
struct Io_s
53
{
54
Io_t* next;
55
char* command;
56
char* pattern;
57
};
58
59
struct Match_s
60
{
61
Match_t* next;
62
Io_t* io[2];
63
char* pattern;
64
};
65
66
static struct State_s
67
{
68
Match_t* match;
69
Sfio_t* cmd;
70
int dump;
71
int init;
72
int verbose;
73
} state;
74
75
static Match_t*
76
initialize(void)
77
{
78
register char* s;
79
register char* t;
80
register char* v;
81
register char* x;
82
register int n;
83
register int d;
84
Match_t* mp;
85
Match_t* me;
86
Match_t* mv;
87
Io_t* io;
88
Io_t* ie[2];
89
90
mp = me = 0;
91
if ((s = getenv("SFOPEN_INTERCEPT")) && (s = strdup(s)))
92
for (;;)
93
{
94
while (isspace(*s))
95
s++;
96
for (t = s; isalnum(*s); s++);
97
if (s == t || !(d = *s))
98
break;
99
*s++ = 0;
100
for (v = s; *s && *s != d; s++);
101
if (*s)
102
*s++ = 0;
103
if (streq(t, "input") || streq(t, "output"))
104
{
105
if (mp)
106
{
107
for (x = s; *s && *s != d; s++);
108
if (*s)
109
*s++ = 0;
110
if (!(io = newof(0, Io_t, 1, 0)))
111
break;
112
if (*v)
113
io->pattern = v;
114
if (*x)
115
io->command = x;
116
n = *t == 'o';
117
if (ie[n])
118
ie[n] = ie[n]->next = io;
119
else
120
ie[n] = mp->io[n] = io;
121
}
122
}
123
else if (streq(t, "program"))
124
{
125
if (!(mv = newof(0, Match_t, 1, 0)))
126
break;
127
if (*v)
128
mv->pattern = v;
129
if (me)
130
me = me->next = mv;
131
else
132
mp = mv;
133
ie[0] = ie[1] = 0;
134
}
135
else if (streq(t, "option"))
136
{
137
if (*v == 'n' && *(v + 1) == 'o')
138
{
139
v += 2;
140
n = 0;
141
}
142
else
143
n = 1;
144
if (streq(v, "dump"))
145
state.dump = n;
146
else if (streq(v, "verbose"))
147
state.verbose = n;
148
}
149
}
150
return mp;
151
}
152
153
Sfio_t*
154
sfopen(Sfio_t* f, const char* path, const char* mode)
155
{
156
register Match_t* mp;
157
register Io_t* io;
158
register const char* s;
159
register ssize_t r;
160
register int c;
161
register int n;
162
register int m;
163
164
ssize_t sub[20];
165
166
if (path && error_info.id)
167
{
168
if (!state.init)
169
{
170
state.init = 1;
171
if (state.cmd = sfstropen())
172
state.match = initialize();
173
if (state.dump)
174
{
175
sfprintf(sfstdout, "SFIO_INTERCEPT\n");
176
if (state.dump)
177
sfprintf(sfstdout, " option dump\n");
178
if (state.verbose)
179
sfprintf(sfstdout, " option verbose\n");
180
for (mp = state.match; mp; mp = mp->next)
181
{
182
sfprintf(sfstdout, " program %s \n", mp->pattern);
183
for (io = mp->io[0]; io; io = io->next)
184
sfprintf(sfstdout, " input %s %s\n", io->pattern, io->command);
185
for (io = mp->io[1]; io; io = io->next)
186
sfprintf(sfstdout, " output %s %s\n", io->pattern, io->command);
187
}
188
}
189
}
190
if (mp = state.match)
191
{
192
n = 0;
193
s = mode;
194
for (;;)
195
{
196
switch (*s++)
197
{
198
case 0:
199
break;
200
case 'b':
201
n = -1;
202
break;
203
case 'w':
204
case '+':
205
n = 1;
206
continue;
207
default:
208
continue;
209
}
210
break;
211
}
212
if (n > 0 || n == 0 && !access(path, R_OK))
213
do
214
{
215
if ((!mp->pattern || strmatch(error_info.id, mp->pattern)) && (io = mp->io[n]))
216
{
217
do
218
{
219
if (!io->pattern && !(m = 0) || (m = strgrpmatch(path, io->pattern, sub, elementsof(sub) / 2, STR_MAXIMAL|STR_LEFT|STR_RIGHT)))
220
break;
221
} while (io = io->next);
222
if (io)
223
{
224
if (s = io->command)
225
{
226
m *= 2;
227
r = 1;
228
while (c = *s++)
229
{
230
if (c == '\\' && *s && (c = *s++) >= '0' && c <= '9')
231
{
232
c = 2 * (c - '0');
233
if (c < m && (r = sub[c+1] - sub[c]))
234
sfwrite(state.cmd, path + sub[c], r);
235
r = 0;
236
}
237
else
238
sfputc(state.cmd, c);
239
}
240
if (r)
241
sfprintf(state.cmd, " %c %s", n == 1 ? '<' : '>', path);
242
if (!(s = sfstruse(state.cmd)))
243
return 0;
244
if (state.verbose)
245
error(0, "%s %s", error_info.id, s);
246
if (f = sfpopen(f, s, mode))
247
sfset(f, SF_SHARE, 0);
248
return f;
249
}
250
break;
251
}
252
}
253
} while (mp = mp->next);
254
}
255
}
256
return _sfopen(f, path, mode);
257
}
258
259