REPORT FORM command does not search the SET PATH path

206 views
Skip to first unread message

Heinz V Bergen

unread,
Jun 4, 2015, 4:56:16 PM6/4/15
to harbou...@googlegroups.com
Hello,

Something has changed in past month or so,

The REPORT FORM <cFRM> does not search the SET PATH path anymore?
Example:

Procedure Main()
SetMode(25,80)
CLS
Set Path To c:\harbour\trunk\tests    //change to match you Harbour path to the "tests" directory

USE test          //no problem finds test.dbf and opens it

//this statement used to work, now fails with DOS error 2 File not found
REPORT FORM test       //( Does not seem to search the "SET PATH" path to find test.frm )

//REPORT FORM c:\harbour\tests\test     //explicitly adding the path works

USE
RETURN

Regards,
Heinz V Bergen

Ash

unread,
Jun 4, 2015, 9:51:08 PM6/4/15
to harbou...@googlegroups.com
Hello Heinz,

Have you tried SET DEFAULT TO?

Regards.
Ash

Heinz V Bergen

unread,
Jun 5, 2015, 10:54:49 AM6/5/15
to harbou...@googlegroups.com
Hi Ash,

Not sure how that is relevant,
SET DEFAULT path is my session working directory, where temp files and such are created and worked with.
SET PATH path points to my LIVE system Data.

Anyways the point is whether the command REPORT FORM <FormName> should be checking the SET PATH path if FormName.Frm is not found in the SET DEFAULT path? It used to and now it doesn't giving a DOS Error 2.

Regards,
Heinz

elch

unread,
Jun 5, 2015, 12:38:50 PM6/5/15
to harbou...@googlegroups.com

Hello Heinz,


confirmed !


In: src/rtl/treport.prg, for method: LoadReportFile()

only SET( _SET_DEFAULT ) is searched.


That is on the contrary to: doc/en/treport.txt,

where explicitly both ( plus SET PATH ) are mentioned.

My 5.3 NG doc write *only* about SET PATH setting, not SET DEFAULT - maybe they meant also both ?


Could be easily added/ changed -- but i'm unsure about how Clipper behaved, as never used this technic.

Heinz, or any else: do you have a running Clipper ( version ? ) to figure that precisely out ?


---

This may also relate to: src/rtl/tlabel.prg and method: LoadLabel(),

aka command: LABEL FORM


best regards

Rolf

Ash

unread,
Jun 5, 2015, 2:31:47 PM6/5/15
to harbou...@googlegroups.com
Hello Rolf,

As a rule, I keep my application and associated *.lbl and *.frm files in one folder and use full paths to get to data files. This arrangement makes for easy access to data be it a folder or an IP address.

Regards.
Ash

Heinz V Bergen

unread,
Jun 5, 2015, 3:15:10 PM6/5/15
to harbou...@googlegroups.com
Hello Rolf,

Yes I confirm Clipper behavior is to first search SET DEFAULT path and then SET PATH path.

I've traced the problem to rtl\treport.prg line 875 currently reads as:
      FOR EACH cPath IN hb_ATokens( StrTran( Set( _SET_DEFAULT ), ",", ";" ), ";" )
and should be:
      FOR EACH cPath IN hb_ATokens( StrTran( Set( _SET_DEFAULT ) + ";" + Set( _SET_PATH ), ",", ";" ), ";" )

I was wrong about this being an issue within the last month, it actually occurred from a change 6 months ago:
    https://github.com/harbour/core/commit/b9b235cff96fb295d041276202b5dae09f553154

You are right this should probably also get fixed for label files also at line 352 in treport.prg

Oh, and here's a link to Clipper NG showing both SET PATH and SET DEFAULT help:
   http://www.ousob.com/ng/clguide/ng6fdf7.php

Thanks,
Heinz

Klas Engwall

unread,
Jun 5, 2015, 3:37:43 PM6/5/15
to harbou...@googlegroups.com
Hi Heinz, Rolf and others

This post became somewhat redundant while I was typing. But to sum it up:

> Something has changed in past month or so,
>
> The REPORT FORM <cFRM> does not search the SET PATH path anymore?

Set(_SET_PATH) seems to have disappeared in this commit:

2014-12-03 00:41 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
[ ... ]
* src/rtl/tlabel.prg
* src/rtl/treport.prg
% use hb_ATokens() instead of local functions ListAsArray()
* simplified reading labels and reports from files

And it looks like the problem in treport.prg is a "contamination" from
the hb_Atokens() fix in tlabel.prg where Set(_SET_DEFAULT) has been the
only path being searched "since forever".

Old treport.prg: Set(_SET_PATH) and Set(_SET_DEFAULT)
New treport.prg: Set(_SET_DEFAULT) only
Old and new tlabel.prg: Set(_SET_DEFAULT) only

The Clipper 5.3 NG and the dead tree manuals say that both REPORT FORM
and LABEL FORM search Set(_SET_PATH) but they do not mention
Set(_SET_DEFAULT) at all.

The Harbour docs (By Luiz Culik, 1999) mention both SET PATH and SET
DEFAULT in the REPORT FORM case but only SET PATH in the LABEL FORM
case. And that it not consistent with old Harbour code in the LABEL FORM
case.

Like Rolf I have never used either REPORT FORM or LABEL FORM, so I am
not familiar with how Clipper behaves in reality. While I was typing
this Heinz confirmed that Clipper searches first Set(_SET_DEFAULT) and
then Set(_SET_PATH) in the REPORT FORM case. Has anyone used LABEL FORM?

Regards,
Klas

frank van nuffel

unread,
Jun 6, 2015, 8:39:47 AM6/6/15
to harbou...@googlegroups.com

Hi Klas,

Actually, the sources are included with both CA-Clipper 5.2(e) and 5.3(b)

       SOURCE/SYS/LBLBACK.PRG for LABEL FORM
and SOURCE/SYS/FRMBACK.PRG for REPORT FORM

I confirm there's no SET( _SET_PATH ) in LBLBACK.PRG - while yes in FRMBACK.PRG

LBLBACK.PRG 5.2e

FUNCTION __LblLoad( cLblFile )
   LOCAL i, j       := 0                  // Counters
   LOCAL cBuff      := SPACE(BUFFSIZE)    // File buffer
   LOCAL nHandle    := 0                  // File handle
   LOCAL nReadCount := 0                  // Bytes read from file
   LOCAL lStatus    := .F.                // Status
   LOCAL nOffset    := FILEOFFSET         // Offset into file
   LOCAL nFileError := F_OK               // File error
   LOCAL cFieldText := ""                 // Text expression container
   LOCAL err                              // error object

   LOCAL cDefPath          // contents of SET DEFAULT string
   LOCAL aPaths            // array of paths
   LOCAL nPathIndex := 0   // iteration counter

   // Create and initialize default label array
   LOCAL aLabel[ LB_COUNT ]
   aLabel[ LB_REMARK ]  := SPACE(60)      // Label remark
   aLabel[ LB_HEIGHT ]  := 5              // Label height
   aLabel[ LB_WIDTH ]   := 35             // Label width
   aLabel[ LB_LMARGIN ] := 0              // Left margin
   aLabel[ LB_LINES ]   := 1              // Lines between labels
   aLabel[ LB_SPACES ]  := 0              // Spaces between labels
   aLabel[ LB_ACROSS ]  := 1              // Number of labels across
   aLabel[ LB_FIELDS ]  := {}             // Array of label fields

   // Open the label file
   nHandle := FOPEN( cLblFile )

   IF ( ! EMPTY( nFileError := FERROR() ) ) .AND. !( "\" $ cLblFile .OR. ":" $ cLblFile )

      // Search through default path; attempt to open label file
      cDefPath := SET( _SET_DEFAULT )     /// line 79
      cDefPath := STRTRAN( cDefPath, ",", ";" )
      aPaths := ListAsArray( cDefPath, ";" )


LBLBACK.PRG 5.3b

FUNCTION __LblLoad( cLblFile )
   LOCAL i, j       := 0                  // Counters
   LOCAL cBuff      := SPACE(BUFFSIZE)    // File buffer
   LOCAL nHandle    := 0                  // File handle
   LOCAL nReadCount := 0                  // Bytes read from file
   LOCAL lStatus    := .F.                // Status
   LOCAL nOffset    := FILEOFFSET         // Offset into file
   LOCAL nFileError := F_OK               // File error
   LOCAL cFieldText := ""                 // Text expression container
   LOCAL err                              // error object

   LOCAL cDefPath          // contents of SET DEFAULT string
   LOCAL aPaths            // array of paths
   LOCAL nPathIndex := 0   // iteration counter

   // Create and initialize default label array
   LOCAL aLabel[ LB_COUNT ]
   aLabel[ LB_REMARK ]  := SPACE(60)      // Label remark
   aLabel[ LB_HEIGHT ]  := 5              // Label height
   aLabel[ LB_WIDTH ]   := 35             // Label width
   aLabel[ LB_LMARGIN ] := 0              // Left margin
   aLabel[ LB_LINES ]   := 1              // Lines between labels
   aLabel[ LB_SPACES ]  := 0              // Spaces between labels
   aLabel[ LB_ACROSS ]  := 1              // Number of labels across
   aLabel[ LB_FIELDS ]  := {}             // Array of label fields

   // Open the label file
   nHandle := FOPEN( cLblFile )

   IF ( ! EMPTY( nFileError := FERROR() ) ) .AND. !( "\" $ cLblFile .OR. ":" $ cLblFile )

      // Search through default path; attempt to open label file
      cDefPath := SET( _SET_DEFAULT )  /// line 79
      cDefPath := STRTRAN( cDefPath, ",", ";" )
      aPaths := ListAsArray( cDefPath, ";" )

FRMBACK.PRG 5.2e

FUNCTION __FrmLoad( cFrmFile )
   LOCAL cFieldsBuff
   LOCAL cParamsBuff
   LOCAL nFieldOffset   := 0
   LOCAL cFileBuff      := SPACE(SIZE_FILE_BUFF)
   LOCAL cGroupExp      := SPACE(200)
   LOCAL cSubGroupExp   := SPACE(200)
   LOCAL nColCount      := 0        // Number of columns in report
   LOCAL nCount
   LOCAL nFrmHandle                 // (.frm) file handle
   LOCAL nBytesRead                 // Read/write and content record counter
   LOCAL nPointer       := 0        // Points to an offset into EXPR_BUFF string
   LOCAL nFileError                 // Contains current file error
   LOCAL cOptionByte                // Contains option byte

   LOCAL aReport[ RP_COUNT ]        // Create report array
   LOCAL err                        // error object

   LOCAL cDefPath          // contents of SET DEFAULT string
   LOCAL aPaths            // array of paths
   LOCAL nPathIndex := 0   // iteration counter

   LOCAL s, paths
   LOCAL i
    LOCAL aHeader                // temporary storage for report form headings
    LOCAL nHeaderIndex        // index into temporary header array

   // Initialize STATIC buffer values
   cLengthsBuff  := ""
   cOffsetsBuff  := ""
   cExprBuff     := ""

   // Default report values
   aReport[ RP_HEADER ]    := {}
   aReport[ RP_WIDTH ]     := 80
   aReport[ RP_LMARGIN ]   := 8
   aReport[ RP_RMARGIN ]   := 0
   aReport[ RP_LINES ]     := 58
   aReport[ RP_SPACING ]   := 1
   aReport[ RP_BEJECT ]    := .T.
   aReport[ RP_AEJECT ]    := .F.
   aReport[ RP_PLAIN ]     := .F.
   aReport[ RP_SUMMARY ]   := .F.
   aReport[ RP_COLUMNS ]   := {}
   aReport[ RP_GROUPS ]    := {}
   aReport[ RP_HEADING ]   := ""

   // Open the report file
   nFrmHandle := FOPEN( cFrmFile )

   IF ( !EMPTY( nFileError := FERROR() ) ) .AND. !( "\" $ cFrmFile .OR. ":" $ cFrmFile )

      // Search through default path; attempt to open report file
      cDefPath := SET( _SET_DEFAULT ) + ";" + SET( _SET_PATH ) /// line 158
      cDefPath := STRTRAN( cDefPath, ",", ";" )
      aPaths := ListAsArray( cDefPath, ";" )

FRMBACK.PRG 5.3b

FUNCTION __FrmLoad( cFrmFile )
   LOCAL cFieldsBuff
   LOCAL cParamsBuff
   LOCAL nFieldOffset   := 0
   LOCAL cFileBuff      := SPACE(SIZE_FILE_BUFF)
   LOCAL cGroupExp      := SPACE(200)
   LOCAL cSubGroupExp   := SPACE(200)
   LOCAL nColCount      := 0        // Number of columns in report
   LOCAL nCount
   LOCAL nFrmHandle                 // (.frm) file handle
   LOCAL nBytesRead                 // Read/write and content record counter
   LOCAL nPointer       := 0        // Points to an offset into EXPR_BUFF string
   LOCAL nFileError                 // Contains current file error
   LOCAL cOptionByte                // Contains option byte

   LOCAL aReport[ RP_COUNT ]        // Create report array
   LOCAL err                        // error object

   LOCAL cDefPath          // contents of SET DEFAULT string
   LOCAL aPaths            // array of paths
   LOCAL nPathIndex := 0   // iteration counter

   LOCAL s, paths
   LOCAL i
    LOCAL aHeader                // temporary storage for report form headings
    LOCAL nHeaderIndex        // index into temporary header array

   // Initialize STATIC buffer values
   cLengthsBuff  := ""
   cOffsetsBuff  := ""
   cExprBuff     := ""

   // Default report values
   aReport[ RP_HEADER ]    := {}
   aReport[ RP_WIDTH ]     := 80
   aReport[ RP_LMARGIN ]   := 8
   aReport[ RP_RMARGIN ]   := 0
   aReport[ RP_LINES ]     := 58
   aReport[ RP_SPACING ]   := 1
   aReport[ RP_BEJECT ]    := .T.
   aReport[ RP_AEJECT ]    := .F.
   aReport[ RP_PLAIN ]     := .F.
   aReport[ RP_SUMMARY ]   := .F.
   aReport[ RP_COLUMNS ]   := {}
   aReport[ RP_GROUPS ]    := {}
   aReport[ RP_HEADING ]   := ""

   // Open the report file
   nFrmHandle := FOPEN( cFrmFile )

   IF ( !EMPTY( nFileError := FERROR() ) ) .AND. !( "\" $ cFrmFile .OR. ":" $ cFrmFile )

      // Search through default path; attempt to open report file
      cDefPath := SET( _SET_DEFAULT ) + ";" + SET( _SET_PATH ) /// line 159
      cDefPath := STRTRAN( cDefPath, ",", ";" )
      aPaths := ListAsArray( cDefPath, ";" )

HTH

Best regards,

Frank

Op vrijdag 5 juni 2015 21:37:43 UTC+2 schreef Klas Engwall:
...[snip] 

Klas Engwall

unread,
Jun 6, 2015, 9:04:46 AM6/6/15
to harbou...@googlegroups.com
Hi Frank,

Good to have you back on board.

> Actually, the sources are included with both CA-Clipper 5.2(e) and 5.3(b)
>
> SOURCE/SYS/LBLBACK.PRG for LABEL FORM
> and SOURCE/SYS/FRMBACK.PRG for REPORT FORM

Hmm, since I had never used them I didn't think of checking if the
sources were included in Clipper.

> I confirm there's no SET( _SET_PATH ) in LBLBACK.PRG - while yes in
> FRMBACK.PRG

One could wonder why they made it like that.

Regards,
Klas

Heinz V Bergen

unread,
Jun 7, 2015, 11:56:38 PM6/7/15
to harbou...@googlegroups.com
NG Clipper 5.3e has this under the "Description" section:

For REPORT FORM:
     When invoked, REPORT FORM searches the current SET PATH drive and
     directory if the <xcReport> file is not found in the current directory
     and the path is not specified.

For LABEL FORM:
     When invoked, LABEL FORM searches the current SET PATH drive and
     directory, if the <xcLabel> file is not found in the current directory,
     and the path is not specified.

I would interpret that as:
  • When invoked, REPORT FORM searches the current SET PATH paths only if the <xcReport> file is not found in the current DEFAULT directory and the path is not specified.
I don't use LABEL FORM myself, but I think the intention was for both commands to search the SET DEFAULT directory and if not found searches the SET PATH paths.

Logically I believe the code in LBLBACK.PRG had mistakenly missed the _SET_PATH part.

This NG description section for SET PATH TO probably says it best:
Description

     SET PATH allows commands and functions that open database and associated
     files to find and open existing files in another drive and/or directory.
     It does this by specifying a path list to search if a referenced file
     cannot be found in the DEFAULT or specified directory.  Note that memo
     and low-level file functions respect neither the DEFAULT nor the PATH
     SETting.

     A path is a pointer to a directory.  It consists of an optional drive
     letter and colon, followed by a list of directories from the root to the
     desired directory separated by backslash (\) characters.  A path list is
     the sequence of paths to search, each separated by a comma or semicolon.

     When you attempt to access a file, CA-Clipper first searches the default
     drive and directory.  The default disk drive and directory are
     established by DOS when your CA-Clipper application is loaded, or,
     during execution, by SET DEFAULT.  If the file is not found, CA-Clipper
     then searches each path in the specified path list until the first
     occurrence of the file is found.

     To create new files in another drive or directory, use SET DEFAULT TO
     <xcPathspec> or explicitly declare the path when specifying a new
     filename.

     SET PATH TO with no argument releases the path list and CA-Clipper
     searches only the DEFAULT directory.

Regards,
Heinz



Przemyslaw Czerpak

unread,
Jun 8, 2015, 11:17:14 AM6/8/15
to harbou...@googlegroups.com
Hi All,

It would be nice if someone can convert this code to use
hb_vf*() functions (Harbour IO API).
hb_vfOpen() with FXO_DEFAULTS attributes enables respecting
_SET_DEFAULT and _SET_PATH.
Additionally after switching to hb_vf*() API it would be
possible to use different redirectors.
Recently Viktor updated his branch and switched to Harbour
IP API.
Maybe someone here can sync this modifications with Harbour
core repository?

best regards,
Przemek
> --
> You received this message because you are subscribed to the Google Groups "Harbour Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to harbour-deve...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages