From 0315e90e6e8a2296e8d299c6e06c25b006383e6e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 19 Jan 2018 11:06:23 -0600 Subject: [PATCH 01/12] Revert "tools: Use Carp" This reverts commit f207b00b052037cbb59928e7d5cab1afc6a93a2d. None of these warn/die messages request a stack dump since they all end with \n, but carp & croak ignore that. --- src/tools/EPICS/Copy.pm | 14 ++++++-------- src/tools/EPICS/Release.pm | 10 ++++------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/tools/EPICS/Copy.pm b/src/tools/EPICS/Copy.pm index d61800e0e..e1ef2a54e 100644 --- a/src/tools/EPICS/Copy.pm +++ b/src/tools/EPICS/Copy.pm @@ -5,8 +5,6 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -use Carp; - # Copy directories and files from a template sub copyTree { @@ -15,7 +13,7 @@ sub copyTree { # $Rtextsubs contains substitutions for file content. opendir my $FILES, $src - or croak "opendir failed while copying $src: $!\n"; + or die "opendir failed while copying $src: $!\n"; my @entries = readdir $FILES; closedir $FILES; @@ -36,9 +34,9 @@ sub copyTree { print "." unless $opt_d; copyFile($srcName, $dstName, $Rtextsubs); } elsif (-l $srcName) { - carp "\nSoft link in template, ignored:\n\t$srcName\n"; + warn "\nSoft link in template, ignored:\n\t$srcName\n"; } else { - carp "\nUnknown file type in template, ignored:\n\t$srcName\n"; + warn "\nUnknown file type in template, ignored:\n\t$srcName\n"; } } } @@ -46,11 +44,11 @@ sub copyTree { sub copyDir { my ($src, $dst, $Rnamesubs, $Rtextsubs) = @_; if (-e $dst && ! -d $dst) { - carp "\nTarget exists but is not a directory, skipping:\n\t$dst\n"; + warn "\nTarget exists but is not a directory, skipping:\n\t$dst\n"; return; } print "Creating directory '$dst'\n" if $opt_d; - mkdir $dst, 0777 or croak "Can't create $dst: $!\n" + mkdir $dst, 0777 or die "Can't create $dst: $!\n" unless -d $dst; copyTree($src, $dst, $Rnamesubs, $Rtextsubs); } @@ -61,7 +59,7 @@ sub copyFile { print "Creating file '$dst'\n" if $opt_d; open(my $SRC, '<', $src) and open(my $DST, '>', $dst) - or croak "$! copying $src to $dst\n"; + or die "$! copying $src to $dst\n"; while (<$SRC>) { # Substitute any @VARS@ in the text s{@(\w+?)@} diff --git a/src/tools/EPICS/Release.pm b/src/tools/EPICS/Release.pm index 98f18514b..9ae6610c3 100644 --- a/src/tools/EPICS/Release.pm +++ b/src/tools/EPICS/Release.pm @@ -5,8 +5,6 @@ # in file LICENSE that is included with this distribution. #************************************************************************* -use Carp; - # # Parse all relevent configure/RELEASE* files and includes # @@ -51,7 +49,7 @@ sub readRelease { "discovered in $file\n"; } - open(my $IN, '<', $file) or croak "Can't open $file: $!\n"; + open(my $IN, '<', $file) or die "Can't open $file: $!\n"; $Ractive->{$file}++; while (<$IN>) { chomp; @@ -79,7 +77,7 @@ sub readRelease { if (-e $path) { &readRelease($path, $Rmacros, $Rapps, $Ractive); } elsif ($op eq "include") { - carp "EPICS/Release.pm: Include file '$path' not found\n"; + warn "EPICS/Release.pm: Include file '$path' not found\n"; } } $Ractive->{$file}--; @@ -109,9 +107,9 @@ sub expandRelease { while (my ($macro, $val) = each %$Rmacros) { while (my ($pre,$var,$post) = $val =~ m/ (.*) \$\( (\w+) \) (.*) /x) { - carp "EPICS/Release.pm: Undefined macro \$($var) used\n" + warn "EPICS/Release.pm: Undefined macro \$($var) used\n" unless exists $Rmacros->{$var}; - croak "EPICS/Release.pm: Circular definition of macro $macro\n" + die "EPICS/Release.pm: Circular definition of macro $macro\n" if $macro eq $var; $val = $pre . $Rmacros->{$var} . $post; $Rmacros->{$macro} = $val; From 729e6fda4da38d2b9a5dfa46b80a0dd202df0fc1 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 19 Jan 2018 13:14:13 -0600 Subject: [PATCH 02/12] tools: Add some context to the 'Undefined macro' warning Mark Rivers saw this warning when he forgot to configure and build a dependent module properly. The additional information given by this change would have helped him track down the problem faster. --- src/tools/EPICS/Release.pm | 9 +++++---- src/tools/convertRelease.pl | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tools/EPICS/Release.pm b/src/tools/EPICS/Release.pm index 9ae6610c3..6ae0dbd9a 100644 --- a/src/tools/EPICS/Release.pm +++ b/src/tools/EPICS/Release.pm @@ -99,17 +99,18 @@ sub expandMacros { } # -# Expand all (possibly nested) macros in dictionary +# Expand all (possibly nested) macros in a dictionary # sub expandRelease { - my ($Rmacros) = @_; + my ($Rmacros, $warn) = @_; # $Rmacros is a reference to a hash + $warn = '' unless defined $warn; while (my ($macro, $val) = each %$Rmacros) { while (my ($pre,$var,$post) = $val =~ m/ (.*) \$\( (\w+) \) (.*) /x) { - warn "EPICS/Release.pm: Undefined macro \$($var) used\n" + warn "EPICS/Release.pm: Undefined macro \$($var) used $warn\n" unless exists $Rmacros->{$var}; - die "EPICS/Release.pm: Circular definition of macro $macro\n" + die "EPICS/Release.pm: Circular definition of macro $var $warn\n" if $macro eq $var; $val = $pre . $Rmacros->{$var} . $post; $Rmacros->{$macro} = $val; diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl index e3fc2644a..d1a054e87 100644 --- a/src/tools/convertRelease.pl +++ b/src/tools/convertRelease.pl @@ -220,7 +220,7 @@ sub checkRelease { my @order = (); my $relfile = "$path/configure/RELEASE"; readReleaseFiles($relfile, \%check, \@order, $arch); - expandRelease(\%check); + expandRelease(\%check, "while checking module\n\t$app = $path"); delete $check{TOP}; delete $check{EPICS_HOST_ARCH}; From ddbdcf94628d7cac5bdef0f18f03c0255bcb1341 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sun, 21 Jan 2018 00:44:10 -0600 Subject: [PATCH 03/12] rec/test: Add missing filename to DBDDEPENDS_FILES --- src/std/rec/test/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/std/rec/test/Makefile b/src/std/rec/test/Makefile index 8084b38b5..5322c8e92 100644 --- a/src/std/rec/test/Makefile +++ b/src/std/rec/test/Makefile @@ -38,6 +38,7 @@ TESTFILES += $(COMMON_DIR)/analogMonitorTest.dbd ../analogMonitorTest.db TESTS += analogMonitorTest TARGETS += $(COMMON_DIR)/regressTest.dbd +DBDDEPENDS_FILES += regressTest.dbd$(DEP) regressTest_DBD += base.dbd TESTPROD_HOST += regressTest regressTest_SRCS += regressTest.c From 1454f42a2737fd476531a1476653f16ffcf7bb9f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 1 Feb 2018 11:19:08 -0600 Subject: [PATCH 04/12] Config fix for parallel builds with MSVC 2015 and later From Mark Rivers and Freddie Akeroyd. --- configure/os/CONFIG.win32-x86.win32-x86 | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86 index 863841923..f5b21cc2e 100644 --- a/configure/os/CONFIG.win32-x86.win32-x86 +++ b/configure/os/CONFIG.win32-x86.win32-x86 @@ -142,6 +142,17 @@ STATIC_LDLIBS_NO= STATIC_LDFLAGS= RANLIB= +# +# option needed for parallel builds with Visual Studio 2015 onward +# +# -FS Force Synchronous PDB Writes +ifneq ($(VisualStudioVersion),) + OPT_CXXFLAGS_NO += -FS + OPT_CFLAGS_NO += -FS +endif + + +# # add -profile here to run the ms profiler # -LTCG whole program optimization # -incremental:no full linking From 734d16291fec37b5517cf15fd134cce0f5c9a4ef Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 1 Feb 2018 09:42:51 -0800 Subject: [PATCH 05/12] rsrv: buffer for IP too small An IPv4 address and port number has 21 characters max. --- src/rsrv/online_notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rsrv/online_notify.c b/src/rsrv/online_notify.c index 883951dce..b7249870f 100644 --- a/src/rsrv/online_notify.c +++ b/src/rsrv/online_notify.c @@ -72,7 +72,7 @@ void rsrv_online_notify_task(void *pParm) char * pStr; int autoBeaconAddr; ELLLIST autoAddrList; - char buf[16]; + char buf[22]; unsigned priorityOfUDP; epicsThreadBooleanStatus tbs; epicsThreadId tid; From 713c2d5080102daa12bea10e27edfb4a373e4d5e Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 2 Feb 2018 17:47:35 -0600 Subject: [PATCH 06/12] Fix for lp: #1747091 generalTimeGetEvent() --- src/libCom/osi/epicsGeneralTime.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libCom/osi/epicsGeneralTime.c b/src/libCom/osi/epicsGeneralTime.c index 98c5566f7..c3dcc7646 100644 --- a/src/libCom/osi/epicsGeneralTime.c +++ b/src/libCom/osi/epicsGeneralTime.c @@ -269,7 +269,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, } } } else { - if (epicsTimeGreaterThanEqual(pDest, + if (epicsTimeGreaterThanEqual(&ts, >Pvt.eventTime[eventNumber])) { *pDest = ts; gtPvt.eventTime[eventNumber] = ts; @@ -279,7 +279,6 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, key = epicsInterruptLock(); gtPvt.ErrorCounts++; epicsInterruptUnlock(key); - } IFDEBUG(10) { char last[40], buff[40]; @@ -291,6 +290,7 @@ static int generalTimeGetEventPriority(epicsTimeStamp *pDest, int eventNumber, " %s, using %s instead\n", ptp->name, buff, last); } + } } break; } From de442e9584d9214533e5e90af4270e34fd45d947 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 5 Feb 2018 12:02:13 -0600 Subject: [PATCH 07/12] Fix for LP: #1743076 Never zero the CA client context private ID. --- src/ca/access.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/ca/access.cpp b/src/ca/access.cpp index 74f74325a..e701c5b00 100644 --- a/src/ca/access.cpp +++ b/src/ca/access.cpp @@ -127,21 +127,10 @@ const char * ca_message_text [] static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT; -extern "C" void ca_client_exit_handler (void *) -{ - if ( caClientContextId ) { - epicsThreadPrivateDelete ( caClientContextId ); - caClientContextId = 0; - } -} - // runs once only for each process extern "C" void ca_init_client_context ( void * ) { caClientContextId = epicsThreadPrivateCreate (); - if ( caClientContextId ) { - epicsAtExit ( ca_client_exit_handler,0 ); - } } /* From ac4d5c95ac37931cf80f6764544cbf98b0b73928 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 9 Feb 2018 10:56:52 -0600 Subject: [PATCH 08/12] Clean up some compiler warnings from clang --- src/db/dbBkpt.c | 2 +- src/db/dbLock.c | 6 +++--- src/misc/epicsRelease.c | 2 -- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/db/dbBkpt.c b/src/db/dbBkpt.c index 790cfae77..df4ee7de2 100644 --- a/src/db/dbBkpt.c +++ b/src/db/dbBkpt.c @@ -409,7 +409,7 @@ long epicsShareAPI dbd(const char *record_name) precord = addr.precord; - if (! precord->bkpt & BKPT_ON_MASK) { + if (!(precord->bkpt & BKPT_ON_MASK)) { printf(" BKPT> No breakpoint set in this record\n"); return(S_db_bkptNotSet); } diff --git a/src/db/dbLock.c b/src/db/dbLock.c index e1cea1581..2afa93c1f 100644 --- a/src/db/dbLock.c +++ b/src/db/dbLock.c @@ -525,10 +525,10 @@ long epicsShareAPI dblsr(char *recordname,int level) printf(" Not Locked\n"); } else { printf(" thread %p",plockSet->thread_id); - if(! plockSet->precord || !plockSet->precord->name) - printf(" NULL record or record name\n"); + if(! plockSet->precord) + printf(" NULL record\n"); else - printf(" record %s\n",plockSet->precord->name); + printf(" record %s\n",plockSet->precord->name); } if(level==0) { if(recordname) break; continue; } for(plockRecord = (lockRecord *)ellFirst(&plockSet->lockRecordList); diff --git a/src/misc/epicsRelease.c b/src/misc/epicsRelease.c index 6e2343e23..d32f8c322 100644 --- a/src/misc/epicsRelease.c +++ b/src/misc/epicsRelease.c @@ -16,8 +16,6 @@ #define epicsExportSharedSymbols #include "epicsRelease.h" -static const char id[] = "@(#) " EPICS_VERSION_STRING ", Misc. Utilities Library" __DATE__; - epicsShareFunc int epicsShareAPI coreRelease(void) { printf ( "############################################################################\n" ); From 550beeab9f9c4864f244a367092d4a11c044d0a7 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 9 Feb 2018 11:29:16 -0600 Subject: [PATCH 09/12] More clang warning clean-ups The short => int change is a UB issue, the second argument to va_start() must be of a type that does not undergo promotion. See https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP58-CPP.+Pass+an+object+of+the+correct+type+to+va_start --- src/ioc/db/dbUnitTest.c | 6 +++--- src/ioc/db/dbUnitTest.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ioc/db/dbUnitTest.c b/src/ioc/db/dbUnitTest.c index 9e3f7d6d0..249fb6032 100644 --- a/src/ioc/db/dbUnitTest.c +++ b/src/ioc/db/dbUnitTest.c @@ -111,7 +111,7 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap) return dbPutField(&addr, dbrType, pod.bytes, 1); } -void testdbPutFieldOk(const char* pv, short dbrType, ...) +void testdbPutFieldOk(const char* pv, int dbrType, ...) { long ret; va_list ap; @@ -123,7 +123,7 @@ void testdbPutFieldOk(const char* pv, short dbrType, ...) testOk(ret==0, "dbPutField(%s, %d, ...) == %ld", pv, dbrType, ret); } -void testdbPutFieldFail(long status, const char* pv, short dbrType, ...) +void testdbPutFieldFail(long status, const char* pv, int dbrType, ...) { long ret; va_list ap; @@ -138,7 +138,7 @@ void testdbPutFieldFail(long status, const char* pv, short dbrType, ...) testFail("dbPutField(\"%s\", %d, ...) != %ld (%ld)", pv, dbrType, status, ret); } -void testdbGetFieldEqual(const char* pv, short dbrType, ...) +void testdbGetFieldEqual(const char* pv, int dbrType, ...) { va_list ap; diff --git a/src/ioc/db/dbUnitTest.h b/src/ioc/db/dbUnitTest.h index 0c78500d5..e1d04e1df 100644 --- a/src/ioc/db/dbUnitTest.h +++ b/src/ioc/db/dbUnitTest.h @@ -46,13 +46,13 @@ epicsShareFunc void testdbCleanup(void); * testdbPutFieldOk("pvname", DBF_FLOAT, (double)4.1); * testdbPutFieldOk("pvname", DBF_STRING, "hello world"); */ -epicsShareFunc void testdbPutFieldOk(const char* pv, short dbrType, ...); +epicsShareFunc void testdbPutFieldOk(const char* pv, int dbrType, ...); /* Tests for put failure */ -epicsShareFunc void testdbPutFieldFail(long status, const char* pv, short dbrType, ...); +epicsShareFunc void testdbPutFieldFail(long status, const char* pv, int dbrType, ...); epicsShareFunc long testdbVPutField(const char* pv, short dbrType, va_list ap); -epicsShareFunc void testdbGetFieldEqual(const char* pv, short dbrType, ...); +epicsShareFunc void testdbGetFieldEqual(const char* pv, int dbrType, ...); epicsShareFunc void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap); /** From ae548d3400da22d0782b24be224edfa256a905bb Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 24 Feb 2018 17:40:45 -0600 Subject: [PATCH 10/12] Remove cantProceed() from dbGetLink() and dbPutLink() Fixes LP: #1528314 Affects 3.15 branch only. --- src/ioc/db/dbLink.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ioc/db/dbLink.c b/src/ioc/db/dbLink.c index 423a51ec5..e93daa312 100644 --- a/src/ioc/db/dbLink.c +++ b/src/ioc/db/dbLink.c @@ -651,7 +651,7 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer, inherit_severity(&plink->value.pv_link, precord, stat, sevr); break; default: - cantProceed("dbGetLinkValue: Illegal link type %d\n", plink->type); + printf("dbGetLinkValue: Illegal link type %d\n", plink->type); status = -1; } if (status) { @@ -755,7 +755,7 @@ long dbPutLink(struct link *plink, short dbrType, const void *pbuffer, status = dbCaPutLink(plink, dbrType, pbuffer, nRequest); break; default: - cantProceed("dbPutLinkValue: Illegal link type %d\n", plink->type); + printf("dbPutLinkValue: Illegal link type %d\n", plink->type); status = -1; } if (status) { @@ -836,4 +836,3 @@ long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len) return dbPutLink(plink, DBR_STRING, pbuffer, 1); } - From e41f8bf518fa4d1730ce6620b495e9328defbabf Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 24 Feb 2018 19:11:54 -0600 Subject: [PATCH 11/12] Translate and escape chars in info tag strings Fixes LP: #1716998 --- src/ioc/dbStatic/dbLexRoutines.c | 1 + src/ioc/dbStatic/dbStaticLib.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ioc/dbStatic/dbLexRoutines.c b/src/ioc/dbStatic/dbLexRoutines.c index 6654fdfbb..f36ace933 100644 --- a/src/ioc/dbStatic/dbLexRoutines.c +++ b/src/ioc/dbStatic/dbLexRoutines.c @@ -1069,6 +1069,7 @@ static void dbRecordInfo(char *name, char *value) if(duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; + dbTranslateEscape(value, value); /* yuck: in-place, but safe */ status = dbPutInfo(pdbentry,name,value); if(status) { epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n", diff --git a/src/ioc/dbStatic/dbStaticLib.c b/src/ioc/dbStatic/dbStaticLib.c index dc2fbe62f..96868eded 100644 --- a/src/ioc/dbStatic/dbStaticLib.c +++ b/src/ioc/dbStatic/dbStaticLib.c @@ -851,10 +851,14 @@ long dbWriteRecordFP( status=dbNextField(pdbentry,dctonly); } status = dbFirstInfo(pdbentry); - while(!status) { - fprintf(fp,"\tinfo(\"%s\",\"%s\")\n", - dbGetInfoName(pdbentry), dbGetInfoString(pdbentry)); - status=dbNextInfo(pdbentry); + while (!status) { + const char *pinfostr = dbGetInfoString(pdbentry); + + fprintf(fp, "\tinfo(\"%s\",\"", + dbGetInfoName(pdbentry)); + epicsStrPrintEscaped(fp, pinfostr, strlen(pinfostr)); + fprintf(fp, "\")\n"); + status = dbNextInfo(pdbentry); } fprintf(fp,"}\n"); status = dbNextRecord(pdbentry); From c18b6f2ccf381b89d21497f99fad5b913e522e72 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Sat, 24 Feb 2018 20:15:08 -0600 Subject: [PATCH 12/12] Deny use of dbgf, dbpf, dbtr, dbtgf and dbtpf before iocInit Can't use locking dbAccess routines until lock-sets have been calculated. Fixes LP: #1725248 --- src/ioc/db/dbTest.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/ioc/db/dbTest.c b/src/ioc/db/dbTest.c index 97279de08..637f8277d 100644 --- a/src/ioc/db/dbTest.c +++ b/src/ioc/db/dbTest.c @@ -308,6 +308,11 @@ long dbgf(const char *pname) if (nameToAddr(pname, &addr)) return -1; + if (addr.precord->lset == NULL) { + printf("dbgf only works after iocInit\n"); + return -1; + } + no_elements = MIN(addr.no_elements, sizeof(buffer)/addr.field_size); if (addr.dbr_field_type == DBR_ENUM) { long status = dbGetField(&addr, DBR_STRING, pbuffer, @@ -344,6 +349,11 @@ long dbpf(const char *pname,const char *pvalue) if (nameToAddr(pname, &addr)) return -1; + if (addr.precord->lset == NULL) { + printf("dbpf only works after iocInit\n"); + return -1; + } + if (addr.no_elements > 1 && (addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) { dbrType = addr.dbr_field_type; @@ -398,6 +408,11 @@ long dbtr(const char *pname) if (nameToAddr(pname, &addr)) return -1; + if (addr.precord->lset == NULL) { + printf("dbtr only works after iocInit\n"); + return -1; + } + precord = (struct dbCommon*)addr.precord; if (precord->pact) { printf("record active\n"); @@ -437,6 +452,11 @@ long dbtgf(const char *pname) if (nameToAddr(pname, &addr)) return -1; + if (addr.precord->lset == NULL) { + printf("dbtgf only works after iocInit\n"); + return -1; + } + /* try all options first */ req_options = 0xffffffff; ret_options = req_options; @@ -534,6 +554,11 @@ long dbtpf(const char *pname, const char *pvalue) if (nameToAddr(pname, &addr)) return -1; + if (addr.precord->lset == NULL) { + printf("dbtpf only works after iocInit\n"); + return -1; + } + val_long = strtol(pvalue, &pend, 10); validLong = (*pend == 0); @@ -797,7 +822,7 @@ static void printBuffer( printf("no_strs = %u:\n", pdbr_enumStrs->no_str); - for (i = 0; i < pdbr_enumStrs->no_str; i++) + for (i = 0; i < pdbr_enumStrs->no_str; i++) printf("\t\"%s\"\n", pdbr_enumStrs->strs[i]); } else {