Transferindo make.c para D

Walter Bright é o "ditador benevolente ao longo da vida" da linguagem de programação D e fundador da Digital Mars . Ele tem décadas de experiência no desenvolvimento de compiladores e interpretadores para várias linguagens, incluindo Zortech C ++, o primeiro compilador C ++ nativo. Ele também é o criador do Império , a principal inspiração para a Civilização de Sid Meier.



Better C Series
  1. D C
  2. ,
  3. make.c D


Melhor C é uma maneira de portar projetos C existentes para D de uma maneira consistente. Este artigo o conduz pelo processo passo a passo de conversão de um projeto não trivial de C para D e mostra os problemas comuns que surgem.



Embora o frontend do compilador de D dmd já tenha sido convertido para D, é um projeto tão grande que é difícil cobri-lo inteiramente. Eu precisava de um projeto menor e mais modesto que pudesse ser totalmente compreendido, mas que não fosse um exemplo especulativo.



Um antigo programa make que escrevi para o compilador Datalight C no início dos anos 1980 me veio à mente . Esta é uma implementação real do programa make clássico, que tem estado em uso constante desde o início dos anos 1980. Ele foi escrito em C antes mesmo de ser padronizado, foi portado de um sistema para outro e se encaixa em apenas 1961 linhas de código, incluindo comentários. Ainda é usado regularmente hoje.



Aqui está a documentação e o código-fonte . O tamanho do executável make.exe é 49.692 bytes e foi modificado pela última vez em 19 de agosto de 2012.



Nosso plano do mal:



  1. Minimize as diferenças entre as versões C e D. Assim, se o comportamento dos programas for diferente, será mais fácil encontrar a origem da diferença.
  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, , :





Para a ação



Se você sabe inglês, vá para o Fórum D e conte-nos como seu projeto Better C está progredindo!




All Articles