Portage de make.c vers D

Walter Bright est le «dictateur bienveillant de toute une vie» du langage de programmation D et fondateur de Digital Mars . Il a des décennies d'expérience dans le développement de compilateurs et d'interprètes pour plusieurs langages, dont Zortech C ++, le premier compilateur C ++ natif. Il est également le créateur d' Empire , la principale source d'inspiration de Sid Meier's Civilization.



Meilleure série C
  1. D C
  2. ,
  3. make.c D


Better C est un moyen de porter des projets C existants vers D de manière cohérente. Cet article vous guide pas à pas dans le processus de conversion d'un projet non trivial de C à D et vous montre les problèmes courants qui se posent.



Bien que l' interface du compilateur D dmd ait déjà été convertie en D, il s'agit d'un projet si volumineux qu'il est difficile de le couvrir entièrement. J'avais besoin d'un projet plus petit et plus modeste qui puisse être pleinement compris, mais qui ne soit pas un exemple spéculatif.



Un vieux programme make que j'ai écrit pour le compilateur Datalight C au début des années 80 m'est venu à l'esprit . Il s'agit d'une réelle implémentation du programme make classique, qui est constamment utilisé depuis le début des années 1980. Il a été écrit en C avant même d'être normalisé, a été porté d'un système à un autre et ne tient que dans 1961 lignes de code, y compris les commentaires. Il est encore utilisé régulièrement aujourd'hui.



Voici la documentation et le code source . La taille de l'exécutable make.exe est de 49 692 octets et a été modifiée pour la dernière fois le 19 août 2012.



Notre plan maléfique:



  1. Minimisez les différences entre les versions C et D. Ainsi, si le comportement des programmes diffère, il sera plus facile de trouver la source de la différence.
  2. C. â„– 1.
  3. . , . â„– 1.
  4. C , .
  5. , â„– 4.


, , , ..



!



C D. — 52 252 ( — 49 692 ). , , - NEWOBJ ( C- ) DMC 2012 .





. 664 1961, — , , , , .



#include D: , #include <stdio.h> import core.stdc.stdio;. , Digital Mars C, D ( ). , 29- 64-. (. import).



#if _WIN32 version (Windows). (. ).



extern(C): C. (. ).



debug1, debug2 debug3 debug prinf. , #ifdef DEBUG debug. (. debug).



/* Delete these old C macro definitions...
#ifdef DEBUG
-#define debug1(a)       printf(a)
-#define debug2(a,b)     printf(a,b)
-#define debug3(a,b,c)   printf(a,b,c)
-#else
-#define debug1(a)
-#define debug2(a,b)
-#define debug3(a,b,c)
-#endif
*/

// And replace their usage with the debug statement
// debug2("Returning x%lx\n",datetime);
debug printf("Returning x%lx\n",datetime);


TRUE, FALSE NULL true, false null.



ESC . (. ).



// #define ESC     '!'
enum ESC =      '!';


NEWOBJ .



// #define NEWOBJ(type)    ((type *) mem_calloc(sizeof(type)))
type* NEWOBJ(type)() { return cast(type*) mem_calloc(type.sizeof); }


filenamecmp .



.



D (thread-local storage, TLS). make — , __gshared. (. __gshared).



// int CMDLINELEN;
__gshared int CMDLINELEN


D , typedef . alias. (. alias). , struct.



/*
typedef struct FILENODE
        {       char            *name,genext[EXTMAX+1];
                char            dblcln;
                char            expanding;
                time_t          time;
                filelist        *dep;
                struct RULE     *frule;
                struct FILENODE *next;
        } filenode;
*/
struct FILENODE
{
        char            *name;
        char[EXTMAX1]  genext;
        char            dblcln;
        char            expanding;
        time_t          time;
        filelist        *dep;
        RULE            *frule;
        FILENODE        *next;
}

alias filenode = FILENODE;


D macro — , MACRO.



C, D , :



// char *name,*text;
// In D, the * is part of the type and 
// applies to each symbol in the declaration.
char* name, text;


C D. (. D).



static D . C D, , . __gshared, . (. static).



/*
static ignore_errors = FALSE;
static execute = TRUE;
static gag = FALSE;
static touchem = FALSE;
static debug = FALSE;
static list_lines = FALSE;
static usebuiltin = TRUE;
static print = FALSE;
...
*/

__gshared
{
    bool ignore_errors = false;
    bool execute = true;
    bool gag = false;
    bool touchem = false;
    bool xdebug = false;
    bool list_lines = false;
    bool usebuiltin = true;
    bool print = false;
    ...
}


D . , , , .



make- .



, , , D .



// int cdecl main(int argc,char *argv[])
int main(int argc,char** argv)


mem_init() , .



C , D , .



void cmderr(const char* format, const char* arg) {...}

// cmderr("can't expand response file\n");
cmderr("can't expand response file\n", null);


- (->) C (.), D .



version.



/*
 #if TERMCODE
    ...
 #endif
*/
    version (TERMCODE)
    {
        ...
    }


. D .



// doswitch(p)
// char *p;
void doswitch(char* p)


D debug . xdebug.



C \n\ . D .



/+ +/. (. , ).



static if #if. (. static if).



D , .ptr.



// utime(name,timep);
utime(name,timep.ptr);


const C D, D . (. const immutable).



// linelist **readmakefile(char *makefile,linelist **rl)
linelist **readmakefile(const char *makefile,linelist **rl)


void* char* D .



// buf = mem_realloc(buf,bufmax);
buf = cast(char*)mem_realloc(buf,bufmax);


unsigned uint.



inout , «» . const, , . (. inout-).



// char *skipspace(p) {...}
inout(char) *skipspace(inout(char)* p) {...}


arraysize .length. (. ).



// useCOMMAND  |= inarray(p,builtin,arraysize(builtin));
useCOMMAND  |= inarray(p,builtin.ptr,builtin.length)


(immutable), , . (. ).



// static char envname[] = "@_CMDLINE";
char[10] envname = "@_CMDLINE";


.sizeof sizeof() C. (. .sizeof).



// q = (char *) mem_calloc(sizeof(envname) + len);
q = cast(char *) mem_calloc(envname.sizeof + len)


Windows .



char * void*.



! , . , , — , .



man.c, , make -man. , D, .



make , make-:



\dmd2.079\windows\bin\dmd make.d dman.d -O -release -betterC -I. -I\dmd2.079\src\druntime\import\ shell32.lib




C D, . .



, , :



  • #include import;
  • D- ;
  • ->;
  • :

    • ,
    • ,
    • ,
    • ,
    • ;
  • ;
  • ;
  • ;
  • ;
  • ;
  • C D.


:



  • ,
  • ,
  • ,
  • ,
  • .




, Better C, , :





Ă€ l'action



Si vous connaissez l'anglais, rendez-vous sur le Forum D et dites-nous comment votre projet Better C progresse!




All Articles