Strange. Can you share the code?
I sure can, but were taling about 15 kb source code, so that won't work on this forum.
This is the .h file and the list.c file.
They compile without problem (cf -> cg -k -> m80 ). When you link with l80 and include list/s there will be no error, but the code won't work anyway. I included a simple welcome function lstWelcome(), that will not execute.
/* list.h */ typedef struct { char name; struct tNode *next; struct tNode *prev; } tNode; extern VOID updNode(); extern unsigned cntNode(); extern tNode *gtNode(); extern tNode *addNode (); extern tNode *gForward(); extern tNode *gBack(); extern tNode *remNode(); extern lstWelcome();
List code, the empty includes happen because the forum doesn't handle bigger and smaller signs.
#include #include #include "list.h" #define Jiffy (unsigned *)0xFC9E #pragma nonrec /* VOID sleep( time ) unsigned time; { unsigned old,lus; for (lus = 0; lus < time ; lus++ ) { old = (*(Jiffy)); while ( old == (*(Jiffy)) ) { } } } */ VOID updNode(start, val) tNode *start; char val; { tNode *tmp=start; tmp->name=val; } unsigned cntNode( start ) tNode *start; { tNode *tmp=start; unsigned count=1; while ( tmp->next) { count++; tmp = (tNode*)tmp->next; } return(count); } tNode *gtNode(start, val) tNode *start; unsigned val; { tNode *tmp=start; unsigned loop; for (loop=0;loopnext != 0 ) { tmp=(tNode *)tmp->next; } else { return(NULL); } return tmp; } /* VOID wait() { while ( !kbhit()); kilbuf(); } */ /* add a value. If next is NULL then we are at the tail, otherwise insert */ tNode *addNode (walker, waarde) char waarde; tNode *walker; { tNode *temp, *temp2, *twalker; /* name == NULL && next == NULL*/ twalker = walker; if (twalker->next == NULL) { /* is there a character */ if (twalker->name ) { temp = twalker; twalker->next=(struct tNode *) alloc (sizeof(tNode)); twalker = (tNode *)twalker->next; twalker->prev = (struct tNode *)temp; } else { twalker->prev = NULL; } twalker->name=waarde; twalker->next=NULL; return(twalker); } else { /* name !=0 && next != 0 */ temp = twalker; temp2 = (tNode *)twalker->next; /* save next enty */ temp = (tNode *)alloc(sizeof(tNode)); /* create new entry */ temp->name=waarde; /* add value to next entry */ temp->next=(struct tNode *)temp2; /* add next entry to new value */ temp->prev=(struct tNode *)walker; walker->next=(struct tNode *)temp; /* connect new to old chain */ temp2->prev = (struct tNode *)temp; /* connect next element to new element*/ return(twalker); } } tNode *gForward( walker) tNode *walker; { if (walker->next ) { return((tNode *)walker->next); } else return((tNode *)walker); } tNode *gBack( walker ) tNode *walker; { if (walker->prev) { return((tNode *)walker->prev); } else return(walker); } tNode *remNode(walker,flag) tNode *walker; char flag; { /* flag == 0 [BS] flag == 1 [DEL] */ tNode *temp; /* are we at the start */ /* check NULL !walker->prev*/ /* only DEL works on first entry */ if ( !walker->prev ) { if (flag) { temp = (tNode *)walker->next; temp->prev=NULL; free(walker); return(temp); /* root needs to be updated, check by prev==NULL*/ } else { return(walker); } } /* are we in between */ /* [DEL] then delete, [BS] move 1 left */ if ((walker->prev) && (!flag)) { walker=(tNode *)walker->prev; } else { if (!flag) return(walker); } /* A->B->C */ if (walker->next) { temp = (tNode *)walker->prev; /* store previous node */ temp->next = (struct tNode *)walker->next; /* previous node points to new next */ temp = (tNode *)walker->next; /* store next node */ temp->prev = (struct tNode *)walker->prev; /* next prev points to new previous */ free(walker); /* remove current issue */ walker=(tNode *)temp->prev; return(temp); } else { /* are we at the end */ if ( temp ) { temp->next = NULL; free(walker); return(temp); } } } VOID lstWelcome() { printf("hello\n"); } /* main() { tNode *old,*temp; tNode *root; temp=(tNode *)alloc(sizeof(tNode)); root = temp; temp->next=NULL; temp->prev=NULL; temp->name=NULL; setbuf(stdout, NULL); temp = addNode(temp,'c'); temp = addNode(temp,'o'); temp = addNode(temp,'m'); temp = addNode(temp,'p'); temp = addNode(temp,'u'); temp = addNode(temp,'t'); temp = addNode(temp,'e'); printf("current entry:%c\n",temp->name); printf("current address:%u\n",temp); printf("root address:%u\n",root); temp=remNode(temp,(char)0); if (!temp->prev) root=temp; printf("current entry after delete: %c\n",temp->name); temp = root; printf("start character:%c\n",temp->name); old=temp; while ((temp = gForward(temp)) != old) { printf("%c",temp->name); old=temp; } printf("number of characers:%u\n",cntNode(root)); temp=gtNode(root,0); printf("root character is:%c",temp->name); temp = remNode(temp,(char)1); if ( !temp->prev ) root=temp; printf("current character after del is:%c",temp->name); } */
Regardless of this list of code: the error is confusing.
All my included functions are "undefined" but when I also declare them in my code, I get error "duplicate definition". The compiler is inconsistent: it shouldn't say "function is undefined" and then "this is a second definition". What happened to my first definition then?
I solved my own issue.
A new question: how to work with long. A long for the FIB has been defined as
typedef unsigned LONG[2];
and MSX-DOS2 correctly dumps the file size in these 4 bytes. The question: does anyone have an algorithm to create the right file size from that. MSX C only handles 16 bits, so the high 2 bytes are displayed as separate numbers. A file of 130 Kb, has bit 1 set in the hight bytes. So the high part is two, which is correct for the unsigned but not the size.
I solved my own issue.
What was the problem?
I read your code but didn't understand what was supposed to do.
A new question: how to work with long. A long for the FIB has been defined as
typedef unsigned LONG[2];
and MSX-DOS2 correctly dumps the file size in these 4 bytes. The question: does anyone have an algorithm to create the right file size from that. MSX C only handles 16 bits, so the high 2 bytes are displayed as separate numbers. A file of 130 Kb, has bit 1 set in the hight bytes. So the high part is two, which is correct for the unsigned but not the size.
Not sure I understand correctly but if I do, the algorithm is just multiplication?
Something like: size[0]*0x100 + size[1].
Or the other way around of [0] and [1] depending on how the most significant bytes are stored.
Thanks for your answer. My question wasn't clear. How do I display the value of a LONG in MSX C?
MSX C can display unsigned but not bigger than 16 bits. The files can be bigger than 16 bits, so MSX C can't display long values. The only work around I can think of is using the math pack which requires me to convert the long (2 x unsigned) to 4 x char. I hope there is a better way, than calling some basic routine and doing all kind of conversions. I decided to take a look at SDCC here, because that has native long support.
SDCC is not my favourite because SDCC has a broken linker that includes all code from a library, even when unused, creating bloated binaries so I hope there is a smart way in MSX C.
Not a common thing I guess, but check sltoa() from math.h, seems it returns exactly what you want.
However, please explain the use case for this... because if it's for displaying the score in a game for example, I'm sure there are better ways to achieve what you want (using unsigned int which is much faster).
Can you please tell us how you solved the previous issue?
I have never created an external library myself and I am curious what the problem was and how you solved it.
SDCC is not my favourite because SDCC has a broken linker that includes all code from a library, even when unused, creating bloated binaries
In fact SDCC only link used modules in a library. The problem is SDCC consider 1 module is 1 file, so to make the most efficient library we should have to split functions file by file. BTW this is how the default SDCC library is done so only used functions are linked.
I'm pretty sure we can found a work-around to have more than 1 module per file but I had no time to check this yet.
I am experiencing many issues with SDCC when choose it as compiler on z88dk, the SmallC compiler seems much more robust and smarter for writing code. I.e. with SmallC I can define a fixed address directly as pointer:
#define g_myvar ((MyStruct*)*(void*)0xAAAA)
As use it directly as a pointer variable:
g_myvar = malloc(); ... g_myvar->member = ...
This doesn't work on SDCC, and must be changed to:
#define g_myvar_address (uint16_t*)0xAAAA #define g_myvar ((MyStruct*)g_myvar_address)
And then cannot use directly to update the address, has to use it separately:
*g_myvar_address = malloc(); ... g_myvar->member = ...
Less intuitive.
It also has many issues for indexing addresses, like:
&myvar_struct_pointer->some_member
Got errors like:
Internal error: validateOpTypeConst failed in OP_VALUE(op) @ SDCCicode.c:1228: expected value, got symbol
And have to change to base address plus offset manually:
myvar_struct_pointer + offsetof(MyStruct, some_member)
And requires too much manual casting, while SmallC does it by its own.
And even when modified everything to fit, continue getting warnings like:
warning 196: pointer target lost const qualifier
What?
warning 110: conditional flow changed by optimizer: so said EVELYN the modified DOG
Nice but don't show me a warning.
I think I'll use SmallC with -O2 and required --opt-code-speed then delegate on ASM libraries and functions when required.