Archives
D Programming
DD.gnu digitalmars.D digitalmars.D.bugs digitalmars.D.dtl digitalmars.D.dwt digitalmars.D.announce digitalmars.D.learn digitalmars.D.debugger C/C++ Programming
c++c++.announce c++.atl c++.beta c++.chat c++.command-line c++.dos c++.dos.16-bits c++.dos.32-bits c++.idde c++.mfc c++.rtl c++.stl c++.stl.hp c++.stl.port c++.stl.sgi c++.stlsoft c++.windows c++.windows.16-bits c++.windows.32-bits c++.wxwindows digitalmars.empire digitalmars.DMDScript |
c++ - Table Initializer Bug?
I'm willing to bet that my code is in error, but here I go anyway. I am not sure DM is initializing the CompositeAtomsTable properly. This is a nested initializer as you can see below. We have an array of key/value paris where value is itself an array. The function GetComponentTypes() performs a lookup against the table. The test driver main() just attempts a few lookups using this function and prints the results. But the program crashes on any but the first entry in the lookup table. I am building under 16-bit Windows large model but the problem might exist in 32-bit builds as well. Don't be blown away by the quantity of #defines here, this is actually a very simple concept at issue. Comments? Kind regards, Mark /* TableTst.c This 16-bit WINIO program (large model) shows a failure in the unsized table initialization of Digital Mars? Makefile follows code. */ #define _WINIO 1 #include <stdio.h> #include <winio.h> #include <windows.h> /* T Y P E C O D E S ****************************************************************************** Clever bit shifting tags the type constants as belonging to one of the three groups: atoms, arrays, and composites. */ typedef short unsigned int TypeCode; #define kTYPE_NONE 0 #define kTYPE_TERMINATION 0 #define kTYPEBASE_ATOM_BITPOS 9 #define kTYPEBASE_ATOM (1<<kTYPEBASE_ATOM_BITPOS) #define kTYPE_U32 (kTYPEBASE_ATOM+1) #define kTYPE_U16 (kTYPEBASE_ATOM+3) #define kTYPE_I32 (kTYPEBASE_ATOM+5) #define kTYPE_I16 (kTYPEBASE_ATOM+7) #define kTYPE_SGL (kTYPEBASE_ATOM+9) #define kTYPE_DBL (kTYPEBASE_ATOM+11) #define kTYPE_SPMHANDLE (kTYPEBASE_ATOM+13) #define kTYPE_SPMJOB (kTYPEBASE_ATOM+14) #define kTYPE_WINDOW (kTYPEBASE_ATOM+15) #define kTYPE_SPMERR (kTYPEBASE_ATOM+16) #define kTYPE_STRING (kTYPEBASE_ATOM+17) #define kTYPE_BOOLCHAR (kTYPEBASE_ATOM+18) #define kTYPE_SPM_MOTOR_SPEED kTYPE_SGL #define kTYPEBASE_ARRAY_BITPOS 10 #define kTYPEBASE_ARRAY (1<<kTYPEBASE_ARRAY_BITPOS) #define kTYPE_U32_ARRAY (kTYPEBASE_ARRAY+2) #define kTYPE_U16_ARRAY (kTYPEBASE_ARRAY+4) #define kTYPE_I32_ARRAY (kTYPEBASE_ARRAY+6) #define kTYPE_I16_ARRAY (kTYPEBASE_ARRAY+8) #define kTYPE_SGL_ARRAY (kTYPEBASE_ARRAY+10) #define kTYPE_DBL_ARRAY (kTYPEBASE_ARRAY+12) #define kTYPE_BOOLCHAR_ARRAY (kTYPEBASE_ARRAY+19) #define kTYPEBASE_COMPOSITE_BITPOS 11 #define kTYPEBASE_COMPOSITE (1<<kTYPEBASE_COMPOSITE_BITPOS) #define kTYPE_RECURSION_TEST_TYPE (kTYPEBASE_COMPOSITE+30) #define kTYPE_SPM_PARAMS (kTYPEBASE_COMPOSITE+32) #define kTYPE_SPM_STATUS_ITEM (kTYPEBASE_COMPOSITE+33) #define kTYPE_SPM_CALIBRATE_PROGRESS (kTYPEBASE_COMPOSITE+34) #define kTYPE_SPM_ERROR_SIGNAL (kTYPEBASE_COMPOSITE+35) #define kTYPE_SPM_SCANNER_Z (kTYPEBASE_COMPOSITE+36) #define kTYPE_SPM_SCANNER_XY (kTYPEBASE_COMPOSITE+37) #define kTYPE_SPM_SCANNER_Z_SLOPE (kTYPEBASE_COMPOSITE+38) #define kTYPE_SPM_BIAS (kTYPEBASE_COMPOSITE+39) #define kTYPE_SPM_DATA_FILTER_PARAMS (kTYPEBASE_COMPOSITE+40) #define kTYPE_SPM_STEP_PIECE (kTYPEBASE_COMPOSITE+41) #define kTYPE_SPM_WAVE_PIECE (kTYPEBASE_COMPOSITE+42) #define kTYPE_SPM_WAVE_ACQ (kTYPEBASE_COMPOSITE+43) #define kTYPE_SPM_SCANNING_PARAMS (kTYPEBASE_COMPOSITE+44) #define kTYPE_SPM_SCAN_RATE_PARAMS (kTYPEBASE_COMPOSITE+45) #define kTYPE_SPM_APPROACH_PARAMS (kTYPEBASE_COMPOSITE+46) #define kTYPE_SPM_APPROACH_PARAMS_LOW (kTYPEBASE_COMPOSITE+47) #define kTYPE_SPM_MOVE_STEPPER_PARAMS (kTYPEBASE_COMPOSITE+48) #define kTYPE_SPM_STEPPER_PARAMS (kTYPEBASE_COMPOSITE+49) #define kTYPE_SPM_MOVE_IMOTOR_PARAMS (kTYPEBASE_COMPOSITE+50) #define kTYPE_SPM_MOVE_PC38_PARAMS (kTYPEBASE_COMPOSITE+51) #define kTYPE_SPM_NCM_SWEEP_LOW_TYPE (kTYPEBASE_COMPOSITE+52) #define kTYPE_SPM_NCM_PHOP_TYPE (kTYPEBASE_COMPOSITE+53) #define kTYPE_SPM_NCM_RESPONSE_LUT (kTYPEBASE_COMPOSITE+54) #define kTYPE_SPM_VOLTAGE_PROBE_PARAMS (kTYPEBASE_COMPOSITE+55) #define kTYPE_SPM_NCM_SWEEP_PARAMS (kTYPEBASE_COMPOSITE+56) #define kTYPE_SPM_NCM_SWEEP_POINT (kTYPEBASE_COMPOSITE+57) /* PrintTypeCode Utility function for debugging purposes. Prints an ASCII string correponding to the type code parameter. Uses preprocessor 'stringization' operator (#). */ void PrintTypeCode(TypeCode t) { #define PRINT_TYPE_CODE_SWITCH( x ) \ /* begin macro */ \ case x: \ printf("\ntype code %s\n", #x ); \ break; \ /* end macro */ switch(t) { PRINT_TYPE_CODE_SWITCH( kTYPE_TERMINATION ); PRINT_TYPE_CODE_SWITCH( kTYPEBASE_ATOM ); PRINT_TYPE_CODE_SWITCH( kTYPE_U32 ); PRINT_TYPE_CODE_SWITCH( kTYPE_U16 ); PRINT_TYPE_CODE_SWITCH( kTYPE_I32 ); PRINT_TYPE_CODE_SWITCH( kTYPE_I16 ); PRINT_TYPE_CODE_SWITCH( kTYPE_SGL ); PRINT_TYPE_CODE_SWITCH( kTYPE_DBL ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPMHANDLE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPMJOB ); PRINT_TYPE_CODE_SWITCH( kTYPE_WINDOW ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPMERR ); PRINT_TYPE_CODE_SWITCH( kTYPE_STRING ); PRINT_TYPE_CODE_SWITCH( kTYPE_BOOLCHAR ); PRINT_TYPE_CODE_SWITCH( kTYPEBASE_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_U32_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_U16_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_I32_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_I16_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_SGL_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_DBL_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPE_BOOLCHAR_ARRAY ); PRINT_TYPE_CODE_SWITCH( kTYPEBASE_COMPOSITE ); PRINT_TYPE_CODE_SWITCH( kTYPE_RECURSION_TEST_TYPE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_STATUS_ITEM ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_CALIBRATE_PROGRESS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_ERROR_SIGNAL ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_SCANNER_Z ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_SCANNER_XY ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_SCANNER_Z_SLOPE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_BIAS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_DATA_FILTER_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_STEP_PIECE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_WAVE_PIECE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_WAVE_ACQ ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_SCANNING_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_SCAN_RATE_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_APPROACH_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_APPROACH_PARAMS_LOW ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_MOVE_STEPPER_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_STEPPER_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_MOVE_IMOTOR_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_MOVE_PC38_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_NCM_SWEEP_LOW_TYPE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_NCM_PHOP_TYPE ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_NCM_RESPONSE_LUT ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_VOLTAGE_PROBE_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_NCM_SWEEP_PARAMS ); PRINT_TYPE_CODE_SWITCH( kTYPE_SPM_NCM_SWEEP_POINT ); default: printf("type code unknown\n"); } #undef PRINT_TYPE_CODE_SWITCH } //=================== Composite Types ======================================== // Simultaneously declare and init table struct { TypeCode key; TypeCode value[]; } __far CompositeAtomsTable[] = { /* begin array of structs */ { kTYPE_SPM_WAVE_PIECE, { /* begin value array */ kTYPE_SGL, kTYPE_SGL, kTYPE_SGL, kTYPE_TERMINATION }}, { kTYPE_RECURSION_TEST_TYPE, { /* begin value array */ kTYPE_I32, kTYPE_SPM_WAVE_PIECE, // recursion here kTYPE_I32, kTYPE_TERMINATION }}, { kTYPE_SPM_APPROACH_PARAMS, { /* begin value array */ kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_I32, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_BOOLCHAR, kTYPE_I32, kTYPE_SGL, kTYPE_SGL, kTYPE_BOOLCHAR, kTYPE_SGL, kTYPE_BOOLCHAR, kTYPE_SGL, kTYPE_I16, kTYPE_SGL, kTYPE_SGL, kTYPE_SGL, kTYPE_BOOLCHAR, kTYPE_SGL, kTYPE_TERMINATION }}, { kTYPE_TERMINATION, /* begin value array */ { kTYPE_TERMINATION } /* end array of structs */} }; TypeCode __far * GetComponentTypes(TypeCode requestedType) { TypeCode compType; int i=0; while((compType = CompositeAtomsTable[i].key) != kTYPE_TERMINATION) { if (compType == requestedType) return CompositeAtomsTable[i].value; i++; } return NULL; // not found } int main(int argc, char *argv[]) { TypeCode __far *pTypeScan; printf("Looking up kTYPE_SPM_WAVE_PIECE\n"); pTypeScan = GetComponentTypes(kTYPE_SPM_WAVE_PIECE); while (*pTypeScan != kTYPE_TERMINATION) { PrintTypeCode(*pTypeScan); pTypeScan++; } printf("\n"); printf("Looking up kTYPE_RECURSION_TEST_TYPE\n"); pTypeScan = GetComponentTypes(kTYPE_RECURSION_TEST_TYPE); while (*pTypeScan != kTYPE_TERMINATION) { PrintTypeCode(*pTypeScan); pTypeScan++; } printf("\n"); printf("Looking up kTYPE_SPM_APPROACH_PARAMS\n"); pTypeScan = GetComponentTypes(kTYPE_SPM_APPROACH_PARAMS); while (*pTypeScan != kTYPE_TERMINATION) { PrintTypeCode(*pTypeScan); pTypeScan++; } printf("\n"); return 0; } /* END TableTst.c END */ # TableTst.mak all: clean TableTst.exe clean: del *.obj del *.com del *.exe OBJECTS = \ TableTst.obj LIBRARIES = \ LWINDOS.LIB \ LIBW.LIB \ COMMDLG.LIB \ SHELL.LIB \ WINSOCK.LIB MAKEFILE=TableTst.mak TableTst.exe : $(OBJECTS) $(MAKEFILE) LINK /CO /L /PACKF /XU /A:16 $(OBJECTS),TableTst.exe,TableTst.map,$(LIBRARIES),TableTst.def,; SCFLAGS = -D_WINIO=1 -D_TableTst -mluw -Jm -p -r -WA -S -5 -a2 -IC:\DigMars\dm\include\;C:\DigMars\dm\include\win16 TableTst.obj : TableTst.c $(MAKEFILE) SC -c $(SCFLAGS) -oTableTst.obj TableTst.c # END TableTst.mak # To build, use command: # smake.exe /f tabletst.mak all May 18 2001
Mark Evans wrote:// Simultaneously declare and init table struct { TypeCode key; TypeCode value[]; May 18 2001
Thanks Jan but I that's missing the point of the exercise. In C it is always possible to use numberless brackets when you supply the initializers. What I need to know is whether this problem qualifies as a bug in Digital Mars. The only alternative is that it may turn out my construction is not proper C in some obscure technical sense. If so, then I am unaware of the fact. In any case the code passes the compiler and therefore should work. Mark On Fri, 18 May 2001 14:55:25 -0400, Jan Knepper <jan smartsoft.cc> wrote:Mark Evans wrote:// Simultaneously declare and init table struct { TypeCode key; TypeCode value[]; May 18 2001
Mark Evans wrote:In any case the code passes the compiler and therefore should work. May 18 2001
Jan, It took me a few minutes to understand the meaning. You are saying that it's possible to write bad code which passes the compiler. My problem is really a compile-time problem, not a run-time problem. So it's a whole different category. I am not asking the compiler to serve as a code debugger. I am asking whether the compile- time behavior corresponds to the C standard. Mark On Fri, 18 May 2001 16:42:38 -0400, Jan Knepper <jan smartsoft.cc> wrote:Mark Evans wrote:In any case the code passes the compiler and therefore should work. May 21 2001
Mark Evans wrote:Thanks Jan but I that's missing the point of the exercise. In C it is always possible to use numberless brackets when you supply the initializers. May 18 2001
The code has an array of variable sized structs. You can't step through that with a fixed increment size. Instead, try doing it as an array of pointers to variable sized structs. Mark Evans wrote in message <1103_990215032 evans>...Thanks Jan but I that's missing the point of the exercise. In C it is May 18 2001
Again, missing the point. Of course there are other ways to do this task. The point is that this *specific* way does not work, even though it is proper C, and that may indicate a compiler bug. Maybe the C standard leaves this sort of thing as "implementation-specific" in which case the compiler could do anything. On the other hand, maybe it spells out what the compiler should do. I'm not the expert but am curious to know. In my thinking what the compiler should do is normalize the element sizes to accomodate the largest one. Mark On Fri, 18 May 2001 14:42:26 -0700, "Walter" <walter digitalmars.com> wrote:The code has an array of variable sized structs. You can't step through that with a fixed increment size. Instead, try doing it as an array of pointers to variable sized structs. Mark Evans wrote in message <1103_990215032 evans>...Thanks Jan but I that's missing the point of the exercise. In C it is May 21 2001
Mark, I think you should read Walter's messages as well. I do not know whether or not it is a compiler bug, a missing piece in the compiler implementation or may be even something missing in the C or C++ standards. Since C isn't BASIC I don't think the compiler should normalize the element size to accomodate the largest one. Actually as I wrote earlier, the element of your particular example is a POINTER. A POINTER is a defined size and points to something which could be either 1 element of the defined type or more of which the compiler has no knowledge. This is basically why I gave you the other example. TypeCode value []; is basically the same thing as: TypeCode *value; Which is something completely different than: TypeCode value [ 16 ]; HTH Jan Mark Evans wrote:Again, missing the point. Of course there are other ways to do this task. The point is that this *specific* way does not work, even though it is proper C, and that may indicate a compiler bug. Maybe the C standard leaves this sort of thing as "implementation-specific" in which case the compiler could do anything. On the other hand, maybe it spells out what the compiler should do. I'm not the expert but am curious to know. In my thinking what the compiler should do is normalize the element sizes to accomodate the largest one. Mark On Fri, 18 May 2001 14:42:26 -0700, "Walter" <walter digitalmars.com> wrote:The code has an array of variable sized structs. You can't step through that with a fixed increment size. Instead, try doing it as an array of pointers to variable sized structs. Mark Evans wrote in message <1103_990215032 evans>...Thanks Jan but I that's missing the point of the exercise. In C it is May 21 2001
I will let the matter rest since I am giving the impression of a novice C programmer. Actually I have worked with C for 13 years. I know how arrays and pointers work -- sized, unsized, void, and otherwise. What the compiler should do in this situation is probably open for debate, but clearly there are better ways to do it than what Digital Mars does now. I think that letting the compiler figure out the largest value[] size is very reasonable and I bet it's even in the C standard. Thank you for the conversation. Mark On Mon, 21 May 2001 13:03:28 -0400, Jan Knepper <jan smartsoft.cc> wrote:Mark, I think you should read Walter's messages as well. I do not know whether or not it is a compiler bug, a missing piece in the compiler implementation or may be even something missing in the C or C++ standards. Since C isn't BASIC I don't think the compiler should normalize the element size to accomodate the largest one. Actually as I wrote earlier, the element of your particular example is a POINTER. A POINTER is a defined size and points to something which could be either 1 element of the defined type or more of which the compiler has no knowledge. This is basically why I gave you the other example. TypeCode value []; is basically the same thing as: TypeCode *value; Which is something completely different than: TypeCode value [ 16 ]; HTH Jan Mark Evans wrote:Again, missing the point. Of course there are other ways to do this task. The point is that this *specific* way does not work, even though it is proper C, and that may indicate a compiler bug. Maybe the C standard leaves this sort of thing as "implementation-specific" in which case the compiler could do anything. On the other hand, maybe it spells out what the compiler should do. I'm not the expert but am curious to know. In my thinking what the compiler should do is normalize the element sizes to accomodate the largest one. Mark On Fri, 18 May 2001 14:42:26 -0700, "Walter" <walter digitalmars.com> wrote:The code has an array of variable sized structs. You can't step through that with a fixed increment size. Instead, try doing it as an array of pointers to variable sized structs. Mark Evans wrote in message <1103_990215032 evans>...Thanks Jan but I that's missing the point of the exercise. In C it is May 21 2001
What the compiler should do in this situation is probably open for debate, but clearly there are better ways to do it than what Digital Mars does now. May 21 2001
My understanding is that it is not standard C. In a practical sense, the compiler cannot generate code to step through an array with variable sized elements with a fixed sized pointer arithmetic. Adjusting all the element sizes upwards to match the largest size would be an extension to the language. You can achieve the same effect in standard C by putting a dimension in the [] that is large enough. C really is rather limited in how you can lay out and initialize data structures. "Mark Evans" <mevans zyvex.com> wrote in message news:1103_990462843 evans...Again, missing the point. Of course there are other ways to do this task. May 21 2001
That's exactly what I know from using the language rather than reading the spec's... I also tried to explain that, but it does not seem to reach goal... <g> Walter wrote:My understanding is that it is not standard C. In a practical sense, the compiler cannot generate code to step through an array with variable sized elements with a fixed sized pointer arithmetic. Adjusting all the element sizes upwards to match the largest size would be an extension to the language. You can achieve the same effect in standard C by putting a dimension in the [] that is large enough. C really is rather limited in how you can lay out and initialize data structures. "Mark Evans" <mevans zyvex.com> wrote in message news:1103_990462843 evans...Again, missing the point. Of course there are other ways to do this task. May 21 2001
|