Omnimaga

Calculator Community => TI Calculators => Calculator C => Topic started by: blue_bear_94 on June 03, 2012, 03:20:13 pm

Title: [68k] Storing a value into n?
Post by: blue_bear_94 on June 03, 2012, 03:20:13 pm
I have trouble with a library in the works. The code I am using is below:
Code: [Select]
// C Source File
// Created 6/3/2012; 2:16:41 PM
// Decthyth General 68k Libraries
#include <tigcclib.h>
#define RETURN_VALUE n
void DlgError(const char* msg)
{
DlgMessage("Error",msg,BT_CANCEL,BT_NONE);
}
void WriteToNInt(long n)
{
push_longint(n);
}
void WriteToNFloat(float n)
{
push_Float(n);
}
// Main Function
/*
NOTE: When I say that a function returns a value,
I mean that the value is stored to n.
*/
void _main(void)
{
int mode;
unsigned char a;
ESI argptr=top_estack;
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("First arg must be + int");
return;
}
mode=GetIntArg(argptr);
switch (mode)
{
case 0:
WriteToNFloat(0.1);
}
}
When I compile this example and put in dcth(0):n, it just returns n (no value stored). Do you know what's wrong? Thanks in advance!
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 03, 2012, 03:29:12 pm
Code: [Select]
#define RETURN_VALUE nOh, it's not that simple: RETURN_VALUE is an argument-less macro :)

If you want to store data to a variable, you need to either use a high-level function such as VarStore, or do it the hard way, by building the variable yourself: HeapAlloc + SymAdd + etc. (lots of error checking), write the two size bytes, write the variable's contents (here, nine out of ten bytes from the float) and end tag (0x23 FLOAT_TAG).
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 03, 2012, 03:34:34 pm
Fixed. I edited the code to
Code: [Select]
// C Source File
// Created 6/3/2012; 2:16:41 PM
// Decthyth General 68k Libraries
#include <tigcclib.h>
//#define RETURN_VALUE n
void DlgError(const char* msg)
{
DlgMessage("Error",msg,BT_CANCEL,BT_NONE);
}
void WriteToNInt(long n)
{
push_longint(n);
VarStore(SYMSTR("n"),STOF_ESI,0,top_estack);
}
void WriteToNFloat(float n)
{
push_Float(n);
VarStore(SYMSTR("n"),STOF_ESI,0,top_estack);
}
// Main Function
/*
NOTE: When I say that a function returns a value,
I mean that the value is stored to n.
*/
void _main(void)
{
int mode;
unsigned char a;
ESI argptr=top_estack;
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("First arg must be + int");
return;
}
mode=GetIntArg(argptr);
switch (mode)
{
case 0:
WriteToNFloat(0.1);
break;
}
}
(again, thanks!)
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 03, 2012, 03:36:40 pm
That's the correct way to use VarStore, indeed :)
Title: Re: [68k] Storing a value into n?
Post by: TravisE on June 03, 2012, 03:37:24 pm
Code: [Select]
#define RETURN_VALUE nOh, it's not that simple: RETURN_VALUE is an argument-less macro :)

If you want to store data to a variable, you need to either use a high-level function such as VarStore, or do it the hard way, by building the variable yourself: HeapAlloc + SymAdd + etc. (lots of error checking), write the two size bytes, write the variable's contents (here, nine out of ten bytes from the float) and end tag (0x23 FLOAT_TAG).

The docs refer to using a variable name as an argument to RETURN_VALUE to automatically store the last value pushed to the expression stack to the variable, and I even seem to remember using this myself once. Has this changed?
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 03, 2012, 03:44:42 pm
Indeed, you're right, http://debrouxl.github.com/gcc4ti/htretval.html indicates that RETURN_VALUE can take an argument :)
I didn't remember about that capability, or even using it, but since I once compiled and ran all GCC4TI examples (finding and fixing several bugs inherited from TIGCC in the process), I did use it...

So I'm not sure at all why blue_bear_94's original code doesn't work...
Title: Re: [68k] Storing a value into n?
Post by: TravisE on June 03, 2012, 04:02:45 pm
Maybe you either need to push END_TAG before pushing your arguments or delete everything up to the END_TAG, or something like that. For instance, I had a very small program that returns the value of FiftyMsecTick (which I used for more precise timing in TI-BASIC programs) that looked like this:

Code: [Select]
/* Program creation date:  2007/04/23
   Compilation command used:  tigcc -O3 -Wall tick.c
*/

#define MIN_AMS 200
#define RETURN_VALUE tmrval

#include <args.h>
#include <estack.h>
#include <system.h>

void _main(void) {   
    // Return result:
    while (GetArgType (top_estack) != END_TAG)  // Clean up arguments
        top_estack = next_expression_index (top_estack);
    top_estack--;
    push_longint(FiftyMsecTick);
}

I don't remember where I got the “clean up arguments” code, but I'm sure I pasted it from somewhere rather than figure out how to write it myself. :)

My other (very small test program) I could find like this added its own END_TAG, like this:

Code: [Select]
// Test routine--returns the string "Hello, world!"

#define RETURN_VALUE ret

#define USE_TI89

#include <args.h>
#include <estack.h>
#include <vat.h>

void _main(void)
{
  ESI argptr = top_estack;
  push_END_TAG ();
  push_zstr("Hello, world!");
}

A quick test in TIEmu seemed to show that this program works.
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 03, 2012, 04:07:24 pm
Indeed, you're right, http://debrouxl.github.com/gcc4ti/htretval.html indicates that RETURN_VALUE can take an argument :)
I didn't remember about that capability, or even using it, but since I once compiled and ran all GCC4TI examples (finding and fixing several bugs inherited from TIGCC in the process), I did use it...

So I'm not sure at all why blue_bear_94's original code doesn't work...
Well, since the modified code works, I'm going to use it. But I have another problem.
Code: [Select]
// C Source File
// Created 6/3/2012; 2:16:41 PM
// Decthyth General 68k Libraries
#include <tigcclib.h>
//#define RETURN_VALUE n
void DlgError(const char* msg)
{
DlgMessage("Error",msg,BT_CANCEL,BT_NONE);
}
void WriteToNInt(long n)
{
push_longint(n);
VarStore(SYMSTR("n"),STOF_ESI,0,top_estack);
}
void WriteToNFloat(float n)
{
push_Float(n);
VarStore(SYMSTR("n"),STOF_ESI,0,top_estack);
}
short show_picvar (SYM_STR SymName, short x, short y, short Attr)
{
  SYM_ENTRY *sym_entry = SymFindPtr (SymName, 0);
  if (!sym_entry) return FALSE;
  if (peek (HToESI (sym_entry->handle)) != PIC_TAG) return FALSE;
  BitmapPut (x, y, HeapDeref (sym_entry->handle) + 2, ScrRect, Attr);
  return TRUE;
}
// Main Function
/*
NOTE: When I say that a function returns a value,
I mean that the value is stored to n.
*/
void _main(void)
{
int mode;
unsigned char a;
ESI argptr=top_estack;
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("First arg must be + int");
return;
}
mode=GetIntArg(argptr);
switch (mode)
{
case 0:
WriteToNFloat(0.11);
break;
case 1:
SYM_STR name;
int x,y,attr;
a=GetArgType(argptr);
if (a!=STR_TAG)
{
DlgError("Arg 2 must be string");
return;
}
name=GetSymstrArg(argptr);
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("Arg 3 must be + int");
return;
}
x=GetIntArg(argptr);
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("Arg 4 must be + int");
return;
}
y=GetIntArg(argptr);
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("Arg 5 must be + int");
return;
}
attr=GetIntArg(argptr);
//*A_REVERSE, *A_NORMAL, *A_XOR, *A_SHADED, *A_REPLACE, *A_OR, *A_AND, A_THICK1, A_SHADE_V, A_SHADE_H, A_SHADE_NS, A_SHADE_PS
if (attr>=7)
{
DlgError("Wrong attribute");
return;
}
if (!show_picvar(name,x,y,attr))
{
DlgError("Pic does not exist");
}

}
}
produces an error "Expected expression before SYM_STR".
Edit: Fixed. However, I am trying to see if a list has any true entries; here is my code. What do you suggest?
Code: [Select]
case 19:
a=GetArgType(argptr);
if (a!=LIST_TAG)
{
DlgError("Arg 2 must be list");
return;
}
temp3=argptr;
do
{
temp3=next_expression_index(temp3);
} while (!(*temp3==TRUE_TAG||*temp3==LIST_END_TAG||*temp3==END_TAG));
WriteToNBool(*temp3==TRUE_TAG);
WriteToNBool is a function to write a Boolean value to n:
Code: [Select]
void WriteToNBool(int n)
{
push_quantum(0x2B+!!n);
VarStore(SYMSTR("n"),STOF_ESI,0,top_estack);
}
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 04, 2012, 01:28:10 am
Quote
I don't remember where I got the “clean up arguments” code, but I'm sure I pasted it from somewhere rather than figure out how to write it myself. :)
Yup, for instance from one of the examples on the htretval.html page I linked above :)
I saw the snippet yesterday evening, but at the time, I didn't remember that GetIntArg and friends do not modify top_estack... So yeah, at a minimum, the code snippet from the first post needs to clean up the arguments, before pushing the result.

Code: [Select]
while (!(*temp3==TRUE_TAG||*temp3==LIST_END_TAG||*temp3==END_TAG));||*temp3==LIST_END_TAG is wrong for two reasons:
* programs are not supposed to see that internal tag from ExtTags when dealing with expressions - if they do, chances are that the calculator is in an unstable state;
* LIST_END_TAG has the same value as NEGINT_TAG (from Tags), so your code will spuriously store "true" to n if the list contains any negative integer.
=> retry without the middle comparison against LIST_END_TAG :)
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 04, 2012, 09:40:54 am
The problem is that false is always stored, even when there is a true entry in the argument list. Also this is supposed to be used with a Boolean list.
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 04, 2012, 01:04:10 pm
Let's look at the code more thoroughly...

Oh, yeah, you're not entering the list at all, because you call next_expression_index on temp3 = argptr when argptr points to the LIST_TAG.
What about
Code: [Select]
case 19:
a=GetArgType(argptr);
if (a!=LIST_TAG)
{
DlgError("Arg 2 must be list");
return;
}
temp3=argptr - 1; // Skip the LIST_TAG
do
{
temp3=next_expression_index(temp3);
} while (!(*temp3==TRUE_TAG||*temp3==END_TAG));
WriteToNBool(*temp3==TRUE_TAG);
?
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 05, 2012, 11:23:59 am
Do I need to use a while or do-while loop in this example?
Code: [Select]
case 19:
a=GetArgType(argptr);
if (a!=LIST_TAG)
{
DlgError("Arg 2 must be list");
return;
}
temp3=argptr-1;
while (!(*temp3==TRUE_TAG||*temp3==END_TAG||*temp3==LIST_START_TAG));
{
temp3=next_expression_index(temp3);
}
WriteToNBool(*temp3==TRUE_TAG);
break;
case 20:
a=GetArgType(argptr);
if (a!=LIST_TAG)
{
DlgError("Arg 2 must be list");
return;
}
temp3=argptr-1;
while (!(*temp3==FALSE_TAG||*temp3==END_TAG||*temp3==LIST_START_TAG));
{
temp3=next_expression_index(temp3);
}
WriteToNBool(*temp3!=FALSE_TAG);
break;
case 21:
a=GetArgType(argptr);
if (a!=LIST_TAG)
{
DlgError("Arg 2 must be list");
return;
}
temp3=argptr-1;
x=1;
while (!(*temp3==TRUE_TAG||*temp3==END_TAG||*temp3==LIST_START_TAG))
{
temp3=next_expression_index(temp3);
x++;
}
WriteToNInt(x*(*temp3==TRUE_TAG));
For example, dcth(19,any list with all entries except the first false) will cause an infinite loop. Thanks again in advance!
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 05, 2012, 01:07:32 pm
* it needs to be a while loop, because the empty list is END_TAG LIST_TAG (E5 D9), in which case you don't want to enter the loop;
* you need to remove the comparisons against LIST_START_TAG, which are even more noxious than the comparisons against LIST_END_TAG in one of your previous code snippets (as LIST_START_TAG collides with positive integers, while LIST_END_TAG collided with negative integers). But that's not the reason why you're seeing an infinite loop.

I'll test your code.

EDIT: you put a ";" at the end of the "while" line in cases 19 and 20, which does definitely cause an infinite loop if the condition for escaping it is not met ;)
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 05, 2012, 04:00:26 pm
I removed the "||*temp3==LIST_START+TAG" and the semicolon. It works now, thanks!
Edit: Now I need to write from a TI-Basic list to a long array... solutions, anyone? How does ARB_REAL_INT work?
Edit 2: Solved!
(just a test to read a list)
Code: [Select]
FILE* WriteListToFilePtr(ESI temp)
{
int i=0,j=0;;
long* u=NULL;
if (!(u=malloc(32)))
return NULL;
clrscr();//!
for(i=0;i<8;i++)
{
u[i]=GetIntArg(temp);
printf("u[%d]=%ld\n",i,u[i]);
}
free(u);
ngetchx();
}
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 06, 2012, 01:38:19 am
Quote
How does ARB_REAL_INT work?
See push_next_arb_int / push_next_arb_real and ARb_int_count / ARb_int_real :)

Quote
Edit: Now I need to write from a TI-Basic list to a long array... solutions, anyone?
What you wrote, or init_list_indices ( http://debrouxl.github.com/gcc4ti/estack.html#init_list_indices ).
Note that unless you're compiling GCC4TI from Git (which is now quite a streamlined process under *nix for the "experimental" branch, https://github.com/debrouxl/gcc4ti/tree/experimental ), init_list_indices is in unknown.h. Documenting that function and moving it to estack.h was done in July 2009, right after the severely outdated current release (June 2009...).
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 06, 2012, 10:53:53 am
Oh, I get ARB_INT_TAG now. It's like when you solve sin(x)=0, the solution is x=pi*@n1. Basically they're numbers into which anything can be stored and the solution is still true?
So I was using fopen and returning a list representing the FILE structure:
Code: [Select]
case 24:
a=GetArgType(argptr);
if (a!=STR_TAG)
{
DlgError("Arg 2 must be string");
return;
}
const char* f3=GetStrnArg(argptr);
fio=fopen(f3,"r+b");
push_END_TAG();
push_longint((long)fio->fpos);
push_longint((long)fio->base);
push_longint(fio->handle);
push_longint(fio->flags);
push_longint(fio->unget);
push_longint(fio->alloc);
push_longint(fio->buffincrement);
push_LIST_TAG();
VarStore(SYMSTR("n"),STOF_ESI,0,top_estack);
break;
The WriteListToFilePtr function writes back to the FILE structure:
Code: [Select]
void WriteListToFilePtr(ESI temp,FILE* fio)
{
int i=0;
long* u=NULL;
if (!(u=calloc(7,sizeof(long))))
return;
//clrscr();
for(i=0;i<7;i++)
{
u[i]=GetIntArg(temp);
//printf("u[%d]=%ld\n",i,u[i]);
}


fio->fpos=(char*)u[6];
fio->base=(void*)u[5];
fio->handle=u[4];
fio->flags=u[3];
fio->unget=u[2];
fio->alloc=u[1];
fio->buffincrement=u[0];
free(u);
}
Do these entries in the structure have to be written to in reverse order or is this order fine? Also, thanks for your help!
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 06, 2012, 03:11:00 pm
The order doesn't matter, but I'm not sure why you're serializing and deserializing the FILE structure's fields ?

BTW: all files on the TI-68k are memory-mapped, BTW, so it's more efficient to use native, non-standard vat.h functions than standard, non-native stdio.h functions (reimplemented on top of vat.h, so they take up some space in your program) :)
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 06, 2012, 03:15:36 pm
I'm serializing/deserializing the fields so that the user will be able to open and close with the same FILE structure. Also, note that this is code from a library I'm writing. The problem is that this code gives me an address error:
Code: [Select]
case 25:
a=GetArgType(argptr);
if (a!=LIST_TAG)
{
DlgError("Arg 2 must be list");
return;
}
WriteListToFilePtr(argptr-1,fio);
fclose(fio);
fio is a pointer to the FILE structure declared before the switch statement.
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 07, 2012, 01:59:03 am
Quote
I'm serializing/deserializing the fields so that the user will be able to open and close with the same FILE structure.
Yeah, that's what I had understood from the code, but I'm trying to understand why do you need / want to do that ? :)
The general rule for fields of a FILE struct, whatever the target platform is, is that these fields are an implementation detail and should not be used, unless there's a very good reason to.
Serializing FILE structs in order to be able to deserialize them, potentially from a different run, is a recipe for disaster if the file's parameters (starting with the addresses - files can move during a both heap compaction and an archive memory garbage collection) change in-between.
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 07, 2012, 09:53:41 am
Then I might replace fopen/fclose/fgetc/fputc with 4 file commands: fread, fwrite, fgetc, and fputc. Thanks for telling me that!
EDIT: Does the handle field (fio->handle) remain consistent between runs though?
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 07, 2012, 09:59:50 am
Quote
Then I might replace fopen/fclose/fgetc/fputc with 4 file commands: fread, fwrite, fgetc, and fputc. Thanks for telling me that!
Hmm, I don't follow you ?
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 15, 2012, 11:09:28 am
On 2nd thought, I am going to use an array of 16 FILE structures, and have the user refer to them by indices (0 to 15). With any file-writing operation, I will update the appropriate element. For fopen and fclose, I might have
Code: [Select]
case 24:
a=GetArgType(argptr);
if (a!=STR_TAG)
{
DlgError("Arg 2 must be string");
return;
}
const char* f3=GetStrnArg(argptr);
a=GetArgType(argptr);
if (a!=STR_TAG)
{
DlgError("Arg 3 must be string");
return;
}
const char* f4=GetStrnArg(argptr);
a=GetArgType(argptr);
for (x=0;x<=16;x++)
{
if (!interface[x].handle) break;
}
if (x!=16)
{
interface[x]=*fopen(f3,f4);
}
WriteToNInt(x);
break;
case 25:
a=GetArgType(argptr);
if (a!=POSINT_TAG)
{
DlgError("Arg 2 must be int");
return;
}
x=GetIntArg(argptr);
if (x<0||x>=16)
{
DlgError("Arg 2 out of range");
return;
}
fclose(&interface[x]);
interface[x].handle=H_NULL;
break;
Title: Re: [68k] Storing a value into n?
Post by: Lionel Debroux on June 15, 2012, 12:55:37 pm
Quote
EDIT: Does the handle field (fio->handle) remain consistent between runs though?
Not in the general case. That's part of the reasons why I'm suggesting you to avoid using the fields of the FILE struct.
Title: Re: [68k] Storing a value into n?
Post by: blue_bear_94 on June 18, 2012, 03:00:10 pm
For some reason the code after "case 25:" results in an Address Error...