2
0

GenCod.pas 26 KB

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