Pouvoir disposer d'un outil de debugging minimal peut revêtir une importance capitale.
C'est encore plus vrai lorsque l'on maintient un vieux logiciel en Clipper (re-compilé avec Harbour + Visual Studio C++ 2008).
Comme je compile le soft en ligne de commande, je n'ai pas cette chance de pouvoir disposer d'un déboggeur ARFF!
Je voulais donc utiliser d'un fichier de déboggage et d'une fonction DMSG (Debug Message) me permettant de laisser des traces dans ce fichier de trace. Fichier bien utile car il permet de capturer des informations sur le fonctionnement du programme.
Clipper à prévu le coup avec les commandes "SET ALTERNATE TO" permettant de rediriger la sortie de la console vers un fichier. Idéal pour laisser une trace :-)
Malheureusement pour moi, cette fonctionnalité est déjà utilisé à d'autres fins... a moi donc d'utiliser un autre procédé pour y arriver.
FT_FUSE - manipulation de fichier
Il existe heureusement les fonction FT_FUSE et consort!
Voici l'implémentation de la procédure DMSG, une fonction qui écrit des message dans un fichier "debug.log".
Cette fonction utilise également la variable globale dbgLineCount pour incrémenter le numéro de ligne.
#include "fileio.ch" ... && DMSG - Debugging Message && line counter for DMSG procedure PUBLIC dbgLineCount dbgLineCount = 0 ... ***************** PROCEDURE DMSG ***************** * Write a debug.log file by inserting records on the top of the file * If the file is not present, nothing is written into it * see FT_USE @ http://www.ousob.com/ng/nanfor/ng2319d.php * see FILE I/O @ http://www.itk.ru/clip-doc.en/categfileio.html * beautiful sample @ http://www.groupsrv.com/computers/about324430.html * * 27/03/2012 - WARNING function is buggy and may turns into infinite loop ! * 29/03/2012 - Fixed :-) parameters sMsg private hFile private sToWrite dbgLineCount = dbgLineCount + 1 && Line counter dbgFilename = "c:\stock\debug.log" ft_fselect(1) hFile := fopen(dbgFilename, FO_READWRITE + FO_SHARED) hFile := ft_fuse(dbgFilename) if hFile < 0 return endif * Data to write in the Debug File (place CR/LF at the end of file) sToWrite = Str(dbgLineCount) + " " + TIME() + " " + sMsg + chr(13) + chr(10) * Write a buffer fwrite(hFile,sToWrite) * close file FT_FUSE() return
L'appel se résume à:
DO DMSG WITH "L477:replace FAMI with TheResult"Note: le "DO" n'est normalement pas nécessaire, il passe les arguments par référence.
Et le contenu du fichier debug ressemble à ceci:
3 11:35:05 ------------------- STARTING STOCK ------------------------ 4 11:35:12 0000, main menu exit, SET PRINT OFF 5 11:35:15 SAYA050 : Say Article - ENTER 6 11:35:15 before call xaFami(Fami) - validation of fami 7 11:35:15 L477:replace FAMI with TheResult 8 11:35:15 after call xaFami(Fami) 9 11:35:15 SAYA050 : Say Article - LEAVE 10 11:35:18 BEFORE SUIVANT - will exec skip
En savoir plus sur la manipulation de fichier en Clipper
Vous trouverez des informations sur les opérations fichier dans les références suivantes
- FT_USE http://www.ousob.com/ng/nanfor/ng2319d.php
- FILE I/O http://www.itk.ru/clip-doc.en/categfileio.html
Je me permet de reprendre le contenu ci-dessous (car il est trop précieux pour prendre le risque qu'il soit perdu!)
//* //* privsmnu.prg source code //* #include "fileio.ch" //* function load temporary privilege dbf Function Prv_qProcess local iEmpnum, iCcde, iUsrid, iSysid local iPrecust, iSecpack, iUsrpriv local prvEmpnum, prvCcde, prvUsrid, prvSysid local prvPrecust, privSecpack, prvUsrpriv local cntmsg, qUsr, dUsr, mycnt := 0 local mrt, mrb, mcl, mcr, msg_scrn local rFilename, tmpFilename tmpFileName := popupdir('C:\IAREVAL\INPUT\*.txt','D','Select Compare file',; "w+/b,w+/r",.t.) rFilename := "C:\IAREVAL\INPUT\" + tmpFilename gFilename := "C:\IAREVAL\REPORTS\GAPFILE.TXT" mFilename := "C:\IAREVAL\REPORTS\INMASTER.TXT" if varlen(rFileName) < 20 return end ft_fselect(1) rfile := ft_fuse(rFilename) ft_fselect(2) gFile := fcreate(gFilename,FO_READWRITE) gFile := fopen(gFilename, FO_READWRITE + FO_SHARED) gFile := ft_fuse(gFilename) ft_fselect(3) mFile := fcreate(mFilename,FO_READWRITE) mFile := fopen(mFilename, FO_READWRITE + FO_SHARED) mFile := ft_fuse(mFilename) qUsr := ft_dispmsg( { { "Press [Y] to continue with", ; "process. Press any other ", ; "key to abort the process. " }, ; { "r/w", "r/w", "r/w" } } , ; "Y" ) if qUsr = .t. use PRIVQDBF index PRIVQDBF shared new plswait(.t.,"Processing compare...") ft_fselect(1) rFile := ft_fuse(rFilename) ft_fgotop() do while ! ft_feof() * read line rline = ft_freadln(rFile) mycnt = mycnt + 1 iEmpnum := substr(rline, 1, 6) iCcde := substr(rline, 18, 3) iUsrid := substr(rline, 28, 20) iSysid := substr(rline, 49, 1Cool *** probablement iSysid := substr(rline, 49, 18) iPrecust := substr(rline, 68, 20) iSecpack := substr(rline, 89, 16) iUsrpriv := substr(rline,106, 45) iRevFile := substr(rline,152, 44) select PRIVQDBF dbgotop() do while !eof() BEGIN SEQUENCE if iEmpnum = Empnum .and. iCcde = Ccde .and. iUsrid = Usrid ; .and. iSysid = Sysid .and. iSecPack = Secpack .and. iUsrpriv = Usrpriv //* write dbf record to txt file *// tmplne := empnum + ccde + usrid + sysid + precust + secpack + usrpriv + revfile fwrite(mfile,tmplne) BREAK else forget() skip endif End end //* record not found - write to gap file *// tmplne := iEmpnum + iCcde + iUsrid + iSysid + iPrecust + iSecpack + iUsrpriv + iRevfile fwrite(gfile,tmplne) tmplne := "" ft_fselect(1) ft_fskip() enddo close all plswait(.f.) msg_scrn = savescreen(0,0,Maxrow(),79) msgcolor = "n/w,n/w,,,n/w" setcolor(msgcolor) mrt := maxrow()/2-2 mrb := maxrow()/2+1 mcl := maxcol()/2-9 mcr := maxcol()/2+9 clearbox(mrt,mcl,mrb,mcr,'Single') @mrt+1,mcl+1 say " # Records read:" @mrt+2,mcl+3 say " ==> " + ltrim(str(mycnt)) inkey(20) setcolor(defColor) restscreen(0,0,Maxrow(),79,msg_scrn) endif return nil *: Eof: privsmnu.prg