Passing command line arguments to FB programs

General discussion for topics related to the FreeBASIC project or its community.
ganache
Posts: 47
Joined: Aug 04, 2016 9:25

Passing command line arguments to FB programs

Post by ganache »

Command line arguments are used in many, if not most programming languages.
Examples: Basic, C/C++, Java, DOS batch file, Python etc.
argc and argv refer to arguments in C.
Basically argc refers to the count, i.e the no. of arguments being passed
argv is a pointer to an array of strings containing the arguments
In FB you use command(i) to refer to arguments.
A few examples to clarify things will follow.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Passing command line arguments to FB programs

Post by D.J.Peters »

argc and argv are macros in FreeBASIC

Joshy

Code: Select all

for i as integer = 0 to __FB_ARGC__-1
  print *__FB_ARGV__[i]
next
sleep
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Passing command line arguments to FB programs

Post by Munair »

When using GTK, one often sees this initialization:

Code: Select all

gtk_init(@__FB_ARGC__, @__FB_ARGV__)
ganache
Posts: 47
Joined: Aug 04, 2016 9:25

Re: Passing command line arguments to FB programs

Post by ganache »

argc and argv are macros in FreeBASIC

Joshy
Yes, those are macros. But I am talking of non-macro usage perhaps.

An example:

Code: Select all

Dim As Integer i = 0
Dim As String arg = command(1)
print "Hello ";command(1); " how are you?"
Sleep
Run like this: if program name is helloarg.exe then type at FB prompt:
helloarg.exe Jenny (A space is expected between program name and every argument being passed)
Output: "Hello Jenny how do you do?"
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Passing command line arguments to FB programs

Post by MrSwiss »

Have a look at: this tread, in General section.
ganache
Posts: 47
Joined: Aug 04, 2016 9:25

Re: Passing command line arguments to FB programs

Post by ganache »

Add arguments together as numbers(integers)...

Code: Select all

  Dim As Integer i=0, sum=0  
  Do
  Dim As String arg = Command(i)
  If Len(arg) = 0 Then Exit Do
  print "command line argument " & i & " = """ & arg & """"
  i += 1
  sum+=  val(Command(i))   ' val is used to get the numeric value 
  Loop
  print "Sum of numbers=";sum
  If i = 0 Then Print "no command line arguments"
  Sleep
  End


Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Passing command line arguments to FB programs

Post by Munair »

ganache wrote:Add arguments together as numbers(integers)...

Code: Select all

  Dim As Integer i=0, sum=0  
  Do
  Dim As String arg = Command(i)
  If Len(arg) = 0 Then Exit Do
  print "command line argument " & i & " = """ & arg & """"
  i += 1
  sum+=  val(Command(i))   ' val is used to get the numeric value 
  Loop
  print "Sum of numbers=";sum
  If i = 0 Then Print "no command line arguments"
  Sleep
  End


Why would you place a DIM inside the loop?

Code: Select all

dim i as integer = 0
dim sum as integer = 0
dim arg as string

Do
	arg = Command(i)
	if len(arg) = 0 then
		exit do
	end if
	print "command line argument " & i & " = """ & arg & """"
	i += 1
	sum += val(arg)   ' val is used to get the numeric value
Loop

print "Sum of numbers="; sum

if i = 0 then
	print "no command line arguments"
end if

sleep
end
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passing command line arguments to FB programs

Post by fxm »

In -lang fb, the [Do...Loop] block has a scope structure, so it is a good habit (as has ganache) to define its local variables inside the block itself (and at least before its first use).
The definition of such variables will only be maintained until the end of the block scope.
Therefore same variable names can be used outside the block scope without risk of mixing with the local variables.

Extract of manual:
DIM page wrote:In the -lang fb and -lang deprecated dialects, variables defined inside compound block statements (For..Next, While..Wend, Do..Loop, If..Then, Select..End Select, With..End With, Scope..End Scope) have local working scopes, and are visible only within these blocks.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Passing command line arguments to FB programs

Post by Munair »

fxm wrote:In -lang fb, the [Do...Loop] block has a scope structure, so it is a good habit (as has ganache) to define its local variables inside the block itself (and at least before its first use).
The definition of such variables will only be maintained until the end of the block scope.
Therefore same variable names can be used outside the block scope without risk of mixing with the local variables.

Extract of manual:
DIM page wrote:In the -lang fb and -lang deprecated dialects, variables defined inside compound block statements (For..Next, While..Wend, Do..Loop, If..Then, Select..End Select, With..End With, Scope..End Scope) have local working scopes, and are visible only within these blocks.
Hmm, it may be a logical feature, but I'm not sure I can appreciate it.
Last edited by Munair on Dec 02, 2017 18:00, edited 1 time in total.
Munair
Posts: 1286
Joined: Oct 19, 2017 15:00
Location: Netherlands
Contact:

Re: Passing command line arguments to FB programs

Post by Munair »

The problem I have with this kind of language structure is that it is an implicit scope and it looks a bit messy. In contrast, a SCOPE .. END SCOPE block is explicit and clear. Just my humble opinion.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passing command line arguments to FB programs

Post by fxm »

Local variables and memory allocation

At the contrary of defining local variables inside procedures, by defining local variables inside compound block statements in -lang fb (For..Next, While..Wend, Do..Loop, If..Then, Select..End Select, With..End With, Scope..End Scope) does not allow to recover memory when program runs outside the compound block statements:
- For a variable defined inside a procedure body, memory is allocated (on the stack) only during each procedure execution (from begin up to end of procedure, whatever the position of the definition in the procedure body).
- For a variable defined inside a compound block statement, a memory zone allocated (on the stack) during all execution of program (from begin up to end of program) is used, although the variable is not accessed from outside the compound block.

But this << implementation detail >> is not so simple for a number of people (because there is often confusion between object destruction and full memory release).
If a such variable is an object (string, dynamic array, instance of UDT):
- When exiting its scope block, a local object is destructed (all dynamic allocated memory is freed), but the static allocated memory on stack (for descriptors, data fields of UDT) is not freed.
- When exiting its scope procedure, a local object is destructed and all memory (both dynamic and on stack) is freed.

For a variable defined (with "Dim ...") inside a compound block statement in -lang fb (For..Next, While..Wend, Do..Loop, If..Then, Select..End Select, With..End With, Scope..End Scope), a memory zone allocated (on the stack) during all execution of program (from begin up to end of program) is used, although the variable is not accessed from outside the compound block.

When there are several scope blocks (compound block statements excluding procedures), a dedicated memory is not allocated for each variable defined (with "Dim ...") in each scope block:
- A memory zone is allocated on the stack with a size corresponding to the scope block which request the more of memory for its own local variables.
- So, a same data address in stack memory can be used for different local variables belonging to different scope blocks.

- When using "Static ..." in a scope block, the allocated memory is not on the stack and each static variable has its own memory allocation.
- When using "Dim ..." (without "= Any") in a loop, the variable is initialized at each iteration (an alternative could be to use "= Any", or otherwise "Static ...").

So, use several scope blocks can also save memory on the stack compared to all variables defined in the global scope.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Passing command line arguments to FB programs

Post by jj2007 »

fxm wrote:the static allocated memory on stack (for descriptors, data fields of UDT) is not freed
In the moment when you return from a procedure, or exit a block, normally your stack pointer is restored from ebp. Whatever was on the stack at that point gets "freed" in the sense that it remains in low memory but the stack pointer moves higher up.

Correct me if I am wrong - FB might handle that differently from other languages; a small testbed would be helpful.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passing command line arguments to FB programs

Post by fxm »

fxm wrote: When there are several scope blocks (compound block statements excluding procedures), a dedicated memory is not allocated for each variable defined (with "Dim ...") in each scope block:
- A memory zone is allocated on the stack with a size corresponding to the scope block which request the more of memory for its own local variables.
I think that when entering and exiting a compound block (excluding any procedure), the stack pointer is not modified because it has been set at the beginning of program in order to allocate a memory zone (corresponding to the scope block which request the more of memory for its own local variables) which is maintained during all execution of program.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passing command line arguments to FB programs

Post by fxm »

jj2007 wrote:In the moment when you return from a procedure, or exit a block, normally your stack pointer is restored.....a small testbed would be helpful.
fxm wrote:I think that when entering and exiting a compound block (excluding any procedure), the stack pointer is not modified because it has been set at the beginning of program in order to allocate a memory zone (corresponding to the scope block which request the more of memory for its own local variables) which is maintained during all execution of program.
Example of a variable defined inside a procedure body (Sub..End Sub):
(working for 32-bit only)

Code: Select all

Function freeStack Naked() As Integer
  Asm
    mov edx, fs:[8]
    mov eax, esp
    add eax, 4
    sub eax, edx
    ret
  End Asm
end function

Sub start () Constructor
  Print "Free stack at module constructor level: " & freeStack()
End Sub

Sub s ()
  Print "  Sub"
  Print "    free stack at procedure level before variable definition: " & freeStack()
  Dim As Byte b(500000-1)
  Print "    Dim As Byte b(500000-1)"
  Print "    free stack at procedure level after variable definition: " & freeStack()
  Print "  End Sub"
End Sub


Print "Program start"
Print "  free stack at user program beginning: " & freeStack()
s()
Print "  free stack at user program ending: " & freeStack()
Print "Program end"

Sleep

Code: Select all

Free stack at module constructor level: 1048204
Program start
  free stack at user program beginning: 1048204
  Sub
    free stack at procedure level before variable definition: 548132
    Dim As Byte b(500000-1)
    free stack at procedure level after variable definition: 548132
  End Sub
  free stack at user program ending: 1048204
Program end
Example of a variable defined inside a compound block statement (Scope..End Scope):
(working for 32-bit only)

Code: Select all

Function freeStack Naked() As Integer
  Asm
    mov edx, fs:[8]
    mov eax, esp
    add eax, 4
    sub eax, edx
    ret
  End Asm
end function

Sub start () Constructor
  Print "Free stack at module constructor level: " & freeStack()
End Sub


Print "Program start"
Print "  Free stack at user program beginning: " & freeStack()
Scope
  Print "  Scope"
  Print "    Free stack at scope level before variable definition: " & freeStack()
  Dim As Byte b(500000-1)
  Print "    Dim As Byte b(500000-1)"
  Print "    Free stack at scope level after variable definition: " & freeStack()
  Print "  End Scope"
End Scope
Print "  Free stack at user program ending: " & freeStack()
Print "Program end"

Sleep

Code: Select all

Free stack at module constructor level: 1048204
Program start
  Free stack at user program beginning: 548148
  Scope
    Free stack at scope level before variable definition: 548148
    Dim As Byte b(500000-1)
    Free stack at scope level after variable definition: 548148
  End Scope
  Free stack at user program ending: 548148
Program end
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Passing command line arguments to FB programs

Post by fxm »

In conclusion, all this can be summed up in a simple but high-level sentence:
The local variables are reserved on stack at procedure granularity only (including main part of program corresponding to main procedure), but not at individual scope blocks.
Post Reply