Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/nmake/convert.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1984-2011 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
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* Glenn Fowler
23
* AT&T Research
24
*
25
* convert single char edit ops to long form
26
*/
27
28
static const char id[] = "\n@(#)$Id: make-convert (AT&T Research) 1995-12-25 $\0\n";
29
30
#include <ast.h>
31
#include <error.h>
32
#include <debug.h>
33
#include <ctype.h>
34
35
#include "expand.h"
36
37
#define EXBUF 1024
38
#define DELETE ((char*)0)
39
#define KEEP ((char*)sfstdout)
40
#define RE_ALL (1<<0)
41
#define RE_LOWER (1<<1)
42
#define RE_UPPER (1<<2)
43
44
static struct Convstate_s
45
{
46
int delimiter;
47
int function;
48
const char* longflag;
49
Edit_map_t** map;
50
} state;
51
52
static char* expand(char*, char*);
53
54
static char*
55
editcontext(register char* beg, register char* cur)
56
{
57
register char* s;
58
59
static char buf[EXBUF];
60
61
s = strcopy(buf, ">>>");
62
strncpy(s, beg, cur - beg);
63
s += strlen(s);
64
strcpy(s, "<<<");
65
return(buf);
66
}
67
68
#define DEL (del==':'?state.delimiter:del)
69
70
static char*
71
expandops(register char* xp, register char* ed, int del)
72
{
73
register int c;
74
register char* s;
75
register int op;
76
register const Edit_map_t* mp;
77
register const Edit_opt_t* fp;
78
const Edit_map_t* zp;
79
Edit_map_t* const* mpp;
80
char* dir;
81
char* bas;
82
char* suf;
83
char* val;
84
char* oldp;
85
char* newp;
86
char* eb;
87
char* dp;
88
char* vp;
89
const Edit_xxx_t* bp;
90
int glob;
91
int cnt;
92
int cntlim;
93
int qual;
94
int n;
95
int m;
96
int e;
97
int sep;
98
int arg;
99
int aux;
100
char buf[EXBUF];
101
char tmp[16];
102
103
int bound = 0;
104
int delimited = 0;
105
106
expand(buf, ed);
107
ed = buf;
108
dir = bas = suf = DELETE;
109
eb = ed;
110
debug((-5, "expandops(`%s')", ed));
111
op = 0;
112
for (;;)
113
{
114
if (op != 'T') bound = 0;
115
for (bp = editxxx; bp->old; bp++)
116
if (strneq(bp->old, ed, bp->len))
117
{
118
strncpy(ed, bp->xxx, bp->len);
119
break;
120
}
121
if (!(op = *ed++)) break;
122
if (op == del) continue;
123
switch (op)
124
{
125
case '@':
126
case 'V':
127
sep = 1;
128
switch (op)
129
{
130
case '@':
131
sep = 0;
132
val = "join";
133
break;
134
case 'V':
135
val = "literal";
136
switch (*ed)
137
{
138
case 'A':
139
ed++;
140
val = "auxilliary";
141
break;
142
case 'P':
143
ed++;
144
val = "primary";
145
break;
146
}
147
break;
148
}
149
*xp++ = ' ';
150
if (!delimited)
151
{
152
delimited = 1;
153
if (del != ':')
154
*xp++ = '`';
155
}
156
*xp++ = DEL;
157
*xp++ = ' ';
158
xp = strcopy(xp, val);
159
if (!sep)
160
delimited = -1;
161
continue;
162
}
163
sep = EQ;
164
165
/*
166
* collect the operands
167
*/
168
169
if (op == 'C' || op == '/' || op == 'Y' || op == '?')
170
{
171
/*
172
* substitute: <delim><old><delim><new><delim>[g]
173
* conditional: <delim><non-null><delim><null><delim>
174
*/
175
176
val = ed;
177
n = op;
178
switch (op)
179
{
180
case 'C':
181
case 'Y':
182
if (n = *ed) ed++;
183
break;
184
case '/':
185
op = 'C';
186
val--;
187
break;
188
case '?':
189
op = 'Y';
190
val--;
191
break;
192
}
193
oldp = ed;
194
for (cnt = 0; c = *ed; ed++)
195
{
196
if (c == '(') cnt++;
197
else if (c == ')' && !--n) cnt = 0;
198
else if (cnt <= 0)
199
{
200
if (c == n)
201
{
202
ed++;
203
break;
204
}
205
if (c == '\\' && !*++ed)
206
error(3, "unterminated lhs of %s: %s", op == 'C' ? "substitution" : "conditional", editcontext(eb, ed));
207
}
208
}
209
newp = ed;
210
for (cnt = 0; c = *ed; ed++)
211
{
212
if (c == '(') cnt++;
213
else if (c == ')' && !--n) cnt = 0;
214
else if (cnt <= 0)
215
{
216
if (c == n)
217
{
218
ed++;
219
break;
220
}
221
if (c == '\\' && !*++ed)
222
error(3, "unterminated rhs of %s: %s", op == 'C' ? "substitution" : "conditional", editcontext(eb, ed));
223
}
224
}
225
glob = 0;
226
while (*ed && *ed != del) switch (*ed++)
227
{
228
case 'G':
229
*(ed - 1) = 'g';
230
/*FALLTHROUGH*/
231
case 'g':
232
glob |= RE_ALL;
233
break;
234
case 'L':
235
*(ed - 1) = 'l';
236
/*FALLTHROUGH*/
237
case 'l':
238
glob |= RE_LOWER;
239
break;
240
case 'O':
241
*(ed - 1) = 'o';
242
/*FALLTHROUGH*/
243
case 'o':
244
glob |= RE_ALL;
245
break;
246
case 'U':
247
*(ed - 1) = 'u';
248
/*FALLTHROUGH*/
249
case 'u':
250
glob |= RE_UPPER;
251
break;
252
default:
253
error(1, "invalid character `%c' after %s", *(ed - 1), op == 'C' ? "substitution" : "conditional");
254
break;
255
}
256
s = ed;
257
if (*ed) ed++;
258
*s = 0;
259
}
260
else if (*ed == del)
261
{
262
ed++;
263
val = KEEP;
264
}
265
else if (*ed)
266
{
267
/*
268
* value: [!<>=][=][<val>]
269
*/
270
271
if (op != '$') switch (*ed++)
272
{
273
case '!':
274
if (*ed == '=')
275
{
276
ed++;
277
sep = NE;
278
}
279
else sep = NOT;
280
break;
281
case '=':
282
if (*ed == '=') ed++;
283
sep = EQ;
284
break;
285
case '<':
286
if (*ed == '=')
287
{
288
ed++;
289
sep = LE;
290
}
291
else if (*ed == '>')
292
{
293
ed++;
294
sep = NE;
295
}
296
else sep = LT;
297
break;
298
case '>':
299
if (*ed == '=')
300
{
301
ed++;
302
sep = GE;
303
}
304
else sep = GT;
305
break;
306
default:
307
error(3, "edit operator delimiter omitted: %s", editcontext(eb, ed));
308
break;
309
}
310
val = ed;
311
for (cnt = n = 0; c = *ed; ed++)
312
{
313
if (cnt)
314
{
315
if (c == cnt) n++;
316
else if (c == cntlim && !--n) cnt = 0;
317
}
318
else if (c == '(')
319
{
320
cnt = '(';
321
cntlim = ')';
322
n++;
323
}
324
else if (c == '[')
325
{
326
cnt = '[';
327
cntlim = ']';
328
n++;
329
}
330
else if (c == del && n <= 0)
331
{
332
*ed++ = 0;
333
break;
334
}
335
}
336
if (!*val) val = DELETE;
337
}
338
else val = KEEP;
339
dp = xp;
340
*xp++ = ' ';
341
if (!delimited)
342
{
343
delimited = 1;
344
if (del != ':')
345
*xp++ = '`';
346
}
347
if (delimited < 0)
348
delimited = 1;
349
else
350
{
351
*xp++ = DEL;
352
*xp++ = ' ';
353
}
354
355
/*
356
* B, D and S are grouped before application
357
*/
358
359
switch (op)
360
{
361
case '$':
362
val--;
363
xp = strcopy(xp, val);
364
error(1, "%s: expand result may need conversion too", val);
365
continue;
366
case 'B':
367
case 'D':
368
case 'S':
369
switch (op)
370
{
371
case 'B':
372
bas = val;
373
break;
374
case 'D':
375
dir = val;
376
break;
377
case 'S':
378
suf = val;
379
break;
380
}
381
switch (*ed)
382
{
383
case 'B':
384
if (bas == DELETE)
385
{
386
xp = dp;
387
continue;
388
}
389
break;
390
case 'D':
391
if (dir == DELETE)
392
{
393
xp = dp;
394
continue;
395
}
396
break;
397
case 'S':
398
if (suf == DELETE)
399
{
400
xp = dp;
401
continue;
402
}
403
break;
404
}
405
sep = 0;
406
if (dir == DELETE)
407
{
408
xp = strcopy(xp, "nodirectory");
409
sep = 1;
410
}
411
else
412
{
413
if (dir != KEEP)
414
{
415
xp += sfsprintf(xp, EXBUF, "directory %s", dir);
416
sep = 1;
417
}
418
dir = DELETE;
419
}
420
if (bas == DELETE)
421
{
422
if (sep)
423
{
424
*xp++ = ' ';
425
*xp++ = DEL;
426
*xp++ = ' ';
427
}
428
else sep = 1;
429
xp = strcopy(xp, "nobase");
430
}
431
else
432
{
433
if (bas != KEEP)
434
{
435
if (sep)
436
{
437
*xp++ = ' ';
438
*xp++ = DEL;
439
*xp++ = ' ';
440
}
441
else sep = 1;
442
xp += sfsprintf(xp, EXBUF, "base %s", bas);
443
}
444
bas = DELETE;
445
}
446
if (suf == DELETE)
447
{
448
if (sep)
449
{
450
*xp++ = ' ';
451
*xp++ = DEL;
452
*xp++ = ' ';
453
}
454
else sep = 1;
455
xp = strcopy(xp, "nosuffix");
456
}
457
else
458
{
459
if (suf != KEEP)
460
{
461
if (sep)
462
{
463
*xp++ = ' ';
464
*xp++ = DEL;
465
*xp++ = ' ';
466
}
467
else sep = 1;
468
xp += sfsprintf(xp, EXBUF, "suffix %s", suf);
469
}
470
suf = DELETE;
471
}
472
break;
473
default:
474
qual = 0;
475
if (op == 'T')
476
{
477
for (;; val++)
478
{
479
switch (*val)
480
{
481
case 'R':
482
xp += sfsprintf(xp, EXBUF, "time %srule", state.longflag);
483
op = 0;
484
break;
485
case 'W':
486
qual |= ED_NOWAIT;
487
continue;
488
case 'X':
489
qual |= ED_NOBIND;
490
continue;
491
}
492
break;
493
}
494
if (*val == 'S' && *(val + 1) == 'F')
495
{
496
qual |= ED_FORCE;
497
sfsprintf(tmp, sizeof(tmp), "S%s", val + 2);
498
val = tmp;
499
}
500
}
501
if (sep == NE)
502
xp = strcopy(xp, "! ");
503
if (!op) break;
504
if (val == DELETE || val == KEEP)
505
{
506
val = "";
507
arg = 0;
508
aux = 0;
509
}
510
else
511
{
512
arg = val[0];
513
aux = val[1];
514
}
515
vp = val;
516
zp = 0;
517
for (mpp = state.map; mpp < &state.map[elementsof(editmap)]; mpp++)
518
{
519
mp = *mpp;
520
if (mp->cmd.type != ED_QUAL)
521
{
522
if (mp->cmd.op != op)
523
{
524
if (!(fp = mp->options))
525
continue;
526
for (; fp->name; fp++)
527
if (fp->cmd.type == ED_OP && fp->cmd.op == op)
528
529
break;
530
if (!fp->name)
531
continue;
532
}
533
m = 0;
534
switch (mp->cmd.arg)
535
{
536
case 0:
537
if (!zp || zp->options && !mp->options)
538
zp = mp;
539
if (arg && !mp->options)
540
continue;
541
break;
542
case '<':
543
if (!(sep & LT))
544
continue;
545
break;
546
case '>':
547
if (!(sep & GT))
548
continue;
549
break;
550
case '*':
551
if (arg)
552
{
553
if (arg != 'F' && arg != '*')
554
continue;
555
val++;
556
}
557
break;
558
default:
559
if (arg != mp->cmd.arg)
560
continue;
561
if (mp->cmd.aux)
562
{
563
if (aux != mp->cmd.aux)
564
continue;
565
if (!mp->options)
566
{
567
if (arg && *val)
568
val++;
569
if (*val)
570
val++;
571
}
572
}
573
else if (arg)
574
{
575
m = 1;
576
if (*val)
577
val++;
578
}
579
break;
580
}
581
dp = xp;
582
if (op == 'T')
583
{
584
if (bound) bound = 0;
585
else if (!(qual & ED_NOBIND))
586
{
587
bound = 1;
588
xp = strcopy(xp, "bind");
589
if (qual & ED_NOWAIT)
590
xp += sfsprintf(xp, EXBUF, " %snowait", state.longflag);
591
if (streq(mp->name, "bind"))
592
break;
593
xp += sfsprintf(xp, EXBUF, " %c ", DEL);
594
}
595
}
596
xp = strcopy(xp, mp->name);
597
if (qual & ED_FORCE)
598
xp += sfsprintf(xp, EXBUF, " %sforce", state.longflag);
599
if (fp = mp->options)
600
{
601
n = sep;
602
for (e = 0; fp->name; fp++)
603
{
604
if (!*fp->name && fp->cmd.type == ED_QUAL)
605
sep ^= fp->cmd.op;
606
else if (fp->cmd.type == ED_QUAL && (sep & fp->cmd.op) || fp->cmd.type == ED_OP && (fp->cmd.op && op == fp->cmd.op || !fp->cmd.op && arg == fp->cmd.arg && (!fp->cmd.aux || aux == fp->cmd.aux)))
607
{
608
if (!*fp->name)
609
e = 1;
610
else
611
{
612
if (!m) m = 1;
613
if (m > 0 && fp->cmd.type == ED_OP)
614
{
615
m = -1;
616
val++;
617
if (fp->cmd.aux)
618
val++;
619
}
620
*xp++ = ' ';
621
xp = strcopy(xp, state.longflag);
622
xp = strcopy(xp, fp->name);
623
}
624
}
625
}
626
if (!m)
627
{
628
if (e)
629
{
630
if (*val) val++;
631
}
632
else if (!aux || isupper(aux))
633
{
634
if (!zp) zp = mp;
635
sep = n;
636
xp = dp;
637
val = vp;
638
continue;
639
}
640
}
641
}
642
if (aux == '=' && *val == '=')
643
val++;
644
if (*val)
645
{
646
*xp++ = ' ';
647
if (*val == '-')
648
{
649
*xp++ = '-';
650
*xp++ = '-';
651
*xp++ = ' ';
652
}
653
if (op != 'P' || arg != 'P')
654
xp = strcopy(xp, val);
655
else
656
{
657
while (c = *val++)
658
*xp++ = c == ',' ? ' ' : c;
659
*xp = 0;
660
}
661
}
662
break;
663
}
664
}
665
if (mpp >= &state.map[elementsof(editmap)])
666
{
667
if (zp)
668
{
669
xp = strcopy(xp, zp->name);
670
if (*val)
671
{
672
*xp++ = ' ';
673
xp = strcopy(xp, val);
674
}
675
}
676
else
677
{
678
error(2, "%c: operator not matched", op);
679
xp = strcopy(xp, ">>>HUH<<<");
680
}
681
}
682
break;
683
}
684
}
685
*xp = 0;
686
return(xp);
687
}
688
689
/*
690
* expand var name into xp
691
*/
692
693
static char*
694
expandvar(register char* xp, register char* v)
695
{
696
register int c;
697
register char* s;
698
699
switch (c = *v++)
700
{
701
case 0:
702
break;
703
case '$':
704
case '"':
705
return(expand(xp, v - 1));
706
case '-':
707
case '+':
708
xp = strcopy(xp, "option ");
709
if (c == '+')
710
xp += sfsprintf(xp, EXBUF, "%sset ", state.longflag);
711
xp = expand(xp, v);
712
break;
713
case '=':
714
xp = strcopy(xp, "makeargs");
715
break;
716
case '#':
717
s = "argc";
718
goto internal;
719
case ';':
720
s = "data";
721
goto internal;
722
case '<':
723
s = "target";
724
goto internal;
725
case '>':
726
s = "prereqs new";
727
goto internal;
728
case '*':
729
s = "prereqs";
730
goto internal;
731
case '~':
732
s = "prereqs all";
733
goto internal;
734
case '@':
735
s = "action";
736
goto internal;
737
case '%':
738
s = state.function ? "args" : "stem";
739
goto internal;
740
case '!':
741
s = "prereqs implicit";
742
goto internal;
743
case '&':
744
s = "prereqs implicit state";
745
goto internal;
746
case '?':
747
s = "prereqs all implicit";
748
goto internal;
749
case '^':
750
s = "target original";
751
goto internal;
752
internal:
753
while (*v == c)
754
{
755
v++;
756
xp = strcopy(xp, "parent ");
757
}
758
for (;;)
759
{
760
switch (*xp++ = *s++)
761
{
762
case 0:
763
xp--;
764
break;
765
case ' ':
766
xp = strcopy(xp, state.longflag);
767
continue;
768
default:
769
continue;
770
}
771
break;
772
}
773
if (*v)
774
{
775
*xp++ = ' ';
776
xp = expand(xp, v);
777
}
778
break;
779
case '.':
780
if (v[0] != '.' || v[1] != '.')
781
goto normal;
782
xp = strcopy(xp, "rules");
783
break;
784
default:
785
if (!isalnum(c))
786
error(2, "%s: unknown internal variable", v - 1);
787
/*FALLTHROUGH*/
788
case '_':
789
case '(':
790
normal:
791
xp = expand(xp, v - 1);
792
break;
793
}
794
*xp = 0;
795
return(xp);
796
}
797
798
/*
799
* expand `$(...)' from a into xp
800
*/
801
802
static char*
803
expand(register char* xp, register char* a)
804
{
805
register int c;
806
register char* s;
807
int del;
808
int p;
809
int q;
810
char* ed;
811
char* var;
812
char* vp;
813
814
char varbuf[EXBUF];
815
816
debug((-4, "expand(`%s')", a));
817
if (!(s = strchr(a, '$')))
818
return(strcopy(xp, a));
819
strncpy(xp, a, s - a);
820
xp += s - a;
821
a = s;
822
while (*a)
823
{
824
if (*a != '$') *xp++ = *a++;
825
else if (*++a == '(')
826
{
827
*xp++ = '$';
828
*xp++ = '(';
829
if (isspace(*++a))
830
*xp++ = *a++;
831
else
832
{
833
var = a;
834
ed = 0;
835
vp = 0;
836
del = ':';
837
q = 0;
838
p = 1;
839
while (c = *a++)
840
{
841
if (c == '"') q = !q;
842
else if (q) /* quoted */;
843
else if (c == '(') p++;
844
else if (c == ')')
845
{
846
if (!--p) break;
847
}
848
else if (!ed && p == 1)
849
{
850
if (c == '|')
851
{
852
*(a - 1) = 0;
853
if (!vp) vp = varbuf;
854
else *vp++ = ' ';
855
vp = expandvar(vp, var);
856
var = a;
857
*(a - 1) = c;
858
c = 0;
859
}
860
else if (c == del)
861
{
862
c = 0;
863
ed = a - 1;
864
}
865
else if (c == '`')
866
{
867
c = 0;
868
ed = a - 1;
869
if (!(del = *a++))
870
{
871
ed--;
872
break;
873
}
874
}
875
}
876
}
877
if (q || !c)
878
{
879
a--;
880
error(1, "missing %c in %s variable expansion", q ? '"' : ')', s);
881
}
882
if (vp)
883
{
884
xp += sfsprintf(xp, EXBUF, "value ");
885
if (*var == '"')
886
{
887
c = *(a - 1);
888
*(a - 1) = 0;
889
xp += sfsprintf(xp, EXBUF, "%sdefault=%s ", state.longflag, var);
890
*(a - 1) = c;
891
var = 0;
892
}
893
}
894
if (ed && *(ed + 1) == 'V')
895
{
896
*ed = 0;
897
if (!vp) xp += sfsprintf(xp, EXBUF, "value ");
898
xp = strcopy(xp, state.longflag);
899
switch (*(ed + 2))
900
{
901
case 'A':
902
ed += 3;
903
xp = strcopy(xp, "auxiliary ");
904
break;
905
case 'P':
906
ed += 3;
907
xp = strcopy(xp, "primary ");
908
break;
909
default:
910
ed += 2;
911
xp = strcopy(xp, "literal ");
912
break;
913
}
914
if (ed == (a - 1))
915
ed = 0;
916
}
917
if (ed)
918
{
919
if (var && strneq(var, "\"\":T=R", 6))
920
xp += sfsprintf(xp, EXBUF, "time %swall", state.longflag);
921
else
922
{
923
c = *ed;
924
*ed = 0;
925
if (vp)
926
{
927
xp = strcopy(xp, varbuf);
928
if (var) *xp++ = ' ';
929
}
930
if (var) xp = expandvar(xp, var);
931
*ed = c;
932
c = *(a - 1);
933
*(a - 1) = 0;
934
xp = expandops(xp, ed + 1, del);
935
*(a - 1) = c;
936
}
937
}
938
else
939
{
940
c = *(a - 1);
941
*(a - 1) = 0;
942
if (vp)
943
{
944
xp = strcopy(xp, varbuf);
945
if (var) *xp++ = ' ';
946
}
947
if (var) xp = expandvar(xp, var);
948
*(a - 1) = c;
949
}
950
}
951
*xp++ = ')';
952
}
953
else *xp++ = '$';
954
}
955
*xp = 0;
956
return(xp);
957
}
958
959
static int
960
byop(const char* a, const char* b)
961
{
962
register Edit_map_t* ap = (Edit_map_t*)a;
963
register Edit_map_t* bp = (Edit_map_t*)b;
964
965
if (ap->cmd.type == ED_QUAL) return(-1);
966
if (bp->cmd.type == ED_QUAL) return(1);
967
if (ap->cmd.op < bp->cmd.op) return(-1);
968
if (ap->cmd.op > bp->cmd.op) return(1);
969
if (!ap->cmd.arg) return(1);
970
if (!bp->cmd.arg) return(-1);
971
if (ap->cmd.arg < bp->cmd.arg) return(-1);
972
if (ap->cmd.arg > bp->cmd.arg) return(1);
973
if (!ap->cmd.aux) return(1);
974
if (!bp->cmd.aux) return(-1);
975
if (ap->cmd.aux < bp->cmd.aux) return(-1);
976
if (ap->cmd.aux > bp->cmd.aux) return(1);
977
return(0);
978
}
979
980
main(int argc, char** argv)
981
{
982
register char* s;
983
register int c;
984
Edit_map_t* mp;
985
Edit_map_t** mpp;
986
Sfio_t* ip;
987
char buf[EXBUF];
988
989
error_info.id = "convert";
990
state.delimiter = ':';
991
state.longflag = "-o ";
992
if (!(state.map = newof(0, Edit_map_t*, elementsof(editmap), 0)))
993
error(ERROR_SYSTEM|3, "out of space [editmap sort]");
994
mpp = state.map;
995
mp = (Edit_map_t*)editmap;
996
while (mp < &editmap[elementsof(editmap)])
997
*mpp++ = mp++;
998
strsort((char**)state.map, elementsof(editmap), byop);
999
while (c = optget(argv, "d:[delimiter]o:[longflag]D#[debug-level]")) switch (c)
1000
{
1001
case 'd':
1002
state.delimiter = *opt_info.arg;
1003
break;
1004
case 'o':
1005
state.longflag = opt_info.arg;
1006
break;
1007
case 'D':
1008
error_info.trace = -opt_info.num;
1009
break;
1010
case '?':
1011
error(ERROR_USAGE|4, opt_info.arg);
1012
break;
1013
case ':':
1014
error(2, opt_info.arg);
1015
break;
1016
}
1017
if (error_info.errors)
1018
error(ERROR_USAGE|4, "%s", optusage(NiL));
1019
argv += opt_info.index;
1020
for (;;)
1021
{
1022
s = *argv++;
1023
if (!s || streq(s, "-") || streq(s, "/dev/stdin") || streq(s, "/dev/fd/0"))
1024
ip = sfstdin;
1025
else if (!(ip = sfopen(NiL, s, "r")))
1026
{
1027
error(2, "%s: cannot read", s);
1028
continue;
1029
}
1030
error_info.file = s;
1031
error_info.line = 0;
1032
while (s = sfgetr(ip, '\n', 1))
1033
{
1034
error_info.line++;
1035
if (*s && !isspace(*s))
1036
state.function = strmatch(s, "*FUNCTION*");
1037
expand(buf, s);
1038
sfputr(sfstdout, buf, '\n');
1039
}
1040
error_info.file = 0;
1041
error_info.line = 0;
1042
if (!s) break;
1043
if (ip != sfstdin) sfclose(ip);
1044
}
1045
exit(error_info.errors != 0);
1046
}
1047
1048