Just started using Harbour and have encountered some issues...

416 views
Skip to first unread message

Dasun

unread,
Apr 22, 2013, 11:29:30 AM4/22/13
to harbou...@googlegroups.com
All,

First up, for a first posting background..

Well I have not used Clipper in the better part of 2 decades and I found some old source code of an application I wrote and thought it would be a it of fun to resurrect it in the the windows world - apparently there is still a user or two out so it might help them.  I choose the latest Marinas-IDE, if there is a better tool for taking this to a windows environment with @SAY GET equivalents let me know.

Workflow get running in console mode, then modal windows and then maybe MDI.  I had forgotten how good clipper was for writing apps - very clean and no-nonsense compared to the windows stuff I have worked since then.  Now if I can get Harbour and a windows GUI to work as clean as @SAY GET does I just might find some real world uses for it.  Maybe find someone who wants to convert old dbase code and charge 'em for the pleasure as I am having a ball

Now the problems.

I am very impressed with Harbour my only real problem getting a compile was clipper tools functions & funcky functions that are not supported.  For the time at least these are stubbed out.

Now ALLTRIM is causing me grief - and I use it a lot -- when passed a variable holding a NIL it falls over.  This is different to clipper because the app used to compile and run.  So I tried this trick and it fell over with a class error at runtime.  I really do not want to visit dozens of modules and put in an check to make sure the strings are set.  Any ideas ?  Dang, I just noticed I left the angled brackets off the last statement so I will compile and test

#xtranslate ALLTRIM(<ls_String>) => IIF(<ls_String> == NIL, "", RTRIM(LTRIM(ls_String)))


Next problem..DBFCDX indexes are truncated to 10 char....is there any core RDD that allows longer than 10 char index names?  I have a nice way of defining database and automating data handling in clipper (burnt a lot of time developing it back in the day) but there is no easy way to automatically truncate to 10 char so I have to do it manually - as show below in bold.

DEFINE DATABASE Consult
        PRIMARY KEY IS consult_no INDEX NAME IS Consult1
        CHILD TERMINATION IS CHILD_NULL


        INDEX IS Consult1 WITH KEY TRANS(consult_no,RECNUMPIC)
        //INDEX IS Consult2 WITH KEY TRANS(pat_no,RECNUMPIC)+DTOS(date_consult) //2013 RDD truncates to 10 char
INDEX IS Consult2 WITH KEY TRANS(pat_no,RECNUMPIC)+DTOS(date_consu) //2013
#ifdef OPMS
        //INDEX IS Consult3 WITH KEY TRANS(locality_no,RECNUMPIC) //2013 RDD truncates to 10 char
INDEX IS Consult3 WITH KEY TRANS(locality_n,RECNUMPIC) //2013
#endif
        INDEX IS Consult4 WITH KEY TRANS(note_no,RECNUMPIC)
        //INDEX IS Consult6 WITH KEY DTOS(date_consult) //2013 RDD truncates to 10 char
INDEX IS Consult6 WITH KEY DTOS(date_consu) //2013
        INDEX IS Consult7 WITH KEY PADR(ALLTRIM(TRANS(pat_no,RECNUMPIC))+TRANS(consult_no,RECNUMPIC),RECNUMSIZE*2)
        INDEX IS Consult8 WITH KEY pat_no
#ifdef OPMS
        //INDEX IS Consult9 WITH KEY IIF(has_paid,"T","F")+DTOS(date_consult)+;
        //                           TRANS(Locality_Number,RECNUMPIC) //2013 RDD truncates to 10 char
INDEX IS Consult9 WITH KEY IIF(has_paid,"T","F")+DTOS(date_consu)+;
                                   TRANS(Locality_N,RECNUMPIC) //2013
#endif
        //INDEX IS Consult9 WITH KEY STR(DESCEND(date_consult))
        
        ADD FIELD consult_no    TYPE IS NUMERICTYPE WIDTH IS RECNUMSIZE;
            DESCRIPTION Consultation_Number;
            PROG ID IS CONSULT_NO
#ifdef OPMS
        ADD FIELD locality_no    TYPE IS NUMERICTYPE WIDTH IS RECNUMSIZE;
            DESCRIPTION Locality_Number;
            PROG ID IS CONSULT_LOCALITY
#endif
        ADD FIELD pat_no    TYPE IS NUMERICTYPE WIDTH IS RECNUMSIZE;
            DESCRIPTION Patient_Number;
            PROG ID IS CONSULT_PATIENT
......................
FOREIGN KEY FIELD note_no     IS PRIMARY KEY note_no    IN DB Note
#ifdef OPMS
        FOREIGN KEY FIELD locality_no IS PRIMARY KEY local_no   IN DB Locality
#endif
        FOREIGN KEY FIELD pat_no      IS PRIMARY KEY pat_no     IN DB Patient
        FOREIGN KEY FIELD optom_no    IS PRIMARY KEY optomet_no IN DB Optomet

        ASSIGN DATABASE TO Table
    END DEFINE
RETURN Table


Pritpal Bedi

unread,
Apr 22, 2013, 2:34:26 PM4/22/13
to harbou...@googlegroups.com
Hi Dusan


Well I have not used Clipper in the better part of 2 decades and I found some old source code of an application I wrote and thought it would be a it of fun to resurrect it in the the windows world - apparently there is still a user or two out so it might help them.  I choose the latest Marinas-IDE, if there is a better tool for taking this to a windows environment with @SAY GET equivalents let me know.


Then, look into QtContribs at :

Group:
Downloads:

And specially ChangeLog:


You may also be interested in:


Pritpal Bedi
a student of software analysis & concepts

elch

unread,
Apr 23, 2013, 4:39:41 AM4/23/13
to harbou...@googlegroups.com
Hi Dasun,

.. I choose the latest Marinas-IDE ..

looks not bad - this seem to be 'only' a combination of Harbour plus something own GUI above all plus the separated Harbour QT-project

-- including all these memory leaks etc. from the last piece ;-)

 

Workflow get running in console mode, then modal windows and then maybe MDI.
If you don't want a true GUI, there are other possibilities in pure Harbour to make a Windows app.
Search maybe a bit for GTWVT and GTWVG, for demos in the test dirs below and what that is ...

 
Now the problems.
I am very impressed with Harbour my only real problem getting a compile was clipper tools functions & funcky functions that are not supported.  For the time at least these are stubbed out.

Harbour has the additional contrib library: hbct

which contains nearly all <C>lipper <T>ools functions - works from finest !

But i fear that you will have no luck with the Funcky lib. There are others available, but i don't know of freaky funcky ;)

So you will need to translate/ transform these function calls ...



Now ALLTRIM is causing me grief - and I use it a lot -- when passed a variable holding a NIL it falls over.  This is different to clipper because the app used to compile and run.

:-) -- I checked against original ! Clipper V5.2e (IMHO best version ever):

ALLTRIM( var_contains_nil_or_not_string )

leads to error:

"wrong argument: ALLTRIM"

which is exact what should expected when reading the original documentation:

http://x-hacker.org/ng/53guide/ngc2e2.html



Next problem..DBFCDX indexes are truncated to 10 char....is there any core RDD that allows longer than 10 char index names?
I don't like to cite your source - looks a bit not as real Clipper source.

[ BTW. function name is either TRANSFORM or TRAN, when shorted to 4! letters - it is a wonder that Harbour even supports that ]


About 240 is max length of an index key - 10 is the standard length of an index key, if the length is improper defined ! - exact like Clipper did.

For this length estimation when index is created, a BLANK value of the given field is evaluated.

Maybe show us your [missing] improper RECNUMPIC


Regards

Rolf

Dasun

unread,
Apr 23, 2013, 10:25:41 AM4/23/13
to harbou...@googlegroups.com
First up I have to thank Bob, Pritpal and Rolf for responding - obviously I need to research the GUI side for the better option as there is so much choice.out there. If QT has serious memory leaks it might be best avoided - maybe newer versions do not; again more digging required.  What GUI has the biggest following and most frequent updates?

Rolf - thank you for the info on ALLTRIM, which is a bit of a puzzle,  I am not sure what version of Clipper 5 I compiled the app with all those years ago but it works fine. Compiled with Harbour it gives me an error.  However using this statement #xtranslate ALLTRIM(<ls_String>) => IIF(<ls_String> == NIL, "", RTRIM(LTRIM(<ls_String>))) gets it running just fine.  Must be something peculiar in what I did when I originally wrote the beast.

The Clipper preprocessor was a really fantastic tool, I used it and a specially written database.prg to automate much of the database operations in a program - really made development faster and less error prone. Guess I will have to extend to the RDBMS world now.  The following snippet gives you an idea of what I was doing - effectively I used the preprocessor to make a data definition language for Clipper.  Incidentally RECNUMPIC is defined as follows #define RECNUMPIC        '999999'.

#xcommand   INDEX [IS] <index_Name> [WITH] [KEY] <char_index> =>;
            TEMP_STRUCT := INDEX_LIST;
            ;TEMP_STRUCT \[1] := <(index_Name)>;
            ;TEMP_STRUCT \[2] := <(char_index)>;
            ;TEMP_STRUCT \[3] := &("{||"+<(char_index)>+"}");
            ;AADD(DB_STRUCT\[4],ACLONE(TEMP_STRUCT))

I think I was using the MachSLX RDD or something like that and it allowed index names to to be quite long - hence my current search for an RDD that has similar functionality so I do not have to truncate my index names to 10 char - which I find hard to read and maintain.  I appreciate Harbours drive for Clipper compatibility - which is really very close - but some things like this could be modernised without impacting Clipper compatibility.

Dasun

elch

unread,
Apr 23, 2013, 11:40:37 AM4/23/13
to harbou...@googlegroups.com
Hi again, Dasun



 What GUI has the biggest following and most frequent updates?
?, perhaps QT ;-)
Without fun, one of the rare ones which have the claim to be multi-platform, the absolute fundamental claim of Harbour core.

 
... hence my current search for an RDD that has similar functionality so I do not have to truncate my index names to 10 char - which I find hard to read and maintain.  I appreciate Harbours drive for Clipper compatibility - which is really very close - but some things like this could be modernised without impacting Clipper compatibility.

I ultra strong believe of an error on your side - when indexing or seeking. Something i can't see from here, check also field types etc., as f.e:

TRANSFORM( "elch", "999999" ) leads to "".

Try to view (don't edit) the index file with a hex editor, there you should be able to see your index keys.

Start debugging to verify the index expression at runtime, check result with [x = index order]:

&( INDEXKEY(x) )

...


Regards

Rolf

Dasun

unread,
Apr 25, 2013, 6:27:55 AM4/25/13
to harbou...@googlegroups.com
Hi Rolf,

I have things compiled and running - although my DOS screens do not look right (see my earlier post) now and I appreciate everyone's help.  Most of my troubles were due to an interesting feature - sometimes I would not pass all the arguments to a function (brain dead polymorphism!) and the resulting variables were initialised differently in Harbour than Clipper when arriving in the called function  .  This did not cause trouble in Clipper 5.2 as  it runs correctly - but caused runtime errors for me in a Harbour compile

Now to explain things more clearly....and this command might be useful to someone - a little pay back for the help people have given me..

#xcommand DEFAULT ARG <arg_num> [VAR ]<variable> TO <value> => IIF (HB_PVALUE(<arg_num>) == NIL,<variable> := <value>,<value>) //2013-04-25 Function args important for Harbour



Examples Below To Explain What I mean      
(NO NEED FOR HELP IT ALL WORKS NOW)

------------ Start Excerpt from the function that creates the DBF database files
       //Make Database
        Make_DB(Data_Records[Loop][R_DATA]FLD_DBNAME,DB_Struct)
        Make_Indecies(Data_Records[Loop][R_DATA]FLD_DBNAME,Indecies) //Note only 1 argumet

--------------- End Excerpt


------------ Start Excerpt
/*
** Makes the index file/files for a table.  Added 19/06/1993
*/
FUNCTION Make_Indecies(DB_Name, DB_Indecies,PK_Name) //Note 3 arguments
    LOCAL Loop := 0, Num_Indecies := LEN(DB_Indecies), Mtr_Increment := 0
    LOCAL Is_PK := .F.
    LOCAL Char_Exp := "", Tag := "", Idx_Name := ""

//Start 2013-04-25 Check args because Harbour seems fussy.
DEFAULT ARG 1 VAR DB_Name TO "" 
DEFAULT ARG 2 VAR DB_Indecies TO {} 
DEFAULT ARG 3 VAR PK_Nane TO "" 
DEFAULT Num_Indecies TO 0
//End 2013
    
IF (Num_Indecies == 0) //No Indecies for this table!
        RETURN .T.
    ENDIF

------------------ Left our a large piece of code

    //Create Each Index
    FOR Loop := 1 TO Num_Indecies
        Is_PK := .F.

        IF (UPPER(ALLTRIM(DB_Indecies[Loop]INDEX_NAME)) ==;
            UPPER(ALLTRIM(PK_Name))) Without the default settings above  this would cause a run time error
            Is_PK := .T.
        ENDIF

----------------- End Excerpt

Juan L. Gamero

unread,
Apr 25, 2013, 6:46:15 AM4/25/13
to harbou...@googlegroups.com
Hi Dasun:

Sorry if I have missed something, but why you can't simply put:

DEFAULT DB_Name TO ""
etc

Didn't it work?

Anyway, please note (It seems that HB_PValue() documentation is incomplete) that the HB_PValue() function has a second optional parameter to put a new value into an argument passed to a function. In the previous statement, it can be:

HB_PValue( 1, "" )  // Puts an empty string into the first parameter

And a last note, you can take a look at HB_Default() function that was created to supersede the DEFAULT ... TO ... command, as of:

HB_Devault( @uVar, nNewValue )

And it sets nNewValue to uVar if this var contains NIL or a value of a diferent type of nNewValue.

p.e. HB_Default( @DB_Name, "" ) // Sets empty string if DB_Name is NIL or has a value of a different type of string.

Best regards,
--
Juan L. Gamero

Dasun

unread,
Apr 25, 2013, 7:29:36 AM4/25/13
to harbou...@googlegroups.com
Hi Juan,

Thanks for the info - nice to know about the second parameter would have made things a hair simpler..  

DEFAULT TO did not work but using the HB_PValue check worked like a charm.  

I only hope someone does not tell me that DEFAULT TO is implemented with a HB_Pvalue check as I will be really scratching my head then!.     

Juan L. Gamero

unread,
Apr 25, 2013, 7:55:49 AM4/25/13
to harbou...@googlegroups.com
Dasun:

:)

No head damage, DEFAULT TO is like your new command, but with xVar == NIL instead of HB_PValue( nParam ) == NIL and is defined in <include/common.ch>. Thats why I was surprised it did not work.

I think this code shows what I mean:

PROCEDURE Main()

   f( 1,, 3 )
   
   RETURN
   
   
FUNCTION f( a, b, c, d )

   ? a, b, c, d
   
   IF d == NIL
      d := 4
   ENDIF
   
   ? d
   
   RETURN NIL      

Best regards,
--
Juan L. Gamero


Dasun

unread,
Apr 25, 2013, 9:28:16 AM4/25/13
to harbou...@googlegroups.com
Hi Juan,

Glad to hear my head is still intact!  

The issue seems to be the unused arguments come across as numeric  - which is fine until I use a string function and then boom!  This is why xVar == NIL followed by value assignment did not work - because it had the wrong data type for strings; although I conceded  testing the HB_PValue for NIL and then assigning the default variable value should be functionally equivalent   Mind you I am basing all this on debugger values and I have not made a small program to prove this definitively - I just did what seemed right to make it work and now it does.   

I appreciate your effort in working up an example - if my theory is correct you should find d is numeric and can be assigned the value 4 but try and do do this: d:= UPPER(d) and it should blow.  I think maybe my coding back in the day was not quite as type safe as it should have been! 
Reply all
Reply to author
Forward
0 new messages