GenCod.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  1. unit GenCod;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Graphics, Forms, Globales, FrameTabSession,
  6. FormRemoteEditor, FrameTabSessions, SynEditHighlighter, MisUtils,
  7. SynFacilBasic, XpresParser, XpresTypes, XpresElements, strutils;
  8. {Implementación de un interprete sencillo para el lenguaje Xpres.
  9. Este módulo no generará código sino que lo ejecutará directamente.
  10. Este intérprete, solo reconoce tipos de datos enteros y de cadena.
  11. Para los enteros se implementan las operaciones aritméticas básicas, y
  12. para las cadenas se implementa solo la concatenación(+)
  13. Se pueden crear nuevas variables.
  14. En este archivo, se pueden declarar tipos, variables, constantes,
  15. procedimientos y funciones. Hay rutinas obligatorias que siempre se deben
  16. implementar.
  17. Este intérprete, está implementado con una arquitectura de pila.
  18. * Todas las operaciones recibe sus dos parámetros en las variables p1 y p2.
  19. * El resultado de cualquier expresión se debe dejar indicado en el objeto "res".
  20. * Los valores enteros y enteros sin signo se cargan en valInt
  21. * Los valores string se cargan en valStr
  22. * Las variables están mapeadas en el arreglo vars[]
  23. * Cada variable, de cualquier tipo, ocupa una celda de vars[]
  24. * Los parámetros de las funciones se pasan siempre usando la pila.
  25. Los procedimientos de operaciones, deben actualizar en el acumulador:
  26. * El tipo de resultado (para poder evaluar la expresión completa como si fuera un
  27. operando nuevo)
  28. * La categoría del operador (constante, expresión, etc), para poder optimizar la generación
  29. de código.
  30. Ceerado Por Tito Hinostroza 30/07/2014
  31. Modificado Por Tito Hinostroza 8/08/2015
  32. Modificado Por Tito Hinostroza 29/11/2016
  33. Modificado Por Tito Hinostroza 27/12/2016
  34. }
  35. const STACK_SIZE = 32;
  36. var
  37. /////// Tipos de datos del lenguaje ////////////
  38. tipInt : TType; //entero flotante
  39. tipStr : Ttype; //cadena
  40. tipBol : TType; //booleano
  41. //Pila virtual
  42. {La pila virtual se representa con una tabla. Cada vez que se agrega un valor con
  43. pushResult, se incrementa "sp". Para retornar "sp" a su valor original, se debe llamar
  44. a PopResult(). Luego de eso, se accede a la pila, de acuerdo al seguienet esquema:
  45. Cuando se usa cpara almacenar los parámetros de las funciones, queda así:
  46. stack[sp] -> primer parámetro
  47. stack[sp+1] -> segundo parámetro
  48. ...
  49. }
  50. sp: integer; //puntero de pila
  51. stack: array[0..STACK_SIZE-1] of TOperand;
  52. //variables auxiliares
  53. Timeout: integer; //variable de límite de cuenta de tiempo
  54. type
  55. { TGenCod }
  56. TGenCod = class(TCompilerBase)
  57. private
  58. procedure bol_asig_bol;
  59. procedure bol_procLoad;
  60. procedure fun_clear(fun: TxpEleFun);
  61. procedure fun_close(fun: TxpEleFun);
  62. procedure fun_connect(fun: TxpEleFun);
  63. procedure fun_connectSSH(fun: TxpEleFun);
  64. procedure fun_connectTelnet(fun: TxpEleFun);
  65. procedure fun_detect_prompt(fun: TxpEleFun);
  66. procedure fun_disconnect(fun: TxpEleFun);
  67. procedure fun_edit(fun: TxpEleFun);
  68. procedure fun_explorer(fun: TxpEleFun);
  69. procedure fun_fileopen(fun: TxpEleFun);
  70. procedure fun_logclose(fun: TxpEleFun);
  71. procedure fun_logopen(fun: TxpEleFun);
  72. procedure fun_logpause(fun: TxpEleFun);
  73. procedure fun_logstart(fun: TxpEleFun);
  74. procedure fun_logwrite(fun: TxpEleFun);
  75. procedure fun_messagebox(fun: TxpEleFun);
  76. procedure fun_messageboxI(fun: TxpEleFun);
  77. procedure fun_pause(fun: TxpEleFun);
  78. procedure fun_puts(fun: TxpEleFun);
  79. procedure fun_putsI(fun: TxpEleFun);
  80. procedure fun_sendln(fun: TxpEleFun);
  81. procedure fun_stop(fun: TxpEleFun);
  82. procedure fun_wait(fun: TxpEleFun);
  83. procedure fun_write(fun: TxpEleFun);
  84. procedure int_asig_int;
  85. procedure int_idiv_int;
  86. procedure int_igual_int;
  87. procedure int_mayori_int;
  88. procedure int_mayor_int;
  89. procedure int_menori_int;
  90. procedure int_menor_int;
  91. procedure int_mult_int;
  92. procedure int_procLoad;
  93. procedure int_resta_int;
  94. procedure int_suma_int;
  95. procedure LoadResBol(val: Boolean; catOp: TCatOperan);
  96. procedure LoadResInt(val: int64; catOp: TCatOperan);
  97. procedure LoadResStr(val: string; catOp: TCatOperan);
  98. procedure PopResult;
  99. procedure PushResult;
  100. procedure str_asig_str;
  101. procedure str_concat_str;
  102. procedure str_igual_str;
  103. procedure str_procLoad;
  104. protected
  105. //referencias de tipos adicionales de tokens
  106. tkStruct : TSynHighlighterAttributes;
  107. tnStruct : integer;
  108. tkExpDelim : TSynHighlighterAttributes;
  109. tnExpDelim : integer;
  110. tkBlkDelim : TSynHighlighterAttributes;
  111. tnBlkDelim : integer;
  112. tnOthers : integer;
  113. ejec: boolean; //permite poner al intérprete en modo "No Ejecución"
  114. procedure Cod_StartData;
  115. procedure Cod_StartProgram;
  116. procedure Cod_EndProgram;
  117. procedure expr_start;
  118. procedure expr_end(isParam: boolean);
  119. public
  120. stop: boolean; //Bandera general para detener la ejecución. No se usa la de TCompilerBase
  121. procedure StartSyntax;
  122. end;
  123. implementation
  124. uses
  125. FormPrincipal, FormConfig, UnTerminal;
  126. { TGenCod }
  127. procedure TGenCod.LoadResInt(val: int64; catOp: TCatOperan);
  128. //Carga en el resultado un valor entero
  129. begin
  130. res.typ := tipInt;
  131. res.valInt:=val;
  132. res.catOp:=catOp;
  133. end;
  134. procedure TGenCod.LoadResStr(val: string; catOp: TCatOperan);
  135. //Carga en el resultado un valor string
  136. begin
  137. res.typ := tipStr;
  138. res.valStr:=val;
  139. res.catOp:=catOp;
  140. end;
  141. procedure TGenCod.LoadResBol(val: Boolean; catOp: TCatOperan);
  142. //Carga en el resultado un valor string
  143. begin
  144. res.typ := tipBol;
  145. res.valBool:=val;
  146. res.catOp:=catOp;
  147. end;
  148. procedure TGenCod.PushResult;
  149. //Coloca el resultado de una expresión en la pila
  150. begin
  151. if sp>=STACK_SIZE then begin
  152. GenError('Desborde de pila.');
  153. exit;
  154. end;
  155. stack[sp].typ := res.typ;
  156. case res.Typ.cat of
  157. t_string: stack[sp].valStr := res.ReadStr;
  158. t_integer: stack[sp].valInt := res.ReadInt;
  159. end;
  160. Inc(sp);
  161. end;
  162. procedure TGenCod.PopResult;
  163. //Reduce el puntero de pila, de modo que queda apuntando al último dato agregado
  164. begin
  165. if sp<=0 then begin
  166. GenError('Desborde de pila.');
  167. exit;
  168. end;
  169. Dec(sp);
  170. end;
  171. ////////////rutinas obligatorias
  172. procedure TGenCod.Cod_StartData;
  173. //Codifica la parte inicial de declaración de variables estáticas
  174. begin
  175. end;
  176. procedure TGenCod.Cod_StartProgram;
  177. //Codifica la parte inicial del programa
  178. begin
  179. sp := 0; //inicia pila
  180. Timeout := config.tpoMax; //inicia variable
  181. stop := false;
  182. //////// variables predefinidas ////////////
  183. CreateVariable('timeout', 'int');
  184. CreateVariable('curIP', 'string');
  185. CreateVariable('curTYPE', 'string');
  186. CreateVariable('curPORT', 'int');
  187. CreateVariable('curENDLINE', 'string');
  188. CreateVariable('curAPP', 'string');
  189. CreateVariable('promptDETECT', 'boolean');
  190. CreateVariable('promptSTART', 'string');
  191. CreateVariable('promptEND', 'string');
  192. end;
  193. procedure TGenCod.Cod_EndProgram;
  194. //Codifica la parte inicial del programa
  195. begin
  196. end;
  197. procedure TGenCod.expr_start;
  198. //Se ejecuta siempre al StartSyntax el procesamiento de una expresión
  199. begin
  200. if exprLevel=1 then begin //es el primer nivel
  201. res.typ := tipInt; //le pone un tipo por defecto
  202. end;
  203. end;
  204. procedure TGenCod.expr_end(isParam: boolean);
  205. //Se ejecuta al final de una expresión, si es que no ha habido error.
  206. begin
  207. if isParam then begin
  208. //Se terminó de evaluar un parámetro
  209. PushResult; //pone parámetro en pila
  210. if HayError then exit;
  211. end;
  212. end;
  213. ////////////operaciones con Enteros
  214. procedure TGenCod.int_procLoad;
  215. begin
  216. //carga el operando en res
  217. res.typ := tipInt;
  218. res.catOp := p1^.catOp;
  219. res.valInt := p1^.ReadInt;
  220. end;
  221. procedure TGenCod.int_asig_int;
  222. begin
  223. if p1^.catOp <> coVariab then begin //validación
  224. GenError('Solo se puede asignar a variable.'); exit;
  225. end;
  226. if not ejec then exit;
  227. //en la VM se puede mover directamente res memoria sin usar el registro res
  228. p1^.rVar.valInt := p2^.ReadInt;
  229. // res.used:=false; //No hay obligación de que la asignación devuelva un valor.
  230. if Upcase(p1^.rVar.name) = 'TIMEOUT' then begin
  231. //variable interna
  232. config.TpoMax := p2^.ReadInt;
  233. end else if Upcase(p1^.rVar.name) = 'CURPORT' then begin
  234. //Variable interna
  235. frmPrincipal.SetCurPort(p2^.ReadInt);
  236. end;
  237. end;
  238. procedure TGenCod.int_suma_int;
  239. begin
  240. LoadResInt(p1^.ReadInt+p2^.ReadInt, coExpres);
  241. end;
  242. procedure TGenCod.int_resta_int;
  243. begin
  244. LoadResInt(p1^.ReadInt-p2^.ReadInt, coExpres);
  245. end;
  246. procedure TGenCod.int_mult_int;
  247. begin
  248. LoadResInt(p1^.ReadInt*p2^.ReadInt, coExpres);
  249. end;
  250. procedure TGenCod.int_idiv_int;
  251. begin
  252. if not ejec then //evitamos evaluar en este modo, para no generar posibles errores
  253. LoadResInt(0, coExpres)
  254. else
  255. LoadResInt(p1^.ReadInt div p2^.ReadInt, coExpres);
  256. end;
  257. procedure TGenCod.int_igual_int;
  258. begin
  259. LoadResBol(p1^.ReadInt = p2^.ReadInt, coExpres);
  260. end;
  261. procedure TGenCod.int_mayor_int;
  262. begin
  263. LoadResBol(p1^.ReadInt > p2^.ReadInt, coExpres);
  264. end;
  265. procedure TGenCod.int_mayori_int;
  266. begin
  267. LoadResBol(p1^.ReadInt >= p2^.ReadInt, coExpres);
  268. end;
  269. procedure TGenCod.int_menor_int;
  270. begin
  271. LoadResBol(p1^.ReadInt < p2^.ReadInt, coExpres);
  272. end;
  273. procedure TGenCod.int_menori_int;
  274. begin
  275. LoadResBol(p1^.ReadInt <= p2^.ReadInt, coExpres);
  276. end;
  277. ////////////operaciones con string
  278. procedure TGenCod.str_procLoad;
  279. begin
  280. //carga el operando en res
  281. res.typ := tipStr;
  282. res.catOp := p1^.catOp;
  283. res.valStr := p1^.ReadStr;
  284. end;
  285. procedure TGenCod.str_asig_str;
  286. var
  287. ses: TfraTabSession;
  288. begin
  289. if p1^.catOp <> coVariab then begin //validación
  290. GenError('Solo se puede asignar a variable.'); exit;
  291. end;
  292. if not ejec then exit;
  293. //aquí se puede mover directamente res memoria sin usar el registro res
  294. p1^.rVar.valStr := p2^.ReadStr;
  295. // res.used:=false; //No hay obligación de que la asignación devuelva un valor.
  296. if Upcase(p1^.rVar.name) = 'CURIP' then begin
  297. //variable interna
  298. frmPrincipal.SetCurIP(p2^.ReadStr);
  299. // end else if Upcase(p1^.rVar.name) = 'CURPORT' then begin
  300. // CURPORT se asigna en TGenCod.int_asig_int() porque es número.
  301. end else if Upcase(p1^.rVar.name) = 'CURTYPE' then begin
  302. //variable interna
  303. case UpCase(p2^.ReadStr) of
  304. 'TELNET': frmPrincipal.SetCurConnType(TCON_TELNET); //Conexión telnet común
  305. 'SSH' : frmPrincipal.SetCurConnType(TCON_SSH); //Conexión ssh
  306. 'SERIAL': frmPrincipal.SetCurConnType(TCON_SERIAL); //Serial
  307. 'OTHER' : frmPrincipal.SetCurConnType(TCON_OTHER); //Otro proceso
  308. end;
  309. end else if Upcase(p1^.rVar.name) = 'CURENDLINE' then begin
  310. //variable interna
  311. if UpCase(p2^.ReadStr) = 'CRLF' then
  312. frmPrincipal.SetCurLineDelimSend(LDS_CRLF);
  313. if UpCase(p2^.ReadStr) = 'CR' then
  314. frmPrincipal.SetCurLineDelimSend(LDS_CR);
  315. if UpCase(p2^.ReadStr) = 'LF' then
  316. frmPrincipal.SetCurLineDelimSend(LDS_LF);
  317. end else if Upcase(p1^.rVar.name) = 'CURAPP' then begin
  318. //indica aplicativo actual
  319. frmPrincipal.SetCurOther(p2^.ReadStr);
  320. end else if Upcase(p1^.rVar.name) = 'PROMPTSTART' then begin
  321. if frmPrincipal.GetCurSession(ses) then begin
  322. ses.prIni:= p2^.ReadStr;
  323. ses.detecPrompt := true; //por defecto
  324. ses.UpdatePromptProc; //actualiza
  325. end;
  326. end else if Upcase(p1^.rVar.name) = 'PROMPTEND' then begin
  327. if frmPrincipal.GetCurSession(ses) then begin
  328. ses.prFin:= p2^.ReadStr;
  329. ses.detecPrompt := true; //por defecto
  330. ses.UpdatePromptProc; //actualiza
  331. end;
  332. end;
  333. end;
  334. procedure TGenCod.str_concat_str;
  335. begin
  336. LoadResStr(p1^.ReadStr + p2^.ReadStr, coExpres);
  337. end;
  338. procedure TGenCod.str_igual_str;
  339. begin
  340. LoadResBol(p1^.ReadStr = p2^.ReadStr, coExpres);
  341. end;
  342. ////////////operaciones con boolean
  343. procedure TGenCod.bol_procLoad;
  344. begin
  345. //carga el operando en res
  346. res.typ := tipStr;
  347. res.catOp := p1^.catOp;
  348. res.valBool := p1^.ReadBool;
  349. end;
  350. procedure TGenCod.bol_asig_bol;
  351. var
  352. ses: TfraTabSession;
  353. begin
  354. if p1^.catOp <> coVariab then begin //validación
  355. GenError('Solo se puede asignar a variable.'); exit;
  356. end;
  357. if not ejec then exit;
  358. //en la VM se puede mover directamente res memoria sin usar el registro res
  359. p1^.rVar.valBool := p2^.ReadBool;
  360. // res.used:=false; //No hay obligación de que la asignación devuelva un valor.
  361. if Upcase(p1^.rVar.name) = 'PROMPTDETECT' then begin
  362. //Variable interna
  363. if frmPrincipal.GetCurSession(ses) then begin
  364. ses.detecPrompt := p2^.ReadBool;
  365. ses.UpdatePromptProc; //actualiza
  366. end;
  367. end;
  368. end;
  369. //funciones básicas
  370. procedure TGenCod.fun_puts(fun :TxpEleFun);
  371. //envia un texto a consola
  372. begin
  373. PopResult; //saca parámetro 1
  374. if HayError then exit;
  375. if not ejec then exit;
  376. msgbox(stack[sp].valStr); //sabemos que debe ser String
  377. //el tipo devuelto lo fijará el framework, al tipo definido
  378. end;
  379. procedure TGenCod.fun_putsI(fun :TxpEleFun);
  380. //envia un texto a consola
  381. begin
  382. PopResult; //saca parámetro 1
  383. if HayError then exit;
  384. if not ejec then exit;
  385. msgbox(IntToStr(stack[sp].valInt)); //sabemos que debe ser Entero
  386. //el tipo devuelto lo fijará el framework, al tipo definido
  387. end;
  388. procedure TGenCod.fun_disconnect(fun :TxpEleFun);
  389. //desconecta la conexión actual
  390. var
  391. ses: TfraTabSession;
  392. begin
  393. // msgbox('desconectado'); //sabemos que debe ser String
  394. if not ejec then exit;
  395. if frmPrincipal.GetCurSession(ses) then begin
  396. if not ses.proc.Close then begin
  397. msgerr('No se puede cerrar el proceso actual.');
  398. end;
  399. end;
  400. end;
  401. procedure TGenCod.fun_edit(fun: TxpEleFun);
  402. var
  403. ses: TfraTabSession;
  404. par1, strRes: String;
  405. tabSessions: TfraTabSessions;
  406. begin
  407. PopResult; //saca parámetro 1
  408. if not ejec then exit;
  409. //Obtiene el frame de la sesión y el frame de todas las sesiones
  410. if not frmPrincipal.GetCurSession(ses) then exit;
  411. if ses.Parent = nil then exit;
  412. tabSessions := TfraTabSessions(ses.Parent.Parent); //Debe ser TFraTabSessions, sino fallará.
  413. if tabSessions=nil then exit;
  414. //Ejecuta comando
  415. par1 := stack[sp].valStr;
  416. if ses.editMode = edtLocal then begin
  417. //Editor local por comando
  418. //Exec(ses.exterEditor, '');
  419. frmRemoteEditor.Init(ses);
  420. frmRemoteEditor.Open(par1);
  421. end else if ses.editMode = edtBashComm then begin
  422. //Editor remoto por comandos bash
  423. //tabSessions.PageEvent('exec_edit', ses, strRes); //Lanza editor
  424. frmRemoteEditor.Init(ses);
  425. //frmRemoteEditor.Show;
  426. if par1<>'' then begin
  427. frmRemoteEditor.Open(par1);
  428. end;
  429. end else if ses.editMode = edtRemotSFTP then begin
  430. //Editor remoto usando SFTP
  431. if par1<>'' then begin
  432. //Se espera que se haya indicado el archivo a editar
  433. frmRemoteEditor.Init(ses);
  434. frmRemoteEditor.Open(par1);
  435. //edit := TfrmRemoteEditor.Create(nil);
  436. //edit.Init(ses);
  437. //edit.Open(par1);
  438. end else begin
  439. Exec('notepad', '');
  440. end;
  441. end else begin
  442. MsgExc('Invalid option');
  443. end;
  444. end;
  445. procedure TGenCod.fun_explorer(fun: TxpEleFun);
  446. var
  447. ses: TfraTabSession;
  448. tabSessions: TfraTabSessions;
  449. strRes: string;
  450. begin
  451. // PopResult; //saca parámetro 1
  452. if not ejec then exit;
  453. //Obtiene el frame de la sesión y el frame de todas las sesiones
  454. if not frmPrincipal.GetCurSession(ses) then exit;
  455. if ses.Parent = nil then exit;
  456. tabSessions := TfraTabSessions(ses.Parent.Parent); //Debe ser TFraTabSessions, sino fallará.
  457. if tabSessions=nil then exit;
  458. //Ejecuta comando
  459. if ses.explorMode = expBashComm then begin
  460. //Explorador Bash
  461. tabSessions.PageEvent('exec_explor', ses, strRes); //Lanza explorador
  462. end else begin
  463. //Explorador de comando
  464. Exec(ses.exterEditor, '');
  465. end;
  466. end;
  467. procedure TGenCod.fun_connect(fun :TxpEleFun);
  468. //Inicia la conexión actual
  469. var
  470. ses: TfraTabSession;
  471. begin
  472. if not ejec then exit;
  473. if frmPrincipal.GetCurSession(ses) then begin
  474. ses.InicConect; //inicia conexión
  475. end;
  476. end;
  477. procedure TGenCod.fun_connectTelnet(fun :TxpEleFun);
  478. //conecta con telnet
  479. var
  480. ses: TfraTabSession;
  481. begin
  482. PopResult; //saca parámetro 1
  483. if not ejec then exit;
  484. if frmPrincipal.GetCurSession(ses) then begin
  485. ses.InicConectTelnet(stack[sp].valStr); //inicia conexión
  486. end;
  487. end;
  488. procedure TGenCod.fun_connectSSH(fun :TxpEleFun);
  489. //conecta con SSH
  490. var
  491. ses: TfraTabSession;
  492. begin
  493. PopResult; //saca parámetro 1
  494. if not ejec then exit;
  495. if frmPrincipal.GetCurSession(ses) then begin
  496. ses.InicConectSSH(stack[sp].valStr); //inicia conexión
  497. end;
  498. end;
  499. procedure TGenCod.fun_sendln(fun :TxpEleFun);
  500. //desconecta la conexión actual
  501. var
  502. lin: String;
  503. pag: TfraTabSession;
  504. begin
  505. PopResult; //saca parámetro 1
  506. if not ejec then exit;
  507. if not frmPrincipal.GetCurSession(pag) then exit;
  508. lin := stack[sp].valStr;
  509. pag.proc.SendLn(lin);
  510. end;
  511. procedure TGenCod.fun_wait(fun :TxpEleFun);
  512. //espera por una cadena
  513. var
  514. lin: String;
  515. tic: Integer;
  516. pag: TfraTabSession;
  517. begin
  518. PopResult; //saca parámetro 1
  519. if not frmPrincipal.GetCurSession(pag) then exit;
  520. //lazo de espera
  521. if not ejec then exit;
  522. lin := stack[sp].valStr;
  523. tic := 0;
  524. while (tic<Timeout*10) and Not stop do begin
  525. Application.ProcessMessages;
  526. sleep(100);
  527. if AnsiEndsStr(lin, pag.proc.LastLine) then break;
  528. Inc(tic);
  529. end;
  530. if tic>=Timeout*10 then begin
  531. GenError('Tiempo de espera excedido, para cadena: "'+lin+'"');
  532. exit;
  533. // end else begin
  534. // msgbox('eureka');
  535. end;
  536. end;
  537. procedure TGenCod.fun_pause(fun :TxpEleFun);
  538. //espera un momento
  539. var
  540. tic: Integer;
  541. n10mil: Integer;
  542. pag: TfraTabSession;
  543. begin
  544. PopResult; //saca parámetro 1
  545. if not frmPrincipal.GetCurSession(pag) then exit;
  546. n10mil := stack[sp].valInt * 100;
  547. //lazo de espera
  548. if not ejec then exit;
  549. tic := 0;
  550. while (tic<n10mil) and Not stop do begin
  551. Application.ProcessMessages;
  552. sleep(10);
  553. Inc(tic);
  554. end;
  555. end;
  556. procedure TGenCod.fun_messagebox(fun :TxpEleFun);
  557. begin
  558. PopResult; //saca parámetro 1
  559. if HayError then exit;
  560. if not ejec then exit;
  561. msgbox(stack[sp].valStr); //sabemos que debe ser String
  562. //el tipo devuelto lo fijará el framework, al tipo definido
  563. end;
  564. procedure TGenCod.fun_messageboxI(fun :TxpEleFun);
  565. begin
  566. PopResult; //saca parámetro 1
  567. if HayError then exit;
  568. if not ejec then exit;
  569. msgbox(IntToStr(stack[sp].valInt)); //sabemos que debe ser String
  570. //el tipo devuelto lo fijará el framework, al tipo definido
  571. end;
  572. procedure TGenCod.fun_detect_prompt(fun :TxpEleFun);
  573. var
  574. ses: TfraTabSession;
  575. begin
  576. if not ejec then exit;
  577. if frmPrincipal.GetCurSession(ses) then begin
  578. ses.AcTerDetPrmExecute(nil);
  579. end;
  580. //el tipo devuelto lo fijará el framework, al tipo definido
  581. end;
  582. procedure TGenCod.fun_clear(fun :TxpEleFun);
  583. var
  584. ses: TfraTabSession;
  585. begin
  586. if not ejec then exit;
  587. if frmPrincipal.GetCurSession(ses) then begin
  588. ses.AcTerLimBufExecute(nil);
  589. end;
  590. //el tipo devuelto lo fijará el framework, al tipo definido
  591. end;
  592. procedure TGenCod.fun_stop(fun: TxpEleFun);
  593. begin
  594. if not ejec then exit;
  595. stop := true; //manda mensaje para detener la macro
  596. //el tipo devuelto lo fijará el framework, al tipo definido
  597. end;
  598. procedure TGenCod.fun_logopen(fun: TxpEleFun);
  599. var
  600. ses: TfraTabSession;
  601. begin
  602. PopResult; //saca parámetro 1
  603. if not ejec then exit;
  604. if frmPrincipal.GetCurSession(ses) then begin
  605. if not ses.StartLog(stack[sp].valStr) then begin
  606. GenError('Error abriendo registro: ' + stack[sp].valStr);
  607. end;
  608. end;
  609. end;
  610. procedure TGenCod.fun_logwrite(fun: TxpEleFun);
  611. var
  612. ses: TfraTabSession;
  613. begin
  614. PopResult; //saca parámetro 1
  615. if not ejec then exit;
  616. if frmPrincipal.GetCurSession(ses) then begin
  617. if not ses.WriteLog(stack[sp].valStr) then begin
  618. GenError('Error escribiendo en registro: ' + ses.logName);
  619. end;
  620. end;
  621. end;
  622. procedure TGenCod.fun_logclose(fun: TxpEleFun);
  623. var
  624. ses: TfraTabSession;
  625. begin
  626. if not ejec then exit;
  627. if frmPrincipal.GetCurSession(ses) then begin
  628. ses.EndLog;
  629. end;
  630. end;
  631. procedure TGenCod.fun_logpause(fun: TxpEleFun);
  632. var
  633. ses: TfraTabSession;
  634. begin
  635. if not ejec then exit;
  636. if frmPrincipal.GetCurSession(ses) then begin
  637. ses.PauseLog;
  638. end;
  639. end;
  640. procedure TGenCod.fun_logstart(fun: TxpEleFun);
  641. var
  642. ses: TfraTabSession;
  643. begin
  644. if not ejec then exit;
  645. if frmPrincipal.GetCurSession(ses) then begin
  646. ses.StartLog;
  647. end;
  648. end;
  649. procedure TGenCod.fun_fileopen(fun: TxpEleFun);
  650. var
  651. nom: String;
  652. modo: Int64;
  653. n: THandle;
  654. begin
  655. PopResult;
  656. PopResult;
  657. PopResult;
  658. if not ejec then exit;
  659. // AssignFile(filHand, stack[sp].valStr);
  660. // Rewrite(filHand);
  661. nom := stack[sp+1].valStr;
  662. modo := stack[sp+2].valInt;
  663. if modo = 0 then begin
  664. if not FileExists(nom) then begin
  665. //Si no existe. lo crea
  666. n := FileCreate(nom);
  667. FileClose(n);
  668. end;
  669. n := FileOpen(nom, fmOpenReadWrite);
  670. stack[sp].valInt:= Int64(n);
  671. end else begin
  672. n := FileOpen(nom, fmOpenRead);
  673. stack[sp].valInt:=Int64(n);
  674. end;
  675. end;
  676. procedure TGenCod.fun_close(fun: TxpEleFun);
  677. begin
  678. PopResult; //manejador de archivo
  679. if not ejec then exit;
  680. fileclose(stack[sp].valInt);
  681. end;
  682. procedure TGenCod.fun_write(fun: TxpEleFun);
  683. var
  684. cad: String;
  685. begin
  686. PopResult; //manejador de archivo
  687. PopResult; //cadena
  688. if not ejec then exit;
  689. cad := stack[sp+1].valStr;
  690. filewrite(stack[sp].valInt, cad , length(cad));
  691. end;
  692. procedure TGenCod.StartSyntax;
  693. //Se ejecuta solo una vez al inicio
  694. var
  695. opr: TxpOperator;
  696. f: TxpEleFun;
  697. begin
  698. OnExprStart := @expr_start;
  699. OnExprEnd := @expr_End;
  700. ///////////define la sintaxis del compilador
  701. //Crea tipos de tokens personalizados
  702. tnExpDelim := xLex.NewTokType('ExpDelim', tkExpDelim);//delimitador de expresión ";"
  703. tnBlkDelim := xLex.NewTokType('BlkDelim', tkBlkDelim); //delimitador de bloque
  704. tnStruct := xLex.NewTokType('Struct', tkStruct); //personalizado
  705. tnOthers := xLex.NewTokType('Others'); //personalizado
  706. //Configura apariencia
  707. tkKeyword.Style := [fsBold]; //en negrita
  708. tkBlkDelim.Foreground:=clGreen;
  709. tkBlkDelim.Style := [fsBold]; //en negrita
  710. tkStruct.Foreground:=clGreen;
  711. tkStruct.Style := [fsBold]; //en negrita
  712. //inicia la configuración
  713. xLex.ClearMethodTables; //limpìa tabla de métodos
  714. xLex.ClearSpecials; //para empezar a definir tokens
  715. //crea tokens por contenido
  716. xLex.DefTokIdentif('[$A-Za-z_]', '[A-Za-z0-9_]*');
  717. xLex.DefTokContent('[0-9]', '[0-9.]*', tnNumber);
  718. //Define palabras claves.
  719. {Notar que si se modifica aquí, se debería también, actualizar el archivo XML de
  720. sintaxis, para que el resaltado y completado sea consistente.}
  721. xLex.AddIdentSpecList('ENDIF ELSE ELSEIF', tnBlkDelim);
  722. xLex.AddIdentSpecList('true false', tnBoolean);
  723. xLex.AddIdentSpecList('CLEAR CONNECT CONNECTSSH DISCONNECT SENDLN WAIT PAUSE STOP', tnSysFunct);
  724. xLex.AddIdentSpecList('LOGOPEN LOGWRITE LOGCLOSE LOGPAUSE LOGSTART', tnSysFunct);
  725. xLex.AddIdentSpecList('FILEOPEN FILECLOSE FILEWRITE', tnSysFunct);
  726. xLex.AddIdentSpecList('MESSAGEBOX CAPTURE ENDCAPTURE EDIT EXPLORER DETECT_PROMPT', tnSysFunct);
  727. xLex.AddIdentSpecList('IF', tnStruct);
  728. xLex.AddIdentSpecList('THEN', tnKeyword);
  729. //símbolos especiales
  730. xLex.AddSymbSpec(';', tnExpDelim);
  731. xLex.AddSymbSpec(',', tnExpDelim);
  732. xLex.AddSymbSpec('+', tnOperator);
  733. xLex.AddSymbSpec('-', tnOperator);
  734. xLex.AddSymbSpec('*', tnOperator);
  735. xLex.AddSymbSpec('/', tnOperator);
  736. xLex.AddSymbSpec(':=', tnOperator);
  737. xLex.AddSymbSpec('=', tnOperator);
  738. xLex.AddSymbSpec('>', tnOperator);
  739. xLex.AddSymbSpec('>=', tnOperator);
  740. xLex.AddSymbSpec('<', tnOperator);
  741. xLex.AddSymbSpec('<=', tnOperator);
  742. xLex.AddSymbSpec('(', tnOthers);
  743. xLex.AddSymbSpec(')', tnOthers);
  744. xLex.AddSymbSpec(':', tnOthers);
  745. //crea tokens delimitados
  746. xLex.DefTokDelim('''','''', tnString);
  747. xLex.DefTokDelim('"','"', tnString);
  748. xLex.DefTokDelim('//','', xLex.tnComment);
  749. xLex.DefTokDelim('/\*','\*/', xLex.tnComment, tdMulLin);
  750. //define bloques de sintaxis
  751. xLex.AddBlock('{','}');
  752. xLex.Rebuild; //es necesario para terminar la definición
  753. ///////////Crea tipos y operaciones
  754. ClearTypes;
  755. tipInt :=CreateType('int',t_integer,4); //de 4 bytes
  756. //debe crearse siempre el tipo char o string para manejar cadenas
  757. // tipStr:=CreateType('char',t_string,1); //de 1 byte
  758. tipStr:=CreateType('string',t_string,-1); //de longitud variable
  759. tipBol:=CreateType('boolean',t_boolean,1);
  760. //////// Operaciones con Int ////////////
  761. {Los operadores deben crearse con su precedencia correcta}
  762. tipInt.OperationLoad:=@int_procLoad;
  763. opr:=tipInt.CreateBinaryOperator(':=',2,'asig'); //asignación
  764. opr.CreateOperation(tipInt,@int_asig_int);
  765. opr:=tipInt.CreateBinaryOperator('+',5,'suma');
  766. opr.CreateOperation(tipInt,@int_suma_int);
  767. opr:=tipInt.CreateBinaryOperator('-',5,'resta');
  768. opr.CreateOperation(tipInt,@int_resta_int);
  769. opr:=tipInt.CreateBinaryOperator('*',6,'mult');
  770. opr.CreateOperation(tipInt,@int_mult_int);
  771. opr:=tipInt.CreateBinaryOperator('/',6,'mult');
  772. opr.CreateOperation(tipInt,@int_idiv_int);
  773. opr:=tipInt.CreateBinaryOperator('=',6,'mult');
  774. opr.CreateOperation(tipInt,@int_igual_int);
  775. opr:=tipInt.CreateBinaryOperator('>',6,'may');
  776. opr.CreateOperation(tipInt,@int_mayor_int);
  777. opr:=tipInt.CreateBinaryOperator('>=',6,'may');
  778. opr.CreateOperation(tipInt,@int_mayori_int);
  779. opr:=tipInt.CreateBinaryOperator('<',6,'men');
  780. opr.CreateOperation(tipInt,@int_menor_int);
  781. opr:=tipInt.CreateBinaryOperator('<=',6,'men');
  782. opr.CreateOperation(tipInt,@int_menori_int);
  783. //////// Operaciones con String ////////////
  784. tipStr.OperationLoad:=@str_procLoad;
  785. opr:=tipStr.CreateBinaryOperator(':=',2,'asig'); //asignación
  786. opr.CreateOperation(tipStr,@str_asig_str);
  787. opr:=tipStr.CreateBinaryOperator('+',7,'concat');
  788. opr.CreateOperation(tipStr,@str_concat_str);
  789. opr:=tipStr.CreateBinaryOperator('=',7,'igual');
  790. opr.CreateOperation(tipStr,@str_igual_str);
  791. //////// Operaciones con Boolean ////////////
  792. tipBol.OperationLoad:=@bol_procLoad;
  793. opr:=tipBol.CreateBinaryOperator(':=',2,'asig'); //asignación
  794. opr.CreateOperation(tipBol,@bol_asig_bol);
  795. //////// Funciones básicas ////////////
  796. f := CreateSysFunction('clear', tipInt, @fun_clear);
  797. f := CreateSysFunction('connect', tipInt, @fun_connectTelnet);
  798. f.CreateParam('',tipStr);
  799. f := CreateSysFunction('connect', tipInt, @fun_connect); //sobrecargada
  800. f := CreateSysFunction('connectSSH', tipInt, @fun_connectSSH);
  801. f.CreateParam('',tipStr);
  802. if FindDuplicFunction then exit;
  803. f := CreateSysFunction('disconnect', tipInt, @fun_disconnect);
  804. f := CreateSysFunction('detect_prompt', tipInt, @fun_detect_prompt);
  805. f := CreateSysFunction('edit', tipInt, @fun_edit);
  806. f.CreateParam('',tipStr);
  807. f := CreateSysFunction('explorer', tipInt, @fun_explorer);
  808. f.CreateParam('',tipStr);
  809. f := CreateSysFunction('fileopen', tipInt, @fun_fileopen);
  810. f.CreateParam('',tipInt);
  811. f.CreateParam('',tipStr);
  812. f.CreateParam('',tipInt);
  813. f := CreateSysFunction('fileclose', tipInt, @fun_close);
  814. f.CreateParam('',tipInt);
  815. f := CreateSysFunction('filewrite', tipInt, @fun_write);
  816. f.CreateParam('',tipInt);
  817. f.CreateParam('',tipStr);
  818. f := CreateSysFunction('logopen', tipInt, @fun_logopen);
  819. f.CreateParam('',tipStr);
  820. f := CreateSysFunction('logwrite', tipInt, @fun_logwrite);
  821. f.CreateParam('',tipStr);
  822. f := CreateSysFunction('logclose', tipInt, @fun_logclose);
  823. f := CreateSysFunction('logpause', tipInt, @fun_logpause);
  824. f := CreateSysFunction('logstart', tipInt, @fun_logstart);
  825. f := CreateSysFunction('messagebox', tipInt, @fun_messagebox);
  826. f.CreateParam('',tipStr);
  827. f := CreateSysFunction('messagebox', tipInt, @fun_messageboxI);
  828. f.CreateParam('',tipInt);
  829. f := CreateSysFunction('pause', tipInt, @fun_pause);
  830. f.CreateParam('',tipInt);
  831. f := CreateSysFunction('puts', tipInt, @fun_puts);
  832. f.CreateParam('',tipStr);
  833. f := CreateSysFunction('puts', tipInt, @fun_putsI); //sobrecargada
  834. f.CreateParam('',tipInt);
  835. f := CreateSysFunction('sendln', tipInt, @fun_sendln);
  836. f.CreateParam('',tipStr);
  837. f := CreateSysFunction('stop', tipInt, @fun_stop);
  838. f := CreateSysFunction('wait', tipInt, @fun_wait);
  839. f.CreateParam('',tipStr);
  840. // f := CreateSysFunction('capture', tipInt, @fun_connectTelnet);
  841. // f := CreateSysFunction('endcapture', tipInt, @fun_connectTelnet);
  842. // f := CreateSysFunction('edit', tipInt, @fun_connectTelnet);}
  843. end;
  844. end.