Re: A89: Re: A Address book With Some Real Problems


[Prev][Next][Index][Thread]

Re: A89: Re: A Address book With Some Real Problems




Hi!

> About globals:
> 
> There are definitely uses for them, but they are also easy
> to overuse. Recently I wrote a program that needed an error
> log to be printed to the screen. Since there were several
> functions that could generate an error and no way to predict
> when an error might occur, I made the error log string global.

Something about globals which is related particularly to TI:

AVOID EXTENSIVE USAGE OF GLOBALS AS MUCH AS POSSIBLE!!!

Reason 1:
---------

Every global variable is translated to absolute addressing mode.
As this mode is non-relocatable, the compiler adds a 4-byte long
entry into the relocation table for each apperance of the global
variable. If global variable "a" is mentioned say 100 times in
the program, this is extra 400 bytes. When I ported some programs
from PC to TI, I suceeded to reduce program space from 20K to 16K
just by eliminating globals. And 4K of space is worth...

Reason 2:
---------

Globals are kept in the .89z file itself. Sometimes it is good
(to keep permanent data which will survive after the program
exits etc.), but very often it is a wasting of file space (as
the file length is limited). In Rob's program, globals arrays 
are necessary, but I prefer dynamic allocation for them, to 
make the length of the program smaller. There is some problems
with dynamic allocation of two-dimensional arrays. Usual method
for creating two-dimensional dynamic arrays given in C books
(by using an array of pointers, or by using a double-pointer)
may be to inefficient on TI due to usage of too many handles
(their number is limited). Fortunately, I know a very efficient
method for creating dynamic 2-dimensional arrays by using a
very ugly typecasting macros (I like to play with ugly casts,
this is what makes C wonderful). In fact, I cast ordinary 
pointers to pointers to arrays, which may be dereferenced as
two-dimensional arrays. This technique may be worth to look,
especially for good C coders. See the program given at the
end of this mail...

> Any idea what it's doing? Poor variable naming is part of 
> the problem, but those ugly constants aren't helping. What
> if it were this instead:
> 
> const int T_PER_SEC = 10;
> const int T_PER_MIN = T_PER_SEC * 60;
> const int T_PER_HOUR = T_PER_MIN * 60;
> const int T_PER_DAY = T_PER_HOUR * 24;

Just for TIGCC: it generate more efficient code when using
#define instead:

#define T_PER_SEC 10
#define T_PER_MIN T_PER_SEC * 60

etc.

Now, the version of Rob's program with dynamic memory
allocation, using tricks for creating 2D dynamic arrays
(look carefully at #define's). Yes, this program will not
keep entries after exiting from the program: they must
be saved in an external file, but this is not the today
topic... 

#define SAVE_SCREEN

#include <nostub.h>
#include <all.h>

int _ti89,_ti92plus;

static char *FName_Ptr=NULL;
static char *LName_Ptr=NULL;
static char *Phone_Ptr=NULL;
static char *Fax_Ptr=NULL;
static char *Email_Ptr=NULL;
static char *Address_Ptr=NULL;
static char *CSZ_Ptr=NULL;

#define FName ((char(*)[15])FName_Ptr)
#define LName ((char(*)[15])LName_Ptr)
#define Phone ((char(*)[10])Phone_Ptr)
#define Fax ((char(*)[10])Fax_Ptr)
#define Email ((char(*)[10])Email_Ptr)
#define Address ((char(*)[30])Address_Ptr)
#define CSZ ((char(*)[30])CSZ_Ptr)

// Now, you can use FName, LName etc. like as they are
// ordinary two-dimensional arrays :-)

int CallBack(int a,long b)
{
  ST_helpMsg("Whatever you want...");
}

int editen(int en)
{
  char buffer[140];
  HANDLE handle;
  int dummy;
  en--;
  memcpy(buffer,FName[en],15);
  memcpy(buffer+15,LName[en],15);
  memcpy(buffer+30,Phone[en],10);
  memcpy(buffer+40,Fax[en],10);
  memcpy(buffer+50,Email[en],30);
  memcpy(buffer+80,Address[en],30);
  memcpy(buffer+110,CSZ[en],30);
  handle=DialogNew(140,93,CallBack);
  DialogAddTitle(handle,"Add/Edit Entry",BT_OK,BT_CANCEL);
  DialogAddRequest(handle,3,13,"First Name:",0,15,10);
  DialogAddRequest(handle,3,23,"Last Name:",15,15,10);
  DialogAddRequest(handle,3,33,"Phone Number:",30,10,10);
  DialogAddRequest(handle,3,43,"Fax Number:",40,10,10);
  DialogAddRequest(handle,3,53,"Email Address:",50,30,10);
  DialogAddRequest(handle,3,63,"Address:",80,30,10);
  DialogAddRequest(handle,3,73,"City State Zip:",110,30,10);
  dummy=DialogDo(handle,CENTER,CENTER,buffer,NULL);
  if(dummy==13)
    {
      memcpy(FName[en],buffer,15);
      memcpy(LName[en],buffer+15,15);
      memcpy(Phone[en],buffer+30,10);
      memcpy(Fax[en],buffer+40,10);
      memcpy(Email[en],buffer+50,30);
      memcpy(Address[en],buffer+80,30);
      memcpy(CSZ[en],buffer+110,30);
      ST_helpMsg("Changes Saved");
      ngetchx();
    }
  else
    {
      ST_helpMsg("Changes Not Saved");
      ngetchx();
    }
}

void ab()
{
  editen(1);
}

void cal()
{
}

int _main()
{
  int result=1;
  HANDLE handle;
  FName_Ptr=calloc(100,sizeof(*FName));  // Allocation...
  LName_Ptr=calloc(100,sizeof(*LName));
  Phone_Ptr=calloc(100,sizeof(*LName));
  Fax_Ptr=calloc(100,sizeof(*Fax));
  Email_Ptr=calloc(100,sizeof(*Email));
  Address_Ptr=calloc(100,sizeof(*Address));
  CSZ_Ptr=calloc(100,sizeof(*CSZ));
  if(!FName_Ptr||!LName_Ptr||!Phone_Ptr||!Fax_Ptr||
    !Email_Ptr||!Address_Ptr||!CSZ_Ptr)
      ST_helpMsg("Not enough memory!");
  else
    {
      ST_helpMsg("Welcome to Address book 2K Plus");  
      while(result!=0&&result!=9)
        {
          handle=PopupNew("Address book 2K PLUS",0);
          PopupAddText(handle,-1,"Calender",1);
          PopupAddText(handle,-1,"Address Book",2);
          PopupAddText(handle,-1,"Quit",9);
          result=PopupDo(handle,CENTER,CENTER,0);
          if(result==2)
            ab();
          if(result==1)
            cal();
        }
    }
  if(FName_Ptr) free(FName_Ptr);       // Freeing...
  if(LName_Ptr) free(LName_Ptr);
  if(Phone_Ptr) free(Phone_Ptr);
  if(Fax_Ptr) free(Fax_Ptr);
  if(Email_Ptr) free(Email_Ptr);
  if(Address_Ptr) free(Address_Ptr);
  if(CSZ_Ptr) free(CSZ_Ptr);
  return 0;
}

Cheers,

Zeljko