Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/ksh93/sh/lex.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1982-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
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* KornShell lexical analyzer
23
*
24
* Written by David Korn
25
* AT&T Labs
26
*
27
*/
28
29
#include <ast.h>
30
#include <stak.h>
31
#include <fcin.h>
32
#include <nval.h>
33
#include "FEATURE/options"
34
35
#if KSHELL
36
# include "defs.h"
37
#else
38
# include <shell.h>
39
# define nv_getval(np) ((np)->nvalue)
40
Shell_t sh = {1};
41
#endif /* KSHELL */
42
43
#include "argnod.h"
44
#include "test.h"
45
#include "lexstates.h"
46
#include "io.h"
47
48
#define TEST_RE 3
49
#define SYNBAD 3 /* exit value for syntax errors */
50
#define STACK_ARRAY 3 /* size of depth match stack growth */
51
52
#if _lib_iswblank < 0 /* set in lexstates.h to enable this code */
53
54
int
55
local_iswblank(wchar_t wc)
56
{
57
static int initialized;
58
static wctype_t wt;
59
60
if (!initialized)
61
{
62
initialized = 1;
63
wt = wctype("blank");
64
}
65
return(iswctype(wc, wt));
66
}
67
68
#endif
69
70
/*
71
* This structure allows for arbitrary depth nesting of (...), {...}, [...]
72
*/
73
struct lexstate
74
{
75
char incase; /* 1 for case pattern, 2 after case */
76
char intest; /* 1 inside [[...]] */
77
char testop1; /* 1 when unary test op legal */
78
char testop2; /* 1 when binary test op legal */
79
char reservok; /* >0 for reserved word legal */
80
char skipword; /* next word can't be reserved */
81
char last_quote; /* last multi-line quote character */
82
char nestedbrace; /* ${var op {...}} */
83
};
84
85
struct lexdata
86
{
87
char nocopy;
88
char paren;
89
char dolparen;
90
char nest;
91
char docword;
92
char nested_tilde;
93
char *docend;
94
char noarg;
95
char balance;
96
char warn;
97
char message;
98
char arith;
99
char *first;
100
int level;
101
int lastc;
102
int lex_max;
103
int *lex_match;
104
int lex_state;
105
int docextra;
106
#if SHOPT_KIA
107
off_t kiaoff;
108
#endif
109
};
110
111
#define _SHLEX_PRIVATE \
112
struct lexdata lexd; \
113
struct lexstate lex;
114
115
#include "shlex.h"
116
117
118
#define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\
119
((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\
120
lp->lexd.lastc=(((s)<<CHAR_BIT)|(c))))
121
#define oldmode(lp) (lp->lexd.lastc>>CHAR_BIT)
122
#define endchar(lp) (lp->lexd.lastc&0xff)
123
#define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c)))
124
#define poplevel(lp) (lp->lexd.lastc=lp->lexd.lex_match[--lp->lexd.level])
125
126
static char *fmttoken(Lex_t*, int, char*);
127
#ifdef SF_BUFCONST
128
static int alias_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
129
#else
130
static int alias_exceptf(Sfio_t*, int, Sfdisc_t*);
131
#endif
132
static void setupalias(Lex_t*,const char*, Namval_t*);
133
static int comsub(Lex_t*,int);
134
static void nested_here(Lex_t*);
135
static int here_copy(Lex_t*, struct ionod*);
136
static int stack_grow(Lex_t*);
137
static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL };
138
139
#if SHOPT_KIA
140
141
static void refvar(Lex_t *lp, int type)
142
{
143
register Shell_t *shp = lp->sh;
144
register Stk_t *stkp = shp->stk;
145
off_t off = (fcseek(0)-(type+1))-(lp->lexd.first?lp->lexd.first:fcfirst());
146
unsigned long r;
147
if(lp->lexd.first)
148
{
149
off = (fcseek(0)-(type+1)) - lp->lexd.first;
150
r=kiaentity(lp,lp->lexd.first+lp->lexd.kiaoff+type,off-lp->lexd.kiaoff,'v',-1,-1,lp->current,'v',0,"");
151
}
152
else
153
{
154
int n,offset = stktell(stkp);
155
char *savptr,*begin;
156
off = offset + (fcseek(0)-(type+1)) - fcfirst();
157
if(lp->lexd.kiaoff < offset)
158
{
159
/* variable starts on stak, copy remainder */
160
if(off>offset)
161
sfwrite(stkp,fcfirst()+type,off-offset);
162
n = stktell(stkp)-lp->lexd.kiaoff;
163
begin = stkptr(stkp,lp->lexd.kiaoff);
164
}
165
else
166
{
167
/* variable in data buffer */
168
begin = fcfirst()+(type+lp->lexd.kiaoff-offset);
169
n = off-lp->lexd.kiaoff;
170
}
171
savptr = stkfreeze(stkp,0);
172
r=kiaentity(lp,begin,n,'v',-1,-1,lp->current,'v',0,"");
173
stkset(stkp,savptr,offset);
174
}
175
sfprintf(lp->kiatmp,"p;%..64d;v;%..64d;%d;%d;r;\n",lp->current,r,shp->inlineno,shp->inlineno);
176
}
177
#endif /* SHOPT_KIA */
178
179
/*
180
* This routine gets called when reading across a buffer boundary
181
* If lexd.nocopy is off, then current token is saved on the stack
182
*/
183
static void lex_advance(Sfio_t *iop, const char *buff, register int size, void *context)
184
{
185
register Lex_t *lp = (Lex_t*)context;
186
register Shell_t *shp = lp->sh;
187
register Sfio_t *log= shp->funlog;
188
Stk_t *stkp = shp->stk;
189
#if KSHELL
190
/* write to history file and to stderr if necessary */
191
if(iop && !sfstacked(iop))
192
{
193
if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
194
log = shp->gd->hist_ptr->histfp;
195
sfwrite(log, (void*)buff, size);
196
if(sh_isstate(SH_VERBOSE))
197
sfwrite(sfstderr, buff, size);
198
}
199
#endif
200
if(lp->lexd.nocopy)
201
return;
202
if(lp->lexd.dolparen && lp->lexd.docword && lp->lexd.docend)
203
{
204
int n = size - (lp->lexd.docend-(char*)buff);
205
sfwrite(shp->strbuf,lp->lexd.docend,n);
206
lp->lexd.docextra += n;
207
if(sffileno(iop)>=0)
208
lp->lexd.docend = sfsetbuf(iop,(Void_t*)iop,0);
209
else
210
lp->lexd.docend = fcfirst();
211
}
212
if(lp->lexd.first)
213
{
214
size -= (lp->lexd.first-(char*)buff);
215
buff = lp->lexd.first;
216
if(!lp->lexd.noarg)
217
lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
218
#if SHOPT_KIA
219
lp->lexd.kiaoff += ARGVAL;
220
#endif /* SHOPT_KIA */
221
}
222
if(size>0 && (lp->arg||lp->lexd.noarg))
223
{
224
sfwrite(stkp,buff,size);
225
lp->lexd.first = 0;
226
}
227
}
228
229
/*
230
* fill up another input buffer
231
* preserves lexical state
232
*/
233
static int lexfill(Lex_t *lp)
234
{
235
register int c;
236
Lex_t savelex;
237
struct argnod *ap;
238
int aok,docextra;
239
savelex = *lp;
240
ap = lp->arg;
241
c = fcfill();
242
if(ap)
243
lp->arg = ap;
244
docextra = lp->lexd.docextra;
245
lp->lex = savelex.lex;
246
lp->lexd = savelex.lexd;
247
if(fcfile() || c)
248
lp->lexd.first = 0;
249
aok= lp->aliasok;
250
ap = lp->arg;
251
memcpy(lp, &savelex, offsetof(Lex_t,lexd));
252
lp->arg = ap;
253
lp->aliasok = aok;
254
if(lp->lexd.docword && docextra)
255
{
256
lp->lexd.docextra = docextra;
257
lp->lexd.docend = fcseek(0)-1;
258
}
259
return(c);
260
}
261
262
/*
263
* mode=1 for reinitialization
264
*/
265
Lex_t *sh_lexopen(Lex_t *lp, Shell_t *sp, int mode)
266
{
267
if(!lp)
268
{
269
lp = (Lex_t*)newof(0,Lex_t,1,0);
270
lp->sh = sp;
271
}
272
fcnotify(lex_advance,lp);
273
lp->lex.intest = lp->lex.incase = lp->lex.skipword = lp->lexd.warn = 0;
274
lp->comp_assign = 0;
275
lp->lex.reservok = 1;
276
if(!sh_isoption(SH_DICTIONARY) && sh_isoption(SH_NOEXEC))
277
lp->lexd.warn=1;
278
if(!mode)
279
{
280
lp->lexd.noarg = lp->lexd.level= lp->lexd.dolparen = lp->lexd.balance = 0;
281
lp->lexd.nocopy = lp->lexd.docword = lp->lexd.nest = lp->lexd.paren = 0;
282
lp->lexd.lex_state = lp->lexd.lastc=0;
283
lp->lexd.docend = 0;
284
lp->lexd.nested_tilde = 0;
285
}
286
lp->comsub = 0;
287
return(lp);
288
}
289
290
#ifdef DBUG
291
extern int lextoken(Lex_t*);
292
int sh_lex(Lex_t *lp)
293
{
294
Shell_t *shp = lp->sh;
295
register int flag;
296
char *quoted, *macro, *split, *expand;
297
char tokstr[3];
298
register int tok = lextoken(lp);
299
quoted = macro = split = expand = "";
300
if(tok==0 && (flag=lp->arg->argflag))
301
{
302
if(flag&ARG_MAC)
303
macro = "macro:";
304
if(flag&ARG_EXP)
305
expand = "expand:";
306
if(flag&ARG_QUOTED)
307
quoted = "quoted:";
308
}
309
sfprintf(sfstderr,"%d: line %d: %o:%s%s%s%s %s\n",getpid(),shp->inlineno,tok,quoted,
310
macro, split, expand, fmttoken(lp,tok,tokstr));
311
return(tok);
312
}
313
#define sh_lex lextoken
314
#endif
315
316
/*
317
* Get the next word and put it on the top of the stak
318
* A pointer to the current word is stored in lp->arg
319
* Returns the token type
320
*/
321
int sh_lex(Lex_t* lp)
322
{
323
register Shell_t *shp = lp->sh;
324
register const char *state;
325
register int n, c, mode=ST_BEGIN, wordflags=0;
326
Stk_t *stkp = shp->stk;
327
int inlevel=lp->lexd.level, assignment=0, ingrave=0;
328
int epatchar=0;
329
Sfio_t *sp;
330
#if SHOPT_MULTIBYTE
331
LEN=1;
332
#endif /* SHOPT_MULTIBYTE */
333
if(lp->lexd.paren)
334
{
335
lp->lexd.paren = 0;
336
return(lp->token=LPAREN);
337
}
338
if(lp->noreserv)
339
{
340
lp->lex.reservok = 0;
341
while((fcgetc(c)) && c==' ' || c== '\t' || c=='\n');
342
fcseek(-LEN);
343
if(c=='[')
344
lp->assignok = SH_ASSIGN;
345
}
346
if(lp->lex.incase)
347
lp->assignok = 0;
348
else
349
lp->assignok |= lp->lex.reservok;
350
if(lp->comp_assign==2)
351
lp->comp_assign = lp->lex.reservok = 0;
352
lp->lexd.arith = (lp->lexd.nest==1);
353
if(lp->lexd.nest)
354
{
355
pushlevel(lp,lp->lexd.nest,ST_NONE);
356
lp->lexd.nest = 0;
357
mode = lp->lexd.lex_state;
358
}
359
else if(lp->lexd.docword)
360
{
361
if(fcgetc(c)=='-' || c=='#')
362
{
363
lp->lexd.docword++;
364
lp->digits=(c=='#'?3:1);
365
}
366
else if(c=='<')
367
{
368
lp->digits=2;
369
lp->lexd.docword=0;
370
}
371
else if(c>0)
372
fcseek(-LEN);
373
}
374
if(!lp->lexd.dolparen)
375
{
376
lp->arg = 0;
377
if(mode!=ST_BEGIN)
378
lp->lexd.first = fcseek(0);
379
else
380
lp->lexd.first = 0;
381
}
382
lp->lastline = lp->sh->inlineno;
383
while(1)
384
{
385
/* skip over characters in the current state */
386
state = sh_lexstates[mode];
387
while((n=STATE(state,c))==0);
388
switch(n)
389
{
390
case S_BREAK:
391
fcseek(-LEN);
392
goto breakloop;
393
case S_EOF:
394
sp = fcfile();
395
if((n=lexfill(lp)) > 0)
396
{
397
fcseek(-1);
398
continue;
399
}
400
/* check for zero byte in file */
401
if(n==0 && fcfile())
402
{
403
if(shp->readscript)
404
{
405
char *cp = error_info.id;
406
errno = ENOEXEC;
407
error_info.id = shp->readscript;
408
errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,cp);
409
}
410
else
411
{
412
lp->token = -1;
413
sh_syntax(lp);
414
}
415
}
416
/* end-of-file */
417
if(mode==ST_BEGIN)
418
return(lp->token=EOFSYM);
419
if(mode >ST_NORM && lp->lexd.level>0)
420
{
421
switch(c=endchar(lp))
422
{
423
case '$':
424
if(mode==ST_LIT)
425
{
426
c = '\'';
427
break;
428
}
429
mode = oldmode(lp);
430
poplevel(lp);
431
continue;
432
case RBRACT:
433
c = LBRACT;
434
break;
435
case 1: /* for ((...)) */
436
case RPAREN:
437
c = LPAREN;
438
break;
439
default:
440
c = LBRACE;
441
break;
442
case '"': case '`': case '\'':
443
lp->lexd.balance = c;
444
break;
445
}
446
if(sp && !(sfset(sp,0,0)&SF_STRING))
447
{
448
lp->lasttok = c;
449
lp->token = EOFSYM;
450
sh_syntax(lp);
451
}
452
lp->lexd.balance = c;
453
}
454
goto breakloop;
455
case S_COM:
456
/* skip one or more comment line(s) */
457
lp->lex.reservok = !lp->lex.intest;
458
if((n=lp->lexd.nocopy) && lp->lexd.dolparen)
459
lp->lexd.nocopy--;
460
do
461
{
462
while(fcgetc(c)>0 && c!='\n');
463
if(c<=0 || lp->heredoc)
464
{
465
shp->inlineno++;
466
break;
467
}
468
while(shp->inlineno++,fcpeek(0)=='\n')
469
fcseek(1);
470
while(state[c=fcpeek(0)]==0)
471
fcseek(1);
472
}
473
while(c=='#');
474
lp->lexd.nocopy = n;
475
if(c<0)
476
return(lp->token=EOFSYM);
477
n = S_NLTOK;
478
shp->inlineno--;
479
/* FALL THRU */
480
case S_NLTOK:
481
/* check for here-document */
482
if(lp->heredoc)
483
{
484
if(!lp->lexd.dolparen)
485
lp->lexd.nocopy++;
486
c = shp->inlineno;
487
if(here_copy(lp,lp->heredoc)<=0 && lp->lasttok)
488
{
489
lp->lasttok = IODOCSYM;
490
lp->token = EOFSYM;
491
lp->lastline = c;
492
sh_syntax(lp);
493
}
494
if(!lp->lexd.dolparen)
495
lp->lexd.nocopy--;
496
lp->heredoc = 0;
497
}
498
lp->lex.reservok = !lp->lex.intest;
499
lp->lex.skipword = 0;
500
/* FALL THRU */
501
case S_NL:
502
/* skip over new-lines */
503
lp->lex.last_quote = 0;
504
while(shp->inlineno++,fcget()=='\n');
505
fcseek(-LEN);
506
if(n==S_NLTOK)
507
{
508
lp->comp_assign = 0;
509
return(lp->token='\n');
510
}
511
case S_BLNK:
512
if(lp->lex.incase<=TEST_RE)
513
continue;
514
/* implicit RPAREN for =~ test operator */
515
if(inlevel+1==lp->lexd.level)
516
{
517
if(lp->lex.intest)
518
fcseek(-LEN);
519
c = RPAREN;
520
goto do_pop;
521
}
522
continue;
523
case S_OP:
524
/* return operator token */
525
if(c=='<' || c=='>')
526
{
527
if(lp->lex.testop2)
528
lp->lex.testop2 = 0;
529
else
530
{
531
lp->digits = (c=='>');
532
lp->lex.skipword = 1;
533
lp->aliasok = lp->lex.reservok;
534
if(lp->lex.incase<2)
535
lp->lex.reservok = 0;
536
}
537
}
538
else
539
{
540
lp->lex.reservok = !lp->lex.intest;
541
if(c==RPAREN)
542
{
543
if(!lp->lexd.dolparen)
544
lp->lex.incase = 0;
545
return(lp->token=c);
546
}
547
lp->lex.testop1 = lp->lex.intest;
548
}
549
if(fcgetc(n)>0)
550
fcseek(-LEN);
551
if(state[n]==S_OP || n=='#')
552
{
553
if(n==c)
554
{
555
if(c=='<')
556
lp->lexd.docword=1;
557
else if(n==LPAREN)
558
{
559
if(lp->lex.intest)
560
return(c);
561
lp->lexd.nest=1;
562
lp->lastline = shp->inlineno;
563
lp->lexd.lex_state = ST_NESTED;
564
fcseek(1);
565
return(sh_lex(lp));
566
}
567
c |= SYMREP;
568
}
569
else if(c=='(' || c==')')
570
return(lp->token=c);
571
else if(c=='&')
572
{
573
if(!sh_isoption(SH_POSIX) && n=='>' && (sh_isoption(SH_BASH) || sh_isstate(SH_PROFILE)))
574
{
575
if(!sh_isoption(SH_BASH) && !lp->nonstandard)
576
{
577
lp->nonstandard = 1;
578
errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno);
579
}
580
lp->digits = -1;
581
c = '>';
582
}
583
else if(n=='|')
584
c |= SYMPIPE;
585
else
586
n = 0;
587
}
588
else if(n=='&')
589
c |= SYMAMP;
590
else if(c!='<' && c!='>')
591
n = 0;
592
else if(n==LPAREN)
593
{
594
c |= SYMLPAR;
595
lp->lex.reservok = 1;
596
lp->lex.skipword = 0;
597
}
598
else if(n=='|')
599
c |= SYMPIPE;
600
else if(c=='<' && n=='>')
601
{
602
lp->digits = 1;
603
c = IORDWRSYM;
604
fcgetc(n);
605
if(fcgetc(n)==';')
606
{
607
lp->token = c = IORDWRSYMT;
608
if(lp->inexec)
609
sh_syntax(lp);
610
}
611
else if(n>0)
612
fcseek(-LEN);
613
n= 0;
614
}
615
else if(n=='#' && (c=='<'||c=='>'))
616
c |= SYMSHARP;
617
else if(n==';' && c=='>')
618
{
619
c |= SYMSEMI;
620
if(lp->inexec)
621
{
622
lp->token = c;
623
sh_syntax(lp);
624
}
625
}
626
else
627
n = 0;
628
if(n)
629
{
630
fcseek(1);
631
lp->lex.incase = (c==BREAKCASESYM || c==FALLTHRUSYM);
632
}
633
else
634
{
635
if(lp->lexd.warn && (n=fcpeek(0))!=RPAREN && n!=' ' && n!='\t')
636
errormsg(SH_DICT,ERROR_warn(0),e_lexspace,shp->inlineno,c,n);
637
}
638
}
639
if(c==LPAREN && lp->comp_assign && !lp->lex.intest && !lp->lex.incase)
640
lp->comp_assign = 2;
641
else
642
lp->comp_assign = 0;
643
return(lp->token=c);
644
case S_ESC:
645
/* check for \<new-line> */
646
fcgetc(n);
647
c=2;
648
#if SHOPT_CRNL
649
if(n=='\r')
650
{
651
if(fcgetc(n)=='\n')
652
c=3;
653
else
654
{
655
n='\r';
656
fcseek(-LEN);
657
}
658
}
659
#endif /* SHOPT_CRNL */
660
if(n=='\n')
661
{
662
Sfio_t *sp;
663
struct argnod *ap;
664
shp->inlineno++;
665
/* synchronize */
666
if(!(sp=fcfile()))
667
state=fcseek(0);
668
fcclose();
669
ap = lp->arg;
670
if(sp)
671
fcfopen(sp);
672
else
673
fcsopen((char*)state);
674
/* remove \new-line */
675
n = stktell(stkp)-c;
676
stkseek(stkp,n);
677
lp->arg = ap;
678
if(n<=ARGVAL)
679
{
680
mode = 0;
681
lp->lexd.first = 0;
682
}
683
continue;
684
}
685
wordflags |= ARG_QUOTED;
686
if(mode==ST_DOL)
687
goto err;
688
#ifndef STR_MAXIMAL
689
else if(mode==ST_NESTED && lp->lexd.warn &&
690
endchar(lp)==RBRACE &&
691
sh_lexstates[ST_DOL][n]==S_DIG
692
)
693
errormsg(SH_DICT,ERROR_warn(0),e_lexfuture,shp->inlineno,n);
694
#endif /* STR_MAXIMAL */
695
break;
696
case S_NAME:
697
if(!lp->lex.skipword)
698
lp->lex.reservok *= 2;
699
/* FALL THRU */
700
case S_TILDE:
701
if(c=='~' && mode==ST_NESTED)
702
{
703
if(endchar(lp)==RBRACE)
704
{
705
lp->lexd.nested_tilde++;
706
goto tilde;
707
}
708
continue;
709
}
710
case S_RES:
711
if(!lp->lexd.dolparen)
712
lp->lexd.first = fcseek(0)-LEN;
713
else if(lp->lexd.docword)
714
lp->lexd.docend = fcseek(0)-LEN;
715
mode = ST_NAME;
716
if(c=='.')
717
fcseek(-LEN);
718
if(n!=S_TILDE)
719
continue;
720
tilde:
721
fcgetc(n);
722
if(n>0)
723
{
724
if(c=='~' && n==LPAREN)
725
{
726
if(lp->lexd.nested_tilde)
727
lp->lexd.nested_tilde++;
728
else if(lp->lex.incase)
729
lp->lex.incase = TEST_RE;
730
}
731
fcseek(-LEN);
732
if(lp->lexd.nested_tilde)
733
{
734
lp->lexd.nested_tilde--;
735
continue;
736
}
737
}
738
if(n==LPAREN)
739
goto epat;
740
wordflags = ARG_MAC;
741
mode = ST_NORM;
742
continue;
743
case S_REG:
744
if(mode==ST_BEGIN)
745
{
746
do_reg:
747
/* skip new-line joining */
748
if(c=='\\' && fcpeek(0)=='\n')
749
{
750
shp->inlineno++;
751
fcseek(1);
752
continue;
753
}
754
fcseek(-LEN);
755
if(!lp->lexd.dolparen)
756
lp->lexd.first = fcseek(0);
757
else if(lp->lexd.docword)
758
lp->lexd.docend = fcseek(0);
759
if(c=='[' && lp->assignok>=SH_ASSIGN)
760
{
761
mode = ST_NAME;
762
continue;
763
}
764
}
765
mode = ST_NORM;
766
continue;
767
case S_LIT:
768
if(oldmode(lp)==ST_NONE && !lp->lexd.noarg) /* in ((...)) */
769
{
770
if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']')
771
{
772
if(fcpeek(1)=='\'')
773
fcseek(2);
774
}
775
continue;
776
}
777
wordflags |= ARG_QUOTED;
778
if(mode==ST_DOL)
779
{
780
if(endchar(lp)!='$')
781
goto err;
782
if(oldmode(lp)==ST_QUOTE) /* $' within "" or `` */
783
{
784
if(lp->lexd.warn)
785
errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
786
mode = ST_LIT;
787
}
788
}
789
if(mode!=ST_LIT)
790
{
791
if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline && fcpeek(-2)!='$')
792
errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
793
lp->lex.last_quote = 0;
794
lp->lastline = shp->inlineno;
795
if(mode!=ST_DOL)
796
pushlevel(lp,'\'',mode);
797
mode = ST_LIT;
798
continue;
799
}
800
/* check for multi-line single-quoted string */
801
else if(shp->inlineno > lp->lastline)
802
lp->lex.last_quote = '\'';
803
mode = oldmode(lp);
804
poplevel(lp);
805
break;
806
case S_ESC2:
807
/* \ inside '' */
808
if(endchar(lp)=='$')
809
{
810
fcgetc(n);
811
if(n=='\n')
812
shp->inlineno++;
813
}
814
continue;
815
case S_GRAVE:
816
if(lp->lexd.warn && (mode!=ST_QUOTE || endchar(lp)!='`'))
817
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete1,shp->inlineno);
818
wordflags |=(ARG_MAC|ARG_EXP);
819
if(mode==ST_QUOTE)
820
ingrave = !ingrave;
821
/* FALL THRU */
822
case S_QUOTE:
823
if(oldmode(lp)==ST_NONE && lp->lexd.arith) /* in ((...)) */
824
{
825
if(n!=S_GRAVE || fcpeek(0)=='\'')
826
continue;
827
}
828
if(n==S_QUOTE)
829
wordflags |=ARG_QUOTED;
830
if(mode!=ST_QUOTE)
831
{
832
if(c!='"' || mode!=ST_QNEST)
833
{
834
if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline)
835
errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
836
lp->lex.last_quote=0;
837
lp->lastline = shp->inlineno;
838
pushlevel(lp,c,mode);
839
}
840
ingrave ^= (c=='`');
841
mode = ST_QUOTE;
842
continue;
843
}
844
else if((n=endchar(lp))==c)
845
{
846
if(shp->inlineno > lp->lastline)
847
lp->lex.last_quote = c;
848
mode = oldmode(lp);
849
poplevel(lp);
850
}
851
else if(c=='"' && n==RBRACE)
852
mode = ST_QNEST;
853
break;
854
case S_DOL:
855
/* don't check syntax inside `` */
856
if(mode==ST_QUOTE && ingrave)
857
continue;
858
#if SHOPT_KIA
859
if(lp->lexd.first)
860
lp->lexd.kiaoff = fcseek(0)-lp->lexd.first;
861
else
862
lp->lexd.kiaoff = stktell(stkp)+fcseek(0)-fcfirst();
863
#endif /* SHOPT_KIA */
864
pushlevel(lp,'$',mode);
865
mode = ST_DOL;
866
continue;
867
case S_PAR:
868
do_comsub:
869
wordflags |= ARG_MAC;
870
mode = oldmode(lp);
871
poplevel(lp);
872
fcseek(-LEN);
873
n = lp->digits;
874
wordflags |= comsub(lp,c);
875
lp->digits = n;
876
continue;
877
case S_RBRA:
878
if((n=endchar(lp)) == '$')
879
goto err;
880
if(mode!=ST_QUOTE || n==RBRACE)
881
{
882
mode = oldmode(lp);
883
poplevel(lp);
884
}
885
break;
886
case S_EDOL:
887
/* end $identifier */
888
#if SHOPT_KIA
889
if(lp->kiafile)
890
refvar(lp,0);
891
#endif /* SHOPT_KIA */
892
if(lp->lexd.warn && c==LBRACT && !lp->lex.intest && !lp->lexd.arith && oldmode(lp)!= ST_NESTED)
893
errormsg(SH_DICT,ERROR_warn(0),e_lexusebrace,shp->inlineno);
894
fcseek(-LEN);
895
mode = oldmode(lp);
896
poplevel(lp);
897
break;
898
case S_DOT:
899
/* make sure next character is alpha */
900
if(fcgetc(n)>0)
901
{
902
if(n=='.')
903
fcgetc(n);
904
if(n>0)
905
fcseek(-LEN);
906
}
907
if(isaletter(n) || n==LBRACT)
908
continue;
909
if(mode==ST_NAME)
910
{
911
if(n=='=')
912
continue;
913
break;
914
}
915
else if(n==RBRACE)
916
continue;
917
if(isastchar(n))
918
continue;
919
goto err;
920
case S_SPC1:
921
wordflags |= ARG_MAC;
922
if(endchar(lp)==RBRACE)
923
{
924
setchar(lp,c);
925
continue;
926
}
927
/* FALL THRU */
928
case S_ALP:
929
if(c=='.' && endchar(lp)=='$')
930
goto err;
931
case S_SPC2:
932
case S_DIG:
933
wordflags |= ARG_MAC;
934
switch(endchar(lp))
935
{
936
case '$':
937
if(n==S_ALP) /* $identifier */
938
mode = ST_DOLNAME;
939
else
940
{
941
mode = oldmode(lp);
942
poplevel(lp);
943
}
944
break;
945
#if SHOPT_TYPEDEF
946
case '@':
947
#endif /* SHOPT_TYPEDEF */
948
case '!':
949
if(n!=S_ALP)
950
goto dolerr;
951
case '#':
952
if(c=='#')
953
n = S_ALP;
954
case RBRACE:
955
if(n==S_ALP)
956
{
957
setchar(lp,RBRACE);
958
if(c=='.')
959
fcseek(-LEN);
960
mode = ST_BRACE;
961
}
962
else
963
{
964
if(fcgetc(c)>0)
965
fcseek(-LEN);
966
if(state[c]==S_ALP)
967
goto err;
968
if(n==S_DIG)
969
setchar(lp,'0');
970
else
971
setchar(lp,'!');
972
}
973
break;
974
case '0':
975
if(n==S_DIG)
976
break;
977
default:
978
goto dolerr;
979
}
980
break;
981
dolerr:
982
case S_ERR:
983
if((n=endchar(lp)) == '$')
984
goto err;
985
if(c=='*' || (n=sh_lexstates[ST_BRACE][c])!=S_MOD1 && n!=S_MOD2)
986
{
987
/* see whether inside `...` */
988
mode = oldmode(lp);
989
poplevel(lp);
990
if((n = endchar(lp)) != '`')
991
goto err;
992
pushlevel(lp,RBRACE,mode);
993
}
994
else
995
setchar(lp,RBRACE);
996
mode = ST_NESTED;
997
continue;
998
case S_MOD1:
999
if(oldmode(lp)==ST_QUOTE || oldmode(lp)==ST_NONE)
1000
{
1001
/* allow ' inside "${...}" */
1002
if(c==':' && fcgetc(n)>0)
1003
{
1004
n = state[n];
1005
fcseek(-LEN);
1006
}
1007
if(n==S_MOD1)
1008
{
1009
mode = ST_QUOTE;
1010
continue;
1011
}
1012
}
1013
/* FALL THRU */
1014
case S_MOD2:
1015
#if SHOPT_KIA
1016
if(lp->kiafile)
1017
refvar(lp,1);
1018
#endif /* SHOPT_KIA */
1019
if(c!=':' && fcgetc(n)>0)
1020
{
1021
if(n!=c)
1022
c = 0;
1023
if(!c || (fcgetc(n)>0))
1024
{
1025
fcseek(-LEN);
1026
if(n==LPAREN)
1027
{
1028
if(c!='%')
1029
{
1030
lp->token = n;
1031
sh_syntax(lp);
1032
}
1033
else if(lp->lexd.warn)
1034
errormsg(SH_DICT,ERROR_warn(0),e_lexquote,shp->inlineno,'%');
1035
}
1036
}
1037
}
1038
lp->lex.nestedbrace = 0;
1039
mode = ST_NESTED;
1040
continue;
1041
case S_LBRA:
1042
if((c=endchar(lp)) == '$')
1043
{
1044
if(fcgetc(c)>0)
1045
fcseek(-LEN);
1046
setchar(lp,RBRACE);
1047
if(state[c]!=S_ERR && c!=RBRACE)
1048
continue;
1049
if((n=sh_lexstates[ST_BEGIN][c])==0 || n==S_OP || n==S_NLTOK)
1050
{
1051
c = LBRACE;
1052
goto do_comsub;
1053
}
1054
}
1055
err:
1056
if(iswalpha(c))
1057
continue;
1058
n = endchar(lp);
1059
mode = oldmode(lp);
1060
poplevel(lp);
1061
if(n!='$')
1062
{
1063
lp->token = c;
1064
sh_syntax(lp);
1065
}
1066
else
1067
{
1068
if(lp->lexd.warn && c!='/' && sh_lexstates[ST_NORM][c]!=S_BREAK && (c!='"' || mode==ST_QUOTE))
1069
errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
1070
else if(c=='"' && mode!=ST_QUOTE && !ingrave)
1071
wordflags |= ARG_MESSAGE;
1072
fcseek(-LEN);
1073
}
1074
continue;
1075
case S_META:
1076
if(lp->lexd.warn && endchar(lp)==RBRACE && !lp->lexd.nested_tilde)
1077
errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
1078
continue;
1079
case S_PUSH:
1080
fcgetc(n);
1081
if(n==RPAREN)
1082
continue;
1083
else
1084
fcseek(-LEN);
1085
pushlevel(lp,RPAREN,mode);
1086
mode = ST_NESTED;
1087
continue;
1088
case S_POP:
1089
do_pop:
1090
if(c==RBRACE && mode==ST_NESTED && lp->lex.nestedbrace)
1091
{
1092
lp->lex.nestedbrace--;
1093
continue;
1094
}
1095
if(lp->lexd.level <= inlevel)
1096
break;
1097
if(lp->lexd.level==inlevel+1 && lp->lex.incase>=TEST_RE && !lp->lex.intest)
1098
{
1099
fcseek(-LEN);
1100
goto breakloop;
1101
}
1102
n = endchar(lp);
1103
if(c==RBRACT && !(n==RBRACT || n==RPAREN))
1104
continue;
1105
if((c==RBRACE||c==RPAREN) && n==RPAREN)
1106
{
1107
if(fcgetc(n)==LPAREN)
1108
{
1109
if(c!=RPAREN)
1110
fcseek(-LEN);
1111
continue;
1112
}
1113
if(n>0)
1114
fcseek(-LEN);
1115
n = RPAREN;
1116
}
1117
if(c==RBRACE)
1118
lp->lexd.nested_tilde = 0;
1119
if(c==';' && n!=';')
1120
{
1121
if(lp->lexd.warn && n==RBRACE)
1122
errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
1123
continue;
1124
}
1125
if(mode==ST_QNEST)
1126
{
1127
if(lp->lexd.warn)
1128
errormsg(SH_DICT,ERROR_warn(0),e_lexescape,shp->inlineno,c);
1129
continue;
1130
}
1131
mode = oldmode(lp);
1132
poplevel(lp);
1133
if(epatchar!='~')
1134
epatchar = '@';
1135
/* quotes in subscript need expansion */
1136
if(mode==ST_NAME && (wordflags&ARG_QUOTED))
1137
wordflags |= ARG_MAC;
1138
/* check for ((...)) */
1139
if(n==1 && c==RPAREN)
1140
{
1141
if(fcgetc(n)==RPAREN)
1142
{
1143
if(mode==ST_NONE && !lp->lexd.dolparen)
1144
goto breakloop;
1145
lp->lex.reservok = 1;
1146
lp->lex.skipword = 0;
1147
return(lp->token=EXPRSYM);
1148
}
1149
/* backward compatibility */
1150
{
1151
if(lp->lexd.warn)
1152
errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno);
1153
if(!(state=lp->lexd.first))
1154
state = fcfirst();
1155
else
1156
{
1157
n = state-fcseek(0);
1158
fcseek(n);
1159
}
1160
lp->lexd.paren = 1;
1161
}
1162
return(lp->token=LPAREN);
1163
}
1164
if(mode==ST_NONE)
1165
return(0);
1166
if(c!=n)
1167
{
1168
lp->token = c;
1169
sh_syntax(lp);
1170
}
1171
if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM))
1172
goto epat;
1173
continue;
1174
case S_EQ:
1175
assignment = lp->assignok;
1176
/* FALL THRU */
1177
case S_COLON:
1178
if(assignment)
1179
{
1180
if(fcgetc(c)=='~')
1181
wordflags |= ARG_MAC;
1182
else if(c!=LPAREN && assignment==SH_COMPASSIGN)
1183
assignment = 0;
1184
if(c!=EOF)
1185
fcseek(-LEN);
1186
}
1187
break;
1188
case S_LABEL:
1189
if(lp->lex.reservok && !lp->lex.incase)
1190
{
1191
c = fcget();
1192
fcseek(-LEN);
1193
if(state[c]==S_BREAK)
1194
{
1195
assignment = -1;
1196
goto breakloop;
1197
}
1198
}
1199
break;
1200
case S_BRACT:
1201
/* check for possible subscript */
1202
if((n=endchar(lp))==RBRACT || n==RPAREN ||
1203
(mode==ST_BRACE) ||
1204
(oldmode(lp)==ST_NONE) ||
1205
(mode==ST_NAME && (lp->assignok||lp->lexd.level)))
1206
{
1207
fcgetc(n);
1208
if(n>0 && n==']')
1209
{
1210
if(mode==ST_NAME)
1211
errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1, shp->inlineno, "[]", "empty subscript");
1212
if(!epatchar || epatchar=='%')
1213
continue;
1214
}
1215
else
1216
fcseek(-LEN);
1217
pushlevel(lp,RBRACT,mode);
1218
wordflags |= ARG_QUOTED;
1219
mode = ST_NESTED;
1220
continue;
1221
}
1222
wordflags |= ARG_EXP;
1223
break;
1224
case S_BRACE:
1225
{
1226
int isfirst;
1227
if(lp->lexd.dolparen)
1228
{
1229
if(mode==ST_BEGIN && (lp->lex.reservok||lp->comsub))
1230
{
1231
if(lp->comsub)
1232
return(lp->token=c);
1233
fcgetc(n);
1234
if(n>0)
1235
fcseek(-LEN);
1236
else
1237
n = '\n';
1238
if(n==RBRACT || sh_lexstates[ST_NORM][n])
1239
return(lp->token=c);
1240
}
1241
break;
1242
}
1243
else if(mode==ST_NESTED && endchar(lp)==RBRACE)
1244
{
1245
lp->lex.nestedbrace++;
1246
continue;
1247
}
1248
else if(mode==ST_BEGIN)
1249
{
1250
if(lp->comsub && c==RBRACE)
1251
return(lp->token=c);
1252
goto do_reg;
1253
}
1254
isfirst = (lp->lexd.first&&fcseek(0)==lp->lexd.first+1);
1255
fcgetc(n);
1256
/* check for {} */
1257
if(c==LBRACE && n==RBRACE)
1258
break;
1259
if(n>0)
1260
fcseek(-LEN);
1261
else if(lp->lex.reservok)
1262
break;
1263
/* check for reserved word { or } */
1264
if(lp->lex.reservok && state[n]==S_BREAK && isfirst)
1265
break;
1266
if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK
1267
&& !lp->lex.incase && !lp->lex.intest
1268
&& !lp->lex.skipword)
1269
{
1270
wordflags |= ARG_EXP;
1271
}
1272
if(c==RBRACE && n==LPAREN)
1273
goto epat;
1274
break;
1275
}
1276
case S_PAT:
1277
wordflags |= ARG_EXP;
1278
/* FALL THRU */
1279
case S_EPAT:
1280
epat:
1281
if(fcgetc(n)==LPAREN && c!='[')
1282
{
1283
epatchar = c;
1284
if(lp->lex.incase==TEST_RE)
1285
{
1286
lp->lex.incase++;
1287
pushlevel(lp,RPAREN,ST_NORM);
1288
mode = ST_NESTED;
1289
}
1290
wordflags |= ARG_EXP;
1291
pushlevel(lp,RPAREN,mode);
1292
mode = ST_NESTED;
1293
continue;
1294
}
1295
if(lp->lexd.warn && c=='[' && n=='^')
1296
errormsg(SH_DICT,ERROR_warn(0),e_lexcharclass,shp->inlineno);
1297
if(n>0)
1298
fcseek(-LEN);
1299
if(n=='=' && c=='+' && mode==ST_NAME)
1300
continue;
1301
break;
1302
}
1303
lp->comp_assign = 0;
1304
if(mode==ST_NAME)
1305
mode = ST_NORM;
1306
else if(mode==ST_NONE)
1307
return(0);
1308
}
1309
breakloop:
1310
if(lp->lexd.nocopy)
1311
{
1312
lp->lexd.balance = 0;
1313
return(0);
1314
}
1315
if(lp->lexd.dolparen)
1316
{
1317
lp->lexd.balance = 0;
1318
if(lp->lexd.docword)
1319
nested_here(lp);
1320
lp->lexd.message = (wordflags&ARG_MESSAGE);
1321
return(lp->token=0);
1322
}
1323
if(!(state=lp->lexd.first))
1324
state = fcfirst();
1325
n = fcseek(0)-(char*)state;
1326
if(!lp->arg)
1327
lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
1328
if(n>0)
1329
sfwrite(stkp,state,n);
1330
/* add balancing character if necessary */
1331
if(lp->lexd.balance)
1332
{
1333
sfputc(stkp,lp->lexd.balance);
1334
lp->lexd.balance = 0;
1335
}
1336
sfputc(stkp,0);
1337
stkseek(stkp,stktell(stkp)-1);
1338
state = stkptr(stkp,ARGVAL);
1339
n = stktell(stkp)-ARGVAL;
1340
lp->lexd.first=0;
1341
if(n==1)
1342
{
1343
/* check for numbered redirection */
1344
n = state[0];
1345
if((c=='<' || c=='>') && isadigit(n))
1346
{
1347
c = sh_lex(lp);
1348
lp->digits = (n-'0');
1349
return(c);
1350
}
1351
if(n==LBRACT)
1352
c = 0;
1353
else if(n==RBRACE && lp->comsub)
1354
return(lp->token=n);
1355
else if(n=='~')
1356
c = ARG_MAC;
1357
else
1358
c = (wordflags&ARG_EXP);
1359
n = 1;
1360
}
1361
else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND))
1362
{
1363
if(!strchr(state,','))
1364
{
1365
stkseek(stkp,stktell(stkp)-1);
1366
lp->arg = (struct argnod*)stkfreeze(stkp,1);
1367
return(lp->token=IOVNAME);
1368
}
1369
c = wordflags;
1370
}
1371
else
1372
c = wordflags;
1373
if(assignment<0)
1374
{
1375
stkseek(stkp,stktell(stkp)-1);
1376
lp->arg = (struct argnod*)stkfreeze(stkp,1);
1377
lp->lex.reservok = 1;
1378
return(lp->token=LABLSYM);
1379
}
1380
if(assignment || (lp->lex.intest&&!lp->lex.incase) || mode==ST_NONE)
1381
c &= ~ARG_EXP;
1382
if((c&ARG_EXP) && (c&ARG_QUOTED))
1383
c |= ARG_MAC;
1384
if(mode==ST_NONE)
1385
{
1386
/* eliminate trailing )) */
1387
stkseek(stkp,stktell(stkp)-2);
1388
}
1389
if(c&ARG_MESSAGE)
1390
{
1391
if(sh_isoption(SH_DICTIONARY))
1392
lp->arg = sh_endword(shp,2);
1393
c |= ARG_MAC;
1394
}
1395
if(c==0 || (c&(ARG_MAC|ARG_EXP|ARG_MESSAGE)))
1396
{
1397
lp->arg = (struct argnod*)stkfreeze(stkp,1);
1398
lp->arg->argflag = (c?c:ARG_RAW);
1399
}
1400
else if(mode==ST_NONE)
1401
lp->arg = sh_endword(shp,-1);
1402
else
1403
lp->arg = sh_endword(shp,0);
1404
state = lp->arg->argval;
1405
lp->comp_assign = assignment;
1406
if(assignment)
1407
lp->arg->argflag |= ARG_ASSIGN;
1408
else if(!lp->lex.skipword)
1409
lp->assignok = 0;
1410
lp->arg->argchn.cp = 0;
1411
lp->arg->argnxt.ap = 0;
1412
if(mode==ST_NONE)
1413
return(lp->token=EXPRSYM);
1414
if(lp->lex.intest)
1415
{
1416
if(lp->lex.testop1)
1417
{
1418
lp->lex.testop1 = 0;
1419
if(n==2 && state[0]=='-' && state[2]==0 &&
1420
strchr(test_opchars,state[1]))
1421
{
1422
if(lp->lexd.warn && state[1]=='a')
1423
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno);
1424
lp->digits = state[1];
1425
lp->token = TESTUNOP;
1426
}
1427
else if(n==1 && state[0]=='!' && state[1]==0)
1428
{
1429
lp->lex.testop1 = 1;
1430
lp->token = '!';
1431
}
1432
else
1433
{
1434
lp->lex.testop2 = 1;
1435
lp->token = 0;
1436
}
1437
return(lp->token);
1438
}
1439
lp->lex.incase = 0;
1440
c = sh_lookup(state,shtab_testops);
1441
switch(c)
1442
{
1443
case TEST_END:
1444
lp->lex.testop2 = lp->lex.intest = 0;
1445
lp->lex.reservok = 1;
1446
lp->token = ETESTSYM;
1447
return(lp->token);
1448
1449
case TEST_SEQ:
1450
if(lp->lexd.warn && state[1]==0)
1451
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno);
1452
/* FALL THRU */
1453
default:
1454
if(lp->lex.testop2)
1455
{
1456
if(lp->lexd.warn && (c&TEST_ARITH))
1457
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state);
1458
if(c&TEST_PATTERN)
1459
lp->lex.incase = 1;
1460
else if(c==TEST_REP)
1461
lp->lex.incase = TEST_RE;
1462
lp->lex.testop2 = 0;
1463
lp->digits = c;
1464
lp->token = TESTBINOP;
1465
return(lp->token);
1466
}
1467
1468
case TEST_OR: case TEST_AND:
1469
case 0:
1470
return(lp->token=0);
1471
}
1472
}
1473
if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2)
1474
{
1475
/* check for {, }, ! */
1476
c = state[0];
1477
if(n==1 && (c=='{' || c=='}' || c=='!'))
1478
{
1479
if(lp->lexd.warn && c=='{' && lp->lex.incase==2)
1480
errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno);
1481
if(lp->lex.incase==1 && c==RBRACE)
1482
lp->lex.incase = 0;
1483
return(lp->token=c);
1484
}
1485
else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT)
1486
{
1487
lp->lex.intest = lp->lex.testop1 = 1;
1488
lp->lex.testop2 = lp->lex.reservok = 0;
1489
return(lp->token=BTESTSYM);
1490
}
1491
}
1492
c = 0;
1493
if(!lp->lex.skipword)
1494
{
1495
if(n>1 && lp->lex.reservok==1 && mode==ST_NAME &&
1496
(c=sh_lookup(state,shtab_reserved)))
1497
{
1498
if(lp->lex.incase)
1499
{
1500
if(lp->lex.incase >1)
1501
lp->lex.incase = 1;
1502
else if(c==ESACSYM)
1503
lp->lex.incase = 0;
1504
else
1505
c = 0;
1506
}
1507
else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM)
1508
{
1509
lp->lex.skipword = 1;
1510
lp->lex.incase = 2*(c==CASESYM);
1511
}
1512
else
1513
lp->lex.skipword = 0;
1514
if(c==INSYM)
1515
lp->lex.reservok = 0;
1516
else if(c==TIMESYM)
1517
{
1518
/* yech - POSIX requires time -p */
1519
while(fcgetc(n)==' ' || n=='\t');
1520
if(n>0)
1521
fcseek(-LEN);
1522
if(n=='-')
1523
c=0;
1524
}
1525
return(lp->token=c);
1526
}
1527
if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok))
1528
{
1529
/* check for aliases */
1530
Namval_t* np;
1531
if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN &&
1532
(np=nv_search(state,shp->alias_tree,HASH_SCOPE))
1533
&& !nv_isattr(np,NV_NOEXPAND)
1534
#if KSHELL
1535
&& (lp->aliasok!=2 || nv_isattr(np,BLT_DCL))
1536
&& (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE))
1537
#endif /* KSHELL */
1538
&& (state=nv_getval(np)))
1539
{
1540
setupalias(lp,state,np);
1541
nv_onattr(np,NV_NOEXPAND);
1542
lp->lex.reservok = 1;
1543
lp->assignok |= lp->lex.reservok;
1544
return(sh_lex(lp));
1545
}
1546
}
1547
lp->lex.reservok = 0;
1548
}
1549
lp->lex.skipword = lp->lexd.docword = 0;
1550
return(lp->token=c);
1551
}
1552
1553
/*
1554
* read to end of command substitution
1555
*/
1556
static int comsub(register Lex_t *lp, int endtok)
1557
{
1558
register int n,c,count=1;
1559
register int line=lp->sh->inlineno;
1560
char *first,*cp=fcseek(0),word[5];
1561
int off, messages=0, assignok=lp->assignok, csub;
1562
struct lexstate save;
1563
save = lp->lex;
1564
csub = lp->comsub;
1565
sh_lexopen(lp,lp->sh,1);
1566
lp->lexd.dolparen++;
1567
lp->lex.incase=0;
1568
pushlevel(lp,0,0);
1569
lp->comsub = (endtok==LBRACE);
1570
if(first=lp->lexd.first)
1571
off = cp-first;
1572
else
1573
off = cp-fcfirst();
1574
if(off<0)
1575
c=*cp, *cp=0;
1576
n = sh_lex(lp);
1577
if(off<0)
1578
*cp = c;
1579
if(n==endtok || off<0)
1580
{
1581
if(endtok==LPAREN && lp->lexd.paren)
1582
{
1583
1584
if(first==lp->lexd.first)
1585
{
1586
n = cp+1-(char*)fcseek(0);
1587
fcseek(n);
1588
}
1589
count++;
1590
lp->lexd.paren = 0;
1591
fcgetc(c);
1592
}
1593
while(1)
1594
{
1595
/* look for case and esac */
1596
n=0;
1597
while(1)
1598
{
1599
fcgetc(c);
1600
/* skip leading white space */
1601
if(n==0 && !sh_lexstates[ST_BEGIN][c])
1602
continue;
1603
if(n==4)
1604
break;
1605
if(sh_lexstates[ST_NAME][c])
1606
goto skip;
1607
word[n++] = c;
1608
}
1609
if(sh_lexstates[ST_NAME][c]==S_BREAK)
1610
{
1611
if(memcmp(word,"case",4)==0)
1612
lp->lex.incase=1;
1613
else if(memcmp(word,"esac",4)==0)
1614
lp->lex.incase=0;
1615
}
1616
skip:
1617
if(c && (c!='#' || n==0))
1618
fcseek(-LEN);
1619
if(c==RBRACE && lp->lex.incase)
1620
lp->lex.incase=0;
1621
c=sh_lex(lp);
1622
switch(c)
1623
{
1624
case LBRACE:
1625
if(endtok==LBRACE && !lp->lex.incase)
1626
{
1627
lp->comsub = 0;
1628
count++;
1629
}
1630
break;
1631
case RBRACE:
1632
rbrace:
1633
if(endtok==LBRACE && --count<=0)
1634
goto done;
1635
if(count==1)
1636
lp->comsub = endtok==LBRACE;
1637
break;
1638
case IPROCSYM: case OPROCSYM:
1639
case LPAREN:
1640
if(endtok==LPAREN && !lp->lex.incase)
1641
count++;
1642
break;
1643
case RPAREN:
1644
if(lp->lex.incase)
1645
lp->lex.incase=0;
1646
else if(endtok==LPAREN && --count<=0)
1647
goto done;
1648
break;
1649
case EOFSYM:
1650
lp->lastline = line;
1651
lp->lasttok = endtok;
1652
sh_syntax(lp);
1653
case IOSEEKSYM:
1654
if(fcgetc(c)!='#' && c>0)
1655
fcseek(-LEN);
1656
break;
1657
case IODOCSYM:
1658
lp->lexd.docextra = 0;
1659
sh_lex(lp);
1660
break;
1661
case 0:
1662
lp->lex.reservok = 0;
1663
messages |= lp->lexd.message;
1664
break;
1665
case ';':
1666
do
1667
fcgetc(c);
1668
while(!sh_lexstates[ST_BEGIN][c]);
1669
if(c==RBRACE && endtok==LBRACE)
1670
goto rbrace;
1671
if(c>0)
1672
fcseek(-LEN);
1673
/* fall through*/
1674
default:
1675
lp->lex.reservok = 1;
1676
}
1677
}
1678
}
1679
done:
1680
poplevel(lp);
1681
lp->comsub = csub;
1682
lp->lastline = line;
1683
lp->lexd.dolparen--;
1684
lp->lex = save;
1685
lp->assignok = (endchar(lp)==RBRACT?assignok:0);
1686
if(lp->heredoc)
1687
errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,lp->sh->inlineno,lp->heredoc->ioname);
1688
return(messages);
1689
}
1690
1691
/*
1692
* here-doc nested in $(...)
1693
* allocate ionode with delimiter filled in without disturbing stak
1694
*/
1695
static void nested_here(register Lex_t *lp)
1696
{
1697
register struct ionod *iop;
1698
register int n=0,offset;
1699
struct argnod *arg = lp->arg;
1700
Stk_t *stkp = lp->sh->stk;
1701
char *base;
1702
if(offset=stktell(stkp))
1703
base = stkfreeze(stkp,0);
1704
if(lp->lexd.docend)
1705
n = fcseek(0)-lp->lexd.docend;
1706
iop = newof(0,struct ionod,1,lp->lexd.docextra+n+ARGVAL);
1707
iop->iolst = lp->heredoc;
1708
stkseek(stkp,ARGVAL);
1709
if(lp->lexd.docextra)
1710
{
1711
sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
1712
sfmove(lp->sh->strbuf,stkp,lp->lexd.docextra,-1);
1713
sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
1714
}
1715
sfwrite(stkp,lp->lexd.docend,n);
1716
lp->arg = sh_endword(lp->sh,0);
1717
iop->ioname = (char*)(iop+1);
1718
strcpy(iop->ioname,lp->arg->argval);
1719
iop->iofile = (IODOC|IORAW);
1720
if(lp->lexd.docword>1)
1721
iop->iofile |= IOSTRIP;
1722
lp->heredoc = iop;
1723
lp->arg = arg;
1724
lp->lexd.docword = 0;
1725
if(offset)
1726
stkset(stkp,base,offset);
1727
else
1728
stkseek(stkp,0);
1729
}
1730
1731
/*
1732
* skip to <close> character
1733
* if <copy> is non,zero, then the characters are copied to the stack
1734
* <state> is the initial lexical state
1735
*/
1736
void sh_lexskip(Lex_t *lp,int close, register int copy, int state)
1737
{
1738
register char *cp;
1739
lp->lexd.nest = close;
1740
lp->lexd.lex_state = state;
1741
lp->lexd.noarg = 1;
1742
if(copy)
1743
fcnotify(lex_advance,lp);
1744
else
1745
lp->lexd.nocopy++;
1746
sh_lex(lp);
1747
lp->lexd.noarg = 0;
1748
if(copy)
1749
{
1750
fcnotify(0,lp);
1751
if(!(cp=lp->lexd.first))
1752
cp = fcfirst();
1753
if((copy = fcseek(0)-cp) > 0)
1754
sfwrite(lp->sh->stk,cp,copy);
1755
}
1756
else
1757
lp->lexd.nocopy--;
1758
}
1759
1760
#if SHOPT_CRNL
1761
ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n)
1762
{
1763
const char *cp = (const char*)buff, *next=cp, *ep = cp + n;
1764
int m=0,k;
1765
while(next = (const char*)memchr(next,'\r',ep-next))
1766
if(*++next=='\n')
1767
{
1768
if(k=next-cp-1)
1769
{
1770
if((k=sfwrite(sp,cp,k)) < 0)
1771
return(m>0?m:-1);
1772
m += k;
1773
}
1774
cp = next;
1775
}
1776
if((k=sfwrite(sp,cp,ep-cp)) < 0)
1777
return(m>0?m:-1);
1778
return(m+k);
1779
}
1780
# define sfwrite _sfwrite
1781
#endif /* SHOPT_CRNL */
1782
1783
/*
1784
* read in here-document from script
1785
* quoted here documents, and here-documents without special chars are
1786
* noted with the IOQUOTE flag
1787
* returns 1 for complete here-doc, 0 for EOF
1788
*/
1789
1790
static int here_copy(Lex_t *lp,register struct ionod *iop)
1791
{
1792
register const char *state;
1793
register int c,n;
1794
register char *bufp,*cp;
1795
register Sfio_t *sp=lp->sh->heredocs, *funlog;
1796
int stripcol=0,stripflg, nsave, special=0;
1797
if(funlog=lp->sh->funlog)
1798
{
1799
if(fcfill()>0)
1800
fcseek(-LEN);
1801
lp->sh->funlog = 0;
1802
}
1803
if(iop->iolst)
1804
here_copy(lp,iop->iolst);
1805
iop->iooffset = sfseek(sp,(off_t)0,SEEK_END);
1806
iop->iosize = 0;
1807
iop->iodelim=iop->ioname;
1808
/* check for and strip quoted characters in delimiter string */
1809
if(stripflg=iop->iofile&IOSTRIP)
1810
{
1811
while(*iop->iodelim=='\t')
1812
iop->iodelim++;
1813
/* skip over leading tabs in document */
1814
if(iop->iofile&IOLSEEK)
1815
{
1816
iop->iofile &= ~IOLSEEK;
1817
while(fcgetc(c)=='\t' || c==' ')
1818
{
1819
if(c==' ')
1820
stripcol++;
1821
else
1822
stripcol += 8 - stripcol%8;
1823
}
1824
}
1825
else
1826
while(fcgetc(c)=='\t');
1827
if(c>0)
1828
fcseek(-LEN);
1829
}
1830
if(iop->iofile&IOQUOTE)
1831
state = sh_lexstates[ST_LIT];
1832
else
1833
state = sh_lexstates[ST_QUOTE];
1834
bufp = fcseek(0);
1835
n = S_NL;
1836
while(1)
1837
{
1838
if(n!=S_NL)
1839
{
1840
/* skip over regular characters */
1841
#if SHOPT_MULTIBYTE
1842
do
1843
{
1844
if(fcleft()< MB_LEN_MAX && mbsize(fcseek(0))<0)
1845
{
1846
n = S_EOF;
1847
LEN = -fcleft();
1848
break;
1849
}
1850
}
1851
#endif /* SHOPT_MULTIBYTE */
1852
1853
while((n=STATE(state,c))==0);
1854
}
1855
if(n==S_EOF || !(c=fcget()))
1856
{
1857
if(LEN < 0)
1858
c = fclast()-bufp;
1859
else
1860
c= (fcseek(0)-1)-bufp;
1861
if(!lp->lexd.dolparen && c)
1862
{
1863
if(n==S_ESC)
1864
c--;
1865
if(!lp->lexd.dolparen && (c=sfwrite(sp,bufp,c))>0)
1866
iop->iosize += c;
1867
}
1868
#if SHOPT_MULTIBYTE
1869
if(LEN==0)
1870
LEN=1;
1871
if(LEN < 0)
1872
{
1873
n = LEN;
1874
c = fcmbget(&LEN);
1875
LEN += n;
1876
}
1877
else
1878
#endif /* SHOPT_MULTIBYTE */
1879
c = lexfill(lp);
1880
if(c<0)
1881
break;
1882
if(n==S_ESC)
1883
{
1884
#if SHOPT_CRNL
1885
if(c=='\r' && (c=fcget())!=NL)
1886
fcseek(-LEN);
1887
#endif /* SHOPT_CRNL */
1888
if(c==NL)
1889
fcseek(1);
1890
else if(!lp->lexd.dolparen)
1891
{
1892
iop->iosize++;
1893
sfputc(sp,'\\');
1894
}
1895
}
1896
bufp = fcseek(-LEN);
1897
}
1898
else
1899
fcseek(-LEN);
1900
switch(n)
1901
{
1902
case S_NL:
1903
lp->sh->inlineno++;
1904
if((stripcol && c==' ') || (stripflg && c=='\t'))
1905
{
1906
if(!lp->lexd.dolparen)
1907
{
1908
/* write out line */
1909
n = fcseek(0)-bufp;
1910
if((n=sfwrite(sp,bufp,n))>0)
1911
iop->iosize += n;
1912
}
1913
/* skip over tabs */
1914
if(stripcol)
1915
{
1916
int col=0;
1917
do
1918
{
1919
fcgetc(c);
1920
if(c==' ')
1921
col++;
1922
else
1923
col += 8 - col%8;
1924
if(col>stripcol)
1925
break;
1926
}
1927
while (c==' ' || c=='\t');
1928
}
1929
else while(c=='\t')
1930
fcgetc(c);
1931
if(c<=0)
1932
goto done;
1933
bufp = fcseek(-LEN);
1934
}
1935
if(c!=iop->iodelim[0])
1936
break;
1937
cp = fcseek(0);
1938
nsave = n = 0;
1939
while(1)
1940
{
1941
if(!(c=fcget()))
1942
{
1943
if(!lp->lexd.dolparen && (c=cp-bufp))
1944
{
1945
if((c=sfwrite(sp,cp=bufp,c))>0)
1946
iop->iosize+=c;
1947
}
1948
nsave = n;
1949
if((c=lexfill(lp))<=0)
1950
{
1951
c = iop->iodelim[n]==0;
1952
goto done;
1953
}
1954
}
1955
#if SHOPT_CRNL
1956
if(c=='\r' && (c=fcget())!=NL)
1957
{
1958
if(c)
1959
fcseek(-LEN);
1960
c='\r';
1961
}
1962
#endif /* SHOPT_CRNL */
1963
if(c==NL)
1964
lp->sh->inlineno++;
1965
if(iop->iodelim[n]==0 && (c==NL||c==RPAREN))
1966
{
1967
if(!lp->lexd.dolparen && (n=cp-bufp))
1968
{
1969
if((n=sfwrite(sp,bufp,n))>0)
1970
iop->iosize += n;
1971
}
1972
lp->sh->inlineno--;
1973
if(c==RPAREN)
1974
fcseek(-LEN);
1975
goto done;
1976
}
1977
if(iop->iodelim[n++]!=c)
1978
{
1979
/*
1980
* The match for delimiter failed.
1981
* nsave>0 only when a buffer boundary
1982
* was crossed while checking the
1983
* delimiter
1984
*/
1985
if(!lp->lexd.dolparen && nsave>0)
1986
{
1987
if((n=sfwrite(sp,iop->iodelim,nsave))>0)
1988
iop->iosize += n;
1989
bufp = fcfirst();
1990
}
1991
if(c==NL)
1992
fcseek(-LEN);
1993
break;
1994
}
1995
}
1996
break;
1997
case S_ESC:
1998
n=1;
1999
#if SHOPT_CRNL
2000
if(c=='\r')
2001
{
2002
fcseek(1);
2003
if(c=fcget())
2004
fcseek(-LEN);
2005
if(c==NL)
2006
n=2;
2007
else
2008
{
2009
special++;
2010
break;
2011
}
2012
}
2013
#endif /* SHOPT_CRNL */
2014
if(c==NL)
2015
{
2016
/* new-line joining */
2017
lp->sh->inlineno++;
2018
if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>=0)
2019
{
2020
if(n && (n=sfwrite(sp,bufp,n))>0)
2021
iop->iosize += n;
2022
bufp = fcseek(0)+1;
2023
}
2024
}
2025
else
2026
special++;
2027
fcget();
2028
break;
2029
2030
case S_GRAVE:
2031
case S_DOL:
2032
special++;
2033
break;
2034
}
2035
n=0;
2036
}
2037
done:
2038
lp->sh->funlog = funlog;
2039
if(lp->lexd.dolparen)
2040
free((void*)iop);
2041
else if(!special)
2042
iop->iofile |= IOQUOTE;
2043
return(c);
2044
}
2045
2046
/*
2047
* generates string for given token
2048
*/
2049
static char *fmttoken(Lex_t *lp, register int sym, char *tok)
2050
{
2051
int n=1;
2052
if(sym < 0)
2053
return((char*)sh_translate(e_lexzerobyte));
2054
if(sym==0)
2055
return(lp->arg?lp->arg->argval:"?");
2056
if(lp->lex.intest && lp->arg && *lp->arg->argval)
2057
return(lp->arg->argval);
2058
if(sym&SYMRES)
2059
{
2060
register const Shtable_t *tp=shtab_reserved;
2061
while(tp->sh_number && tp->sh_number!=sym)
2062
tp++;
2063
return((char*)tp->sh_name);
2064
}
2065
if(sym==EOFSYM)
2066
return((char*)sh_translate(e_endoffile));
2067
if(sym==NL)
2068
return((char*)sh_translate(e_newline));
2069
tok[0] = sym;
2070
if(sym&SYMREP)
2071
tok[n++] = sym;
2072
else
2073
{
2074
switch(sym&SYMMASK)
2075
{
2076
case SYMAMP:
2077
sym = '&';
2078
break;
2079
case SYMPIPE:
2080
sym = '|';
2081
break;
2082
case SYMGT:
2083
sym = '>';
2084
break;
2085
case SYMLPAR:
2086
sym = LPAREN;
2087
break;
2088
case SYMSHARP:
2089
sym = '#';
2090
break;
2091
case SYMSEMI:
2092
if(tok[0]=='<')
2093
tok[n++] = '>';
2094
sym = ';';
2095
break;
2096
default:
2097
sym = 0;
2098
}
2099
tok[n++] = sym;
2100
}
2101
tok[n] = 0;
2102
return(tok);
2103
}
2104
2105
/*
2106
* print a bad syntax message
2107
*/
2108
2109
void sh_syntax(Lex_t *lp)
2110
{
2111
register Shell_t *shp = lp->sh;
2112
register const char *cp = sh_translate(e_unexpected);
2113
register char *tokstr;
2114
register int tok = lp->token;
2115
char tokbuf[3];
2116
Sfio_t *sp;
2117
if((tok==EOFSYM) && lp->lasttok)
2118
{
2119
tok = lp->lasttok;
2120
cp = sh_translate(e_unmatched);
2121
}
2122
else
2123
lp->lastline = shp->inlineno;
2124
tokstr = fmttoken(lp,tok,tokbuf);
2125
if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd])))
2126
{
2127
/* clear out any pending input */
2128
register Sfio_t *top;
2129
while(fcget()>0);
2130
fcclose();
2131
while(top=sfstack(sp,SF_POPSTACK))
2132
sfclose(top);
2133
}
2134
else
2135
fcclose();
2136
shp->inlineno = lp->inlineno;
2137
shp->st.firstline = lp->firstline;
2138
#if KSHELL
2139
if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE))
2140
#else
2141
if(shp->inlineno!=1)
2142
#endif
2143
errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp);
2144
else
2145
errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp);
2146
}
2147
2148
static char *stack_shift(Stk_t *stkp, register char *sp,char *dp)
2149
{
2150
register char *ep;
2151
register int offset = stktell(stkp);
2152
register int left = offset-(sp-stkptr(stkp,0));
2153
register int shift = (dp+1-sp);
2154
offset += shift;
2155
stkseek(stkp,offset);
2156
sp = stkptr(stkp,offset);
2157
ep = sp - shift;
2158
while(left--)
2159
*--sp = *--ep;
2160
return(sp);
2161
}
2162
2163
/*
2164
* Assumes that current word is unfrozen on top of the stak
2165
* If <mode> is zero, gets rid of quoting and consider argument as string
2166
* and returns pointer to frozen arg
2167
* If mode==1, just replace $"..." strings with international strings
2168
* The result is left on the stak
2169
* If mode==2, the each $"" string is printed on standard output
2170
*/
2171
struct argnod *sh_endword(Shell_t *shp,int mode)
2172
{
2173
register const char *state = sh_lexstates[ST_NESTED];
2174
register int n;
2175
register char *sp,*dp;
2176
register int inquote=0, inlit=0; /* set within quoted strings */
2177
struct argnod* argp=0;
2178
char *ep=0, *xp=0;
2179
int bracket=0;
2180
Stk_t *stkp=shp->stk;
2181
sfputc(stkp,0);
2182
sp = stkptr(stkp,ARGVAL);
2183
#if SHOPT_MULTIBYTE
2184
if(mbwide())
2185
{
2186
do
2187
{
2188
int len;
2189
switch(len = mbsize(sp))
2190
{
2191
case -1: /* illegal multi-byte char */
2192
case 0:
2193
case 1:
2194
n=state[*sp++];
2195
break;
2196
default:
2197
/*
2198
* None of the state tables contain
2199
* entries for multibyte characters,
2200
* however, they should be treated
2201
* the same as any other alph
2202
* character. Therefore, we'll use
2203
* the state of the 'a' character.
2204
*/
2205
n=state['a'];
2206
sp += len;
2207
}
2208
}
2209
while(n == 0);
2210
}
2211
else
2212
#endif /* SHOPT_MULTIBYTE */
2213
while((n=state[*sp++])==0);
2214
dp = sp;
2215
if(mode<0)
2216
inquote = 1;
2217
while(1)
2218
{
2219
switch(n)
2220
{
2221
case S_EOF:
2222
stkseek(stkp,dp-stkptr(stkp,0));
2223
if(mode<=0)
2224
{
2225
argp = (struct argnod*)stkfreeze(stkp,0);
2226
argp->argflag = ARG_RAW|ARG_QUOTED;
2227
}
2228
return(argp);
2229
case S_LIT:
2230
if(!(inquote&1))
2231
{
2232
inlit = !inlit;
2233
if(mode==0 || (mode<0 && bracket))
2234
{
2235
dp--;
2236
if(ep)
2237
{
2238
*dp = 0;
2239
stresc(ep);
2240
dp = ep+ strlen(ep);
2241
}
2242
ep = 0;
2243
}
2244
}
2245
break;
2246
case S_QUOTE:
2247
if(mode<0 && !bracket)
2248
break;
2249
if(!inlit)
2250
{
2251
if(mode<=0)
2252
dp--;
2253
inquote = inquote^1;
2254
if(ep)
2255
{
2256
char *msg;
2257
if(mode==2)
2258
{
2259
sfprintf(sfstdout,"%.*s\n",dp-ep,ep);
2260
ep = 0;
2261
break;
2262
}
2263
*--dp = 0;
2264
#if ERROR_VERSION >= 20000317L
2265
msg = ERROR_translate(0,error_info.id,0,ep);
2266
#else
2267
# if ERROR_VERSION >= 20000101L
2268
msg = ERROR_translate(error_info.id,ep);
2269
# else
2270
msg = ERROR_translate(ep,2);
2271
# endif
2272
#endif
2273
n = strlen(msg);
2274
dp = ep+n;
2275
if(sp-dp <= 1)
2276
{
2277
sp = stack_shift(stkp,sp,dp);
2278
dp = sp-1;
2279
ep = dp-n;
2280
}
2281
memmove(ep,msg,n);
2282
*dp++ = '"';
2283
}
2284
ep = 0;
2285
}
2286
break;
2287
case S_DOL: /* check for $'...' and $"..." */
2288
if(inlit)
2289
break;
2290
if(*sp==LPAREN || *sp==LBRACE)
2291
{
2292
inquote <<= 1;
2293
break;
2294
}
2295
if(inquote&1)
2296
break;
2297
if(*sp=='\'' || *sp=='"')
2298
{
2299
if(*sp=='"')
2300
inquote |= 1;
2301
else
2302
inlit = 1;
2303
sp++;
2304
if((mode==0||(mode<0&&bracket)) || (inquote&1))
2305
{
2306
if(mode==2)
2307
ep = dp++;
2308
else if(mode==1)
2309
(ep=dp)[-1] = '"';
2310
else
2311
ep = --dp;
2312
}
2313
}
2314
break;
2315
case S_ESC:
2316
#if SHOPT_CRNL
2317
if(*sp=='\r' && sp[1]=='\n')
2318
sp++;
2319
#endif /* SHOPT_CRNL */
2320
if(inlit || mode>0)
2321
{
2322
if(mode<0)
2323
{
2324
if(dp>=sp)
2325
{
2326
sp = stack_shift(stkp,sp,dp+1);
2327
dp = sp-2;
2328
}
2329
*dp++ = '\\';
2330
}
2331
if(ep)
2332
*dp++ = *sp++;
2333
break;
2334
}
2335
n = *sp;
2336
#if SHOPT_DOS
2337
if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0)
2338
break;
2339
#endif /* SHOPT_DOS */
2340
if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE))
2341
{
2342
if(n=='\n')
2343
dp--;
2344
else
2345
dp[-1] = n;
2346
sp++;
2347
}
2348
break;
2349
case S_POP:
2350
if(sp[-1]!=RBRACT)
2351
break;
2352
if(!inlit && !(inquote&1))
2353
{
2354
inquote >>= 1;
2355
if(xp)
2356
dp = sh_checkid(xp,dp);
2357
xp = 0;
2358
if(--bracket<=0 && mode<0)
2359
inquote = 1;
2360
}
2361
else if((inlit||inquote) && mode<0)
2362
{
2363
dp[-1] = '\\';
2364
if(dp>=sp)
2365
{
2366
sp = stack_shift(stkp,sp,dp);
2367
dp = sp-1;
2368
}
2369
*dp++ = ']';
2370
}
2371
break;
2372
case S_BRACT:
2373
if(dp[-2]=='.')
2374
xp = dp;
2375
if(mode<0)
2376
{
2377
if(inlit || (bracket&&inquote))
2378
{
2379
dp[-1] = '\\';
2380
if(dp>=sp)
2381
{
2382
sp = stack_shift(stkp,sp,dp);
2383
dp = sp-1;
2384
}
2385
*dp++ = '[';
2386
}
2387
else if(bracket++==0)
2388
inquote = 0;
2389
}
2390
break;
2391
}
2392
#if SHOPT_MULTIBYTE
2393
if(mbwide())
2394
{
2395
do
2396
{
2397
int len;
2398
switch(len = mbsize(sp))
2399
{
2400
case -1: /* illegal multi-byte char */
2401
case 0:
2402
case 1:
2403
n=state[*dp++ = *sp++];
2404
break;
2405
default:
2406
/*
2407
* None of the state tables contain
2408
* entries for multibyte characters,
2409
* however, they should be treated
2410
* the same as any other alph
2411
* character. Therefore, we'll use
2412
* the state of the 'a' character.
2413
*/
2414
while(len--)
2415
*dp++ = *sp++;
2416
n=state['a'];
2417
}
2418
}
2419
while(n == 0);
2420
}
2421
else
2422
#endif /* SHOPT_MULTIBYTE */
2423
while((n=state[*dp++ = *sp++])==0);
2424
}
2425
}
2426
2427
struct alias
2428
{
2429
Sfdisc_t disc;
2430
Namval_t *np;
2431
int nextc;
2432
int line;
2433
char buf[2];
2434
Lex_t *lp;
2435
};
2436
2437
/*
2438
* This code gets called whenever an end of string is found with alias
2439
*/
2440
2441
#ifndef SF_ATEXIT
2442
# define SF_ATEXIT 0
2443
#endif
2444
/*
2445
* This code gets called whenever an end of string is found with alias
2446
*/
2447
#ifdef SF_BUFCONST
2448
static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle)
2449
#else
2450
static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle)
2451
#endif
2452
{
2453
register struct alias *ap = (struct alias*)handle;
2454
register Namval_t *np;
2455
register Lex_t *lp;
2456
if(type==0 || type==SF_ATEXIT || !ap)
2457
return(0);
2458
lp = ap->lp;
2459
np = ap->np;
2460
if(type!=SF_READ)
2461
{
2462
if(type==SF_CLOSING)
2463
{
2464
register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC);
2465
if(dp!=handle)
2466
sfdisc(iop,dp);
2467
}
2468
else if(type==SF_FINAL)
2469
free((void*)ap);
2470
goto done;
2471
}
2472
if(ap->nextc)
2473
{
2474
/* if last character is a blank, then next work can be alias */
2475
register int c = fcpeek(-1);
2476
if(isblank(c))
2477
lp->aliasok = 1;
2478
*ap->buf = ap->nextc;
2479
ap->nextc = 0;
2480
sfsetbuf(iop,ap->buf,1);
2481
return(1);
2482
}
2483
done:
2484
if(np)
2485
nv_offattr(np,NV_NOEXPAND);
2486
return(0);
2487
}
2488
2489
2490
static void setupalias(Lex_t *lp, const char *string,Namval_t *np)
2491
{
2492
register Sfio_t *iop, *base;
2493
struct alias *ap = (struct alias*)malloc(sizeof(struct alias));
2494
ap->disc = alias_disc;
2495
ap->lp = lp;
2496
ap->buf[1] = 0;
2497
if(ap->np = np)
2498
{
2499
#if SHOPT_KIA
2500
if(lp->kiafile)
2501
{
2502
unsigned long r;
2503
r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,"");
2504
sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno);
2505
}
2506
#endif /* SHOPT_KIA */
2507
if((ap->nextc=fcget())==0)
2508
ap->nextc = ' ';
2509
}
2510
else
2511
ap->nextc = 0;
2512
iop = sfopen(NIL(Sfio_t*),(char*)string,"s");
2513
sfdisc(iop, &ap->disc);
2514
lp->lexd.nocopy++;
2515
if(!(base=fcfile()))
2516
base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
2517
fcclose();
2518
sfstack(base,iop);
2519
fcfopen(base);
2520
lp->lexd.nocopy--;
2521
}
2522
2523
/*
2524
* grow storage stack for nested constructs by STACK_ARRAY
2525
*/
2526
static int stack_grow(Lex_t *lp)
2527
{
2528
lp->lexd.lex_max += STACK_ARRAY;
2529
if(lp->lexd.lex_match)
2530
lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max);
2531
else
2532
lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY);
2533
return(lp->lexd.lex_match!=0);
2534
}
2535
2536
2537