make.cをDに移植する

ウォルターブライトのDプログラミング言語と創業者の「慈悲深い、生涯の独裁者」であるデジタル火星彼は、最初のネイティブC ++コンパイラであるZortechC ++を含む、いくつかの言語用のコンパイラとインタプリタの開発に12年以上の経験があります。彼はまた、シド・マイヤーの文明の主なインスピレーションであるエンパイアの作成者でもあります。



より良いCシリーズ
  1. D C
  2. ,
  3. make.c D


Better Cは、既存のCプロジェクトを一貫した方法でDに移植する方法です。この記事では、重要なプロジェクトをCからDに変換するためのステップバイステップのプロセスを示し、発生する一般的な問題を示します。



DコンパイラのdmdフロントエンドはすでにDに変換されていますが、非常に大きなプロジェクトであるため、完全に網羅することは困難です。完全に理解できるが、投機的な例ではない、より小さく、より控えめなプロジェクトが必要でした。



1980年代初頭にDatalightCコンパイラ用に作成した古いmakeプログラムが思い浮かびましたこれは、1980年代初頭から絶えず使用されてきた古典的なmakeプログラムの実際の実装です。標準化される前からCで記述されており、あるシステムから別のシステムに移植され、コメントを含めて1961行のコードに収まります。それは今日でも定期的に使用されています。



これがドキュメントソースコードです。make.exe実行可能ファイルのサイズは49,692バイトで、最終変更日は2012年8月19日です。



私たちの邪悪な計画:



  1. CバージョンとDバージョンの違いを最小限に抑えます。したがって、プログラムの動作が異なる場合、違いの原因を見つけるのは簡単です。
  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, , :





アクションに



英語をご存知の場合は、フォーラムDにアクセスして、BetterCプロジェクトの進捗状況をお知らせください。




All Articles