mwg_pp.awk (47942B)
1 #!/usr/bin/gawk -f 2 3 # 20120726 行番号出力機能 (例: '#line 12 a.cpp') 4 5 function awk_getfiledir(_ret) { 6 _ret = m_lineno_cfile; 7 sub(/[^\/\\]+$/, "", _ret); 8 if (_ret == "/") return "/"; 9 sub(/[\/\\]$/, "", _ret); 10 return _ret; 11 } 12 13 function print_error(title, msg) { 14 global_errorCount++; 15 print "\33[1;31m" title "!\33[m " msg > "/dev/stderr"; 16 } 17 18 function trim(text) { 19 #gsub(/^[ \t]+|[ \t]+$/, "", text); 20 gsub(/^[[:space:]]+|[[:space:]]+$/, "", text); 21 return text; 22 } 23 24 function slice(text, start, end, _l) { 25 _l = length(text); 26 if (start < 0) start += _l; 27 end = end == null ? _l : end < 0 ? end + _l : end; 28 29 return substr(text, start + 1, end - start); 30 } 31 32 #function head_token(text, ret, _, _i, _l) { 33 # _i = match(text, /[^-a-zA-Z:0-9_]/); 34 # _l = _i ? _i - 1 : length(text); 35 # ret[0] = trim(substr(text, 1, _l)); 36 # ret[1] = trim(substr(text, _l + 1)); 37 #} 38 39 #------------------------------------------------------------------------------- 40 function unescape(text, _, _ret, _capt) { 41 _ret = ""; 42 while (match(text, /\\(.)/, _capt) > 0) { 43 _ret = _ret substr(text, 1, RSTART - 1) _capt[1]; 44 text = substr(text, RSTART + RLENGTH); 45 } 46 return _ret text; 47 } 48 49 #------------------------------------------------------------------------------- 50 # replace 51 function replace(text, before, after, _is_tmpl, _is_head, _captures, _rep, _ltext, _rtext) { 52 _is_tmpl = (match(after, /\$[0-9]+/) > 0); 53 _is_head = (substr(before, 1, 1) == "^"); 54 55 _ret = ""; 56 while (match(text, before, _captures) > 0) { 57 _ltext = substr(text, 1, RSTART - 1); 58 _rtext = substr(text, RSTART + RLENGTH); 59 60 _rep = _is_tmpl ? rep_instantiate_tmpl(after, _captures) : after; 61 62 _ret = _ret _ltext _rep; 63 text = _rtext; 64 65 if (_is_head) break; 66 if (RLENGTH == 0) { 67 _ret = _ret substr(text, 1, 1); 68 text = substr(text, 2); 69 if (length(text) == 0) break; 70 } 71 } 72 return _ret text; 73 } 74 function rep_instantiate_tmpl(text, captures, _, _ret, _num, _insert) { 75 _ret = ""; 76 while (match(text, /\\(.)|\$([0-9]+)/, _num)) { 77 #print "dbg: $ captured: RSTART = " RSTART "; num = " _num[1] "; captures[num] = " captures[_num[1]] > "/dev/stderr" 78 if (_num[2] != "") { 79 _insert = captures[_num[2]]; 80 } else if (_num[1] ~ /^[$\\]$/) { 81 _insert = _num[1]; 82 } else { 83 _insert = _num[0]; 84 } 85 _ret = _ret substr(text, 1, RSTART - 1) _insert; 86 text = substr(text, RSTART + RLENGTH); 87 } 88 return _ret text; 89 } 90 91 #=============================================================================== 92 # mwg_pp.eval 93 #------------------------------------------------------------------------------- 94 # function eval_expr(expression); 95 96 # -*- mode:awk -*- 97 98 function ev1scan_init_opregister(opname, optype, opprec) { 99 ev_db_operator[opname] = optype; 100 ev_db_operator[opname, "a"] = opprec; 101 } 102 103 function ev1scan_init() { 104 OP_BIN = 1; 105 OP_UNA = 2; # prefix 106 OP_SGN = 3; # prefix or binary 107 OP_INC = 4; # prefix or suffix 108 109 ev1scan_init_opregister("." , OP_BIN, 12.0); 110 111 ev1scan_init_opregister("++", OP_INC, 11.0); 112 ev1scan_init_opregister("--", OP_INC, 11.0); 113 ev1scan_init_opregister("!" , OP_UNA, 11.0); 114 115 ev1scan_init_opregister("*" , OP_BIN, 10.0); 116 ev1scan_init_opregister("/" , OP_BIN, 10.0); 117 ev1scan_init_opregister("%" , OP_BIN, 10.0); 118 119 ev1scan_init_opregister("+" , OP_SGN, 9.0); 120 ev1scan_init_opregister("-" , OP_SGN, 9.0); 121 122 ev1scan_init_opregister("==", OP_BIN, 8.0); 123 ev1scan_init_opregister("!=", OP_BIN, 8.0); 124 ev1scan_init_opregister("<" , OP_BIN, 8.0); 125 ev1scan_init_opregister("<=", OP_BIN, 8.0); 126 ev1scan_init_opregister(">" , OP_BIN, 8.0); 127 ev1scan_init_opregister(">=", OP_BIN, 8.0); 128 129 ev1scan_init_opregister("&" , OP_BIN, 7.4); 130 ev1scan_init_opregister("^" , OP_BIN, 7.2); 131 ev1scan_init_opregister("|" , OP_BIN, 7.0); 132 ev1scan_init_opregister("&&", OP_BIN, 6.4); 133 ev1scan_init_opregister("||", OP_BIN, 6.0); 134 135 ev1scan_init_opregister("=" , OP_BIN, 2.0); 136 ev1scan_init_opregister("+=", OP_BIN, 2.0); 137 ev1scan_init_opregister("-=", OP_BIN, 2.0); 138 ev1scan_init_opregister("*=", OP_BIN, 2.0); 139 ev1scan_init_opregister("/=", OP_BIN, 2.0); 140 ev1scan_init_opregister("%=", OP_BIN, 2.0); 141 ev1scan_init_opregister("|=", OP_BIN, 2.0); 142 ev1scan_init_opregister("^=", OP_BIN, 2.0); 143 ev1scan_init_opregister("&=", OP_BIN, 2.0); 144 ev1scan_init_opregister("," , OP_BIN, 1.0); 145 146 # for ev2 147 SE_VALU = 1; 148 SE_PREF = 0; 149 SE_MARK = -1; 150 151 ATTR_SET = "t"; 152 ATTR_TYP = "T"; 153 ATTR_MOD = "M"; 154 155 MOD_NUL = 0; 156 MOD_REF = 1; 157 ATTR_REF = "R"; 158 MOD_ARG = 2; 159 MOD_ARR = 4; 160 MOD_MTH = 8; 161 ATTR_MTH_OBJ = "Mo"; 162 ATTR_MTH_MEM = "Mf"; 163 164 TYPE_NUM = 0; 165 TYPE_STR = 1; 166 } 167 168 function ev1scan_scan(expression, words, _wlen, _i, _len, _c, _t, _w) { 169 _wlen = 0; 170 _len = length(expression); 171 for (_i = 0; _i < _len; _i++) { 172 _c = substr(expression, _i + 1, 1); 173 174 if (_c ~ /[.0-9]/) { 175 _t = "n"; 176 _w = _c; 177 while (_i + 1 < _len) { 178 _c = substr(expression, _i + 2, 1); 179 if (_c !~ /[.0-9]/) break; 180 _w = _w _c; 181 _i++; 182 } 183 #if (_w == ".")_w = 0; 184 if (_w == ".") { 185 _t = "o"; 186 } 187 } else if (ev_db_operator[_c] != "") { 188 _t = "o"; 189 _w = _c; 190 while (_i + 1 < _len) { 191 _c = substr(expression, _i + 2, 1); 192 #print "dbg: ev_db_op[" _w _c "] = " ev_db_operator[_w _c] > "/dev/stderr" 193 if (ev_db_operator[_w _c] != "") { 194 _w = _w _c; 195 _i++; 196 } else break; 197 } 198 } else if (_c ~ "[[({?]") { 199 _t = "op"; 200 _w = _c; 201 } else if (_c ~ "[])}:]") { 202 _t = "cl"; 203 _w = _c; 204 } else if (_c ~ /[_a-zA-Z]/) { 205 _t = "w"; 206 _w = _c; 207 while (_i + 1 < _len) { 208 _c = substr(expression, _i + 2, 1); 209 if (_c !~ /[_a-zA-Z0-9]/) break; 210 _w = _w _c; 211 _i++; 212 } 213 } else if (_c == "\"") { 214 # string literal 215 _t = "S"; 216 _w = ""; 217 while (_i + 1 < _len) { 218 _c = substr(expression, _i + 2, 1); 219 _i++; 220 if (_c == "\"") { 221 break; 222 } else if (_c == "\\") { 223 #print_error("dbg: (escchar = " _c " " substr(expression, _i + 2, 1) ")" ); 224 if (_i + 1 < _len) { 225 _w = _w ev1scan_scan_escchar(substr(expression, _i + 2, 1)); 226 _i++; 227 } else { 228 _w = _w _c; 229 } 230 } else { 231 _w = _w _c; 232 } 233 } 234 } else if (_c ~ /[[:space:]]/) { 235 continue; # ignore blank 236 } else { 237 print_error("mwg_pp.eval_expr", "unrecognizable character '" _c "'"); 238 continue; # ignore unknown character 239 } 240 241 words[_wlen, "t"] = _t; 242 words[_wlen, "w"] = _w; 243 _wlen++; 244 } 245 246 # debug 247 #for (_i = 0; _i < _wlen; _i++) { 248 # print "yield " words[_i, "w"] " as " words[_i, "t"] > "/dev/stderr" 249 #} 250 251 return _wlen; 252 } 253 254 function ev1scan_scan_escchar(c) { 255 if (c !~ /[nrtvfaeb]/) return c; 256 if (c == "n") return "\n"; 257 if (c == "r") return "\r"; 258 if (c == "t") return "\t"; 259 if (c == "v") return "\v"; 260 if (c == "f") return "\f"; 261 if (c == "a") return "\a"; 262 if (c == "e") return "\33"; 263 if (c == "b") return "\b"; 264 return c; 265 } 266 267 function ev1scan_cast_bool(arg) { 268 return arg != 0 && arg != ""; 269 } 270 # -*- mode: awk -*- 271 272 function eval_expr(expression) { 273 return ev2_expr(expression); 274 } 275 276 function ev2_expr(expression, _wlen, _words, _i, _len, _t, _w, _v, _sp, _s, _sp1, _optype) { 277 _wlen = ev1scan_scan(expression, _words); 278 279 # <param name="_s"> 280 # parsing stack 281 # _s[index, "t"] : SE_PREF SE_MARK SE_VALU 282 # _s[index] : lhs value 283 # _s[index, "T"] : dataType dataType 284 # _s[index, "c"] : b+ u! op 285 # _s[index, "l"] : assoc 286 # 287 # _s[index, "M"] = MOD_ARG; 288 # _s[index, "A"] = length; 289 # _s[index, "A", i] = element; 290 # </param> 291 292 # parse 293 _sp = -1; 294 for (_i = 0; _i < _wlen; _i++) { 295 # _t: token type 296 # _w: token word 297 # _l: token prefix level 298 _t = _words[_i, "t"]; 299 _w = _words[_i, "w"]; 300 301 #-- process token -- 302 if (_t == "n") { 303 _sp++; 304 _s[_sp] = 0 + _w; 305 _s[_sp, "t"] = SE_VALU; 306 _s[_sp, "T"] = TYPE_NUM; 307 _s[_sp, "M"] = MOD_NUL; 308 #--------------------------------------------------------------------------- 309 } else if (_t == "o") { 310 _optype = ev_db_operator[_w]; 311 if (_optype == OP_SGN) { # signature operator +- 312 if (_sp >= 0 && _s[_sp, "t"] == SE_VALU) { 313 _t = "b"; # binary operator 314 } else { 315 _t = "u"; # unary operator 316 } 317 } else if (_optype == OP_BIN) { # binary operator 318 _t = "b"; 319 } else if (_optype == OP_UNA) { # unary prefix operator 320 _t = "u"; 321 } else if (_optype == OP_INC) { # operator++ -- 322 if (_sp >= 0 && _s[_sp, "t"] == SE_VALU) { 323 if (and(_s[_sp, "M"], MOD_REF)) { 324 if (_w == "++") 325 d_data[_s[_sp, "R"]]++; 326 else if (_w == "--") 327 d_data[_s[_sp, "R"]]--; 328 else 329 print_error("mwg_pp.eval", "unknown increment operator " _w); 330 331 _s[_sp, "M"] = MOD_NUL; 332 delete _s[_sp, "R"]; 333 } 334 335 _t = ""; 336 } else { 337 _t = "u"; # unary operator 338 } 339 } else { 340 print_error("mwg_pp.eval", "unknown operator " _w); 341 } 342 343 if (_t == "b") { 344 #-- binary operator 345 _l = ev_db_operator[_w, "a"]; 346 #print "dbg: binary operator level = " _l > "/dev/stderr" 347 348 # get lhs 349 _sp = ev2_pop_value(_s, _sp, _l); # left assoc 350 #_sp = ev2_pop_value(_s, _sp, _l + 0.1); # right assoc # TODO = 351 352 # overwrite to lhs 353 _s[_sp, "t"] = SE_PREF; 354 _s[_sp, "p"] = "b"; 355 _s[_sp, "P"] = _w; 356 _s[_sp, "l"] = _l; # assoc level 357 } else if (_t == "u") { 358 # unary operator 359 _l = ev_db_operator[_w, "a"]; 360 361 _sp++; 362 _s[_sp, "t"] = SE_PREF 363 _s[_sp, "p"] = "u"; 364 _s[_sp, "P"] = _w; 365 _s[_sp, "l"] = _l; # assoc level 366 } 367 #--------------------------------------------------------------------------- 368 } else if (_t == "op") { 369 _sp++; 370 _s[_sp, "t"] = SE_MARK; 371 _s[_sp, "m"] = _w; 372 } else if (_t == "cl") { 373 if (_sp >= 0 && _s[_sp, "t"] == SE_VALU) { 374 _sp1 = ev2_pop_value(_s, _sp, 0); 375 _sp = _sp1-1; 376 } else { 377 # empty arg 378 _sp1 = _sp+1; 379 _s[_sp1] = ""; 380 _s[_sp1, "t"] = SE_VALU; 381 _s[_sp1, "T"] = TYPE_STR; 382 _s[_sp1, "M"] = MOD_ARG; 383 _s[_sp1, "A"] = 0; 384 } 385 # state: [.. _sp=open _sp1] 386 387 # parentheses 388 if (!(_sp >= 0 && _s[_sp, "t"] == SE_MARK)) { 389 print_error("mwg_pp.eval: no matching open paren to " _w " in " expression); 390 continue; 391 } 392 _w = _s[_sp, "m"] _w; 393 _sp--; 394 395 396 # state: [_sp open _sp1] 397 if (_sp >= 0 && _s[_sp, "t"] == SE_VALU) { 398 if (_w == "?:") { 399 _sp = ev2_pop_value(_s, _sp, 3.0); # assoc_value_3 400 _v = (_s[_sp] != 0 && _s[_sp] != "") ? "T" : "F"; 401 #print_error("dbg: _s[_sp]=" _s[_sp] " _v=" _v); 402 403 # last element 404 _s[_sp] = _s[_sp1]; 405 _s[_sp, "t"] = SE_VALU; 406 _s[_sp, "T"] = _s[_sp1, "T"]; 407 _s[_sp, "M"] = MOD_NUL; #TODO reference copy 408 409 # overwrite pref 410 _s[_sp, "t"] = SE_PREF; 411 _s[_sp, "p"] = _w; 412 _s[_sp, "P"] = _v; 413 _s[_sp, "l"] = 3.0; # level 414 } else { 415 _sp = ev2_pop_value(_s, _sp, 12); # assoc_value_12 416 417 if (_w == "[]" && and(_s[_sp, "M"], MOD_REF)) { 418 # indexing 419 _s[_sp] = d_data[_s[_sp, "R"], _s[_sp1]]; 420 _s[_sp, "t"] = SE_VALU; 421 _s[_sp, "T"] = (_s[_sp] == 0 + _s[_sp]? TYPE_NUM: TYPE_STR); 422 _s[_sp, "M"] = MOD_REF; 423 _s[_sp, "R"] = _s[_sp, "R"] SUBSEP _s[_sp1]; 424 } else if (and(_s[_sp, "M"], MOD_REF)) { 425 # function call 426 ev2_funcall(_s, _sp, _s[_sp, "R"], _s, _sp1); 427 } else if (and(_s[_sp, "M"], MOD_MTH)) { 428 # member function call 429 ev2_memcall(_s, _sp, _s, _sp SUBSEP ATTR_MTH_OBJ, _s[_sp, ATTR_MTH_MEM], _s, _sp1); 430 } else { 431 print "mwg_pp.eval: invalid function call " _s[_sp] " " _w " in " expression > "/dev/stderr" 432 } 433 } 434 } else { 435 _sp++; 436 if (_w == "[]") { 437 # array 438 ev2_copy(_s, _sp, _s, _sp1); 439 _s[_sp, "M"] = MOD_ARR; 440 } else { 441 # last element 442 _s[_sp] = _s[_sp1]; 443 _s[_sp, "t"] = SE_VALU; 444 _s[_sp, "T"] = _s[_sp1, "T"]; 445 _s[_sp, "M"] = MOD_NUL; 446 } 447 } 448 #--------------------------------------------------------------------------- 449 } else if (_t == "w") { 450 _sp++; 451 _s[_sp] = d_data[_w]; 452 _s[_sp, "t"] = SE_VALU; 453 _s[_sp, "T"] = (_s[_sp] == 0 + _s[_sp]? TYPE_NUM: TYPE_STR); 454 _s[_sp, "M"] = MOD_REF; 455 _s[_sp, "R"] = _w; 456 } else if (_t == "S") { 457 # string 458 _sp++; 459 _s[_sp] = _w; 460 _s[_sp, "t"] = SE_VALU; 461 _s[_sp, "T"] = TYPE_STR; 462 _s[_sp, "M"] = MOD_NUL; 463 } else { 464 print_error("mwg_pp.eval:fatal", "unknown token type " _t); 465 } 466 } 467 468 _sp = ev2_pop_value(_s, _sp, 0); 469 return _sp >= 1? "err": _s[_sp]; 470 } 471 472 function ev2_pop_value(s, sp, assoc, rDict, rName, _vp, _value) { 473 # <param> rDict [default = s] 474 # <param> rName [default = <final stack top>] 475 # <returns> sp = <final stack top> 476 477 # read value 478 if (sp >= 0 && s[sp, "t"] == SE_VALU) { 479 sp--; 480 } else { 481 _vp = sp + 1; 482 s[_vp] = 0; 483 s[_vp, "t"] = SE_VALU; 484 s[_vp, "T"] = TYPE_NUM; 485 s[_vp, "M"] = MOD_NUL; 486 } 487 488 # proc prefices 489 while(sp >= 0 && s[sp, "t"] == SE_PREF && s[sp, "l"] >= assoc) { 490 ev2_apply(s, sp, sp + 1); 491 sp--; 492 } 493 494 if (rDict == "") 495 sp++; 496 else 497 ev2_copy(rDict, rName, s, sp + 1); 498 499 return sp; 500 } 501 502 function ev2_memget(dDict, dName, oDict, oName, memname) { 503 #print_error("mwg_pp.eval", "dbg: ev2_memget(memname=" memname ")"); 504 505 # embedded special member 506 if (oDict[oName, "T"] == TYPE_STR) { 507 if (memname == "length") { 508 dDict[dName] = length(oDict[oName]); 509 dDict[dName, "t"] = SE_VALU; 510 dDict[dName, "T"] = TYPE_NUM; 511 dDict[dName, "M"] = MOD_NUL; 512 return; 513 } else if (memname == "replace" || memname == "Replace" || memname == "slice" || memname ~ /^to(upper|lower)$/) { 514 ev2_copy(dDict, dName SUBSEP ATTR_MTH_OBJ, oDict, oName); 515 dDict[dName, ATTR_MTH_MEM] = memname; 516 dDict[dName] = ""; 517 dDict[dName, "t"] = SE_VALU; 518 dDict[dName, "T"] = TYPE_STR; 519 dDict[dName, "M"] = MOD_MTH; 520 #print_error("mwg_pp.eval", "dbg: method = String#" memname); 521 return; 522 } 523 } else { 524 # members for other types (TYPE_NUM MOD_ARR etc..) 525 } 526 527 # normal data member 528 if (and(oDict[oName, ATTR_MOD], MOD_REF)) { 529 dDict[dName] = d_data[oDict[oName, ATTR_REF], memname]; 530 dDict[dName, "t"] = SE_VALU; 531 dDict[dName, "T"] = (dDict[dName] == 0 + dDict[dName]? TYPE_NUM: TYPE_STR); 532 dDict[dName, "M"] = MOD_REF; 533 dDict[dName, ATTR_REF] = oDict[oName, ATTR_REF] SUBSEP memname; 534 } else { 535 print_error("mwg.eval", "invalid member name '" memname "'"); 536 dDict[dName] = ""; 537 dDict[dName, "t"] = SE_VALU; 538 dDict[dName, "T"] = TYPE_STR; 539 dDict[dName, "M"] = MOD_NUL; 540 } 541 542 # rep: dDict dName oDict oName 543 } 544 545 function ev2_memcall(dDict, dName, oDict, oName, memname, aDict, aName, _a, _i, _c, _result, _resultT) { 546 #print_error("mwg_pp.eval", "dbg: ev2_memcall(memname=" memname ")"); 547 548 _resultT = ""; 549 550 # read arguments 551 if (aDict[aName, "M"] != MOD_ARG) { 552 _c = 1; 553 _a[0] = aDict[aName]; 554 } else { 555 _c = aDict[aName, "A"]; 556 for (_i = 0; _i < _c; _i++) _a[_i] = aDict[aName, "A", _i]; 557 } 558 559 #----------------- 560 # process 561 if (oDict[oName, "T"] == TYPE_STR) { 562 if (memname == "replace") { 563 _result = oDict[oName]; 564 gsub(_a[0], _a[1], _result); 565 _resultT = TYPE_STR; 566 } else if (memname == "Replace") { 567 _result = replace(oDict[oName], _a[0], _a[1]); 568 _resultT = TYPE_STR; 569 } else if (memname == "slice") { 570 _result = slice(oDict[oName], _a[0], _a[1]); 571 _resultT = TYPE_STR; 572 } else if (memname == "toupper") { 573 _result = toupper(oDict[oName]); 574 _resultT = TYPE_STR; 575 } else if (memname == "tolower") { 576 _result = tolower(oDict[oName]); 577 _resultT = TYPE_STR; 578 } 579 } 580 581 #----------------- 582 # write value 583 if (_resultT == "") { 584 print_error("mwg.eval", "invalid member function name '" memname "'"); 585 _result = ""; 586 _resultT = TYPE_STR; 587 } 588 589 dDict[dName] = _result; 590 dDict[dName, "t"] = SE_VALU; 591 dDict[dName, "T"] = _resultT; 592 dDict[dName, "M"] = MOD_NUL; 593 } 594 595 function ev2_funcall(dDict, dName, funcname, aDict, aName, _a, _i, _c, _result, _resultT, _cmd, _line) { 596 _resultT = TYPE_NUM; 597 598 if (aDict[aName, "M"] != MOD_ARG) { 599 _c = 1; 600 _a[0] = aDict[aName]; 601 } else { 602 _c = aDict[aName, "A"]; 603 for (_i = 0; _i < _c; _i++) _a[_i] = aDict[aName, "A", _i]; 604 } 605 606 if (funcname == "int") { 607 _result = int(_a[0]); 608 } else if (funcname == "float") { 609 _result = 0 + _a[0]; 610 } else if (funcname == "floor") { 611 if (_a[0] >= 0) { 612 _result = int(_a[0]); 613 } else { 614 _result = int(1 - _a[0]); 615 _result = int(_a[0] + _result)-_result; 616 } 617 } else if (funcname == "ceil") { 618 if (_a[0] <= 0) { 619 _result = int(_a[0]); 620 } else { 621 _result = int(1 + _a[0]); 622 _result = int(_a[0]-_result) + _result; 623 } 624 } else if (funcname == "sqrt") { 625 _result = sqrt(_a[0]); 626 } else if (funcname == "sin") { 627 _result = sin(_a[0]); 628 } else if (funcname == "cos") { 629 _result = cos(_a[0]); 630 } else if (funcname == "tan") { 631 _result = sin(_a[0]) / cos(_a[0]); 632 } else if (funcname == "atan") { 633 _result = atan2(_a[0], 1); 634 } else if (funcname == "atan2") { 635 _result = atan2(_a[0], _a[1]); 636 } else if (funcname == "exp") { 637 _result = exp(_a[0]); 638 } else if (funcname == "log") { 639 _result = log(_a[0]); 640 } else if (funcname == "sinh") { 641 _x = exp(_a[0]); 642 _result = 0.5*(_x-1/_x); 643 } else if (funcname == "cosh") { 644 _x = exp(_a[0]); 645 _result = 0.5 * (_x + 1 / _x); 646 } else if (funcname == "tanh") { 647 _x = exp(2 * _a[0]); 648 _result = (_x - 1) / (_x + 1); 649 } else if (funcname == "rand") { 650 _result = rand(); 651 } else if (funcname == "srand") { 652 _result = srand(_a[0]); 653 } else if (funcname == "trim") { 654 _resultT = TYPE_STR; 655 _result = _a[0]; 656 gsub(/^[[:space:]]+|[[:space:]]+$/, "", _result); 657 } else if (funcname == "sprintf") { 658 _resultT = TYPE_STR; 659 _result = sprintf(_a[0], _a[1], _a[2], _a[3], _a[4], _a[5], _a[6], _a[7], _a[8], _a[9]); 660 } else if (funcname == "slice") { 661 _resultT = TYPE_STR; 662 _result = slice(_a[0], _a[1], _a[2]); 663 } else if (funcname == "length") { 664 _result = length(_a[0]); 665 } else if (funcname == "getenv") { 666 _resultT = TYPE_STR; 667 _result = ENVIRON[_a[0]]; 668 } else if (funcname == "system") { 669 _resultT = TYPE_STR; 670 _result = ""; 671 _cmd = _a[0]; 672 while ((_cmd | getline _line) > 0) 673 _result = _result _line "\n"; 674 close(_cmd); 675 sub(/\n+$/, "", _result); 676 } else { 677 print_error("mwg_pp.eval", "unknown function " funcname); 678 _result = 0; 679 } 680 681 dDict[dName] = _result; 682 dDict[dName, "t"] = SE_VALU; 683 dDict[dName, "T"] = _resultT; 684 dDict[dName, "M"] = MOD_NUL; 685 } 686 687 function ev2_unsigned(value) { 688 return value >= 0 ? value : value + 0x100000000; 689 } 690 691 function ev2_apply(stk, iPre, iVal, _pT, _pW, _lhs, _rhs, _lhsT, _rhsT, _result, _i, _a, _b, _c) { 692 # <param name="stk">stack</param> 693 # <param name="iPre">prefix operator/resulting value</param> 694 # <param name="iVal">input value</param> 695 696 _pT = stk[iPre, "p"]; 697 _pW = stk[iPre, "P"]; 698 699 if (_pT == "b") { 700 _lhs = stk[iPre]; 701 _rhs = stk[iVal]; 702 _lhsT = stk[iPre, "T"]; 703 _rhsT = stk[iVal, "T"]; 704 _resultT = TYPE_NUM; 705 706 #print "binary " _lhs " " _pW " " _rhs > "/dev/stderr" 707 if (_pW == "+") { 708 if (_lhsT == TYPE_STR || _rhsT == TYPE_STR) { 709 _result = _lhs _rhs; 710 _resultT = TYPE_STR; 711 } else 712 _result = _lhs+_rhs; 713 } else if (_pW == "-") _result = _lhs - _rhs; 714 else if (_pW == "*") _result = _lhs * _rhs; 715 else if (_pW == "/") _result = _lhs / _rhs; 716 else if (_pW == "%") _result = _lhs % _rhs; 717 else if (_pW == "==") _result = _lhs == _rhs; 718 else if (_pW == "!=") _result = _lhs != _rhs; 719 else if (_pW == ">=") _result = _lhs >= _rhs; 720 else if (_pW == "<=") _result = _lhs <= _rhs; 721 else if (_pW == "<") _result = _lhs < _rhs; 722 else if (_pW == ">") _result = _lhs > _rhs; 723 else if (_pW == "|") _result = or(ev2_unsigned(_lhs), ev2_unsigned(_rhs)); 724 else if (_pW == "^") _result = xor(ev2_unsigned(_lhs), ev2_unsigned(_rhs)); 725 else if (_pW == "&") _result = and(ev2_unsigned(_lhs), ev2_unsigned(_rhs)); 726 else if (_pW == "||") _result = ev1scan_cast_bool(_lhs) || ev1scan_cast_bool(_rhs); # not lazy evaluation 727 else if (_pW == "&&") _result = ev1scan_cast_bool(_lhs) && ev1scan_cast_bool(_rhs); # not lazy evaluation 728 else if (_pW ~ /[-+*/%|^&]?=/) { 729 if (and(stk[iPre, "M"], MOD_REF)) { 730 _resultT = TYPE_NUM; 731 if (_pW == "=") { 732 _result = _rhs; 733 _resultT = _rhsT; 734 } else if (_pW == "+=") _result = _lhs + _rhs; 735 else if (_pW == "-=") _result = _lhs - _rhs; 736 else if (_pW == "*=") _result = _lhs * _rhs; 737 else if (_pW == "/=") _result = _lhs / _rhs; 738 else if (_pW == "%=") _result = _lhs % _rhs; 739 else if (_pW == "|=") _result = or(ev2_unsigned(_lhs), ev2_unsigned(_rhs)); 740 else if (_pW == "^=") _result = xor(ev2_unsigned(_lhs), ev2_unsigned(_rhs)); 741 else if (_pW == "&=") _result = and(ev2_unsigned(_lhs), ev2_unsigned(_rhs)); 742 743 stk[iPre] = _result; 744 stk[iPre, "t"] = SE_VALU; 745 stk[iPre, "T"] = _resultT; 746 d_data[stk[iPre, "R"]] = _result; 747 748 # TODO: array copy? 749 } else { 750 ev2_copy(stk, iPre, stk, iVal); 751 # err? 752 } 753 return; 754 } else if (_pW == ",") { 755 if (stk[iPre, "M"] == MOD_ARG) { 756 stk[iPre] = _rhs; 757 stk[iPre, "t"] = SE_VALU; 758 stk[iPre, "T"] = _rhsT; 759 _i = stk[iPre, "A"]++; 760 ev2_copy(stk, iPre SUBSEP "A" SUBSEP _i, stk, iVal); 761 } else { 762 stk[iPre, "t"] = SE_VALU; 763 ev2_copy(stk, iPre SUBSEP "A" SUBSEP 0, stk, iPre); 764 ev2_copy(stk, iPre SUBSEP "A" SUBSEP 1, stk, iVal); 765 stk[iPre] = _rhs; 766 stk[iPre, "T"] = _rhsT; 767 stk[iPre, "M"] = MOD_ARG; 768 stk[iPre, "A"] = 2; 769 } 770 return; 771 } else if (_pW == ".") { 772 _a = and(stk[iVal, "M"], MOD_REF)? stk[iVal, ATTR_REF]: _rhs; 773 stk[iPre, "t"] = SE_VALU; 774 ev2_memget(stk, iPre, stk, iPre, _a); 775 return; 776 } 777 778 stk[iPre] = _result; 779 stk[iPre, "t"] = SE_VALU; 780 stk[iPre, "T"] = _resultT; 781 stk[iPre, "M"] = MOD_NUL; 782 } else if (_pT == "u") { 783 _rhs = stk[iVal]; 784 785 if (_pW == "+") _result = _rhs; 786 else if (_pW == "-") _result = -_rhs; 787 else if (_pW == "!") _result = !ev1scan_cast_bool(_rhs); 788 else if (_pW == "++") { 789 _result = _rhs+1; 790 stk[iPre] = _result; 791 stk[iPre, "t"] = SE_VALU; 792 stk[iPre, "T"] = TYPE_NUM; 793 if (and(stk[iVal, "M"], MOD_REF)) { 794 stk[iPre, "M"] = MOD_REF; 795 stk[iPre, "R"] = stk[iVal, "R"]; 796 d_data[stk[iPre, "R"]] = _result; 797 } else { 798 stk[iPre, "M"] = MOD_NUL; 799 } 800 return; 801 } else if (_pW == "--") { 802 _result = _rhs-1; 803 stk[iPre] = _result; 804 stk[iPre, "t"] = SE_VALU; 805 stk[iPre, "T"] = TYPE_NUM; 806 if (and(stk[iVal, "M"], MOD_REF)) { 807 stk[iPre, "M"] = MOD_REF; 808 stk[iPre, "R"] = stk[iVal, "R"]; 809 d_data[stk[iPre, "R"]] = _result; 810 } else { 811 stk[iPre, "M"] = MOD_NUL; 812 } 813 return; 814 } 815 816 stk[iPre] = _result; 817 stk[iPre, "t"] = SE_VALU; 818 stk[iPre, "T"] = TYPE_NUM; 819 stk[iPre, "M"] = MOD_NUL; 820 } else if (_pT == "?:") { 821 if (_pW == "T") { 822 stk[iPre, "t"] = SE_VALU; 823 } else { 824 ev2_copy(stk, iPre, stk, iVal); 825 } 826 } else { 827 ev2_copy(stk, iPre, stk, iVal); 828 } 829 } 830 831 function ev2_copy(dDict, dName, sDict, sName, _M, _t, _i, _iN) { 832 # assertion 833 if (sDict[sName, "t"] != SE_VALU) { 834 print_error("mwg_pp.eval:fatal", "copying not value element"); 835 } 836 837 dDict[dName] = sDict[sName]; # value 838 _t = dDict[dName, "t"] = sDict[sName, "t"]; # sttype 839 _M = dDict[dName, "M"] = sDict[sName, "M"]; # mod 840 841 if (_t == SE_VALU) 842 dDict[dName, "T"] = sDict[sName, "T"]; # datatype 843 844 # special data 845 if (and(_M, MOD_REF)) { 846 # reference 847 dDict[dName, "R"] = sDict[sName, "R"]; # name in d_data 848 } 849 if (and(_M, MOD_ARG) || and(_M, MOD_ARR)) { 850 # argument/array 851 _iN = dDict[dName, "A"] = sDict[sName, "A"]; # array length 852 for (_i = 0; _i < _iN; _i++) 853 ev2_copy(dDict, dName SUBSEP "A" SUBSEP _i, sDict, sName SUBSEP "A" SUBSEP _i); 854 } 855 if (and(_M, MOD_MTH)) { 856 # member function 857 dDict[dName, ATTR_MTH_MEM] = sDict[sName, ATTR_MTH_MEM]; 858 ev2_copy(dDict, dName SUBSEP ATTR_MTH_OBJ, sDict, sName SUBSEP ATTR_MTH_OBJ); 859 } 860 } 861 862 function ev2_delete(sDict, sName) { 863 if (sDict[sName, "t"] != SE_VALU) { 864 print_error("mwg_pp.eval:fatal", "deleting not value element"); 865 } 866 867 delete sDict[sName]; # value 868 delete sDict[sName, "t"]; # sttype 869 delete sDict[sName, "T"]; # datatype 870 _M = sDict[sName, "M"]; # mod 871 delete sDict[sName, "M"]; 872 873 # special data 874 if (_M == MOD_REF) { 875 # reference 876 delete sDict[sName, "R"]; # name in d_data 877 } else if (_M == MOD_ARG || _M == MOD_ARR) { 878 # argument/array 879 _iN = sDict[sName, "A"]; 880 delete sDict[sName, "A"]; # array length 881 for (_i = 0; _i < _iN; _i++) 882 ev2_delete(sDict, sName SUBSEP "A" SUBSEP _i); 883 } 884 } 885 886 # TODO? Dict[sp] -> Dict[sp, "v"] 887 # TODO? s[i, "c"]="b+" -> s[i, "k"]="b" s["o"]="+" 888 889 #=============================================================================== 890 # Parameter Expansion 891 #------------------------------------------------------------------------------- 892 function inline_expand(text, _, _ret, _ltext, _rtext, _mtext, _name, _r, _s, _a, _caps) { 893 _ret = ""; 894 while (match(text, /\${([^{}]|\\.)+}|\$"([^"]|\\.)+"/) > 0) { 895 _ltext = substr(text, 1, RSTART - 1); 896 _mtext = substr(text, RSTART, RLENGTH); 897 _rtext = substr(text, RSTART + RLENGTH); 898 _name = unescape(slice(_mtext, 2, -1)); 899 if (match(_name, /^[-a-zA-Z0-9_]+$/) > 0) { # ${key} 900 _r = "" d_data[_name]; 901 } else if (match(_name, /^[-a-zA-Z0-9_]+:-/) > 0) { # ${key:-alter} 902 _s["key"] = slice(_name, 0, RLENGTH - 2); 903 _s["alter"] = slice(_name, RLENGTH); 904 _r = "" d_data[_s["key"]]; 905 if (_r == "") _r = _s["alter"]; 906 } else if (match(_name, /^[-a-zA-Z0-9_]+:\+/) > 0) { # ${key:+value} 907 _s["key"] = slice(_name, 0, RLENGTH - 2); 908 _s["value"] = slice(_name, RLENGTH); 909 _r = "" d_data[_s["key"]]; 910 _r = _r == "" ? "" : _s["value"]; 911 } else if (match(_name, /^[-a-zA-Z0-9_]+:\?/) > 0) { # ${key:?warn} 912 _s["key"] = slice(_name, 0, RLENGTH - 2); 913 _s["warn"] = slice(_name, RLENGTH); 914 _r = "" d_data[_s["key"]]; 915 if (_r == "") { 916 print "(parameter expansion:" _mtext ")! " _s["warn"] > "/dev/stderr" 917 _ltext = _ltext _mtext; 918 _r = ""; 919 } 920 } else if (match(_name, /^([-a-zA-Z0-9_]+):([0-9]+):([0-9]+)$/, _caps) > 0) { # ${key:start:length} 921 _r = substr(d_data[_caps[1]], _caps[2] + 1, _caps[3]); 922 } else if (match(_name, /^([-a-zA-Z0-9_]+)(\/\/?)(([^/]|\\.)+)\/(.*)$/, _caps) > 0) { # ${key/before/after} 923 _r = d_data[_caps[1]]; 924 if (_caps[3] == "/") 925 sub(_caps[3], _caps[5], _r); 926 else 927 gsub(_caps[3], _caps[5], _r); 928 } else if (match(_name, /^([-a-zA-Z0-9_]+)(##?|%%?)(.+)$/, _caps) > 0) { # ${key#head} ${key%tail} 929 if (length(_caps[2]) == 2) { 930 # TODO 931 gsub(/\./, /\./, _caps[3]); 932 gsub(/\*/, /.+/, _caps[3]); 933 gsub(/\?/, /./, _caps[3]); 934 } 935 if (_caps[2] == "#" || _caps[2] == "##") { 936 _caps[3] = "^" _caps[3]; 937 } else { 938 _caps[3] = _caps[3] "$"; 939 } 940 941 _r = d_data[_caps[1]]; 942 sub(_caps[3], "", _r); 943 } else if (match(_name, /^#[-a-zA-Z0-9_]+$/) > 0) { # ${#key} 944 _r = length("" d_data[substr(_name, 2)]); 945 } else if (match(_name, /^([-a-zA-Z0-9_]+)(\..+)$/, _caps) > 0) { # ${key.modifiers} 946 _r = modify_text(d_data[_caps[1]], _caps[2]); 947 } else if (match(_name, /^\.[-a-zA-Z0-9_]+./) > 0) { # ${.function:args...} 948 match(_name, /^\.[-a-zA-Z0-9_]+./); 949 _s["i"] = RLENGTH; 950 _s["func"] = substr(_name, 2, _s["i"] - 2); 951 _s["sep"] =substr(_name, _s["i"], 1); 952 _s["args"] = substr(_name, _s["i"] + 1); 953 _s["argc"] = split(_s["args"], _a, _s["sep"]); 954 if (_s["func"] == "for" && _s["argc"] == 5) { 955 _r = inline_function_for(_a); 956 } else if (_s["func"] == "sep_for" && _s["argc"] == 5) { 957 _r = inline_function_sepfor(_a); 958 } else if (_s["func"] == "for_sep" && _s["argc"] == 5) { 959 _r = inline_function_forsep(_a); 960 } else if (_s["func"] == "eval" && _s["argc"] == 1) { 961 _r = inline_function_eval(_a); 962 } else { 963 print "(parameter function:" _s["func"] ")! unrecognized function." > "/dev/stderr"; 964 _r = _mtext; 965 } 966 } else { 967 print "(parameter expansion:" _mtext ")! unrecognized expansion." > "/dev/stderr"; 968 _r = _mtext; 969 } 970 971 if (_mtext ~ /^\${/) { 972 # enable re-expansion ${} 973 _ret = _ret _ltext; 974 text = _r _rtext; 975 } else { 976 # disable re-expansion $"" 977 _ret = _ret _ltext _r; 978 text = _rtext; 979 } 980 } 981 return _ret text; 982 } 983 984 function inline_function_forsep(args, _, _r, _sep) { 985 _sep = args[5]; 986 _r = inline_function_for(args); 987 return _r == "" ? "" : _r _sep; 988 } 989 function inline_function_sepfor(args, _, _r, _sep) { 990 _sep = args[5]; 991 _r = inline_function_for(args); 992 return _r == "" ? "" : _sep _r; 993 } 994 function inline_function_for(args, _, _rex_i, _i0, _iM, _field, _sep, _i, _r, _t) { 995 # ${for:%i%:1:9:typename A%i%:,} 996 _rex_i = args[1]; 997 _i0 = int(eval_expr(args[2])); 998 _iM = int(eval_expr(args[3])); 999 _field = args[4]; 1000 _sep = args[5]; 1001 1002 _r = ""; 1003 for (_i = _i0; _i < _iM; _i++) { 1004 _t = _field; 1005 gsub(_rex_i, _i, _t); 1006 _r = _i == _i0?_t:_r _sep _t; 1007 } 1008 return _r; 1009 } 1010 function inline_function_eval(args) { 1011 return eval_expr(args[1]); 1012 } 1013 1014 #=============================================================================== 1015 # mwg.pp text modification 1016 #------------------------------------------------------------------------------- 1017 function modify_text__replace0(text, before, after, flags) { 1018 if (index(flags, "R")) { 1019 return replace(text, before, after); 1020 } else { 1021 gsub(before, after, text); 1022 return text; 1023 } 1024 } 1025 1026 function modify_text__replace(content, before, after, flags) { 1027 if (index(flags, "m")) { 1028 _jlen = split(content, _lines, "\n"); 1029 content = modify_text__replace0(_lines[1], before, after, flags); 1030 #print_error("mwg_pp(modify_text)", "replace('" _lines[1] "','" before "','" after "') = '" content "'"); 1031 for (_j = 1; _j < _jlen; _j++) 1032 content = content "\n" modify_text__replace0(_lines[_j + 1], before, after, flags); 1033 } else { 1034 content = modify_text__replace0(content, before, after, flags); 1035 } 1036 return content; 1037 } 1038 1039 function modify_text(content, args, _len, _i, _m, _s, _c, _j, _jlen, _lines) { 1040 # _len: length of args 1041 # _i: index in args 1042 # _c: current character in args 1043 # _m: current context mode in args 1044 # _s: data store 1045 1046 _m = ""; 1047 _len = length(args); 1048 for (_i = 0; _i < _len; _i++) { 1049 _c = substr(args, _i + 1, 1); 1050 #------------------------------------------------- 1051 if (_m == "c") { 1052 if (_c == "r" || _c == "R") { 1053 _m = "r0"; 1054 _s["flags"] = _c == "R"?_c:""; 1055 _s["sep"] = ""; 1056 _s["rep_before"] = ""; 1057 _s["rep_after"] = ""; 1058 } else if (_c == "f") { 1059 _m = "f0"; 1060 _s["sep"] = ""; 1061 _s["for_var"] = ""; 1062 _s["for_begin"] = ""; 1063 _s["for_end"] = ""; 1064 } else if (_c == "i") { 1065 content = inline_expand(content); 1066 _m = ""; 1067 } else { 1068 print "unrecognized expand fun '" _c "'" > "/dev/stderr" 1069 } 1070 #------------------------------------------------- 1071 # r, R: replace 1072 } else if (_m == "r0") { 1073 _s["sep"] = _c; 1074 _m = "r1"; 1075 } else if (_m == "r1") { 1076 if (_c == _s["sep"]) { 1077 _m = "r2"; 1078 } else { 1079 _s["rep_before"] = _s["rep_before"] _c; 1080 } 1081 } else if (_m == "r2") { 1082 if (_c == _s["sep"]) { 1083 1084 # check flag m 1085 _c = substr(args, _i + 2, 1); 1086 if (_c == "m") { 1087 _s["flags"] = _s["flags"] "m"; 1088 _i++; 1089 } 1090 1091 content = modify_text__replace(content, _s["rep_before"], _s["rep_after"], _s["flags"]); 1092 _m = ""; 1093 } else { 1094 _s["rep_after"] = _s["rep_after"] _c; 1095 } 1096 #------------------------------------------------- 1097 # f: for 1098 } else if (_m == "f0") { 1099 _s["sep"] = _c; 1100 _m = "f1"; 1101 } else if (_m == "f1") { 1102 if (_c != _s["sep"]) { 1103 _s["for_var"] = _s["for_var"] _c; 1104 } else { 1105 _m = "f2"; 1106 } 1107 } else if (_m == "f2") { 1108 if (_c != _s["sep"]) { 1109 _s["for_begin"] = _s["for_begin"] _c; 1110 } else { 1111 _s["for_begin"] = int(eval_expr(_s["for_begin"])); 1112 _m = "f3"; 1113 } 1114 } else if (_m == "f3") { 1115 if (_c != _s["sep"]) { 1116 _s["for_end"] = _s["for_end"] _c; 1117 } else { 1118 _s["for_end"] = int(eval_expr(_s["for_end"])); 1119 _m = ""; 1120 1121 _s["content"] = content; 1122 content = ""; 1123 for (_s["i"] = _s["for_begin"]; _s["i"] < _s["for_end"]; _s["i"]++) { 1124 _c = _s["content"]; 1125 gsub(_s["for_var"], _s["i"], _c); 1126 content = content _c; 1127 } 1128 } 1129 #------------------------------------------------- 1130 } else { 1131 if (_c == ".") { 1132 _m = "c"; 1133 } else if (_c ~ /[/#]/) { 1134 break; 1135 } else if (_c !~ /[ \t\r\n]/) { 1136 print "unrecognized expand cmd '" _c "'" > "/dev/stderr" 1137 } 1138 } 1139 } 1140 1141 return content; 1142 } 1143 #=============================================================================== 1144 # mwg.pp commands 1145 #------------------------------------------------------------------------------- 1146 function range_begin(cmd, arg) { 1147 d_level++; 1148 d_rstack[d_level, "c"] = cmd; 1149 d_rstack[d_level, "a"] = arg; 1150 d_content[d_level] = ""; 1151 d_content[d_level, "L"] = ""; 1152 d_content[d_level, "F"] = ""; 1153 } 1154 function range_end(args, _cmd, _arg, _txt, _clines, _cfiles) { 1155 if (d_level == 0) { 1156 print "mwg_pp.awk:#%}: no matching range beginning" > "/dev/stderr" 1157 return; 1158 } 1159 1160 # pop data 1161 _cmd = d_rstack[d_level, "c"]; 1162 _arg = d_rstack[d_level, "a"]; 1163 _txt = d_content[d_level]; 1164 if (m_lineno) { # 20120726 1165 _clines = d_content[d_level, "L"]; 1166 _cfiles = d_content[d_level, "F"]; 1167 } 1168 d_level--; 1169 1170 if (args != "") 1171 _txt = modify_text(_txt, args); 1172 1173 # process 1174 if (_cmd == "define") { 1175 d_data[_arg] = _txt; 1176 if (m_lineno) { # 20120726 1177 d_data[_arg, "L"] = _clines; 1178 d_data[_arg, "F"] = _cfiles; 1179 } 1180 } else if (_cmd == "expand" || _cmd == "IF1" || _cmd == "IF4") { 1181 process_multiline(_txt, _clines, _cfiles); # 20120726 1182 } else if (_cmd == "none" || _cmd ~ /IF[023]/) { 1183 # do nothing 1184 } else { 1185 print "mwg_pp.awk:#%}: unknown range beginning '" _cmd " ( " _arg " )'" > "/dev/stderr" 1186 } 1187 } 1188 1189 function dctv_define(args, _, _cap, _name, _name2) { 1190 if (match(args, /^([-A-Za-z0-9_:]+)[[:space:]]*(\([[:space:]]*)?$/, _cap) > 0) { 1191 # dctv: #%define hoge 1192 # dctv: #%define hoge ( 1193 _name = _cap[1]; 1194 if (_name == "end") 1195 range_end(""); 1196 else 1197 range_begin("define", _name); 1198 } else if (match(args, /^([-_:[:alnum:]]+)[[:space:]]+([-_:[:alnum:]]+)(.*)$/, _cap) > 0) { 1199 # dctv: #%define a b.mods 1200 _name = _cap[1]; 1201 _name2 = _cap[2]; 1202 _args = trim(_cap[3]); 1203 if (_args != "") 1204 d_data[_name] = modify_text(d_data[_name2], _args); 1205 else 1206 d_data[_name] = d_data[_name2]; 1207 1208 if (m_lineno) { 1209 d_data[_name, "L"] = d_data[_name2, "L"]; 1210 d_data[_name, "F"] = d_data[_name2, "F"]; 1211 } 1212 } else { 1213 print "mwg_pp.awk:#%define: missing data name" > "/dev/stderr" 1214 return; 1215 } 1216 } 1217 1218 # 状態は何種類あるか? 1219 # END CONDT CONDF ELSE 1220 # IF0 出力せず IF1 IF0 IF4 (not matched) 1221 # IF1 出力する IF2 IF2 IF3 (matched) 1222 # IF2 出力せず IF2 IF2 IF3 (finished) 1223 # IF3 出力せず !IF3 !IF3 !IF3 (else unmatched) 旧 "el0" 1224 # IF4 出力する !IF3 !IF3 !IF3 (else matched) 旧 "el1" 1225 1226 function dctv_if(cond, _, _cap) { 1227 gsub(/^[ \t]+|[ \t]*(\([ \t]*)?$/, "", cond); 1228 if (cond != "") { 1229 #print "dbg: if( "cond " ) -> " eval_expr(cond) > "/dev/stderr" 1230 if (cond == "end") { 1231 range_end(""); 1232 } else if (eval_expr(cond)) { 1233 range_begin("IF1"); 1234 } else { 1235 range_begin("IF0"); 1236 } 1237 } else { 1238 print "mwg_pp.awk:#%define: missing data name" > "/dev/stderr" 1239 return; 1240 } 1241 } 1242 function dctv_elif(cond, _cmd) { 1243 if (d_level == 0) { 1244 print "mwg_pp.awk:#%elif: no matching if directive" > "/dev/stderr" 1245 return; 1246 } 1247 1248 _cmd = d_rstack[d_level, "c"]; 1249 if (_cmd ~ /IF[0-4]/) { 1250 range_end(""); 1251 if (_cmd == "IF0") { 1252 if (eval_expr(cond)) { 1253 range_begin("IF1"); 1254 } else { 1255 range_begin("IF0"); 1256 } 1257 } else if (_cmd ~ /IF[12]/) { 1258 range_begin("IF2"); 1259 } else { 1260 range_begin("IF3"); 1261 if (_cmd ~ /IF[34]/) 1262 print_error("mwgpp:#%else", "if clause have already ended!"); 1263 } 1264 } else { 1265 print_error("mwgpp:#%else", "no matching if directive"); 1266 } 1267 } 1268 function dctv_else(_, _cap, _cmd) { 1269 if (d_level == 0) { 1270 print_error("mwgpp:#%else", "no matching if directive"); 1271 return; 1272 } 1273 1274 _cmd = d_rstack[d_level, "c"]; 1275 if (_cmd ~ /IF[0-4]/) { 1276 range_end(""); 1277 if (_cmd == "IF0") { 1278 range_begin("IF4"); 1279 } else { 1280 range_begin("IF3"); 1281 if (_cmd ~ /IF[34]/) 1282 print_error("mwgpp:#%else", "if clause have already ended!"); 1283 } 1284 } else { 1285 print_error("mwgpp:#%else", "no matching if directive"); 1286 } 1287 } 1288 1289 function dctv_expand(args, _, _cap, _txt, _type) { 1290 if (match(args, /^([-a-zA-Z:0-9_]+|[\(])(.*)$/, _cap) > 0) { 1291 if (_cap[1] == "(") { 1292 _type = 1; 1293 } else { 1294 _txt = d_data[_cap[1]]; 1295 _txt = modify_text(_txt, _cap[2]); 1296 process_multiline(_txt, d_data[_cap[1], "L"], d_data[_cap[1], "F"]); 1297 } 1298 } else if (match(args, /^[[:space:]]*$/) > 0) { 1299 _type = 1; 1300 } else { 1301 print "mwg_pp.awk:#%expand: missing data name" > "/dev/stderr" 1302 return; 1303 } 1304 1305 if (_type == 1) { 1306 # begin expand 1307 range_begin("expand", _cap[2]); # _cap[2] not used 1308 } 1309 } 1310 1311 function dctv_modify(args, _, _i, _len, _name, _content) { 1312 _i = match(args, /[^-a-zA-Z:0-9_]/); 1313 _len = _i?_i - 1:length(args); 1314 _name = substr(args, 1, _len); 1315 args = trim(substr(args, _len + 1)); 1316 1317 d_data[_name] = modify_text(d_data[_name], args); 1318 } 1319 1320 function include_file(file, _line, _lines, _i, _n, _dir, _originalFile, _originalLine) { 1321 if (file ~ /^<.+>$/) { 1322 gsub(/^<|>$/, "", file); 1323 file = INCLUDE_DIRECTORY "/" file; 1324 } else { 1325 gsub(/^"|"$/, "", file); 1326 if (file !~ /^\//) { 1327 _dir = awk_getfiledir(); 1328 if (_dir != "") file = _dir "/" file; 1329 } 1330 } 1331 1332 _n = 0; 1333 while ((_r = getline _line < file) >0) 1334 _lines[_n++] = _line; 1335 if (_r < 0) 1336 print_error("could not open the include file '" file "'"); 1337 close(file); 1338 1339 dependency_add(file); 1340 1341 _originalFile = m_lineno_cfile; 1342 _originalLine = m_lineno_cline; 1343 for (_i = 0; _i < _n; _i++) { 1344 m_lineno_cfile = file; # 20120726 1345 m_lineno_cline = _i + 1; # 20120726 1346 process_line(_lines[_i]); 1347 } 1348 m_lineno_cfile = _originalFile; # 2015-01-24 1349 m_lineno_cline = _originalLine; # 2015-01-24 1350 } 1351 1352 function dctv_error(message, _title) { 1353 if (m_lineno_cfile != "" || m_lineno) 1354 _title = m_lineno_cfile ":" m_lineno_cline; 1355 else 1356 _title = FILENAME; 1357 1358 print_error(_title, message); 1359 } 1360 1361 #=============================================================================== 1362 function data_define(pair, _sep, _i, _k, _v, _capt, _rex) { 1363 if (pair ~ /^[^\(_a-zA-Z0-9]/) { # #%data/name/value/ 1364 1365 _sep = "\\" substr(pair, 1, 1); 1366 _rex = "^" _sep "([^" _sep "]+)" _sep "([^" _sep "]+)" _sep 1367 if (match(pair, _rex, _capt)) { 1368 _k = _capt[1]; 1369 _v = _capt[2]; 1370 d_data[_k] = _v; 1371 } else { 1372 printf("(#%%data directive)! ill-formed. (pair=%s, _rex=%s)\n", pair, _rex) > "/dev/stderr" 1373 return 0; 1374 } 1375 } else { # #%data name value 1376 # #%data(=) name=value 1377 _sep = ""; 1378 if (match(pair, /^\([^\)]+\)/) > 0) { 1379 _sep = substr(pair, 2, RLENGTH - 2); 1380 pair = trim(substr(pair, RLENGTH + 1)); 1381 } 1382 1383 _i = _sep != ""?index(pair, _sep):match(pair, /[ \t]/); 1384 if (_i <= 0) { 1385 printf("(#%%data directive)! ill-formed. (pair=%s, _sep=%s)\n", pair, _sep) > "/dev/stderr" 1386 return 0; 1387 } 1388 1389 _k = substr(pair, 1, _i - 1); 1390 _v = trim(substr(pair, _i + length(_sep))) 1391 d_data[_k] = _v; 1392 1393 #_t[0]; head_token(pair, _t); 1394 #d_data[_t[0]] = _t[1]; 1395 } 1396 } 1397 function data_print(key) { 1398 add_line(d_data[key]); 1399 } 1400 function execute(command, _line, _caps, _n, _cfile) { 1401 if (match(command, /^(>>?)[[:space:]]*([^[:space:]]*)/, _caps) > 0) { 1402 # 出力先の変更 1403 fflush(m_outpath); 1404 m_outpath = _caps[2]; 1405 m_addline_cfile = ""; 1406 if (_caps[1] == ">" && m_outpath != "") { 1407 printf("") > m_outpath 1408 } 1409 } else { 1410 _n = 0; 1411 while ((command | getline _line) > 0) 1412 _lines[_n++] = _line; 1413 close(command); 1414 1415 _cfile = "$(" command ")"; 1416 gsub(/[\\"]/, "\\\\&", _cfile); 1417 for (_i = 0; _i < _n; _i++) { 1418 m_lineno_cfile = _cfile; 1419 m_lineno_cline = _i + 1; 1420 process_line(_lines[_i]); 1421 } 1422 } 1423 } 1424 #=============================================================================== 1425 function add_line(line) { 1426 if (d_level == 0) { 1427 if (m_lineno) { # 20120726 1428 if (m_addline_cfile != m_lineno_cfile||++m_addline_cline != m_lineno_cline) { 1429 m_addline_cline = m_lineno_cline; 1430 m_addline_cfile = m_lineno_cfile; 1431 if (m_addline_cline != "" && m_addline_cfile != "") { 1432 if (m_outpath == "") 1433 print "#line " m_addline_cline " \"" m_addline_cfile "\"" 1434 else 1435 print "#line " m_addline_cline " \"" m_addline_cfile "\"" >> m_outpath 1436 } 1437 } 1438 } 1439 1440 if (m_outpath == "") 1441 print line 1442 else 1443 print line >> m_outpath 1444 } else { 1445 d_content[d_level] = d_content[d_level] line "\n" 1446 d_content[d_level, "L"] = d_content[d_level, "L"] m_lineno_cline "\n"; 1447 d_content[d_level, "F"] = d_content[d_level, "F"] m_lineno_cfile "\n"; 1448 } 1449 } 1450 1451 # function process_multiline2(txt, cline, cfile, _s, _l, _f, _len, _i) { 1452 # _len = split(txt, _s, "\n"); 1453 # if (length(_s[_len]) == 0) _len--; 1454 1455 # split(clines, _l, "\n"); 1456 # split(cfiles, _f, "\n"); 1457 # for (_i = 0; _i < _len; _i++) { 1458 # m_lineno_cline = _l[_i + 1]; 1459 # m_lineno_cfile = _f[_i + 1]; 1460 # process_line(_s[_i + 1]); 1461 # } 1462 # } 1463 1464 function process_multiline(txt, clines, cfiles, _, _s, _l, _f, _len, _i) { 1465 _len = split(txt, _s, "\n"); 1466 if (length(_s[_len]) == 0) _len--; 1467 1468 split(clines, _l, "\n"); 1469 split(cfiles, _f, "\n"); 1470 for (_i = 0; _i < _len; _i++) { 1471 m_lineno_cline = _l[_i + 1]; 1472 m_lineno_cfile = _f[_i + 1]; 1473 process_line(_s[_i + 1]); 1474 } 1475 } 1476 1477 function process_line(line, _line, _text, _ind, _len, _directive, _cap) { 1478 _line = line; 1479 1480 sub(/^[ \t]+/, "", _line); 1481 sub(/[ \t\r]+$/, "", _line); 1482 if (m_comment_cpp) 1483 sub(/^\/\//, "#", _line); 1484 if (m_comment_pragma) 1485 sub(/^[[:space:]]*#[[:space:]]*pragma/, "#", _line); 1486 if (m_comment_c && match(_line, /^\/\*(.+)\*\/$/, _cap) > 0) 1487 _line = "#" _cap[1]; 1488 1489 if (_line ~ /^#%[^%]/) { 1490 # cut directive 1491 if (match(_line, /^#%[ \t]*([-a-zA-Z_0-9:]+)(.*)$/, _cap) > 0) { 1492 _directive = _cap[1]; 1493 _text = trim(_cap[2]); 1494 } else if (match(_line, /^#%[ \t]*([^-a-zA-Z_0-9:])(.*)$/, _cap) > 0) { 1495 _directive = _cap[1]; 1496 _text = trim(_cap[2]); 1497 } else { 1498 print_error("unrecognized directive line: " line); 1499 return; 1500 } 1501 1502 # switch directive 1503 if (_directive == "(" || _directive == "begin") { 1504 range_begin("none", _text); 1505 } else if (_directive == ")" || _directive == "end") { 1506 range_end(_text); 1507 } else if (_directive == "define" || _directive == "m") { 1508 dctv_define(_text); 1509 } else if (_directive == "expand" || _directive == "x") { 1510 dctv_expand(_text); 1511 } else if (_directive == "if") { 1512 dctv_if(_text); 1513 } else if (_directive == "else") { 1514 dctv_else(_text); 1515 } else if (_directive == "elif") { 1516 dctv_elif(_text); 1517 } else if (_directive == "modify") { # obsoleted. use #%define name name.mods 1518 print_error("obsoleted directive modify"); 1519 dctv_modify(_text); 1520 } else if (_directive == "include" || _directive == "<") { 1521 include_file(_text); 1522 } else if (_directive == "data") { # obs → データ設定に有意。残す? 1523 data_define(_text); 1524 } else if (_directive == "print") { #obs 1525 data_print(_text); 1526 } else if (_directive == "eval") { 1527 eval_expr(_text); 1528 } else if (_directive == "[" && match(_text, /^(.+)\]$/, _cap) > 0) { 1529 eval_expr(_cap[1]); 1530 } else if (_directive == "exec" || _directive == "$") { 1531 execute(_text); 1532 } else if (_directive == "#") { 1533 # comment. just ignored. 1534 } else if (_directive == "error") { 1535 dctv_error(_text); 1536 } else { 1537 print_error("unrecognized directive " _directive); 1538 } 1539 } else if (_line ~ /^##+%/) { 1540 add_line(substr(_line, 2)); 1541 } else if (_line ~ /^#%%+/) { 1542 add_line("#" substr(_line, 3)); 1543 } else { 1544 add_line(line); 1545 } 1546 } 1547 1548 BEGIN{ 1549 FS = "MWG_PP" "_COMMENT"; 1550 ev1scan_init(); 1551 d_level = 0; 1552 d_data[0] = ""; 1553 1554 m_outpath = ""; 1555 m_comment_c = int(ENVIRON["PPC_C"]) != 0; 1556 m_comment_cpp = int(ENVIRON["PPC_CPP"]) != 0; 1557 m_comment_pragma = int(ENVIRON["PPC_PRAGMA"]) != 0; 1558 1559 m_lineno = int(ENVIRON["PPLINENO"]) != 0; 1560 1561 INCLUDE_DIRECTORY = ENVIRON["HOME"] "/.mwg/mwgpp/include" 1562 1563 m_dependency_count = 0 1564 m_dependency_guard[""] = 1; 1565 m_dependency[0] = ""; 1566 } 1567 1568 { 1569 if (FNR == 1) { 1570 if (ENVIRON["PPLINENO_FILE"] != "") 1571 m_rfile = ENVIRON["PPLINENO_FILE"]; 1572 else 1573 m_rfile = FILENAME; 1574 dependency_add(m_rfile); 1575 } 1576 m_lineno_cfile = m_rfile; 1577 m_lineno_cline = FNR; 1578 process_line($1); 1579 } 1580 1581 function dependency_add(file) { 1582 if (!m_dependency_guard[file]) { 1583 m_dependency_guard[file] = 1; 1584 m_dependency[m_dependency_count++] = file; 1585 } 1586 } 1587 function dependency_generate(output, target, is_phony, _i, _iMax, _line, _file) { 1588 if (!target) { 1589 target = m_rfile; 1590 sub(/\.pp$/, "", target); 1591 target = target ".out"; 1592 } 1593 1594 if (m_dependency_count == 0) 1595 print target ":" > output; 1596 else { 1597 _iMax = m_dependency_count - 1; 1598 for (_i = 0; _i < m_dependency_count; _i++) { 1599 _file = m_dependency[_i]; 1600 gsub(/[[:space:]]/, "\\\\&", _file); 1601 _line = _i == 0? target ": ": " "; 1602 _line = _line _file; 1603 if (_i < _iMax) _line = _line " \\"; 1604 print _line > output; 1605 } 1606 1607 if (is_phony) { 1608 for (_i = 0; _i < m_dependency_count; _i++) { 1609 _file = m_dependency[_i]; 1610 gsub(/[[:space:]]/, "\\\\&", _file); 1611 printf("%s:\n\n", _file) > output; 1612 } 1613 } 1614 } 1615 } 1616 1617 END { 1618 # output dependencies 1619 DEPENDENCIES_OUTPUT = ENVIRON["DEPENDENCIES_OUTPUT"]; 1620 if (DEPENDENCIES_OUTPUT) { 1621 is_phony = ENVIRON["DEPENDENCIES_PHONY"]; 1622 dependency_generate(DEPENDENCIES_OUTPUT, ENVIRON["DEPENDENCIES_TARGET"], is_phony); 1623 } 1624 1625 if (global_errorCount) exit(1); 1626 }