Passing command line arguments to FB programs
Passing command line arguments to FB programs
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.
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.
-
- Posts: 8586
- Joined: May 28, 2005 3:28
- Contact:
Re: Passing command line arguments to FB programs
argc and argv are macros in FreeBASIC
Joshy
Joshy
Code: Select all
for i as integer = 0 to __FB_ARGC__-1
print *__FB_ARGV__[i]
next
sleep
Re: Passing command line arguments to FB programs
When using GTK, one often sees this initialization:
Code: Select all
gtk_init(@__FB_ARGC__, @__FB_ARGV__)
Re: Passing command line arguments to FB programs
Yes, those are macros. But I am talking of non-macro usage perhaps.argc and argv are macros in FreeBASIC
Joshy
An example:
Code: Select all
Dim As Integer i = 0
Dim As String arg = command(1)
print "Hello ";command(1); " how are you?"
Sleep
helloarg.exe Jenny (A space is expected between program name and every argument being passed)
Output: "Hello Jenny how do you do?"
Re: Passing command line arguments to FB programs
Have a look at: this tread, in General section.
Re: Passing command line arguments to FB programs
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
Re: Passing command line arguments to FB programs
Why would you place a DIM inside the loop?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
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
Re: Passing command line arguments to FB programs
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:
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.
Re: Passing command line arguments to FB programs
Hmm, it may be a logical feature, but I'm not sure I can appreciate it.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.
Last edited by Munair on Dec 02, 2017 18:00, edited 1 time in total.
Re: Passing command line arguments to FB programs
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.
Re: Passing command line arguments to FB programs
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.
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.
Re: Passing command line arguments to FB programs
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.fxm wrote:the static allocated memory on stack (for descriptors, data fields of UDT) is not freed
Correct me if I am wrong - FB might handle that differently from other languages; a small testbed would be helpful.
Re: Passing command line arguments to FB programs
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 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.
Re: Passing command line arguments to FB programs
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.
Example of a variable defined inside a procedure body (Sub..End Sub):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.
(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
(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
Re: Passing command line arguments to FB programs
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.
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.