/*	
 *	clipexpr.c
 *
 *	憖幵応傾儖僑儕僘儉(夵椙斉)
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2016 Naoyuki Sawa
 *
 *	* Fri Jun 24 21:38:01 JST 2016 Naoyuki Sawa
 *	- 1st儕儕乕僗丅
 *	- 婎杮揑偵偼婛懚偺clipshya.c儌僕儏乕儖偺摦嶌偲摨偠偱偡偑丄埲壓偺揰傪夵椙偟傑偟偨丅
 *	  丒clipshya.c偺ShuntingYard()偼丄擖椡僉儏乕,弌椡僉儏乕,僗僞僢僋傪屄暿偵愝偗偰偄傑偟偨丅
 *	    偦傟偵懳偟偰丄clipexpr.c偺exprsort()偼丄擖椡僉儏乕傪偦偺傑傑弌椡僉儏乕,媦傃,僗僞僢僋偲偟偰傕巊梡偟傑偡丅
 *	    偙傟偵傛偭偰丄嶌嬈梡儊儌儕偺徚旓検偑掅尭偟傑偟偨丅
 *	  丒ShuntingYard()偼丄僩乕僋儞傪(int)偱昞偡帠偟偐弌棃傑偣傫偱偟偨丅
 *	    exprsort()偼丄擟堄偺僶僀僩悢偺僨乕僞偱丄僩乕僋儞傪昞偣傞傛偆偵側傝傑偟偨丅
 *	  丒ShuntingYard()偼丄擖椡僉儏乕偺廔抂傪0偱帵偟偰偄傑偟偨丅
 *	    exprsort()偼丄擖椡僉儏乕偺梫慺悢傪丄柧帵揑偵堷悢偱帵偡傛偆偵側傝傑偟偨丅
 *	  丒埲忋偺夵椙偵敽偄丄exprsort()偺堷悢宍幃偼丄qsort()摍偺僜乕僩娭悢偵嬤偄傕偺偲側傝傑偟偨丅
 *	    幚嵺偺強丄憖幵応傾儖僑儕僘儉偼堦庬偺僜乕僩偲尒側偣傑偡偺偱丄娭悢巇條偑敾傝堈偔側偭偨偲巚偄傑偡丅
 *	  丒ShuntingYard()偑撪曪偟偰偄偨僶僌傪丄exprsort()偱偼廋惓偟傑偟偨丅
 *	    徻嵶偼丄ShuntingYard()撪偺乽//{{2016/06/24僐儊儞僩捛婰:乣乿傪嶲徠偟偰壓偝偄丅
 *	- 婎杮揑側娭悢偱偁傞丄exprsort()偺夵椙揰偼丄埲忋偱偡丅
 *	  偝傜偵丄婎杮揑側娭悢傪巊梡偟偨儐乕僥傿儕僥傿娭悢偵偮偄偰傕丄埲壓偺夵椙傪峴偄傑偟偨丅
 *	  丒clipshya.c偺ShuntingYard_Eval()偼丄惍悢偺幃偟偐埖偊傑偣傫偱偟偨丅
 *	    偦傟偵懳偟偰丄clipexpr.c偺expreval()偼丄幚悢偺幃傕埖偊傞傛偆偵側傝傑偟偨丅
 *	    'USE_EXPREVAL_NEWVER'僔儞儃儖傪掕媊偡傞偲丄幚悢斉偺expreval()偑桳岠偵側傝傑偡丅
 *	  丒堷悢傪庢傜側偄娭悢偺幚憰椺偲偟偰丄rnd()傪捛壛偟傑偟偨丅
 *	* Fri Jun 24 22:10:38 JST 2016 Naoyuki Sawa
 *	- exprsort(),媦傃,exprsort_r()偵丄娭悢偺幚堷悢偺悢傪捠抦偡傞僐乕儖僶僢僋娭悢(fnIncrFnNumArgs)傪捛壛偟傑偟偨丅
 *	  巊梡椺偼丄乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉偺expreval()偺幚憰傪嶲徠偟偰壓偝偄丅
 *	* Sat Jun 25 21:55:36 JST 2016 Naoyuki Sawa
 *	- 乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉偺expreval()偵丄傾僾儕働乕僔儑儞掕媊曄悢,娭悢偵懳墳偡傞婡擻傪捛壛偟傑偟偨丅
 *	  尦乆expreval()偼exprsort()偺巊梡曽朄傪帵偡偨傔偺僒儞僾儖偱偟偨偑丄幚嵺偺傾僾儕働乕僔儑儞偱斈梡揑偵巊梡弌棃傞偖傜偄偺婡擻偵側偭偨偲巚偄傑偡丅
 *	  彯丄乽惍悢斉丆摦揑儊儌儕妋曐柍偟乿斉偺expreval()偵偼丄忋婰偺婡擻偼捛壛偟偰偄傑偣傫丅
 *	* Sun Sep 04 21:41:17 JST 2016 Naoyuki Sawa
 *	- 64價僢僩斉偱偼丄椺奜僐乕僪傪傾僪儗僗偱側偔丄堦堄側FourCC幆暿巕偱昞偡傛偆偵偟傑偟偨丅
 *	  setjmp()/longjmp()偺僷儔儊乕僞偼(int)偱偁傝丄(void*)傗(intptr_t)傪巊偊側偄偐傜偱偡丅
 *	  彯丄32價僢僩斉傕64價僢僩斉偲嫟捠偵曄峏偟偰傕椙偄偺偱偡偑丄枩堦婛懚偺僐乕僪偵塭嬁偑惗偠傞帠傪杊偖偨傔偵丄32價僢僩斉偼偙傟傑偱捠傝偲偟傑偟偨丅
 */
#include "clip.h"
#ifdef  USE_EXPR_SEH
//USE_EXPR_SEH僔儞儃儖偑掕媊偝傟偨傜丄clipexpr.c撪偺DIE()傪慡偰丄SEH_throw(ExprException)偵抲偒姺偊傑偡丅
#undef  DIE
#ifndef PIECE
  #define DIE() SEH_throw(ExprException)
#else //PIECE
  //P/ECE偱傕忋偺傛偆偵掕媊偟偰傕椙偄偺偱偡偑丄儊儌儕愡栺偺偨傔壓偺傛偆偵掕媊偡傞帠偵偟傑偟偨丅寢壥偼摨偠偵側傝傑偡丅
  //埲壓偺掕媊偼clipseh.h偺SEH_throw()偺掕媊偵埶懚偟偰偄傑偡丅傕偟崱屻SEH_throw()傪曄峏偡傞帪偼埲壓傕曄峏偟偰壓偝偄丅
  #define DIE() do { Expr_throw(__FILE__, __LINE__); } while(0)
  static void __attribute__((noreturn)) Expr_throw(const char* file, int line) {
    SEH_info.file = file;
    SEH_info.line = line;
    SEH_info.msg  = NULL;
    SEH_longjmp((int)ExprException); }
#endif//PIECE
//{{2016/09/04曄峏:64價僢僩斉偱偼丄椺奜僐乕僪傪傾僪儗僗偱側偔丄堦堄側FourCC幆暿巕偱昞偡傛偆偵偟傑偟偨丅
//const char ExprException[1/*dummy*/];
//伀2016/09/04曄峏:64價僢僩斉偱偼丄椺奜僐乕僪傪傾僪儗僗偱側偔丄堦堄側FourCC幆暿巕偱昞偡傛偆偵偟傑偟偨丅
#ifndef _WIN64
const char ExprException[1/*dummy*/];	//32價僢僩斉
#endif//_WIN64
//}}2016/09/04曄峏:64價僢僩斉偱偼丄椺奜僐乕僪傪傾僪儗僗偱側偔丄堦堄側FourCC幆暿巕偱昞偡傛偆偵偟傑偟偨丅
#endif//USE_EXPR_SEH
/****************************************************************************
 *	exprsort()偺摦嶌偵偮偄偰愢柧
 ****************************************************************************/
#if 0
仭攝楍憖嶌偺椺
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆
劆			base									num
劆			劆									nInput
劆			伀									伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂侾丂劆丂亊丂劆丂乮丂劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆												仾
劆												iOutput			劉偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵iOutput傪帵偟偨偑丄幚嵺偵偼iOutput偼晄梫偱偁傞丅
劆												iStack			劊iOutput偲iStack偼丄堦庤弴枅偵忢偵堦抳偡傞偐傜偱偡丅~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num			劉
劆			劆								nInput	劆			劆
劆			伀								伀	伀			劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		侾	劆丂亊丂劆丂乮丂劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆(嬻偒)劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆											仾	仾			劆
劆											iOutput	劆			劆
劆												iStack			劆
劆															劆偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵乽侾傪堦帪揑側曄悢偵庢傝弌偟偨乿傛偆偵昤偄偰偄傞偑丄
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆幚嵺偵偼丄width偑晄掕側偺偱堦帪揑側曄悢偵庢傝弌偡帠偼弌棃側偄丅
劆															劆幚嵺偵偼丄base[0]乣base[iStack*width]偺斖埻傪'memrotate'偡傞丅
劆			base									num			劆
劆			劆								nInput	劆			劆
劆			伀								伀	伀			劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆			劆丂亊丂劆丂乮丂劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆												仾			劆
劆												iOutput			劆
劆												iStack			劊
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num			劉
劆			劆							nInput		劆			劆
劆			伀							伀		伀			劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		亊	劆丂乮丂劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆(嬻偒)劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆											仾	仾			劆
劆											iOutput	劆			劆
劆												iStack			劆
劆															劆偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵乽亊傪堦帪揑側曄悢偵庢傝弌偟偨乿傛偆偵昤偄偰偄傞偑丄
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆幚嵺偵偼丄width偑晄掕側偺偱堦帪揑側曄悢偵庢傝弌偡帠偼弌棃側偄丅
劆															劆幚嵺偵偼丄base[0]乣base[iStack*width]偺斖埻傪'memrotate'偡傞丅
劆			base									num			劆
劆			劆							nInput		劆			劆
劆			伀							伀		伀			劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆			劆丂乮丂劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂亊丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆											仾				劆
劆											iOutput				劆
劆											iStack				劊
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆						nInput			劆
劆			伀						伀			伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆		乮	劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆(嬻偒)劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆										仾	仾
劆										iOutput	劆
劆											iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆						nInput			劆
劆			伀						伀			伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂俀丂劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆										仾
劆										iOutput	
劆										iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆					nInput				劆
劆			伀					伀				伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆		俀	劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆(嬻偒)劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆									仾	仾
劆									iOutput	劆
劆										iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆					nInput				劆
劆			伀					伀				伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂亄丂劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆										仾
劆										iOutput
劆										iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆				nInput					劆
劆			伀				伀					伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆		亄	劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆(嬻偒)劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆									仾	仾
劆									iOutput	劆
劆										iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆				nInput					劆
劆			伀				伀					伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂俁丂劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂亄丂劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆									仾
劆									iOutput
劆									iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆			nInput						劆
劆			伀			伀						伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆		俁	劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆(嬻偒)劆丂亄丂劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆								仾	仾
劆								iOutput	劆
劆									iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num
劆			劆			nInput						劆
劆			伀			伀						伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂乯丂劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂乮丂劆丂亊丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆									仾
劆									iOutput
劆									iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base									num			劉
劆			劆		nInput							劆			劆
劆			伀		伀							伀			劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		乯	劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆(嬻偒)劆丂亄丂劆丂乮丂劆丂亊丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆								仾	仾						劆
劆								iOutput	劆						劆
劆									iStack						劆
劆															劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆
劆															劆仭岺晇偟偨揰仭
劆			base								num				劆
劆			劆		nInput						劆				劆尦乆偺憖幵応傾儖僑儕僘儉偱偼丄乽乮乿乽乯乿乽丆乿僩乕僋儞偼扨偵幪偰傞偩偗側偺偩偑丄傕偟摦揑儊儌儕傪巊梡偟偰偄偨応崌偵丄儊儌儕儕乕僋偑敪惗偡傞嫲傟偑桳傞丅
劆			伀		伀						伀				劆摉幚憰偱偼丄傾僾儕働乕僔儑儞偑屻偱乽乮乿乽乯乿乽丆乿僩乕僋儞偺儊儌儕傪夝曻弌棃傞傛偆偵丄乽乮乿乽乯乿乽丆乿僩乕僋儞傪幪偰偢偵枛旜偵奿擺偟偰偍偔帠偵偟偨丅
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		乯	劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂乮丂劆丂亊丂劆(嬻偒)劆			劆偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵乽乯傪堦帪揑側曄悢偵庢傝弌偟偨乿傛偆偵昤偄偰偄傞偑丄
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆幚嵺偵偼丄width偑晄掕側偺偱堦帪揑側曄悢偵庢傝弌偡帠偼弌棃側偄丅
劆								仾							劆幚嵺偵偼丄base[0]乣base[num*width]偺斖埻傪'memrotate'偡傞丅
劆								iOutput							劆
劆								iStack							劆num埲崀偺椞堟偵偼丄乽乮乿乽乯乿乽丆乿僩乕僋儞偟偐奿擺偝傟側偄偼偢偱偁傞丅
劆															劆偙偺椞堟傪丄僩儔僢僔儏僶僢僼傽偲屇傇帠偵偟偨丅
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆
劆															劆
劆			base								num				劆
劆			劆		nInput						劆				劆
劆			伀		伀						伀				劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆			劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂乮丂劆丂亊丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆								仾							劆
劆								iOutput							劆
劆								iStack							劊
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base								num				劉
劆			劆		nInput						劆				劆
劆			伀		伀						伀				劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		亄	劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆(嬻偒)劆丂乮丂劆丂亊丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆								仾	仾						劆
劆								iOutput	劆						劆
劆									iStack						劆
劆															劆偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵乽亄傪堦帪揑側曄悢偵庢傝弌偟偨乿傛偆偵昤偄偰偄傞偑丄
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆幚嵺偵偼丄width偑晄掕側偺偱堦帪揑側曄悢偵庢傝弌偡帠偼弌棃側偄丅
劆															劆幚嵺偵偼丄iStack傪+1偡傞偩偗偱偁傞丅
劆			base								num				劆
劆			劆		nInput						劆				劆
劆			伀		伀						伀				劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆			劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂乮丂劆丂亊丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆									仾						劆
劆									iOutput						劆
劆									iStack						劊
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base								num				劉
劆			劆		nInput						劆				劆
劆			伀		伀						伀				劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		乮	劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆(嬻偒)劆丂亊丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆									仾	仾					劆
劆									iOutput	劆					劆
劆										iStack					劆
劆															劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆
劆															劆
劆			base							num					劆
劆			劆		nInput					劆					劆
劆			伀		伀					伀					劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵乽乮傪堦帪揑側曄悢偵庢傝弌偟偨乿傛偆偵昤偄偰偄傞偑丄
劆		乮	劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆(嬻偒)劆丂乯丂劆			劆幚嵺偵偼丄width偑晄掕側偺偱堦帪揑側曄悢偵庢傝弌偡帠偼弌棃側偄丅
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆幚嵺偵偼丄base[iStack*width]乣base[num*width]偺斖埻傪'memrotate'偡傞丅
劆									仾						劆
劆									iOutput						劆
劆									iStack						劆
劆															劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆
劆															劆
劆			base							num					劆
劆			劆		nInput					劆					劆
劆			伀		伀					伀					劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆			劆丂亅丂劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆丂乮丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆									仾						劆
劆									iOutput						劆
劆									iStack						劊
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base							num					劉
劆			劆	nInput						劆					劆
劆			伀	伀						伀					劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆		亅	劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆(嬻偒)劆丂亊丂劆丂乮丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆								仾	仾						劆
劆								iOutput	劆						劆
劆									iStack						劆
劆															劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆
劆															劆
劆			base							num					劆
劆			劆	nInput						劆					劆
劆			伀	伀						伀					劆偙偺恾偱偼丄傢偐傝傗偡偝偺偨傔偵乽亅傪堦帪揑側曄悢偵庢傝弌偟偨乿傛偆偵昤偄偰偄傞偑丄
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆幚嵺偵偼丄width偑晄掕側偺偱堦帪揑側曄悢偵庢傝弌偡帠偼弌棃側偄丅
劆		亅	劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆(嬻偒)劆丂乮丂劆丂乯丂劆			劆幚嵺偵偼丄埲壓偺傛偆偵張棟偡傞丅
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆墘嶼巕偺桪愭弴埵偺斾妑忦審偑惉棫偡傞偐丄僗僞僢僋偑嬻偵側傞傑偱丄iStack傪+1偡傞丅
劆									仾	仾					劆墘嶼巕偺桪愭弴埵偺斾妑忦審偑惉棫偟偨傜丄base[0]乣base[iStack*width]偺斖埻傪'memrotate'偡傞丅
劆									iOutput	劆					劆
劆										iStack					劆
劆															劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣	劆
劆															劆
劆			base							num					劆
劆			劆	nInput						劆					劆
劆			伀	伀						伀					劆
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉			劆
劆			劆丂係丂劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆丂亅丂劆丂乮丂劆丂乯丂劆			劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊			劆
劆									仾						劆
劆									iOutput						劆
劆									iStack						劊
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base							num
劆			nInput							劆
劆			伀							伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆		係	劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆(嬻偒)劆丂亅丂劆丂乮丂劆丂乯丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆								仾	仾
劆								iOutput	劆
劆									iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base							num
劆			nInput							劆
劆			伀							伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆丂係丂劆丂亅丂劆丂乮丂劆丂乯丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆									仾
劆									iOutput
劆									iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base							num
劆			nInput							劆
劆			伀							伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆		亅	劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆丂係丂劆(嬻偒)劆丂乮丂劆丂乯丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆									仾	仾
劆									iOutput	劆
劆										iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
劆			base							num
劆			nInput							劆
劆			伀							伀
劆			劇劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劍劅劅劅劉
劆			劆丂侾丂劆丂俀丂劆丂俁丂劆丂亄丂劆丂亊丂劆丂係丂劆丂亅丂劆丂乮丂劆丂乯丂劆
劆			劋劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劏劅劅劅劊
劆										仾
劆										iOutput
劆										iStack
劆
劆	乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣乣
劆
仭傑偲傔傞偲丄攝楍偵懳偟偰幚嵺偵峴偆憖嶌偼丄埲壓偺捠傝偱偡丅
劆
劆	丒擖椡僉儏乕偑嬻偱側偄偐傪挷傋傞丅
劆
劆		(nInput)
劆
劆	丒僗僞僢僋偑嬻偱側偄偐傪挷傋傞丅
劆
劆		(iStack < num)
劆
劆	丒擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傊偺億僀儞僞傪庢摼偡傞丅
劆
劆		base
劆
劆	丒僗僞僢僋偺僩僢僾偵偁傞僩乕僋儞傊偺億僀儞僞傪庢摼偡傞丅
劆
劆		&base[iStack * width]
劆
劆	丒擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傪丄弌椡僉儏乕偵捛壛偡傞丅
劆
劆		memrotate(base, -width, iStack * width)
劆		nInput--
劆
劆	丒擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傪丄僗僞僢僋偵僾僢僔儏偡傞丅
劆
劆		memrotate(base, -width, iStack * width)
劆		nInput--
劆		iStack--
劆
劆	丒僗僞僢僋偐傜墘嶼巕傪億僢僾偟偰弌椡僉儏乕偵捛壛偡傞丅
劆
劆		iStack++
劆
劆	丒擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傪丄僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
劆
劆		memrotate(base, -width, num * width)
劆		nInput--
劆		iStack--
劆		num--
劆
劆	丒僗僞僢僋偺僩僢僾偵偁傞僩乕僋儞傪丄僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
劆
劆		memrotate(&base[iStack * width], -width, (num - iStack) * width)
劆		num--
劆
#endif
/****************************************************************************
 *	婎杮揑側娭悢
 ****************************************************************************/
typedef struct _ST_ExprSort {
	char*	const	base;		//攝楍偺愭摢傾僪儗僗			屌掕抣
	int		num;		//僩儔僢僔儏僶僢僼傽偺奐巒埵抲
	int	const	width;		//僩乕僋儞偺僶僀僩悢			屌掕抣
	int		nInput;		//擖椡僉儏乕偺巆傝僩乕僋儞悢
	int		iStack;		//僗僞僢僋僩僢僾偺埵抲
} ST_ExprSort;
/*--------------------------------------------------------------------------*/
//擖椡僉儏乕偑嬻偱側偗傟偽丄擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傊偺億僀儞僞傪曉偡丅
//擖椡僉儏乕偑嬻側傜偽丄NULL傪曉偡丅
static void* exprsort_GetInputToken(ST_ExprSort* pExprSort) {
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
	return pExprSort->nInput ? pExprSort->base : NULL;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//僗僞僢僋偑嬻偱側偗傟偽丄僗僞僢僋偺僩僢僾偵桳傞僩乕僋儞傊偺億僀儞僞傪曉偡丅
//僗僞僢僋偑嬻側傜偽丄NULL傪曉偡丅
static void* exprsort_GetStackToken(ST_ExprSort* pExprSort) {
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
	return (pExprSort->iStack < pExprSort->num) ? &pExprSort->base[pExprSort->iStack * pExprSort->width] : NULL;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傪丄弌椡僉儏乕偵捛壛偡傞丅
static void exprsort_MoveInputToOutput(ST_ExprSort* pExprSort) {
	memrotate(exprsort_GetInputToken(pExprSort), -pExprSort->width, pExprSort->iStack * pExprSort->width);
	pExprSort->nInput--;
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傪丄僗僞僢僋偵僾僢僔儏偡傞丅
static void exprsort_MoveInputToStack(ST_ExprSort* pExprSort) {
	exprsort_MoveInputToOutput(pExprSort);	//嫟捠張棟
	pExprSort->iStack--;
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//僗僞僢僋偐傜墘嶼巕傪億僢僾偟偰弌椡僉儏乕偵捛壛偡傞丅
static void exprsort_MoveStackToOutput(ST_ExprSort* pExprSort) {
	pExprSort->iStack++;
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//擖椡僉儏乕偺愭摢偵桳傞僩乕僋儞傪丄僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
static void exprsort_MoveInputToTrash(ST_ExprSort* pExprSort) {
	memrotate(exprsort_GetInputToken(pExprSort), -pExprSort->width, pExprSort->num * pExprSort->width);
	pExprSort->nInput--;
	pExprSort->iStack--;
	pExprSort->num--;
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//僗僞僢僋偺僩僢僾偵偁傞僩乕僋儞傪丄僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
static void exprsort_MoveStackToTrash(ST_ExprSort* pExprSort) {
	memrotate(exprsort_GetStackToken(pExprSort), -pExprSort->width, (pExprSort->num - pExprSort->iStack) * pExprSort->width);
	pExprSort->num--;
#ifdef  _DEBUG
	if((pExprSort->num < 0) || (pExprSort->width < 0) || (pExprSort->nInput < 0) || (pExprSort->iStack < 0) ||
	   (pExprSort->nInput > pExprSort->iStack) || (pExprSort->iStack > pExprSort->num)) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
}
/*--------------------------------------------------------------------------*/
int exprsort(void* base, size_t num, size_t width,
  int (*fnGetTokenType)(const void* pToken),					//傾僾儕働乕僔儑儞掕媊偺娭悢:僩乕僋儞偺庬椶傪曉偡丅		exprsort_TokenType_乣偺偄偢傟偐偺抣傪曉偟偰壓偝偄丅
  int (*fnIsOpLeftAssoc)(const void* pOpTok),					//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偑嵍寢崌偐傪曉偡丅		嵍寢崌側傜偽0埲奜偺抣,塃寢崌側傜偽0傪曉偟偰壓偝偄丅
  int (*fnCompareOpPrec)(const void* pOpTok1, const void* pOpTok2),		//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偺桪愭弴埵傪妑傋傞丅		pOpTok1偺桪愭弴埵偑崅偗傟偽惓偺抣,pOpTok2偺桪愭弴埵偑崅偗傟偽晧偺抣,摨偠側傜偽0傪曉偟偰壓偝偄丅
  void (*fnIncrFnNumArgs/*NULL壜*/)(void* pFnTok)) {				//傾僾儕働乕僔儑儞掕媊偺娭悢:娭悢偺幚堷悢偺悢傪捠抦偡傞丅	幚堷悢偺悢偺夞悢暘屇傃弌偝傟傞丅屄乆偺娭悢僩乕僋儞偵幚堷悢偺悢傪婰榐偟偰偍偒丄幚堷悢偺悢偑惓偟偄帠傪専嵏偟偨傝丄壜曄堷悢偵懳墳偡傞帠傕弌棃傞丅	幃偺拞偱娭悢傪巊梡偟偰偄側偄,枖偼,娭悢傪巊梡偟偰偄偰傕捠抦偑晄梫側傜偽丄NULL傪巜掕弌棃傑偡丅
	return exprsort_r(base, num, width,
		(int (*)(const void*, void*))fnGetTokenType,
		(int (*)(const void*, void*))fnIsOpLeftAssoc,
		(int (*)(const void*, const void*, void*))fnCompareOpPrec,
		(void (*)(void*, void*))fnIncrFnNumArgs,
		NULL);
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
int exprsort_r(void* base, size_t num, size_t width,
  int (*fnGetTokenType)(const void* pToken, void* arg),				//傾僾儕働乕僔儑儞掕媊偺娭悢:僩乕僋儞偺庬椶傪曉偡丅		exprsort_TokenType_乣偺偄偢傟偐偺抣傪曉偟偰壓偝偄丅
  int (*fnIsOpLeftAssoc)(const void* pOpTok, void* arg),			//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偑嵍寢崌偐傪曉偡丅		嵍寢崌側傜偽0埲奜偺抣,塃寢崌側傜偽0傪曉偟偰壓偝偄丅
  int (*fnCompareOpPrec)(const void* pOpTok1, const void* pOpTok2, void* arg),	//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偺桪愭弴埵傪妑傋傞丅		pOpTok1偺桪愭弴埵偑崅偗傟偽惓偺抣,pOpTok2偺桪愭弴埵偑崅偗傟偽晧偺抣,摨偠側傜偽0傪曉偟偰壓偝偄丅
  void (*fnIncrFnNumArgs/*NULL壜*/)(void* pFnTok, void* arg),			//傾僾儕働乕僔儑儞掕媊偺娭悢:娭悢偺幚堷悢偺悢傪捠抦偡傞丅	幚堷悢偺悢偺夞悢暘屇傃弌偝傟傞丅屄乆偺娭悢僩乕僋儞偵幚堷悢偺悢傪婰榐偟偰偍偒丄幚堷悢偺悢偑惓偟偄帠傪専嵏偟偨傝丄壜曄堷悢偵懳墳偡傞帠傕弌棃傞丅	幃偺拞偱娭悢傪巊梡偟偰偄側偄,枖偼,娭悢傪巊梡偟偰偄偰傕捠抦偑晄梫側傜偽丄NULL傪巜掕弌棃傑偡丅
  void* arg) {
	ST_ExprSort stExprSort = {
		base,	//base
		num,	//num
		width,	//width
		num,	//nInput
		num,	//iStack
	};
	void *pToken1, *pToken2;
	int iTokenType;
	//仩嶲徠帒椏
	//劆乽Wikipedia - 憖幵応傾儖僑儕僘儉乿(https://ja.wikipedia.org/wiki/憖幵応傾儖僑儕僘儉)	(2016/06/24帪揰)
	//劆埲壓偺僐儊儞僩偼丄忋婰偺儁乕僕偺乽傾儖僑儕僘儉偺徻嵶乿偺愢柧暥偲1:1偵懳墳偟偰偄傑偡丅
	//撉傒崬傓傋偒僩乕僋儞偑偁傞娫丄埲壓傪孞傝曉偡丅
	//僩乕僋儞傪1偮撉傒崬傓丅
	while((pToken1 = exprsort_GetInputToken(&stExprSort))) {
		switch((*fnGetTokenType)(pToken1, arg)) {
		default:DIE();	//偙偙偱僄儔乕掆巭偟偨傜傾僾儕働乕僔儑儞掕媊偺fnGetTokenType娭悢偺僶僌偱偡丅
		//僩乕僋儞偑悢抣偺応崌丄
		case exprsort_TokenType_Number:
			//偦傟傪弌椡僉儏乕偵捛壛偡傞丅
			exprsort_MoveInputToOutput(&stExprSort);
			break;
		//僩乕僋儞偑娭悢偺応崌丄
		case exprsort_TokenType_Function:
			//偦傟傪僗僞僢僋偵僾僢僔儏偡傞丅
			exprsort_MoveInputToStack(&stExprSort);										//偙傟偵傛偭偰丄pToken1偼娭悢僩乕僋儞傪巜偝側偔側偭偰偄傞偺偱乧	劅劅劅劅劉嘆
//{{嶲徠帒椏偺憖幵応傾儖僑儕僘儉偵偼柍偄撈帺張棟											//									劆
			//娭悢偺幚堷悢偺悢傪捠抦偡傞娭悢偑巜掕偝傟偰偄偨傜乧								//									劆
			if(fnIncrFnNumArgs) {												//									劆
				//忋偺張棟偱僗僞僢僋偺僩僢僾偵堏摦偟偨丄娭悢僩乕僋儞偺傾僪儗僗傪嵞庢摼偡傞丅				//									劆
				pToken1 = exprsort_GetStackToken(&stExprSort);								//pToken1偑娭悢僩乕僋儞傪巜偡傛偆偵丄傾僪儗僗傪嵞庢摼偟偰偍偔丅	劅劅劅劅劎嘇
				//堷悢偑柍偄娭悢偼丄偙偙偱敾掕偟偰姰寢偝偣傞丅								//									劆
				// - 堷悢偑柍偄娭悢傪摿暿埖偄偡傞棟桼偼丄乽fn()乿偲乽fn(1)乿偼偳偪傜傕乽丆乿偑柍偔丄僗僞僢僋偵愊傫偱偟傑偆偲屻偱嬫暿弌棃側偔側傞偐傜偱偡丅					劆
				//   娭悢偺幚堷悢偺悢傪捠抦偡傞娭悢偑巜掕偝傟偰偄側偗傟偽丄椉幰傪嬫暿偡傞昁梫偼柍偄偺偱丄堷悢偑柍偄娭悢傪偙偙偱敾掕偡傞昁梫偼柍偄偺偱偡偑丄					劆
				//   娭悢偺幚堷悢偺悢傪捠抦偡傞娭悢偑巜掕偝傟偰偄傞応崌偼丄幚堷悢偺悢偺夞悢暘fnIncrFnNumArgs傪屇傃弌偡偨傔偵丄偙偙偱敾掕偡傞昁梫偑桳傝傑偡丅					劆
				pToken2 = exprsort_GetInputToken(&stExprSort);								//娭悢偺捈屻偺僩乕僋儞傪庢摼偡傞丅					劆
				if(!pToken2 || ((*fnGetTokenType)(pToken2, arg) != exprsort_TokenType_LeftParenthesis)) { DIE(); }	//娭悢偺捈屻偵嵍妵屖偑柍偗傟偽擖椡幃偺僄儔乕丅				劆
				exprsort_MoveInputToStack(&stExprSort);									//嵍妵屖傪僗僞僢僋偵僾僢僔儏偡傞丅					劆	嘇乣嘊偺娫偵僗僞僢僋慡懱偑偢傟傞傛偆側張棟傪擖傟側偄傛偆偵拲堄偣傛丅偙偺峴偺exprsort_MoveInputToStack()偼僗僞僢僋僩僢僾傪曄壔偝偣傞偑丄嘇偱嵞庢摼偟偰偍偄偨娭悢僩乕僋儞偺埵抲偼曄傢傜側偄偺偱戝忎晇偱偡丅
				pToken2 = exprsort_GetInputToken(&stExprSort);								//嵍妵屖偺捈屻偺僩乕僋儞傪庢摼偡傞丅					劆
				if(pToken2 && ((*fnGetTokenType)(pToken2, arg) == exprsort_TokenType_RightParenthesis)) {		//嵍妵屖偺捈屻偵塃妵屖偑桳傟偽乧					劆
					exprsort_MoveInputToTrash(&stExprSort);								//塃妵屖傪僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅				劆
					exprsort_MoveStackToTrash(&stExprSort);								//嵍妵屖傪僗僞僢僋偐傜億僢僾偟偰僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅		劆
					exprsort_MoveStackToOutput(&stExprSort);							//娭悢傪僗僞僢僋偐傜億僢僾偟偰弌椡僉儏乕偵捛壛偡傞丅			劆
				} else {												//堷悢偑桳傞娭悢側傜偽乧						劆
					(*fnIncrFnNumArgs)(pToken1, arg);								//娭悢偵嵟弶偺堷悢偑桳傞帠傪捠抦偡傞丅	仼劅劅劅劅劅劅劅劅劅劅劅劅劅劅劅劊嘊
					//偙傟埲崀偼丄乽丆乿偑弌偰棃傞搙偵丄捈嬤偺娭悢偺幚堷悢偺悢傪憹傗偟偰峴偔丅
				}
			}
//}}嶲徠帒椏偺憖幵応傾儖僑儕僘儉偵偼柍偄撈帺張棟
			break;
		//僩乕僋儞偑娭悢偺堷悢僙僷儗乕僞(僇儞儅側偳)偺応崌
		case exprsort_TokenType_FunctionArgumentSeparator:
			exprsort_MoveInputToTrash(&stExprSort);		//摉幚憰偱偼乽乮乿乽乯乿乽丆乿傪幪偰偢偵僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
			//僗僞僢僋偺僩僢僾偵偁傞僩乕僋儞偑嵍妵屖偲側傞傑偱丄僗僞僢僋偐傜墘嶼巕傪億僢僾偟偰弌椡僉儏乕偵捛壛偡傞摦嶌傪孞傝曉偡丅
			//嵍妵屖偑弌偰偙側偄応崌丄堷悢僙僷儗乕僞偺埵抲偑偍偐偟偄偐丄嵍塃偺妵屖偑晄堦抳偲側偭偰偄傞(僄儔乕)丅
			for(;;) {
				if(!(pToken2 = exprsort_GetStackToken(&stExprSort))) { DIE(); }	//嵍妵屖偑弌偰棃傞慜偵僗僞僢僋偑嬻偵側偭偨傜擖椡幃偺僄儔乕丅椺偊偽乽1,2乿偲彂偄偨応崌偙偙偱僄儔乕掆巭偡傞丅
				iTokenType = (*fnGetTokenType)(pToken2, arg);
				if(iTokenType == exprsort_TokenType_LeftParenthesis) { break; }
				if(iTokenType != exprsort_TokenType_Operator) { DIE(); }	//嵍妵屖,枖偼,墘嶼巕埲奜偑弌偰棃偨傜擖椡幃偺僄儔乕丅嬶懱揑偵偼娭悢偑弌偰棃偨傜僄儔乕丅椺偊偽乽function(1,2)乿偲彂偔傋偒強乽function 1,2乿偲彂偄偨応崌偙偙偱僄儔乕掆巭偡傞丅
				exprsort_MoveStackToOutput(&stExprSort);
			}
//{{嶲徠帒椏偺憖幵応傾儖僑儕僘儉偵偼柍偄撈帺張棟
			//娭悢偺幚堷悢偺悢傪捠抦偡傞娭悢偑巜掕偝傟偰偄偨傜乧
			if(fnIncrFnNumArgs) {
				//僗僞僢僋偺僩僢僾偵偁傞嵍妵屖偺丄師偺僩乕僋儞偑娭悢僩乕僋儞側傜偽乧
				if((stExprSort.iStack + 1) < stExprSort.num) {
					pToken2 = &stExprSort.base[(stExprSort.iStack + 1) * stExprSort.width];
					if((*fnGetTokenType)(pToken2, arg) == exprsort_TokenType_Function) {
						//娭悢偵師偺堷悢偑桳傞帠傪捠抦偡傞丅
						(*fnIncrFnNumArgs)(pToken2, arg);
					}
				}
			}
//}}嶲徠帒椏偺憖幵応傾儖僑儕僘儉偵偼柍偄撈帺張棟
			break;
		//僩乕僋儞偑墘嶼巕o1偺応崌:
		case exprsort_TokenType_Operator:
			//僗僞僢僋偺僩僢僾偵墘嶼巕僩乕僋儞o2偑偁傝丄o1偑嵍寢崌惈偱丄偐偮桪愭弴埵偑o2偲摍偟偄偐掅偄応崌丄偁傞偄偼丄o1偺桪愭弴埵偑o2傛傝掅偄応崌丄埲壓傪孞傝曉偡丅
			while((pToken2 = exprsort_GetStackToken(&stExprSort)) &&						//僗僞僢僋偺僩僢僾偵
			      ((*fnGetTokenType)(pToken2, arg) == exprsort_TokenType_Operator) &&				//墘嶼巕僩乕僋儞o2偑偁傝丄
			      (((*fnIsOpLeftAssoc)(pToken1, arg) && ((*fnCompareOpPrec)(pToken1, pToken2, arg) <= 0)) ||	//o1偑嵍寢崌惈偱丄偐偮桪愭弴埵偑o2偲摍偟偄偐掅偄応崌丄
			                                            ((*fnCompareOpPrec)(pToken1, pToken2, arg) <  0))) {	//偁傞偄偼丄o1偺桪愭弴埵偑o2傛傝掅偄応崌丄埲壓傪孞傝曉偡丅
				//o2傪僗僞僢僋偐傜億僢僾偟丄弌椡僉儏乕偵捛壛偡傞丅
				exprsort_MoveStackToOutput(&stExprSort);
			}
			//o1傪僗僞僢僋偵僾僢僔儏偡傞丅
			exprsort_MoveInputToStack(&stExprSort);
			break;
		//僩乕僋儞偑嵍妵屖偺応崌丄
		case exprsort_TokenType_LeftParenthesis:
			//僗僞僢僋偵僾僢僔儏偡傞丅
			exprsort_MoveInputToStack(&stExprSort);
			break;
		//僩乕僋儞偑塃妵屖偺応崌
		case exprsort_TokenType_RightParenthesis:
			exprsort_MoveInputToTrash(&stExprSort);		//摉幚憰偱偼乽乮乿乽乯乿乽丆乿傪幪偰偢偵僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
			//僗僞僢僋偺僩僢僾偵偁傞僩乕僋儞偑嵍妵屖偵側傞傑偱丄僗僞僢僋偐傜億僢僾偟偨墘嶼巕傪弌椡僉儏乕偵捛壛偡傞摦嶌傪孞傝曉偡丅
			//嵍妵屖偑僗僞僢僋忋偵尒偮偐傜側偐偭偨応崌丄嵍塃偺妵屖偺晄堦抳偑偁傞(僄儔乕)丅
			for(;;) {
				if(!(pToken2 = exprsort_GetStackToken(&stExprSort))) { DIE(); }	//嵍妵屖偑弌偰棃傞慜偵僗僞僢僋偑嬻偵側偭偨傜擖椡幃偺僄儔乕丅椺偊偽乽1,2乿偲彂偄偨応崌偙偙偱僄儔乕掆巭偡傞丅
				iTokenType = (*fnGetTokenType)(pToken2, arg);
				if(iTokenType == exprsort_TokenType_LeftParenthesis) { break; }
				if(iTokenType != exprsort_TokenType_Operator) { DIE(); }	//嵍妵屖,枖偼,墘嶼巕埲奜偑弌偰棃偨傜擖椡幃偺僄儔乕丅嬶懱揑偵偼娭悢偑弌偰棃偨傜僄儔乕丅椺偊偽乽function(1,2)乿偲彂偔傋偒強乽function 1,2)乿偲彂偄偨応崌偙偙偱僄儔乕掆巭偡傞丅
				exprsort_MoveStackToOutput(&stExprSort);
			}
			//嵍妵屖傪僗僞僢僋偐傜億僢僾偡傞偑丄弌椡偵偼捛壛偣偢偵幪偰傞丅
			exprsort_MoveStackToTrash(&stExprSort);		//摉幚憰偱偼乽乮乿乽乯乿乽丆乿傪幪偰偢偵僩儔僢僔儏僶僢僼傽偵捛壛偡傞丅
			//僗僞僢僋偺僩僢僾偵偁傞僩乕僋儞偑娭悢僩乕僋儞側傜丄偦傟傪億僢僾偟偰弌椡僉儏乕偵捛壛偡傞丅
			if((pToken2 = exprsort_GetStackToken(&stExprSort)) &&
			   ((*fnGetTokenType)(pToken2, arg) == exprsort_TokenType_Function)) {
				exprsort_MoveStackToOutput(&stExprSort);
			}
			break;
		}
	}
	//撉傒崬傓傋偒僩乕僋儞偑側偄応崌
	//僗僞僢僋忋偵墘嶼巕僩乕僋儞偑偁傞娫丄埲壓傪孞傝曉偡丅
	while((pToken1 = exprsort_GetStackToken(&stExprSort))) {
		//僗僞僢僋偺僩僢僾偵偁傞墘嶼巕僩乕僋儞偑妵屖側傜丄妵屖偺晄堦抳偑偁傞(僄儔乕)丅
		if((*fnGetTokenType)(pToken1, arg) != exprsort_TokenType_Operator) { DIE(); }	//墘嶼巕埲奜偑弌偰棃偨傜擖椡幃偺僄儔乕丅嬶懱揑偵偼嵍妵屖傗娭悢偑弌偰棃偨傜僄儔乕丅椺偊偽乽function()乿偲彂偔傋偒強乽function乿偲彂偄偨応崌偙偙偱僄儔乕掆巭偡傞丅
		//墘嶼巕傪僗僞僢僋偐傜億僢僾偟偰弌椡僉儏乕偵捛壛偡傞丅
		exprsort_MoveStackToOutput(&stExprSort);
	}
	//廔椆
#ifdef  _DEBUG
	if(stExprSort.num != stExprSort.iStack) { DIE(); }	//偙偙偱僄儔乕掆巭偟偨傜摉儌僕儏乕儖偺僶僌偱偡丅
#endif//_DEBUG
	return stExprSort.num;	//弌椡僉儏乕偵捛壛偟偨僩乕僋儞悢傪曉偡丅
}
/****************************************************************************
 *	儐乕僥傿儕僥傿娭悢偺慖戰
 ****************************************************************************/
#define USE_EXPREVAL_NEWVER	//偙偺僔儞儃儖傪掕媊偟側偗傟偽丄乽惍悢斉丆摦揑儊儌儕妋曐柍偟乿斉偺expreval()傪桳岠偵偟傑偡丅偙偺僔儞儃儖傪掕媊偡傟偽丄乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉偺expreval()傪桳岠偵偟傑偡丅2016/06/24尰嵼偼丄乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉偺expreval()傪桳岠偵偟偰偄傑偡丅
#ifndef USE_EXPREVAL_NEWVER
/****************************************************************************
 *	儐乕僥傿儕僥傿娭悢	惍悢斉丆摦揑儊儌儕妋曐柍偟
 ****************************************************************************/
//乽惍悢斉丆摦揑儊儌儕妋曐柍偟乿斉偺expreval()偼丄clipshya.c偺ShuntingYard_Eval()傪丄傎傏偦偺傑傑堏怉偟偨傕偺偱偡丅
//偙傟偼丄摉儌僕儏乕儖偺嶌惉弶婜偵丄摦嶌妋擣偺偨傔偩偗偵嶌惉偟偨傕偺偱偁傝丄崱屻偼乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉偺expreval()傊堏峴偡傞梊掕偱偡丅
//偨偩偟丄摦揑儊儌儕妋曐柍偟偱偁傞揰傗丄expreval_PostProcess()偱僗僞僢僋儊儌儕偺徚旓検傪尭傜偟偰偄傞揰偼丄儊儌儕偺惂栺偑尩偟偄娐嫬偵偼揔偟偰偄傞帠傕桳傞偐偲巚偆偺偱丄僐乕僪偼巆偟偰偍偔帠偵偟傑偟偨丅
/*--------------------------------------------------------------------------*/
#undef  BUFLEN
#define BUFLEN	64	//挷惍壜
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//偙偺僒儞僾儖偑懳墳偟偰偄傞幃偺梫慺
enum {
	op_umi=INT_MIN,	//墘嶼巕:-(扨崁)
	op_pow,		//墘嶼巕:^
	op_add,		//墘嶼巕:+
	op_sub,		//墘嶼巕:-(擇崁)
	op_mul,		//墘嶼巕:*
	op_div,		//墘嶼巕:/
	fn_rnd,		//娭悢:rnd
	fn_abs,		//娭悢:abs
	fn_mod,		//娭悢:mod
	fn_sep,		//娭悢偺堷悢僙僷儗乕僞(僇儞儅側偳):,
	lf_par,		//嵍妵屖:(
	ri_par,		//塃妵屖:)
	nu_min,		//悢抣偺嵟彫抣
};
/*--------------------------------------------------------------------------*/
//傾僾儕働乕僔儑儞掕媊偺娭悢:僩乕僋儞偺庬椶傪曉偡丅
static int expreval_GetTokenType(const void* pToken) {
	int iToken = *(int*)pToken;
	switch(iToken) {
	case op_umi:	//墘嶼巕:-(扨崁)
	case op_pow:	//墘嶼巕:^
	case op_add:	//墘嶼巕:+
	case op_sub:	//墘嶼巕:-(擇崁)
	case op_mul:	//墘嶼巕:*
	case op_div:	//墘嶼巕:/
		return exprsort_TokenType_Operator;
	case fn_rnd:	//娭悢:rnd
	case fn_abs:	//娭悢:abs
	case fn_mod:	//娭悢:mod
		return exprsort_TokenType_Function;
	case fn_sep:	//娭悢偺堷悢僙僷儗乕僞(僇儞儅側偳)
		return exprsort_TokenType_FunctionArgumentSeparator;
	case lf_par:	//嵍妵屖
		return exprsort_TokenType_LeftParenthesis;
	case ri_par:	//塃妵屖
		return exprsort_TokenType_RightParenthesis;
	//case nu_min:	//悢抣
	default:
		return exprsort_TokenType_Number;
	}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偑嵍寢崌偐傪曉偡丅
static int expreval_IsOpLeftAssoc(const void* pOpTok) {
	int iOpTok = *(int*)pOpTok;
	switch(iOpTok) {
	default:DIE();
	case op_umi:	//墘嶼巕:-(扨崁)
	case op_pow:	//墘嶼巕:^
		return 0;
	case op_add:	//墘嶼巕:+
	case op_sub:	//墘嶼巕:-(擇崁)
	case op_mul:	//墘嶼巕:*
	case op_div:	//墘嶼巕:/
		return 1;
	}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偺桪愭弴埵傪妑傋傞丅
static int expreval_CompareOpPrec(const void* pOpTok1, const void* pOpTok2) {
	int iOpTok1 = *(int*)pOpTok1;
	int iOpTok2 = *(int*)pOpTok2;
	switch(iOpTok1) {
	default:DIE();
	case op_umi:	//墘嶼巕:-(扨崁)
		iOpTok1 = 2; break;
	case op_pow:	//墘嶼巕:^
		iOpTok1 = 3; break;
	case op_add:	//墘嶼巕:+
	case op_sub:	//墘嶼巕:-(擇崁)
		iOpTok1 = 0; break;
	case op_mul:	//墘嶼巕:*
	case op_div:	//墘嶼巕:/
		iOpTok1 = 1; break;
	}
	switch(iOpTok2) {
	default:DIE();
	case op_umi:	//墘嶼巕:-(扨崁)
		iOpTok2 = 2; break;
	case op_pow:	//墘嶼巕:^
		iOpTok2 = 3; break;
	case op_add:	//墘嶼巕:+
	case op_sub:	//墘嶼巕:-(擇崁)
		iOpTok2 = 0; break;
	case op_mul:	//墘嶼巕:*
	case op_div:	//墘嶼巕:/
		iOpTok2 = 1; break;
	}
	return iOpTok1 - iOpTok2;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//僥僉僗僩傪拞抲婰朄偺僩乕僋儞暲傃偵曄姺偡傞丅
static int expreval_PreProcess(const char* expr, int buf[/*BUFLEN*/]) {
	int c, i = 0;
	while((c = *expr++)) {
		if(!isspace(c)) {
			if(i >= BUFLEN) { DIE(); }
			if(isdigit(c)) {
				buf[i++] = strtoul(expr - 1, (char**)&expr, 0);
			} else if(!strncmp(expr - 1, "rnd", 3)) {
				buf[i++] = fn_rnd;
				expr += (3 - 1);
			} else if(!strncmp(expr - 1, "abs", 3)) {
				buf[i++] = fn_abs;
				expr += (3 - 1);
			} else if(!strncmp(expr - 1, "mod", 3)) {
				buf[i++] = fn_mod;
				expr += (3 - 1);
			} else {
				switch(c) {
				default:DIE();
				case '^': buf[i++] = op_pow;   break;
				case '+': buf[i++] = op_add;   break;
//{{2016/06/24廋惓:嵍曈偺'i++'偲塃曈偺'i'偺昡壙弴彉偼枹掕媊偱偁傝寢壥偑晄掕偲側傞僶僌傪廋惓偟傑偟偨丅廋惓慜偺僐乕僪偱偼丄VC++6.0偱偼塃曈偑愭偵昡壙偝傟傞傛偆偱嬼慠捠傝偺摦嶌偵側傝傑偡偑丄gcc33.exe偱偼嵍曈偑愭偵昡壙偝傟傞傛偆偱晄惓側摦嶌偵側傝傑偟偨丅
//				case '-': buf[i++] = (i && (buf[i-1] >= ri_par)) ? op_sub : op_umi; break;
//伀2016/06/24廋惓:嵍曈偺'i++'偲塃曈偺'i'偺昡壙弴彉偼枹掕媊偱偁傝寢壥偑晄掕偲側傞僶僌傪廋惓偟傑偟偨丅廋惓慜偺僐乕僪偱偼丄VC++6.0偱偼塃曈偑愭偵昡壙偝傟傞傛偆偱嬼慠捠傝偺摦嶌偵側傝傑偡偑丄gcc33.exe偱偼嵍曈偑愭偵昡壙偝傟傞傛偆偱晄惓側摦嶌偵側傝傑偟偨丅
				case '-': if(i && (buf[i-1] >= ri_par)) {
				          buf[i++] = op_sub; } else {
				          buf[i++] = op_umi; } break;
//}}2016/06/24廋惓:嵍曈偺'i++'偲塃曈偺'i'偺昡壙弴彉偼枹掕媊偱偁傝寢壥偑晄掕偲側傞僶僌傪廋惓偟傑偟偨丅廋惓慜偺僐乕僪偱偼丄VC++6.0偱偼塃曈偑愭偵昡壙偝傟傞傛偆偱嬼慠捠傝偺摦嶌偵側傝傑偡偑丄gcc33.exe偱偼嵍曈偑愭偵昡壙偝傟傞傛偆偱晄惓側摦嶌偵側傝傑偟偨丅
				case '*': buf[i++] = op_mul;   break;
				case '/': buf[i++] = op_div;   break;
				case ',': buf[i++] = fn_sep;   break;
				case '(': buf[i++] = lf_par;   break;
				case ')': buf[i++] = ri_par;   break;
				}
			}
		}
	}
	return i;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//媡億乕儔儞僪婰朄偺僩乕僋儞暲傃傪寁嶼偡傞丅
// - clipshya.c偺ShuntingYard_PostProcess()偱偼丄儘乕僇儖曄悢偲偟偰撈棫偟偨僗僞僢僋(aStack[])傪愝偗偰偄傑偟偨偑丄
//   摉幚憰偱偼丄buf[]偺撉傒弌偟嵪傒偺椞堟傪僗僞僢僋偲偟偰棙梡偡傞傛偆偵偟偰丄僗僞僢僋儊儌儕偺徚旓検傪尭傜偟傑偟偨丅
static int expreval_PostProcess(int buf[/*BUFLEN*/], int num) {
	int i, iToken, iStackTop = -1;
	for(i = 0; i < num; i++) {
		iToken = buf[i];
		switch(iToken) {
		case op_umi:	//墘嶼巕:-(扨崁)
			if((iStackTop < 0) || (buf[iStackTop] < nu_min)) { DIE(); }
			buf[iStackTop] = -buf[iStackTop];
			break;
		case op_pow:	//墘嶼巕:^
			if((iStackTop < 1) || (buf[iStackTop] < nu_min) || (buf[iStackTop - 1] < nu_min)) { DIE(); }
			buf[iStackTop - 1] = (int)pow(buf[iStackTop - 1], buf[iStackTop]);
			iStackTop--;
			break;
		case op_add:	//墘嶼巕:+
			if((iStackTop < 1) || (buf[iStackTop] < nu_min) || (buf[iStackTop - 1] < nu_min)) { DIE(); }
			buf[iStackTop - 1] = buf[iStackTop - 1] + buf[iStackTop];
			iStackTop--;
			break;
		case op_sub:	//墘嶼巕:-(擇崁)
			if((iStackTop < 1) || (buf[iStackTop] < nu_min) || (buf[iStackTop - 1] < nu_min)) { DIE(); }
			buf[iStackTop - 1] = buf[iStackTop - 1] - buf[iStackTop];
			iStackTop--;
			break;
		case op_mul:	//墘嶼巕:*
			if((iStackTop < 1) || (buf[iStackTop] < nu_min) || (buf[iStackTop - 1] < nu_min)) { DIE(); }
			buf[iStackTop - 1] = buf[iStackTop - 1] * buf[iStackTop];
			iStackTop--;
			break;
		case op_div:	//墘嶼巕:/
			if((iStackTop < 1) || (buf[iStackTop] < nu_min) || (buf[iStackTop - 1] < nu_min)) { DIE(); }
			if(!buf[iStackTop]) { DIE(); }
			buf[iStackTop - 1] = buf[iStackTop - 1] / buf[iStackTop];
			iStackTop--;
			break;
		case fn_rnd:	//娭悢:rnd
			iStackTop++;
			buf[iStackTop] = rand();
			break;
		case fn_abs:	//娭悢:abs
			if((iStackTop < 0) || (buf[iStackTop] < nu_min)) { DIE(); }
			buf[iStackTop] = abs(buf[iStackTop]);
			break;
		case fn_mod:	//娭悢:mod
			if((iStackTop < 1) || (buf[iStackTop] < nu_min) || (buf[iStackTop - 1] < nu_min)) { DIE(); }
			if(!buf[iStackTop]) { DIE(); }
			buf[iStackTop - 1] = buf[iStackTop - 1] % buf[iStackTop];
			iStackTop--;
			break;
		case fn_sep:	//娭悢偺堷悢僙僷儗乕僞(僇儞儅側偳):,
		case lf_par:	//嵍妵屖:(
		case ri_par:	//塃妵屖:)
			DIE();
		//case nu_min:	//悢抣
		default:
			if(++iStackTop >= num) { DIE(); }
			buf[iStackTop] = iToken;
			break;
		}
	}
	if((iStackTop != 0) || (buf[iStackTop] < nu_min)) { DIE(); }
	return buf[iStackTop];
}
/*--------------------------------------------------------------------------*/
//憖幵応傾儖僑儕僘儉傪棙梡偟偰丄幃僥僉僗僩偺寁嶼傪峴偆丅
double expreval(const char* expr,
  double (*fnGetVar/*NULL壜*/)(const char* name),							//傾僾儕働乕僔儑儞掕媊偺娭悢:曄悢偺抣傪曉偡丅	幃偺拞偱曄悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
  double (*fnDoFunc/*NULL壜*/)(const char* name, int argc, const double* argv/*[argc]*/)) {		//傾僾儕働乕僔儑儞掕媊偺娭悢:娭悢偺寢壥傪曉偡丅	幃偺拞偱娭悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
	return expreval_r(expr,
		(double (*)(const char*, void*))fnGetVar,
		(double (*)(const char*, int, const double*, void*))fnDoFunc,
		NULL);
}
double expreval_r(const char* expr,
  double (*fnGetVar/*NULL壜*/)(const char* name, void* arg),						//傾僾儕働乕僔儑儞掕媊偺娭悢:曄悢偺抣傪曉偡丅	幃偺拞偱曄悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
  double (*fnDoFunc/*NULL壜*/)(const char* name, int argc, const double* argv/*[argc]*/, void* arg),	//傾僾儕働乕僔儑儞掕媊偺娭悢:娭悢偺寢壥傪曉偡丅	幃偺拞偱娭悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
  void* arg) {
	int num, buf[64/*挷惍壜*/];
	if(fnGetVar || fnDoFunc) { DIE(); }	//乽惍悢斉丆摦揑儊儌儕妋曐柍偟乿斉偺expreval()偼丄fnGetVar偲fnDoFunc偺巜掕偵懳墳偟偰偄傑偣傫丅
	num = expreval_PreProcess(expr, buf);	//僥僉僗僩佀拞抲婰朄偺僩乕僋儞暲傃
	num = exprsort(buf, num, sizeof(int),	//拞抲婰朄偺僩乕僋儞暲傃佀媡億乕儔儞僪婰朄偺僩乕僋儞暲傃
		expreval_GetTokenType ,
		expreval_IsOpLeftAssoc,
		expreval_CompareOpPrec,
		NULL);
	return expreval_PostProcess(buf, num);	//媡億乕儔儞僪婰朄偺僩乕僋儞暲傃佀寁嶼寢壥
}
#if 0
void TestSuite() { //巊梡椺
	printf("%d\n", (int)expreval("-10 + mod(-9,-abs(-10+5))^2",NULL,NULL)); //佀6	仸巆擮側偑傜P/ECE偱幚峴偡傞偲丄寢壥偼6偱偼側偔5偵側傝傑偡丅墘嶼偺搑拞偱丄pow()偺墘嶼岆嵎偺偨傔偵丄5^2=24.999...佀愗傝幪偰偰24偵側傞偐傜偱偡丅framdbl1.s偺墘嶼岆嵎偺栤戣偱偁傝丄摉儌僕儏乕儖撪偱偼夝寛弌棃傑偣傫丅慡懱傪幚悢偱埖偆寁嶼側傜偽懡彮偺岆嵎偼嫋梕偱偒傞偺偱偡偑丄偙偺椺偺傛偆偵惍悢壔慜採偺寁嶼偱偼塭嬁偑戝偒偔側傝傑偡丅
}
#endif
#else //USE_EXPREVAL_NEWVER
/****************************************************************************
 *	儐乕僥傿儕僥傿娭悢	幚悢斉丆摦揑儊儌儕妋曐桳傝
 ****************************************************************************/
//崱屻偼丄乽惍悢斉丆摦揑儊儌儕妋曐柍偟乿斉偺expreval()偱偼側偔丄偙偪傜偺乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉偺expreval()傪儀乕僗偵丄婡擻傪捛壛偟偰峴偔梊掕偱偡丅
//尰帪揰偱偼丄乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉傕偝傎偳暋嶨偱偼側偔丄摦揑儊儌儕妋曐柍偟偱嶌惉偡傞帠傕壜擻偩偭偨偺偱偡偑丄姼偊偰摦揑儊儌儕妋曐桳傝偲偟傑偟偨丅
//偦偆偟偨棟桼偼丄崱屻丄乽幚悢斉丆摦揑儊儌儕妋曐桳傝乿斉傪婡擻奼挘偟偰峴偔偲嫲傜偔摦揑儊儌儕妋曐偼昁梫偵側傞偩傠偆偐傜丄崱偺撪偐傜偦偆偟偰偍偙偆偲巚偭偨帠丆
//媦傃丄僩儔僢僔儏僶僢僼傽偑惓偟偔摦嶌偟偰偄傞帠傪妋擣偡傞偨傔偱偡丅(傕偟僩儔僢僔儏僶僢僼傽偵僶僌偑桳偭偨傜丄Boehm GC偺儊儌儕儕乕僋専弌婡擻偱専弌偝傟傑偡丅)
/*--------------------------------------------------------------------------*/
typedef struct _ST_ExprEval_Token {
	int			type;		//exprsort_TokenType_乣
} ST_ExprEval_Token;
static ST_ExprEval_Token* ExprEval_Token_New(int type) {
	ST_ExprEval_Token* pToken = calloc(1, sizeof(ST_ExprEval_Token));
	if(!pToken) { DIE(); }
	pToken->type = type;
	return pToken;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
typedef struct _ST_ExprEval_Token_nu {
	int			type;		//exprsort_TokenType_Number
	double			value;		//抣
} ST_ExprEval_Token_nu;
static ST_ExprEval_Token* ExprEval_Token_nu_New(double value) {
	ST_ExprEval_Token_nu* pNuTok = calloc(1, sizeof(ST_ExprEval_Token_nu));
	if(!pNuTok) { DIE(); }
	pNuTok->type = exprsort_TokenType_Number;
	pNuTok->value = value;
	return (ST_ExprEval_Token*)pNuTok;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
typedef struct _ST_ExprEval_Token_op {
	int			type;		//exprsort_TokenType_Operator
	int			name;		//'n'(扨崁-,Neg偺N偱偡),'^'(傋偒忔),'+','-'(擇崁-),'*','/'
} ST_ExprEval_Token_op;
static ST_ExprEval_Token* ExprEval_Token_op_New(int name) {
	ST_ExprEval_Token_op* pOpTok = calloc(1, sizeof(ST_ExprEval_Token_op));
	if(!pOpTok) { DIE(); }
	pOpTok->type = exprsort_TokenType_Operator;
	pOpTok->name = name;
	return (ST_ExprEval_Token*)pOpTok;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
typedef struct _ST_ExprEval_Token_fn {
	int			type;		//exprsort_TokenType_Function
	int			argc;		//幚堷悢偺悢
	char			name[0];	//娭悢柤
} ST_ExprEval_Token_fn;
static ST_ExprEval_Token* ExprEval_Token_fn_New(const char* name) {
	ST_ExprEval_Token_fn* pFnTok = calloc(1, sizeof(ST_ExprEval_Token_fn) + strlen(name) + 1/*nul*/);
	if(!pFnTok) { DIE(); }
	pFnTok->type = exprsort_TokenType_Function;
	strcpy(pFnTok->name, name);
	return (ST_ExprEval_Token*)pFnTok;
}
/*--------------------------------------------------------------------------*/
//傾僾儕働乕僔儑儞掕媊偺娭悢:僩乕僋儞偺庬椶傪曉偡丅
static int expreval_GetTokenType(const void* _pToken) {
	ST_ExprEval_Token* pToken = *(ST_ExprEval_Token**)_pToken;
	return pToken->type;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偑嵍寢崌偐傪曉偡丅
static int expreval_IsOpLeftAssoc(const void* _pOpTok) {
	ST_ExprEval_Token_op* pOpTok = *(ST_ExprEval_Token_op**)_pOpTok;
	switch(pOpTok->name) {
	default:DIE();
	case 'n':	//'n'(扨崁-,Neg偺N偱偡)
	case '^':	//'^'(傋偒忔)
		return 0;	//塃寢崌
	case '+':	//'+'
	case '-':	//'-'(擇崁-)
	case '*':	//'*'
	case '/':	//'/'
		return 1;	//嵍寢崌
	}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//傾僾儕働乕僔儑儞掕媊偺娭悢:墘嶼巕偺桪愭弴埵傪妑傋傞丅
static int expreval_CompareOpPrec(const void* _pOpTok1, const void* _pOpTok2) {
	ST_ExprEval_Token_op* pOpTok[2] = {
		*(ST_ExprEval_Token_op**)_pOpTok1,
		*(ST_ExprEval_Token_op**)_pOpTok2,
	};
	int i, iOpPri[2];
	for(i = 0; i < 2; i++) {
		switch(pOpTok[i]->name) {
		default:DIE();
		case 'n':	//'n'(扨崁-,Neg偺N偱偡)
			iOpPri[i] = 2; break;
		case '^':	//'^'(傋偒忔)
			iOpPri[i] = 3; break;
		case '+':	//'+'
		case '-':	//'-'(擇崁-)
			iOpPri[i] = 0; break;
		case '*':	//'*'
		case '/':	//'/'
			iOpPri[i] = 1; break;
		}
	}
	return iOpPri[0] - iOpPri[1];
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static void expreval_IncrFnNumArgs(void* _pFnTok) {
	ST_ExprEval_Token_fn* pFnTok = *(ST_ExprEval_Token_fn**)_pFnTok;
	pFnTok->argc++;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//僥僉僗僩傪拞抲婰朄偺僩乕僋儞暲傃偵曄姺偡傞丅
static void expreval_PreProcess(const char* expr, GPtrArray* array,
  double (*fnGetVar)(const char* name, void* arg),
  void* arg) {
	for(;;) {
		ST_ExprEval_Token* pToken;
		double d;
		int c;
		while(isspace(c = *expr)) { expr++; }	//嬻敀傪撉傒旘偽偡丅
		if(!c) { break; }
		if(isdigit(c)) {
			d = strtod(expr, (char**)&expr);
			pToken = ExprEval_Token_nu_New(d);
		} else if(iscsymf(c)) {
			GString* s = g_string_new(NULL);
			while(iscsym(*expr)) { g_string_append_c(s, *expr++); }
			if(*expr == '(') {	//僔儞儃儖偺捈屻偵(嬻敀傕嫴傑偢偵)丄'('偑桳傟偽娭悢丅
				pToken = ExprEval_Token_fn_New(s->str);
			} else {		//偦偆偱側偗傟偽曄悢丅
				d = (*fnGetVar)(s->str, arg);
				pToken = ExprEval_Token_nu_New(d);
			}
			g_string_free(s, 1/*free_segment*/);
		} else {
			switch(c) {
			default:DIE();
			case '^':	//'^'(傋偒忔)
			case '+':
			case '-':	//'n'(扨崁-,Neg偺N偱偡),枖偼,'-'(擇崁-)
			case '*':
			case '/':
				if(c == '-') {
					c = 'n';	//'n'(扨崁-,Neg偺N偱偡)
					if(array->len) {
						ST_ExprEval_Token* pToken2 = (ST_ExprEval_Token*)g_ptr_array_index(array, array->len - 1);
						if((pToken2->type == exprsort_TokenType_Number) ||
						   (pToken2->type == exprsort_TokenType_RightParenthesis)) { c = '-'; }	//'-'(擇崁-)
					}
				}
				pToken = ExprEval_Token_op_New(c);
				break;
			case ',':
				pToken = ExprEval_Token_New(exprsort_TokenType_FunctionArgumentSeparator);
				break;
			case '(':
				pToken = ExprEval_Token_New(exprsort_TokenType_LeftParenthesis);
				break;
			case ')':
				pToken = ExprEval_Token_New(exprsort_TokenType_RightParenthesis);
				break;
			}
			expr++;
		}
		g_ptr_array_add(array, pToken);
	}
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//媡億乕儔儞僪婰朄偺僩乕僋儞暲傃傪寁嶼偡傞丅
static double expreval_PostProcess(GPtrArray* array,
  double (*fnDoFunc)(const char* name, int argc, const double* argv/*[argc]*/, void* arg),
  void* arg) {
	GArray* stack = g_array_new(0, 0, sizeof(double));
	double d;
	int i, argc;
	for(i = 0; i < array->len; i++) {
		ST_ExprEval_Token* pToken = g_ptr_array_index(array, i);
		if(pToken->type == exprsort_TokenType_Number) {
			ST_ExprEval_Token_nu* pNuTok = (ST_ExprEval_Token_nu*)pToken;
			argc = 0;
			d = pNuTok->value;
		} else if(pToken->type == exprsort_TokenType_Function) {
			ST_ExprEval_Token_fn* pFnTok = (ST_ExprEval_Token_fn*)pToken;
			argc = pFnTok->argc;
			if(stack->len < argc) { DIE(); }
			d = (*fnDoFunc)(pFnTok->name, argc, &g_array_index(stack, double, stack->len - argc), arg);
		} else if(pToken->type == exprsort_TokenType_Operator) {
			ST_ExprEval_Token_op* pOpTok = (ST_ExprEval_Token_op*)pToken;
			switch(pOpTok->name) {
			default:DIE();
			case 'n':	//'n'(扨崁-,Neg偺N偱偡)
				argc = 1;
				if(stack->len < argc) { DIE(); }
				d = -g_array_index(stack, double, stack->len - argc);
				break;
			case '^':	//'^'(傋偒忔)
				argc = 2;
				if(stack->len < argc) { DIE(); }
				d = pow(g_array_index(stack, double, stack->len - argc), g_array_index(stack, double, stack->len - argc + 1));
				break;
			case '+':	//'+'
				argc = 2;
				if(stack->len < argc) { DIE(); }
				d = g_array_index(stack, double, stack->len - argc) + g_array_index(stack, double, stack->len - argc + 1);
				break;
			case '-':	//'-'(擇崁-)
				argc = 2;
				if(stack->len < argc) { DIE(); }
				d = g_array_index(stack, double, stack->len - argc) - g_array_index(stack, double, stack->len - argc + 1);
				break;
			case '*':	//'*'
				argc = 2;
				if(stack->len < argc) { DIE(); }
				d = g_array_index(stack, double, stack->len - argc) * g_array_index(stack, double, stack->len - argc + 1);
				break;
			case '/':	//'/'
				argc = 2;
				if(stack->len < argc) { DIE(); }
				d = g_array_index(stack, double, stack->len - argc) / g_array_index(stack, double, stack->len - argc + 1);
				break;
			}
		} else {
			DIE();
		}
		g_array_set_size(stack, stack->len - argc);
		g_array_append_val(stack, d);
	}
	if(stack->len != 1) { DIE(); }
	d = g_array_index(stack, double, 0);
	g_array_unref(stack);
	return d;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//僩乕僋儞傪奐曻偡傞丅
static void expreval_FreeToken(void* data) {
	free(data);
}
/*--------------------------------------------------------------------------*/
//fnGetVar偺僒儞僾儖幚憰偱偡丅杮棃偼傾僾儕働乕僔儑儞偑掕媊偡傋偒偱偡偑丄NULL偑巜掕偝傟偨応崌偵偙偺僒儞僾儖幚憰傪巊梡偟傑偡丅
static double expreval_fnGetVar(const char* name, void* arg) {
	double d;
	if(!strcmp(name, "E")) {
		d = M_E;
	} else if(!strcmp(name, "PI")) {
		d = M_PI;
	} else {
		DIE();
	}
	return d;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//fnDoFunc偺僒儞僾儖幚憰偱偡丅杮棃偼傾僾儕働乕僔儑儞偑掕媊偡傋偒偱偡偑丄NULL偑巜掕偝傟偨応崌偵偙偺僒儞僾儖幚憰傪巊梡偟傑偡丅
static double expreval_fnDoFunc(const char* name, int argc, const double* argv/*[argc]*/, void* arg) {
	double d;
	if(!strcmp(name, "rnd")) {
		if(argc != 0) { DIE(); }	//堷悢0屄偺椺
		d = drand48();
	} else if(!strcmp(name, "abs")) {
		if(argc != 1) { DIE(); }
		d = fabs(argv[0]);
	} else if(!strcmp(name, "mod")) {
		if((argc != 2) || !argv[1]) { DIE(); }
		d = fmod(argv[0], argv[1]);
	} else if(!strcmp(name, "min")) {
		if(!argc) { DIE(); }		//堷悢1屄埲忋偺壜曄堷悢偺椺
		d = *argv++;
		while(--argc) {
			double d2 = *argv++;
			d = min(d, d2);
		}
	} else if(!strcmp(name, "max")) {
		if(!argc) { DIE(); }		//堷悢1屄埲忋偺壜曄堷悢偺椺
		d = *argv++;
		while(--argc) {
			double d2 = *argv++;
			d = max(d, d2);
		}
	} else {
		DIE();
	}
	return d;
}
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
//憖幵応傾儖僑儕僘儉傪棙梡偟偰丄幃僥僉僗僩偺寁嶼傪峴偆丅
double expreval(const char* expr,
  double (*fnGetVar/*NULL壜*/)(const char* name),							//傾僾儕働乕僔儑儞掕媊偺娭悢:曄悢偺抣傪曉偡丅	幃偺拞偱曄悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
  double (*fnDoFunc/*NULL壜*/)(const char* name, int argc, const double* argv/*[argc]*/)) {		//傾僾儕働乕僔儑儞掕媊偺娭悢:娭悢偺寢壥傪曉偡丅	幃偺拞偱娭悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
	return expreval_r(expr,
		(double (*)(const char*, void*))fnGetVar,
		(double (*)(const char*, int, const double*, void*))fnDoFunc,
		NULL);
}
double expreval_r(const char* expr,
  double (*fnGetVar/*NULL壜*/)(const char* name, void* arg),						//傾僾儕働乕僔儑儞掕媊偺娭悢:曄悢偺抣傪曉偡丅	幃偺拞偱曄悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
  double (*fnDoFunc/*NULL壜*/)(const char* name, int argc, const double* argv/*[argc]*/, void* arg),	//傾僾儕働乕僔儑儞掕媊偺娭悢:娭悢偺寢壥傪曉偡丅	幃偺拞偱娭悢傪巊梡偟偰偄側偗傟偽丄NULL傪巜掕弌棃傑偡丅
  void* arg) {
	int n;
	double d;
	//攝楍傪嶌惉偡傞丅
	GPtrArray* array = g_ptr_array_new_with_free_func(expreval_FreeToken);	//捈愙free傪巜掕偟偰偼偄偗側偄丅棟桼偼garray.c偺g_array_set_clear_func()偺僐儊儞僩傪嶲徠偣傛丅
	//僥僉僗僩傪拞抲婰朄偺僩乕僋儞暲傃偵曄姺偡傞丅
	expreval_PreProcess(expr, array,
	                    fnGetVar ? fnGetVar : expreval_fnGetVar,		//fnGetVar偺僒儞僾儖幚憰偱偡丅杮棃偼傾僾儕働乕僔儑儞偑掕媊偡傋偒偱偡偑丄NULL偑巜掕偝傟偨応崌偵偙偺僒儞僾儖幚憰傪巊梡偟傑偡丅
	                    arg);
	//拞抲婰朄偺僩乕僋儞暲傃傪媡億乕儔儞僪婰朄偺僩乕僋儞暲傃偵曄姺偡傞丅
	n = exprsort(array->pdata, array->len, sizeof(void*),
	             expreval_GetTokenType,
	             expreval_IsOpLeftAssoc,
	             expreval_CompareOpPrec,
	             expreval_IncrFnNumArgs);
	//攝楍偺枛旜偺丄僩儔僢僔儏僶僢僼傽偺晹暘傪奐曻偡傞丅
	g_ptr_array_set_size(array, n);
	//媡億乕儔儞僪婰朄偺僩乕僋儞暲傃傪寁嶼偡傞丅
	d = expreval_PostProcess(array,
	                         fnDoFunc ? fnDoFunc : expreval_fnDoFunc,	//fnDoFunc偺僒儞僾儖幚憰偱偡丅杮棃偼傾僾儕働乕僔儑儞偑掕媊偡傋偒偱偡偑丄NULL偑巜掕偝傟偨応崌偵偙偺僒儞僾儖幚憰傪巊梡偟傑偡丅
	                         arg);
	//攝楍傪夝曻偡傞丅
	g_ptr_array_unref(array);
	return d;
}
#if 0
void TestSuite() { //巊梡椺
	printf("%f\n", expreval("-(abs(max(-1.5,0.5,1.5,0.5) - PI) * 10)^2",NULL,NULL)); //佀-269.482644
}
#endif
#endif//USE_EXPREVAL_NEWVER
