Macros

General FreeBASIC programming questions.
Post Reply
St_W
Posts: 1618
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Macros

Post by St_W »

I'm trying to write a macro that implements a very simple linked list.
Here is my attempt:

Code: Select all

#macro LL_Add(DataType, BasicType, Parameters)
	dim Cnt as Integer
	dim q as integer
	dim ElemA as DataType ptr
	dim ElemB as DataType ptr
	dim tmpIndex as Integer
	Cnt = this.##BasicType##Count()
	ElemA = new DataType(Parameters)
	if Cnt = 0 then
		this._##BasicType = ElemA
		ElemA->_next = 0
		return 0
	else
		if index < 0 or index > Cnt then tmpIndex = Cnt else tmpIndex = index
		ElemB = this._##BasicType
		for q = 1 to tmpIndex-1
			ElemB = ElemB->_next
		next
		if tmpIndex = 0 then
			ElemA->_next = this._##BasicType
			this._##BasicType = ElemA
		else
			ElemA->_next = ElemB->_next
			ElemB->_next = ElemA
		EndIf
	EndIf
	return 0
#endmacro
But it doesn't work at all. I don't know how to pass Strings without quotes but with commas.

There is some code that may help understanding what I want to do:

Code: Select all

type myImage
	
	ImageFile as String
	Description as String
	Timestamp as String
	
	_next as myImage ptr
	
	declare constructor(ImageFile_ as String, Description_ as String, Timestamp_ as String)
	
End Type


type myImgClass
	
	private:
	
	_Image as myImage ptr
	
	public:
	
	
	declare property Image(index as Integer) as myImage ptr
	declare function ImageAdd(ImageFile as String, Description as String, Timestamp as String, index as Integer = -1) as Integer
	declare function ImageRemove(index as Integer = -1) as Integer
	declare function ImageCount() as Integer
	declare function ImageClear() as Integer
	
	
End Type

constructor myImage(ImageFile_ as String, Description_ as String, Timestamp_ as String)
	this.ImageFile = ImageFile_
	this.Description = Description_
	this.Timestamp = Timestamp_

End Constructor

property myImgClass.Image(index as Integer) as myImage ptr
	dim Cnt as Integer
	dim ElemA as myImage ptr
	dim q as Integer
	Cnt = this.ImageCount()
	if index < 0 or index >= Cnt then return 0
	ElemA = this._Image
	for q = 1 to index
		ElemA = ElemA->_next
	Next
	return ElemA
End Property

function myImgClass.ImageCount() as Integer
	dim Zaehler as Integer = 0
	dim ElemA as myImage ptr
	if this._Image = 0 then return Zaehler
	ElemA = this._Image
	do
		Zaehler += 1
		if ElemA->_next=0 then return Zaehler
		ElemA = ElemA->_next
	Loop
End Function

function myImgClass.ImageAdd(ImageFile as String, Description as String, Timestamp as String, index as Integer = -1) as Integer
	'===========================================
	'Macro should look like this when expanded:
	'===========================================
	'dim Cnt as Integer
	'dim ElemA as myImage ptr
	'dim ElemB as myImage ptr
	'dim q as integer
	'dim tmpIndex as Integer
	'Cnt = this.ImageCount()
	'ElemA = new myImage(ImageFile, Description, Timestamp)
	'if Cnt = 0 then
	'	this._Image = ElemA
	'	ElemA->_next = 0
	'	return 0
	'else
	'	if index < 0 or index > Cnt then tmpIndex = Cnt else tmpIndex = index
	'	ElemB = this._Image
	'	for q = 1 to tmpIndex-1
	'		ElemB = ElemB->_next
	'	next
	'	if tmpIndex = 0 then
	'		ElemA->_next = this._Image
	'		this._Image = ElemA
	'	else
	'		ElemA->_next = ElemB->_next
	'		ElemB->_next = ElemA
	'	EndIf
	'EndIf
	'return 0
	LL_Add(myImage,Image,"ImageFile, Description, Timestamp")
End Function

function myImgClass.ImageRemove(index as integer = -1) as integer
	dim Cnt as Integer
	dim ElemA as myImage ptr
	dim ElemB as myImage ptr
	dim tmpIndex as Integer
	dim q as Integer
	Cnt = this.ImageCount()
	if Cnt = 0 then return 0
	if index = 0 then
		ElemA = this._Image
		this._Image = ElemA->_next
		Delete(ElemA)
		return 0
	EndIf
	if index < 0 or index >= Cnt then tmpIndex = Cnt-1 else tmpIndex = index
	ElemA = this._Image
	for q = 1 to tmpIndex
		ElemB = ElemA
		ElemA = ElemA->_next
	Next
	ElemB->_next = ElemA->_next
	Delete(ElemA)
	return 0
End Function

function myImgClass.ImageClear() as Integer
	dim ElemA as myImage ptr
	dim ElemB as myImage ptr
	if this._Image = 0 then return 0
	ElemA = this._Image
	this._Image = 0
	do
		ElemB = ElemA->_next
		Delete(ElemA)
		if ElemB = 0 then exit do
		ElemA = ElemB
	Loop
	return 0
End Function
Please help!
(Is there a simplier solution than macros?)

Thanks for your answers in advance!
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Post by MichaelW »

If the macro will be expanded only once in your source, why not just place the macro code inline and avoid the unnecessary complexity of the macro? If the macro were expanded more than once, the internal DIMs would cause problems with duplicated definitions.
St_W
Posts: 1618
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Post by St_W »

The macro will be expanded in various functions. So the DIMs wouldn't cause problems.

I've detected a strange behaviour of the compiler:

Code: Select all

dim _test as String = "Hello"

'#define r(_variable_)   _##_variable_
#define s(_variable_)   _t##_variable_

'print r(test)
print s(est)

sleep
I think fbc is buggy because strange errors occur when you remove the comment before the first line. It looks like it can't handle underscores at the end before ## (maybe it thinks it's a line-break?!).
stylin
Posts: 1253
Joined: Nov 06, 2005 5:19

Post by stylin »

St_W, yeah, the preprocessor doesn't like to concatenate single underscores; try using double underscores. Also, you can pass parameters as a parenthesized list, like,

LL_Add( DT, BT, ( a, b, c ) )

Hope this helps.
St_W
Posts: 1618
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Post by St_W »

Thank you very much stylin!

I'll use double underscores because FBedit doesn't like single ones too.
//edit: FBedit also doesn't like double underscores.
Passing the parameters in brackets works fine!
Post Reply