We could have a ts2.h include file that included ts.h. It would contain stuff like:
#define TSExistingStructType TSExistingStructTypeVer2 typedef struct { ... fields ... } TSExistingStructTypeVer2; #define TSExistingAPIFunc TSExistingAPIFuncVer2 void TSExistingAPIFuncVer2(... formal parameter list ...); As well as new declarations / definitions. Once all plugins were using ts2.h, then ts.h could be revised to be equivalent to ts2.h. ts2.h would become a symbolic link to ts.h. Once all plugins were changed back to including ts.h, the symbolic link could be removed. There could hypothetically be multiple layers using this approach. There could be a ts3.h include file that includes ts2.h. I could contain stuff like #undef TSExistingAPIFunc #define TSExistingAPIFuncVer3 void TSExistingAPIFuncVer3(... formal parameter list ...); Clearly there are some API changes where this approach would not work, but many where it would work. One way I'm thinking I would like to use this approach is to substitute multiple, more specific types for the TSMLoc type. The goal is to have more compile time checking. Currently we rely on run time checks, and there are also cases where a coding error could result in undefined run time behavior (memory corruption).