J'aimerais récolter des critiques sur mon code, ici très simple (le binaire fait 2 ko).
Je débute, je me fais pas d'illusions. Quelles sont mes erreurs les plus grossières ? Qu'est-ce qui m'handicapera quand le programme deviendra plus gros ? Est-ce que dès éléments font que dès maintenant, on voit que ça ne sera pas maintenable ?
Il y a trois sources :
Main
#include "kernel.h"
#include "asti68k.h"
#include "config.h"
#include "funcs.h"
#include "strings.h"
// Used to quit properly
JMP_BUF JmpBuf;
/**************************************************************************************************************
* Main function *
* *
* Parse the command line *
* Create some handles for each source file *
* Call the assembler for each file *
* Call the linker for the whole program *
* Wrap the final program *
* *
**************************************************************************************************************/
void main(void)
{
// Set up exit handler
if (setjmp(&JmpBuf))
return;
// Clear the screen and reset point position
clrscr();
// Create default flags mask
unsigned long Flags = (FLAG_ADDA_SUBA << BIT_ADDA_SUBA) +
(FLAG_LEA << BIT_LEA) +
(FLAG_MOVEM << BIT_MOVEM) +
(FLAG_QUICK << BIT_QUICK) +
(FLAG_XAN << BIT_XAN) +
(FLAG_BCC << BIT_BCC) +
(FLAG_STRICT << BIT_STRICT) +
(FLAG_ALIGN_DS << BIT_ALIGN_DS) +
(FLAG_ALIGN_DC << BIT_ALIGN_DC) +
(FLAG_ALIGN_DCB << BIT_ALIGN_DCB) +
(FLAG_CACHE << BIT_CACHE);
/**************************************************************************************************************
* Parse the command line *
* *
* 0 arg : invalid, disp a message *
* 1 arg : it must be a command, else it's invalid *
* 2 args : invalid, disp a message *
* 3+ args : it should be a program to assemble. See Readme.txt to get informations about command line args *
**************************************************************************************************************/
ESI const ArgPtr = top_estack;
unsigned short ArgCount;
if (*ArgPtr == END_TAG)
{
printf(ErrorInvalidCall);
Quit();
}
ArgCount = remaining_element_count(ArgPtr);
if (ArgCount == 1)
ReadCommand(ArgPtr, Flags);
if (ArgCount == 2)
{
printf(ErrorInvalidCall);
Quit();
}
}
/**************************************************************************************************************
* End of main() *
**************************************************************************************************************/
/**************************************************************************************************************
* Quit *
* *
* 0 arg : disp the help *
**************************************************************************************************************/
void Quit(void)
{
printf(PressAKey);
ngetchx();
longjmp(JmpBuf, 1);
}Ligne de commande
#include "kernel.h"
#include "asti68k.h"
#include "funcs.h"
#include "strings.h"
#include "config.h"
/*************************************************************************
* CheckArgType
*
* Check if an arg pointed to by an ESI ptr is a string
* Return a ptr to the first char of the string
* Quit in case of error
*************************************************************************/
unsigned char* CheckArgType(ESI Ptr)
{
if (*Ptr != STR_TAG)
{
printf(ErrorInvalidArgType);
Quit();
}
Ptr -= 2; // Skip tag & terminal \0
while(*(Ptr--));
return (char*) Ptr + 2;
}
/*************************************************************************
* ReadCommand
*
* Read an arg in the command line and execute the right routine
* Quit in case of error
*************************************************************************/
void ReadCommand(ESI Ptr, unsigned long Flags)
{
unsigned short Count = 0;
unsigned char* ArgPtr = CheckArgType(Ptr);
const unsigned char* CommandPtr = StrCommands;
while (*CommandPtr && (strcmp(CommandPtr, ArgPtr)))
{
Count++;
CommandPtr += strlen(CommandPtr) + 1;
}
switch (Count)
{
case 0: printf(HelpText);
break;
case 1: PrintFlags(Flags);
break;
case 2: printf(AboutText);
break;
case 3: Flags = ReadConfigFile(Flags);
PrintFlags(Flags);
break;
default: printf(ErrorInvalidCommand, ArgPtr);
}
Quit();
}
/*************************************************************************
* PrintFlags
*
* Disp the default flags of asTI68k
*************************************************************************/
void PrintFlags(const unsigned long Flags)
{
const unsigned char* StrFlag = StrFlags;
unsigned short Count = 0;
while (*StrFlag)
{
printf("%s: ", StrFlag);
if (Flags & (1 << Count))
printf("Enabled\n");
else
printf("Disabled\n");
Count++;
StrFlag += strlen(StrFlag) + 1;
}
printf("cache: %s",(FLAG_CACHE ? "Enabled\n" : "Disabled\n"));
}
/*************************************************************************
* ReadConfigFile
*
* Read the config file and apply it to the default flags
*************************************************************************/
unsigned long ReadConfigFile(unsigned long Flags)
{
const SYM_ENTRY* FileSym;
const unsigned char* FilePtr;
unsigned short Line = 1;
PARSE_WORD ParseData;
unsigned short ArgType;
unsigned short FlagIndex;
unsigned char Filename[20];
unsigned char* NamePtr = Filename;
*NamePtr = 0;
NamePtr++;
// Copy default folder name if it exists
if (*DEFAULT_PATH)
{
strcpy(NamePtr, DEFAULT_PATH);
NamePtr += strlen(DEFAULT_PATH);
*NamePtr = '\';
NamePtr++;
}
// Copy default file name if it exists
if (*DEFAULT_FILE)
{
strcpy(NamePtr, DEFAULT_FILE);
NamePtr += strlen(DEFAULT_FILE);
}
else
// else use the standard name
{
NamePtr = Filename + 1;
strcpy(NamePtr, DefaultConfigFile);
NamePtr += strlen(DefaultConfigFile);
}
// Look for the file in the VAT
FileSym = SymFindPtr(NamePtr, 0);
if (!FileSym)
{
printf(NoConfigFileFound);
return Flags;
}
// Check the type of the file
FilePtr = HeapDeref(FileSym->handle);
if (FilePtr[*(short*)FilePtr + 1] != TEXT_TAG)
{
printf(ErrorConfigFileNotText);
return Flags;
}
FilePtr +=2;
// Infinite loop: parse the file
// Read it and eval its args
while (1)
{
// Skip leading spaces, empty lines and return in case of EOF
FilePtr = SkipSpaces(FilePtr);
if (!*FilePtr)
return Flags;
if (*FilePtr == 13)
{
FilePtr++;
Line++;
continue;
}
// Skip comments
if (*FilePtr == '#')
{
FilePtr = SkipEndOfLine(FilePtr);
continue;
}
// Item found : it must be a global option or a flag, else skip the line
ArgType = FLAG;
CompareStrings(StrFlags, FilePtr, Separator1, &ParseData);
if (!ParseData.Index)
{
ArgType = OPTION;
CompareStrings(StrGlobalOptions, FilePtr, Separator1, &ParseData);
if (!ParseData.Index)
{
printf(ErrorInvalidArg, Line);
FilePtr = SkipEndOfLine(FilePtr);
continue;
}
}
// Okay, we have an index, a type of table, we must find a value (O/1)
FlagIndex = ParseData.Index;
FilePtr += ParseData.Length;
FilePtr = SkipSpaces(FilePtr);
CompareStrings(StrFlagValue, FilePtr, Separator2, &ParseData);
if (!ParseData.Index)
{
printf(ErrorInvalidArg, Line);
FilePtr = SkipEndOfLine(FilePtr);
continue;
}
// Okay, we have a flag/option, and its value to set. Let's do it
if (ArgType != FLAG)
FlagIndex += 10;
Flags = Flags | (1 << FlagIndex);
if (ParseData.Index == 1)
Flags = Flags & !(1 << FlagIndex);
// Now we can find spaces + [comment | EOL | EOF]. Else there is an error
FilePtr += ParseData.Length;
FilePtr = SkipSpaces(FilePtr);
if ((*FilePtr == '#') || (*FilePtr == 13) || (!*FilePtr))
{
FilePtr = SkipEndOfLine(FilePtr);
continue;
}
printf(ErrorInvalidArg, Line);
}
}Parseur
#include "kernel.h"
#include "funcs.h"
/************************************************
* SkipSpaces
*
* Skip the blank spaces until EOL/EOF
************************************************/
const unsigned char* SkipSpaces(const unsigned char* Ptr)
{
while (*Ptr == 32)
Ptr++;
return Ptr;
}
/************************************************
* SkipEndOfLine
*
* Skip all chars of a line until EOF/EOL
************************************************/
const unsigned char* SkipEndOfLine(const unsigned char* Ptr)
{
while (!(*Ptr || (*Ptr == 13)))
Ptr++;
return Ptr;
}
/************************************************
* CompareStrings
*
* Check if two strings match
* The Reference string is string list NULL terminated
* The Argument string is terminated by a char of Separator (a list of chars null-terminated)
* Return #item found in the Reference list
************************************************/
void CompareStrings(const unsigned char* Ref, const unsigned char* const Arg, const unsigned char* const Separator, PARSE_WORD* const ParseData)
{
const unsigned char* Text;
const unsigned char* SepItem;
ParseData->Index = 0;
while (*Ref)
{
Text = Arg;
ParseData->Length = 0;
(ParseData->Index)++;
// Check if strings are identical
while (!*Ref)
{
(ParseData->Length)++;
if (*Ref++ != *Text++)
{
ParseData->Length = 0;
break;
}
}
// Strings mismatch. Skip current Ref, reset Arg and loop
if (!ParseData->Length)
{
while (*Ref++);
continue;
}
// Strings seem to match, check the Separator after Arg
SepItem = Separator;
while (*SepItem++)
{
if (*Arg == *SepItem)
return;
}
}
// Nothing match. Reset index and quit
ParseData->Index = 0;
}Et quelques headers :
Header principal
#ifndef __ASTI68K__
#define __ASTI68K__
/************************************************
* Bits of flags
************************************************/
#define BIT_ADDA_SUBA 0
#define BIT_LEA 1
#define BIT_MOVEM 2
#define BIT_QUICK 3
#define BIT_XAN 4
#define BIT_BCC 5
#define BIT_STRICT 6
#define BIT_ALIGN_DS 7
#define BIT_ALIGN_DC 8
#define BIT_ALIGN_DCB 9
#define BIT_CACHE 10
/************************************************
* Indicates in which table an item was found
************************************************/
#define FLAG 0
#define OPTION 1
/************************************************
* Structure used when parsing files
************************************************/
typedef struct
{
unsigned short Length;
unsigned short Index;
} PARSE_WORD;
#endifFonctions
#ifndef __FUNCS__
#define __FUNCS__
#include "asti68k.h"
extern void Quit(void);
/************************************************
* Command line
************************************************/
extern unsigned char* CheckArgType(ESI);
extern void ReadCommand(ESI const, unsigned long);
extern void PrintFlags(const unsigned long);
extern unsigned long ReadConfigFile(unsigned long);
/************************************************
* Parser
************************************************/
extern const unsigned char* SkipSpaces(const unsigned char*);
extern const unsigned char* SkipEndOfLine(const unsigned char*);
extern void CompareStrings(const unsigned char*, const unsigned char* const, const unsigned char* const, PARSE_WORD* const);
#endif[/pre]
#define __FUNCS__
#include "asti68k.h"
extern void Quit(void);
/************************************************
* Command line
************************************************/
extern unsigned char* CheckArgType(ESI);
extern void ReadCommand(ESI const, unsigned long);
extern void PrintFlags(const unsigned long);
extern unsigned long ReadConfigFile(unsigned long);
/************************************************
* Parser
************************************************/
extern const unsigned char* SkipSpaces(const unsigned char*);
extern const unsigned char* SkipEndOfLine(const unsigned char*);
extern void CompareStrings(const unsigned char*, const unsigned char* const, const unsigned char* const, PARSE_WORD* const);
#endif[/pre]
Config
#ifndef __CONFIG__ #define __CONFIG__ #define FLAG_ADDA_SUBA 1 #define FLAG_LEA 1 #define FLAG_MOVEM 1 #define FLAG_QUICK 1 #define FLAG_XAN 1 #define FLAG_BCC 1 #define FLAG_STRICT 1 #define FLAG_ALIGN_DS 0 #define FLAG_ALIGN_DC 0 #define FLAG_ALIGN_DCB 0 #define FLAG_CACHE 0 #define DEFAULT_PATH "system" #define DEFAULT_FILE "asti68k" #endif
J'ai pas mis les chaines de caractères, ça me semble inutile.
Voilà, si certains ont la grande patience de m'aider, qu'ils en soient remerciés d'avance.

(ça devrait plutôt s'appeler FindEndOfLine pour être logique)
Entre les copier/coller pas corrigés et les bugs, faut que je revoie ça, merci
(ça devrait plutôt s'appeler FindEndOfLine pour être logique)
)