blob: 79978b69d2b669b1d2db88ce5c14abf03cdfe000 [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +090015package kati
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090016
17import (
18 "bytes"
19 "errors"
20 "fmt"
21 "io"
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +090022 "regexp"
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +090023 "strconv"
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090024 "strings"
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +090025
26 "github.com/golang/glog"
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090027)
28
29var (
Fumitoshi Ukaicba36c92015-07-07 16:04:18 +090030 errEndOfInput = errors.New("unexpected end of input")
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +090031 errNotLiteral = errors.New("valueNum: not literal")
Fumitoshi Ukaicdf55a02015-07-07 16:07:01 +090032
33 errUnterminatedVariableReference = errors.New("*** unterminated variable reference.")
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090034)
35
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +090036type evalWriter interface {
37 io.Writer
38 writeWord([]byte)
39 writeWordString(string)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +090040 resetSep()
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +090041}
42
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090043// Value is an interface for value.
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090044type Value interface {
45 String() string
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +090046 Eval(w evalWriter, ev *Evaluator) error
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +090047 serialize() serializableVar
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090048 dump(d *dumpbuf)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090049}
50
51// literal is literal value.
52type literal string
53
54func (s literal) String() string { return string(s) }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +090055func (s literal) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai5541c7e2015-04-18 22:47:03 +090056 io.WriteString(w, string(s))
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090057 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090058}
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +090059func (s literal) serialize() serializableVar {
60 return serializableVar{Type: "literal", V: string(s)}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090061}
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090062func (s literal) dump(d *dumpbuf) {
63 d.Byte(valueTypeLiteral)
64 d.Bytes([]byte(s))
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090065}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090066
67// tmpval is temporary value.
68type tmpval []byte
69
70func (t tmpval) String() string { return string(t) }
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +090071func (t tmpval) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090072 w.Write(t)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090073 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090074}
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +090075func (t tmpval) Value() []byte { return []byte(t) }
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +090076func (t tmpval) serialize() serializableVar {
77 return serializableVar{Type: "tmpval", V: string(t)}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +090078}
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090079func (t tmpval) dump(d *dumpbuf) {
80 d.Byte(valueTypeTmpval)
81 d.Bytes(t)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +090082}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090083
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090084// expr is a list of values.
85type expr []Value
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090086
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +090087func (e expr) String() string {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090088 var s []string
89 for _, v := range e {
90 s = append(s, v.String())
91 }
92 return strings.Join(s, "")
93}
94
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +090095func (e expr) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +090096 for _, v := range e {
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +090097 w.resetSep()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +090098 err := v.Eval(w, ev)
99 if err != nil {
100 return err
101 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900102 }
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900103 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900104}
105
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900106func (e expr) serialize() serializableVar {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900107 r := serializableVar{Type: "expr"}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900108 for _, v := range e {
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900109 r.Children = append(r.Children, v.serialize())
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900110 }
111 return r
112}
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900113func (e expr) dump(d *dumpbuf) {
114 d.Byte(valueTypeExpr)
115 d.Int(len(e))
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900116 for _, v := range e {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900117 v.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900118 }
119}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900120
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900121func compactExpr(e expr) Value {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900122 if len(e) == 1 {
123 return e[0]
124 }
125 // TODO(ukai): concat literal
126 return e
127}
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900128func toExpr(v Value) expr {
Fumitoshi Ukai201df422015-07-07 17:31:05 +0900129 if v == nil {
130 return nil
131 }
Fumitoshi Ukaib97be672015-07-02 15:12:48 +0900132 if e, ok := v.(expr); ok {
133 return e
134 }
135 return expr{v}
136}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900137
138// varref is variable reference. e.g. ${foo}.
139type varref struct {
140 varname Value
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900141 paren byte
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900142}
143
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900144func (v *varref) String() string {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900145 varname := v.varname.String()
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900146 if len(varname) == 1 && v.paren == 0 {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900147 return fmt.Sprintf("$%s", varname)
148 }
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900149 paren := v.paren
150 if paren == 0 {
151 paren = '{'
152 }
153 return fmt.Sprintf("$%c%s%c", paren, varname, closeParen(paren))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900154}
155
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900156func (v *varref) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900157 te := traceEvent.begin("var", v, traceEventMain)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900158 buf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900159 err := v.varname.Eval(buf, ev)
160 if err != nil {
161 return err
162 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900163 vv := ev.LookupVar(buf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900164 buf.release()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900165 err = vv.Eval(w, ev)
166 if err != nil {
167 return err
168 }
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900169 traceEvent.end(te)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900170 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900171}
172
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900173func (v *varref) serialize() serializableVar {
174 return serializableVar{
Shinichiro Hamaji3d6d0aa2015-04-28 16:18:44 +0900175 Type: "varref",
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900176 V: string(v.paren),
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900177 Children: []serializableVar{v.varname.serialize()},
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900178 }
179}
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900180func (v *varref) dump(d *dumpbuf) {
181 d.Byte(valueTypeVarref)
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900182 d.Byte(v.paren)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900183 v.varname.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900184}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900185
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900186// paramref is parameter reference e.g. $1.
187type paramref int
188
189func (p paramref) String() string {
190 return fmt.Sprintf("$%d", int(p))
191}
192
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900193func (p paramref) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900194 te := traceEvent.begin("param", p, traceEventMain)
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900195 n := int(p)
196 if n < len(ev.paramVars) {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900197 err := ev.paramVars[n].Eval(w, ev)
198 if err != nil {
199 return err
200 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900201 } else {
Fumitoshi Ukaie16c2b72015-06-19 00:15:59 +0900202 vv := ev.LookupVar(fmt.Sprintf("%d", n))
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900203 err := vv.Eval(w, ev)
204 if err != nil {
205 return err
206 }
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900207 }
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900208 traceEvent.end(te)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900209 return nil
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900210}
211
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900212func (p paramref) serialize() serializableVar {
213 return serializableVar{Type: "paramref", V: strconv.Itoa(int(p))}
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900214}
215
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900216func (p paramref) dump(d *dumpbuf) {
217 d.Byte(valueTypeParamref)
218 d.Int(int(p))
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900219}
220
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900221// varsubst is variable substitutaion. e.g. ${var:pat=subst}.
222type varsubst struct {
223 varname Value
224 pat Value
225 subst Value
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900226 paren byte
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900227}
228
229func (v varsubst) String() string {
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900230 paren := v.paren
231 if paren == 0 {
232 paren = '{'
233 }
234 return fmt.Sprintf("$%c%s:%s=%s%c", paren, v.varname, v.pat, v.subst, closeParen(paren))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900235}
236
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900237func (v varsubst) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900238 te := traceEvent.begin("varsubst", v, traceEventMain)
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900239 buf := newEbuf()
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900240 params, err := ev.args(buf, v.varname, v.pat, v.subst)
241 if err != nil {
242 return err
243 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900244 vname := string(params[0])
245 pat := string(params[1])
246 subst := string(params[2])
247 buf.Reset()
248 vv := ev.LookupVar(vname)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900249 err = vv.Eval(buf, ev)
250 if err != nil {
251 return err
252 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900253 vals := splitSpaces(buf.String())
Fumitoshi Ukaia4a02252015-07-09 14:25:18 +0900254 buf.release()
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900255 space := false
256 for _, val := range vals {
257 if space {
Fumitoshi Ukai5541c7e2015-04-18 22:47:03 +0900258 io.WriteString(w, " ")
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900259 }
Fumitoshi Ukaib06cd9d2015-05-07 12:56:12 +0900260 io.WriteString(w, substRef(pat, subst, val))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900261 space = true
262 }
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900263 traceEvent.end(te)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900264 return nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900265}
266
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900267func (v varsubst) serialize() serializableVar {
268 return serializableVar{
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900269 Type: "varsubst",
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900270 V: string(v.paren),
Fumitoshi Ukaia045ccb2015-06-25 12:57:25 +0900271 Children: []serializableVar{
272 v.varname.serialize(),
273 v.pat.serialize(),
274 v.subst.serialize(),
Shinichiro Hamajic8bc7312015-04-28 02:48:03 +0900275 },
276 }
277}
278
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900279func (v varsubst) dump(d *dumpbuf) {
280 d.Byte(valueTypeVarsubst)
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900281 d.Byte(v.paren)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900282 v.varname.dump(d)
283 v.pat.dump(d)
284 v.subst.dump(d)
Shinichiro Hamaji723f56a2015-05-15 17:12:55 +0900285}
286
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900287func str(buf []byte, alloc bool) Value {
288 if alloc {
289 return literal(string(buf))
290 }
291 return tmpval(buf)
292}
293
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900294func appendStr(exp expr, buf []byte, alloc bool) expr {
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900295 if len(buf) == 0 {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900296 return exp
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900297 }
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900298 if len(exp) == 0 {
299 return append(exp, str(buf, alloc))
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900300 }
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900301 switch v := exp[len(exp)-1].(type) {
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900302 case literal:
303 v += literal(string(buf))
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900304 exp[len(exp)-1] = v
305 return exp
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900306 case tmpval:
307 v = append(v, buf...)
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900308 exp[len(exp)-1] = v
309 return exp
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900310 }
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900311 return append(exp, str(buf, alloc))
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900312}
313
314func valueNum(v Value) (int, error) {
315 switch v := v.(type) {
316 case literal, tmpval:
317 n, err := strconv.ParseInt(v.String(), 10, 64)
318 return int(n), err
319 }
320 return 0, errNotLiteral
321}
322
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900323type parseOp struct {
324 // alloc indicates text will be allocated as literal (string)
325 alloc bool
326
327 // matchParen matches parenthesis.
328 // note: required for func arg
329 matchParen bool
330}
331
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900332// parseExpr parses expression in `in` until it finds any byte in term.
333// if term is nil, it will parse to end of input.
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900334// if term is not nil, and it reaches to end of input, return error.
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900335// it returns parsed value, and parsed length `n`, so in[n-1] is any byte of
336// term, and in[n:] is next input.
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900337func parseExpr(in, term []byte, op parseOp) (Value, int, error) {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900338 var exp expr
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900339 b := 0
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900340 i := 0
341 var saveParen byte
342 parenDepth := 0
343Loop:
344 for i < len(in) {
345 ch := in[i]
Fumitoshi Ukai96c79f12015-04-18 22:58:13 +0900346 if term != nil && bytes.IndexByte(term, ch) >= 0 {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900347 break Loop
348 }
349 switch ch {
350 case '$':
351 if i+1 >= len(in) {
352 break Loop
353 }
354 if in[i+1] == '$' {
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900355 exp = appendStr(exp, in[b:i+1], op.alloc)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900356 i += 2
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900357 b = i
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900358 continue
359 }
360 if bytes.IndexByte(term, in[i+1]) >= 0 {
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900361 exp = appendStr(exp, in[b:i], op.alloc)
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900362 exp = append(exp, &varref{varname: literal("")})
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900363 i++
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900364 b = i
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900365 break Loop
366 }
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900367 exp = appendStr(exp, in[b:i], op.alloc)
368 v, n, err := parseDollar(in[i:], op.alloc)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900369 if err != nil {
370 return nil, 0, err
371 }
372 i += n
Fumitoshi Ukai00178d12015-04-18 00:11:05 +0900373 b = i
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900374 exp = append(exp, v)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900375 continue
376 case '(', '{':
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900377 if !op.matchParen {
378 break
379 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900380 cp := closeParen(ch)
381 if i := bytes.IndexByte(term, cp); i >= 0 {
382 parenDepth++
383 saveParen = cp
384 term[i] = 0
385 } else if cp == saveParen {
386 parenDepth++
387 }
388 case saveParen:
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900389 if !op.matchParen {
390 break
391 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900392 parenDepth--
393 if parenDepth == 0 {
394 i := bytes.IndexByte(term, 0)
395 term[i] = saveParen
396 saveParen = 0
397 }
398 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900399 i++
400 }
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900401 exp = appendStr(exp, in[b:i], op.alloc)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900402 if i == len(in) && term != nil {
Fumitoshi Ukai6450d0f2015-07-10 16:34:06 +0900403 glog.Warningf("parse: unexpected end of input: %q %d [%q]", in, i, term)
Fumitoshi Ukaicba36c92015-07-07 16:04:18 +0900404 return exp, i, errEndOfInput
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900405 }
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900406 return compactExpr(exp), i, nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900407}
408
409func closeParen(ch byte) byte {
410 switch ch {
411 case '(':
412 return ')'
413 case '{':
414 return '}'
415 }
416 return 0
417}
418
419// parseDollar parses
420// $(func expr[, expr...]) # func = literal SP
421// $(expr:expr=expr)
422// $(expr)
423// $x
424// it returns parsed value and parsed length.
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900425func parseDollar(in []byte, alloc bool) (Value, int, error) {
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900426 if len(in) <= 1 {
427 return nil, 0, errors.New("empty expr")
428 }
429 if in[0] != '$' {
430 return nil, 0, errors.New("should starts with $")
431 }
432 if in[1] == '$' {
433 return nil, 0, errors.New("should handle $$ as literal $")
434 }
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900435 oparen := in[1]
436 paren := closeParen(oparen)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900437 if paren == 0 {
438 // $x case.
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900439 if in[1] >= '0' && in[1] <= '9' {
440 return paramref(in[1] - '0'), 2, nil
441 }
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900442 return &varref{varname: str(in[1:2], alloc)}, 2, nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900443 }
444 term := []byte{paren, ':', ' '}
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900445 var varname expr
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900446 i := 2
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900447 op := parseOp{alloc: alloc}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900448Again:
449 for {
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900450 e, n, err := parseExpr(in[i:], term, op)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900451 if err != nil {
Fumitoshi Ukaicdf55a02015-07-07 16:07:01 +0900452 if err == errEndOfInput {
Fumitoshi Ukaif76eac82015-07-08 10:18:06 +0900453 // unmatched_paren2.mk
454 varname = append(varname, toExpr(e)...)
455 if len(varname) > 0 {
456 for i, vn := range varname {
457 if vr, ok := vn.(*varref); ok {
458 if vr.paren == oparen {
459 varname = varname[:i+1]
460 varname[i] = expr{literal(fmt.Sprintf("$%c", oparen)), vr.varname}
461 return &varref{varname: varname, paren: oparen}, i + 1 + n + 1, nil
462 }
463 }
464 }
465 }
Fumitoshi Ukaicdf55a02015-07-07 16:07:01 +0900466 return nil, 0, errUnterminatedVariableReference
467 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900468 return nil, 0, err
469 }
Fumitoshi Ukaif76eac82015-07-08 10:18:06 +0900470 varname = append(varname, toExpr(e)...)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900471 i += n
472 switch in[i] {
473 case paren:
474 // ${expr}
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900475 vname := compactExpr(varname)
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900476 n, err := valueNum(vname)
477 if err == nil {
478 // ${n}
479 return paramref(n), i + 1, nil
Fumitoshi Ukaif0a2ba72015-04-19 00:02:32 +0900480 }
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900481 return &varref{varname: vname, paren: oparen}, i + 1, nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900482 case ' ':
483 // ${e ...}
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900484 switch token := e.(type) {
485 case literal, tmpval:
486 funcName := intern(token.String())
Shinichiro Hamaji2216dd62015-04-11 13:44:39 +0900487 if f, ok := funcMap[funcName]; ok {
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900488 return parseFunc(f(), in, i+1, term[:1], funcName, op.alloc)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900489 }
490 }
491 term = term[:2] // drop ' '
492 continue Again
493 case ':':
494 // ${varname:...}
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900495 colon := in[i : i+1]
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900496 var vterm []byte
497 vterm = append(vterm, term[:2]...)
498 vterm[1] = '=' // term={paren, '='}.
499 e, n, err := parseExpr(in[i+1:], vterm, op)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900500 if err != nil {
501 return nil, 0, err
502 }
503 i += 1 + n
504 if in[i] == paren {
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900505 varname = appendStr(varname, colon, op.alloc)
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900506 return &varref{varname: varname, paren: oparen}, i + 1, nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900507 }
508 // ${varname:xx=...}
509 pat := e
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900510 subst, n, err := parseExpr(in[i+1:], term[:1], op)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900511 if err != nil {
512 return nil, 0, err
513 }
514 i += 1 + n
515 // ${first:pat=e}
516 return varsubst{
517 varname: compactExpr(varname),
518 pat: pat,
519 subst: subst,
Fumitoshi Ukaibbb0db52015-06-30 16:51:27 +0900520 paren: oparen,
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900521 }, i + 1, nil
522 default:
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900523 return nil, 0, fmt.Errorf("unexpected char %c at %d in %q", in[i], i, string(in))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900524 }
525 }
526}
527
528// skipSpaces skips spaces at front of `in` before any bytes in term.
529// in[n] will be the first non white space in in.
530func skipSpaces(in, term []byte) int {
531 for i := 0; i < len(in); i++ {
532 if bytes.IndexByte(term, in[i]) >= 0 {
533 return i
534 }
535 switch in[i] {
536 case ' ', '\t':
537 default:
538 return i
539 }
540 }
541 return len(in)
542}
543
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900544// trimLiteralSpace trims literal space around v.
545func trimLiteralSpace(v Value) Value {
546 switch v := v.(type) {
547 case literal:
548 return literal(strings.TrimSpace(string(v)))
549 case tmpval:
550 b := bytes.TrimSpace([]byte(v))
551 if len(b) == 0 {
552 return literal("")
553 }
554 return tmpval(b)
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900555 case expr:
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900556 if len(v) == 0 {
557 return v
558 }
559 switch s := v[0].(type) {
560 case literal, tmpval:
561 t := trimLiteralSpace(s)
562 if t == literal("") {
563 v = v[1:]
564 } else {
565 v[0] = t
566 }
567 }
568 switch s := v[len(v)-1].(type) {
569 case literal, tmpval:
570 t := trimLiteralSpace(s)
571 if t == literal("") {
572 v = v[:len(v)-1]
573 } else {
574 v[len(v)-1] = t
575 }
576 }
577 return compactExpr(v)
578 }
579 return v
580}
581
582// concatLine concatinates line with "\\\n" in function expression.
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900583// TODO(ukai): less alloc?
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900584func concatLine(v Value) Value {
585 switch v := v.(type) {
586 case literal:
587 for {
588 s := string(v)
589 i := strings.Index(s, "\\\n")
590 if i < 0 {
591 return v
592 }
593 v = literal(s[:i] + strings.TrimLeft(s[i+2:], " \t"))
594 }
595 case tmpval:
596 for {
597 b := []byte(v)
598 i := bytes.Index(b, []byte{'\\', '\n'})
599 if i < 0 {
600 return v
601 }
602 var buf bytes.Buffer
603 buf.Write(b[:i])
604 buf.Write(bytes.TrimLeft(b[i+2:], " \t"))
Fumitoshi Ukaid8d84252015-04-19 17:30:13 +0900605 v = tmpval(buf.Bytes())
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900606 }
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900607 case expr:
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900608 for i := range v {
609 switch vv := v[i].(type) {
610 case literal, tmpval:
611 v[i] = concatLine(vv)
612 }
613 }
614 return v
615 }
616 return v
617}
618
Fumitoshi Ukaiebf945c2015-04-10 17:30:04 +0900619// parseFunc parses function arguments from in[s:] for f.
Fumitoshi Ukaib2670d92015-04-16 10:28:27 +0900620// in[0] is '$' and in[s] is space just after func name.
Fumitoshi Ukaiebf945c2015-04-10 17:30:04 +0900621// in[:n] will be "${func args...}"
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900622func parseFunc(f mkFunc, in []byte, s int, term []byte, funcName string, alloc bool) (Value, int, error) {
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900623 f.AddArg(str(in[1:s-1], alloc))
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900624 arity := f.Arity()
625 term = append(term, ',')
Fumitoshi Ukaiebf945c2015-04-10 17:30:04 +0900626 i := skipSpaces(in[s:], term)
627 i = s + i
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900628 if i == len(in) {
629 return f, i, nil
630 }
631 narg := 1
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900632 op := parseOp{alloc: alloc, matchParen: true}
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900633 for {
634 if arity != 0 && narg >= arity {
635 // final arguments.
636 term = term[:1] // drop ','
637 }
Fumitoshi Ukaie9aa3802015-07-03 11:33:23 +0900638 v, n, err := parseExpr(in[i:], term, op)
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900639 if err != nil {
Fumitoshi Ukaicba36c92015-07-07 16:04:18 +0900640 if err == errEndOfInput {
641 return nil, 0, fmt.Errorf("*** unterminated call to function `%s': missing `)'.", funcName)
642 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900643 return nil, 0, err
644 }
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900645 v = concatLine(v)
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900646 // TODO(ukai): do this in funcIf, funcAnd, or funcOr's compactor?
Fumitoshi Ukaiee5c6fc2015-04-16 13:13:10 +0900647 if (narg == 1 && funcName == "if") || funcName == "and" || funcName == "or" {
648 v = trimLiteralSpace(v)
649 }
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900650 f.AddArg(v)
651 i += n
652 narg++
653 if in[i] == term[0] {
654 i++
655 break
656 }
657 i++ // should be ','
658 if i == len(in) {
659 break
660 }
661 }
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900662 var fv Value
663 fv = f
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900664 if compactor, ok := f.(compactor); ok {
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900665 fv = compactor.Compact()
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900666 }
Fumitoshi Ukai744bb2b2015-06-25 00:10:52 +0900667 if EvalStatsFlag || traceEvent.enabled() {
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +0900668 fv = funcstats{
669 Value: fv,
670 str: fv.String(),
671 }
672
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900673 }
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900674 return fv, i, nil
Fumitoshi Ukaib36f3872015-04-10 15:06:38 +0900675}
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900676
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900677type compactor interface {
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900678 Compact() Value
Fumitoshi Ukaida7f2552015-04-16 13:33:37 +0900679}
680
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900681type funcstats struct {
Fumitoshi Ukai9f6b6352015-04-16 16:25:09 +0900682 Value
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +0900683 str string
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900684}
685
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900686func (f funcstats) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900687 te := traceEvent.begin("func", literal(f.str), traceEventMain)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900688 err := f.Value.Eval(w, ev)
689 if err != nil {
690 return err
691 }
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900692 // TODO(ukai): per functype?
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900693 traceEvent.end(te)
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900694 return nil
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900695}
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900696
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900697type matcherValue struct{}
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900698
Fumitoshi Ukaib44b12d2015-07-07 14:19:32 +0900699func (m matcherValue) Eval(w evalWriter, ev *Evaluator) error {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900700 return fmt.Errorf("couldn't eval matcher")
701}
702func (m matcherValue) serialize() serializableVar {
703 return serializableVar{Type: ""}
704}
705
706func (m matcherValue) dump(d *dumpbuf) {
707 d.err = fmt.Errorf("couldn't dump matcher")
708}
709
710type matchVarref struct{ matcherValue }
711
712func (m matchVarref) String() string { return "$(match-any)" }
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900713
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900714type literalRE struct {
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900715 matcherValue
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900716 *regexp.Regexp
717}
718
719func mustLiteralRE(s string) literalRE {
720 return literalRE{
721 Regexp: regexp.MustCompile(s),
722 }
723}
724
Fumitoshi Ukai65c72332015-06-26 21:32:50 +0900725func (r literalRE) String() string { return r.Regexp.String() }
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900726
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900727func matchValue(exp, pat Value) bool {
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900728 switch pat := pat.(type) {
729 case literal:
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900730 return literal(exp.String()) == pat
Fumitoshi Ukai7c9aa9f2015-06-12 23:51:38 +0900731 }
732 // TODO: other type match?
733 return false
734}
735
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900736func matchExpr(exp, pat expr) ([]Value, bool) {
737 if len(exp) != len(pat) {
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900738 return nil, false
739 }
740 var mv matchVarref
741 var matches []Value
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900742 for i := range exp {
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900743 if pat[i] == mv {
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900744 switch exp[i].(type) {
Fumitoshi Ukaib8acae92015-06-18 15:36:57 +0900745 case paramref, *varref:
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900746 matches = append(matches, exp[i])
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900747 continue
748 }
749 return nil, false
750 }
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900751 if patre, ok := pat[i].(literalRE); ok {
752 re := patre.Regexp
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900753 m := re.FindStringSubmatch(exp[i].String())
Fumitoshi Ukai44ae8cf2015-06-24 16:44:15 +0900754 if m == nil {
755 return nil, false
756 }
757 for _, sm := range m[1:] {
758 matches = append(matches, literal(sm))
759 }
760 continue
761 }
Fumitoshi Ukai55c8fa92015-06-25 15:56:10 +0900762 if !matchValue(exp[i], pat[i]) {
Fumitoshi Ukai4a708512015-06-11 17:15:49 +0900763 return nil, false
764 }
765 }
766 return matches, true
767}