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.
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:
- 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.
- C. â„– 1.
- . , . â„– 1.
- C , .
- , â„– 4.
, , , ..
!
C D. — 52 252 ( — 49 692 ). , , - NEWOBJ ( C- ) DMC 2012 .
#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); }
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
.
// char *name,*text;
// In D, the * is part of the type and
// applies to each symbol in the declaration.
char* name, text;
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 .
// int cdecl main(int argc,char *argv[])
int main(int argc,char** argv)
mem_init()
, .
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 .
/*
#if TERMCODE
...
#endif
*/
version (TERMCODE)
{
...
}
// doswitch(p)
// char *p;
void doswitch(char* p)
D debug
. xdebug
.
C \n\
. D .
/+ +/
. (. , ).
// 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);
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*
.
! , . , , — , .
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, , :
- !
- accès sécurisé à la mémoire (y compris vérification du dépassement de la mémoire tampon )
- métaprogrammation,
- RAII ,
- Unicode,
- fonctions imbriquées ,
- méthodes ,
- surcharge de l'opérateur ,
- générateur de documentation ,
- programmation fonctionnelle ,
- exécution de la fonction à la compilation (CTFE) ,
- et bien plus encore .
Ă€ l'action
Si vous connaissez l'anglais, rendez-vous sur le Forum D et dites-nous comment votre projet Better C progresse!