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; #endif
Fonctions
#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.
