AddressOf with Const String Arrays

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

AddressOf with Const String Arrays

Post by SHughes_Fusion » Wed Oct 15, 2014 3:20 pm

I've hit an odd problem. I've got a routine which writes a string to an LCD display. I've found that when using Consts if I pass by value it uses a lot of code space so I've written a routine which can accept a string byrefconst. This works fine with a plain Const, but if I define an array of const strings it seems the wrong reference gets passed.

Is there any way to do what I want? I'm guessing there is no easy way for Swordfish to give a const reference in to an array where the index is a variable?

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: AddressOf with Const String Arrays

Post by Jerry Messina » Wed Oct 15, 2014 5:22 pm

Arrays of const strings are just different.

Maybe somebody has a better suggestion, but for this type of thing I usually use something like:

Code: Select all

// error messages
// note: an array of const strings uses a fixed size for all strings
// so this array will take up N * length(longest string)
const pon_stat_msgs() as string =
(
    "pon",
    "software reset",
    "wdt from sleep",
    "mclr from sleep",
    "brownout reset",
    "wdt reset",
    "stack overflow",
    "stack underflow",
    "clock failure",
    "unknown event"
)

//
// given a msg index (0-9), return the rom address of the string
//
public function get_msg(ix as byte) as TABLEPTR
    dim wix as word

    if (ix > bound(pon_stat_msgs)) then
        ix = bound(pon_stat_msgs)
    endif

    // compute the address of the string (they're all the same length)
    wix = ix * sizeof(pon_stat_msgs(0))
    TABLEPTR = @pon_stat_msgs
    result = TABLEPTR + wix
end function
But you need a "print" method that will accept a word/dword address, and that gets messy with compound subs finding the correct match.

I just have a Print.Conststr() function, ie Print.Conststr(get_msg(1))

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: AddressOf with Const String Arrays

Post by SHughes_Fusion » Thu Oct 16, 2014 8:40 am

Thanks, Jerry, I did suspect this was just one of those things you can't do in Swordfish.

I do have a WriteCStr routine but this depends on being passed the address of the const string. I guess I can use that and an intermediate routine which calculates the offset in the array.

I've tried the following and it does save around 24 bytes per array and I have 24 arrays so that's going to make a modest code saving as well as reducing overhead.
[code] wix = locale * SizeOf(Str1Text(0))
result = WriteCStr(SmallFont,@Str1Text+wix,Str1X(Locale),Str1Y(Locale)) [/code]

This is all to do with localising my product. Each string contains the same text in all supported languages, Locale is the offset in to the array which specifies the current language. The Str1X and Str1Y arrays just specify where on the screen the text is printed. I don't really need Y at the moment but I might have to support Asian languages in the future so may need to move things around so thought it best to put it in there.

I was actually wondering how much code space I'd save by joining all my strings in to one large string and have a secondary array of offsets. As you note each entry in a string array is the size of the largest string. I've currently got 24 arrays to localise my product, and I have 8 languages programmed at the moment. I'd estimate this uses around 4.5k but hard to tell. I'd need two bytes for each offset so I'd need to save 384 bytes plus whatever code overhead there is before it becomes a benefit. Oh, and there would be the hassle of linking the strings and calculating the offsets.

Jerry Messina
Swordfish Developer
Posts: 1473
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: AddressOf with Const String Arrays

Post by Jerry Messina » Thu Oct 16, 2014 9:10 am

I do have a WriteCStr routine but this depends on being passed the address of the const string. I guess I can use that and an intermediate routine which calculates the offset in the array
That's what the function "get_msg()" does in my example. You pass it the index of the string you want and it returns the rom address of the string in the TABLEPTR register pair. Turning the address computation into a function might save you a bit more code, but only if you call WriteCStr multiple times for that same Str1Text array.
Oh, and there would be the hassle of linking the strings and calculating the offsets
Linking them together isn't too bad. For combining strings i just use the format

Code: Select all

const str_help2 =
(
    "setup cmds:" + #13 + #10 +
    "  SET" + #13 + #10 +
    "    IPADDR [n.n.n.n|DHCP|AUTOIP]" + #13 + #10 +
    "    NETMASK n.n.n.n" + #13 + #10 +
    "    DHCP onoff" + #13 + #10 +
    "    AUTOIP onoff" + #13 + #10
)
which puts them all together into one large const string. If you have a large number of strings that can save a bunch of space.

As you say, the trick is finding the offsets at compile time to be able to create an array of them. If you had enough ram I'd say maybe you could do that at runtime startup, but ram's usually a precious commodity.

I'm not sure if there's an easy way of declaring the strings individually and then combining them into one large array. Let us know if you find one.

Post Reply