Hard-working priests of the god IBM,
Here is my news:
I had a very hard look at the diff between the 2 commits that John so
diligently found by bisecting
the non-working one has basically only one addition:
Jeff Eppler did this (the commit message):
----------------------------
defer formatting of realtime motion messages to userspace
this enables userspace to provide translations of messages printed by
motion, and in the future will allow floating-point values to be
included in these messages.
----------------------------
and in the process he made a shared memory area to catch the messages from
realtime, so you can read them from the user interface.
So I have the itch that we are not going to find the issue by gdb etc. but
only by getting learned on the issue of
1. rtai interfaces
2. rt_preempt interfaces
and how to go from the one to the other.
I can see where John fixed the original patch to accommodate the changes by
Jeff, but I have not been able to identify the trouble spot / area /
thinking. Mainly because my dull brain.
So unless you guys have a good reason to convince me otherwise I will
continue on this road of figuring out how the changing over process aught
to work.
I have added the diff for the interested parties.
j.
On Sat, Apr 28, 2012 at 10:45 PM, Charles Steinkuehler <
char...@steinkuehler.net> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 4/28/2012 1:53 PM, John Morris wrote:
> <snip>
> > From the debugging side, neither of my tacks have gotten very far.
> > I've never done anything terribly difficult with C, gdb or
> > assembly before, so I've been reading docs at every step.
>
>
> I'm in the same boat, I typically don't code on linux and dubug with
> gdb. Normally, I'm writing VHDL (for Altera FPGAs) and debugging via
> a few blinking LEDs (and by staring at the code for a long time! :).
>
> > The two tacks:
> >
> > - Use the debugger to understand why test_and_set_bit returns 0. I
> > don't know what the 'tsbbl' instruction is, and haven't figured
> > out how to examine memory yet.
> >
> > - Find some way to log function calls and argument values as the
> > execution progresses. I hope to (dis)confirm that the pre-problem
> > and problem versions are taking the same path up to the point
> > where the problem version starts spinning. Stepping through with
> > gdb is, of course, too painful. I read that valgrind might be
> > able to help with this, but it doesn't seem to be a common usage.
> > Charles, have you heard of using valgrind for that purpose?
> >
>
>
> I wasn't able to get anywhere easily with gdb, so I switched to the
> GUI front-end program nemiver. It's been pretty easy to use so-far,
> but I'm sure I'm missing out on some of what gdb is capable of. It is
> reasonably easy to monitor memory and the call stack (at least most of
> the time...I've had times where the call stack appears empty even
> though there should be something there).
>
> As for valgrind, the on-line manual (not the man page) indicates a few
> tests geared at multi-threaded code to find potential race conditions
> and deadlocks. I haven't tried running any of these yet, as it
> appears to assume you are using the available library mutex functions
> while the linuxcnc code in question is running with custom locking
> functions (which you can 'teach' valgrind about, but that is beyond my
> current skill level).
>
> Also, I doubt there is a serious problem with the locking code, as it
> is the same code that is used successfully without the linux-rtapi
> patch. Instead, it seems like there is some form of memory corruption
> happening, which is why I pulled out valgrind to begin with (or at
> least that's what googling "crash in malloc" leads me to believe). I
> suspect the change in how message strings are being handled has caused
> some portion of memory to get corrupted or overwritten, but I still
> don't understand the code well enough to start figuring out exactly
> what's going wrong. I think I need to step back and start looking at
> the program flow instead of the diffs between versions, and see when
> anything related to messaging might be running and causing a problem.
>
> - --
> Charles Steinkuehler
> char...@steinkuehler.net
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.11 (MingW32)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
>
> iEYEARECAAYFAk+cVtAACgkQLywbqEHdNFxhbwCgpVT0jUjE0Ze5wum2Tr88gMI/
> 6KYAn04mouf8z4tiJtwTWdRLdp8s89js
> =EJZ0
> -----END PGP SIGNATURE-----
>
>
> ------------------------------------------------------------------------------
> Live Security Virtual Conference
> Exclusive live event will cover all the ways today's security and
> threat landscape has changed and how IT managers can respond. Discussions
> will include endpoint security, mobile security and the latest in malware
> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
> _______________________________________________
> Emc-developers mailing list
> Emc-developers@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/emc-developers
>
Author: Jeff Epler <jep...@unpythonic.net> 2009-08-11 17:43:28
Committer: Jeff Epler <jep...@unpythonic.net> 2010-02-24 16:24:14
Parent: 3c2a3cadca404a765403c3b31ce00465905bb219 (fix 'make install' and
deb-building error introduced in 80cc6b)
Child: 4bc762a2df3c1774c8f5b466dd3584db93284509 (mark most strings in the
motion controller)
Branches: master, remotes/origin/asciidoc-latexmath,
remotes/origin/iotask_remove, remotes/origin/joints_axes3,
remotes/origin/master, remotes/origin/multiturn-arcs,
remotes/origin/multiturn-arcs-v2.5, remotes/origin/pncconf,
remotes/origin/segmentqueue, remotes/origin/separate-g92, remotes/origin/sivar,
remotes/origin/touchy-macro, remotes/origin/v2.5_branch
Follows: v2.4.0-pre1, v2.5.0-pre0
Precedes: v2.5.0-pre1
defer formatting of realtime motion messages to userspace
this enables userspace to provide translations of messages printed by
motion, and in the future will allow floating-point values to be
included in these messages.
--------------------------------- src/Makefile ---------------------------------
index 1ac0f2f..33f8580 100644
@@ -741,6 +741,8 @@ motmod-objs += emc/motion/control.o
motmod-objs += emc/motion/homing.o
motmod-objs += emc/motion/emcmotglb.o
motmod-objs += emc/motion/emcmotutil.o
+motmod-objs += emc/motion/stashf.o
+motmod-objs += emc/motion/dbuf.o
motmod-objs += libnml/posemath/_posemath.o
motmod-objs += libnml/posemath/sincos.o $(MATHSTUB)
---------------------------- src/emc/motion/dbuf.c ----------------------------
new file mode 100644
index 0000000..a91c10e
@@ -0,0 +1,195 @@
+// This is a component of emc
+// Copyright © 2009 Jeff Epler
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#ifdef RTAPI
+#else
+#include <stdlib.h>
+#endif
+#include "rtapi_string.h"
+#include "rtapi_errno.h"
+#include "dbuf.h"
+
+typedef struct dbuf dbuf;
+typedef struct dbuf_iter dbuf_iter;
+
+#ifndef RTAPI
+dbuf *dbuf_new(unsigned sz) {
+ dbuf *d = malloc(sizeof(dbuf) + sz);
+ if(d) dbuf_init(d, (unsigned char*)(d+1), sz);
+ return d;
+}
+void dbuf_delete(dbuf *d) {
+ if(d) free(d);
+}
+#endif
+
+void dbuf_init(dbuf *d, unsigned char *data, unsigned sz) {
+ if(!d) return;
+ d->data = data;
+ d->sz = sz;
+ memset(data, 0, sz);
+}
+
+#ifndef RTAPI
+dbuf_iter *dbuf_iter_new(dbuf *d) {
+ dbuf_iter *di = malloc(sizeof(dbuf_iter));
+ if(di) dbuf_iter_init(di, d);
+ return di;
+}
+
+void dbuf_iter_delete(dbuf_iter *di) {
+ if(di) free(di);
+}
+#endif
+
+
+void dbuf_iter_init(dbuf_iter *di, dbuf *d) {
+ if(!di) return;
+ di->base = d;
+ di->offset = 0;
+}
+
+int dbuf_put_byte(dbuf_iter *di, unsigned char data) {
+ dbuf *d;
+
+ if(!di) return -EINVAL;
+ d = di->base;
+
+ if(!d) return -EINVAL;
+
+ if(di->offset == d->sz) return -ENOSPC;
+ d->data[di->offset++] = data;
+
+ return 0;
+}
+
+int dbuf_put_bytes(dbuf_iter *di, const unsigned char *data, unsigned sz) {
+ dbuf *d;
+ unsigned char *p;
+
+ if(!di) return -EINVAL;
+
+ d = di->base;
+ if(!d) return -EINVAL;
+
+ if(d->sz - di->offset < sz) return -ENOSPC;
+
+ p = d->data + di->offset;
+ di->offset += sz;
+
+ for(; sz; sz--) {
+ *p++ = *data++;
+ }
+ return sz;
+}
+
+int dbuf_put_int(dbuf_iter *di, int i) {
+ return dbuf_put_bytes(di, (unsigned char *)&i, sizeof(int));
+}
+
+int dbuf_put_long(dbuf_iter *di, long i) {
+ return dbuf_put_bytes(di, (unsigned char *)&i, sizeof(long));
+}
+
+int dbuf_put_float(dbuf_iter *di, float i) {
+ return dbuf_put_bytes(di, (unsigned char *)&i, sizeof(float));
+}
+
+int dbuf_put_double(dbuf_iter *di, double i) {
+ return dbuf_put_bytes(di, (unsigned char *)&i, sizeof(double));
+}
+
+int dbuf_put_string(dbuf_iter *di, const char *s) {
+ return dbuf_put_bytes(di, (unsigned char *)s, strlen(s)+1);
+}
+
+int dbuf_get_byte(dbuf_iter *di, unsigned char *b) {
+ dbuf *d;
+
+ if(!di) return -EINVAL;
+ d = di->base;
+
+ if(!d) return -EINVAL;
+
+ if(di->offset == d->sz) return -ENODATA;
+
+ *b = d->data[di->offset++];
+ return 0;
+}
+
+int dbuf_get_bytes(dbuf_iter *di, unsigned char *data, unsigned sz) {
+ dbuf *d;
+ unsigned char *p;
+
+ if(!di) return -EINVAL;
+
+ d = di->base;
+ if(!d) return -EINVAL;
+
+ if(d->sz - di->offset < sz) return -ENODATA;
+ p = d->data + di->offset;
+ di->offset += sz;
+ for(; sz; sz--) {
+ *data++ = *p++;
+ }
+ return sz;
+}
+
+int dbuf_get_int(dbuf_iter *di, int *i) {
+ return dbuf_get_bytes(di, (unsigned char *)i, sizeof(int));
+}
+
+int dbuf_get_long(dbuf_iter *di, long *i) {
+ return dbuf_get_bytes(di, (unsigned char *)i, sizeof(long));
+}
+
+int dbuf_get_float(dbuf_iter *di, float *i) {
+ return dbuf_get_bytes(di, (unsigned char *)i, sizeof(float));
+}
+
+int dbuf_get_double(dbuf_iter *di, double *i) {
+ return dbuf_get_bytes(di, (unsigned char *)i, sizeof(double));
+}
+
+int dbuf_get_string(dbuf_iter *di, const char **s) {
+ dbuf *d;
+ unsigned char *p, ch;
+ int result;
+
+ if(!di) return -EINVAL;
+
+ d = di->base;
+ if(!d) return -EINVAL;
+
+ if(d->sz == di->offset) return -ENODATA;
+ p = d->data + di->offset;
+ *s = (char*)p;
+
+ do {
+ result = dbuf_get_byte(di, &ch);
+ } while(result >= 0 && ch != 0);
+
+ // dbuf_put_string should never put when there's no room for the trailing
+ // NUL, but let's be safe and not return a string if there's no terminated
+ // string in the dbuf
+ if(ch != 0) {
+ *s = 0;
+ return -ENODATA;
+ }
+
+ return 0;
+}
---------------------------- src/emc/motion/dbuf.h ----------------------------
new file mode 100644
index 0000000..c280d8e
@@ -0,0 +1,63 @@
+// This is a component of emc
+// Copyright © 2009 Jeff Epler
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#ifndef DBUF_H
+#define DBUF_H
+#include "rtapi_string.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dbuf {
+ size_t sz;
+ unsigned char *data;
+};
+
+struct dbuf_iter {
+ struct dbuf *base;
+ size_t offset;
+};
+
+struct dbuf *dbuf_new(unsigned sz);
+void dbuf_delete(struct dbuf *d);
+void dbuf_init(struct dbuf *d, unsigned char *data, unsigned sz);
+
+struct dbuf_iter *dbuf_iter_new(struct dbuf *d);
+void dbuf_iter_delete(struct dbuf_iter *di);
+void dbuf_iter_init(struct dbuf_iter *di, struct dbuf *d);
+
+int dbuf_put_byte(struct dbuf_iter *di, unsigned char data);
+int dbuf_put_bytes(struct dbuf_iter *di, const unsigned char *data, unsigned
sz);
+int dbuf_put_int(struct dbuf_iter *di, int i);
+int dbuf_put_long(struct dbuf_iter *di, long i);
+int dbuf_put_float(struct dbuf_iter *di, float i);
+int dbuf_put_double(struct dbuf_iter *di, double i);
+int dbuf_put_string(struct dbuf_iter *di, const char *s);
+
+int dbuf_get_byte(struct dbuf_iter *di, unsigned char *b);
+int dbuf_get_bytes(struct dbuf_iter *di, unsigned char *data, unsigned sz);
+int dbuf_get_int(struct dbuf_iter *di, int *i);
+int dbuf_get_long(struct dbuf_iter *di, long *i);
+int dbuf_get_float(struct dbuf_iter *di, float *i);
+int dbuf_get_double(struct dbuf_iter *di, double *i);
+int dbuf_get_string(struct dbuf_iter *di, const char **s);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
-------------------------- src/emc/motion/emcmotcfg.h --------------------------
index ca2bb2f..c762119 100644
@@ -32,7 +32,7 @@
#define EMCMOT_MAX_AIO 16
#define EMCMOT_ERROR_NUM 32 /* how many errors we can queue */
-#define EMCMOT_ERROR_LEN 256 /* how long error string can be */
+#define EMCMOT_ERROR_LEN 1024 /* how long error string can be */
/*
Shared memory keys for simulated motion process. No base address
------------------------- src/emc/motion/emcmotutil.c -------------------------
index 9f5d76e..7dfd360 100644
@@ -15,6 +15,8 @@
#include "emcmotcfg.h" /* EMCMOT_ERROR_NUM,LEN */
#include "motion.h" /* these decls */
+#include "dbuf.h"
+#include "stashf.h"
int emcmotErrorInit(emcmot_error_t * errlog)
{
@@ -31,11 +33,10 @@ int emcmotErrorInit(emcmot_error_t * errlog)
return 0;
}
-int emcmotErrorPut(emcmot_error_t * errlog, const char *error)
+int emcmotErrorPutfv(emcmot_error_t * errlog, const char *fmt, va_list ap)
{
- char *p1;
- const char *p2;
- int i;
+ struct dbuf errbuf;
+ struct dbuf_iter it;
if (errlog == 0 || errlog->num == EMCMOT_ERROR_NUM) {
/* full */
@@ -44,18 +45,9 @@ int emcmotErrorPut(emcmot_error_t * errlog, const char
*error)
errlog->head++;
- // strncpy(errlog->error[errlog->end], error, EMCMOT_ERROR_LEN);
- // replaced strncpy with manual copy
- p1 = errlog->error[errlog->end];
- p2 = error;
- i = 0;
- while (*p2 && i < EMCMOT_ERROR_LEN) {
- *p1 = *p2;
- p1++;
- p2++;
- i++;
- }
- *p1 = 0;
+ dbuf_init(&errbuf, (unsigned char*)errlog->error[errlog->end],
EMCMOT_ERROR_LEN);
+ dbuf_iter_init(&it, &errbuf);
+ vstashf(&it, fmt, ap);
errlog->end = (errlog->end + 1) % EMCMOT_ERROR_NUM;
errlog->num++;
@@ -65,34 +57,32 @@ int emcmotErrorPut(emcmot_error_t * errlog, const char
*error)
return 0;
}
+int emcmotErrorPutf(emcmot_error_t *errlog, const char *fmt, ...)
+{
+ int result;
+ va_list ap;
+ va_start(ap, fmt);
+ result = emcmotErrorPutfv(errlog, fmt, ap);
+ va_end(ap);
+ return result;
+}
+
+int emcmotErrorPut(emcmot_error_t *errlog, const char *error)
+{
+ return emcmotErrorPutf(errlog, "%s", error);
+}
+
int emcmotErrorGet(emcmot_error_t * errlog, char *error)
{
- char *p1;
- const char *p2;
- int i;
if (errlog == 0 || errlog->num == 0) {
/* empty */
return -1;
}
errlog->head++;
-
- // strncpy(error, errlog->error[errlog->start], EMCMOT_ERROR_LEN);
- // replaced strncpy with manual copy
- p1 = error;
- p2 = errlog->error[errlog->start];
- i = 0;
- while (*p2 && i < EMCMOT_ERROR_LEN) {
- *p1 = *p2;
- p1++;
- p2++;
- i++;
- }
- *p1 = 0;
-
+ memcpy(error, errlog->error[errlog->start], EMCMOT_ERROR_LEN);
errlog->start = (errlog->start + 1) % EMCMOT_ERROR_NUM;
errlog->num--;
-
errlog->tail = errlog->head;
return 0;
--------------------------- src/emc/motion/motion.c ---------------------------
index 963c960..d0d6ff9 100644
@@ -149,23 +149,23 @@ extern int vsnprintf(char *, size_t size, const char
*format, va_list ap);
void reportError(const char *fmt, ...)
{
va_list args;
- char error[EMCMOT_ERROR_LEN + 2];
va_start(args, fmt);
- /* Don't use the rtapi_snprintf... */
- vsnprintf(error, EMCMOT_ERROR_LEN, fmt, args);
+ emcmotErrorPutfv(emcmotError, fmt, args);
va_end(args);
-/*! \todo FIXME - eventually should print _only_ to the RCS buffer, I think */
-/* print to the kernel buffer... */
- rtapi_print("%d: ERROR: %s\n", emcmotStatus->heartbeat, error);
-/* print to the RCS buffer... */
- emcmotErrorPut(emcmotError, error);
}
+#ifndef va_copy
+#define va_copy(dest, src) ((dest)=(src))
+#endif
+
rtapi_msg_handler_t old_handler = NULL;
-static void emc_message_handler(msg_level_t level, const char *message) {
- if(level == RTAPI_MSG_ERR) emcmotErrorPut(emcmotError, message);
- if(old_handler) old_handler(level, message);
+static void emc_message_handler(msg_level_t level, const char *fmt, va_list ap)
+{
+ va_list apc;
+ va_copy(apc, ap);
+ if(level == RTAPI_MSG_ERR) emcmotErrorPutfv(emcmotError, fmt, apc);
+ if(old_handler) old_handler(level, fmt, ap);
}
int rtapi_app_main(void)
--------------------------- src/emc/motion/motion.h ---------------------------
index 17bea4a..6645b65 100644
@@ -78,6 +78,7 @@ to another.
#include "cubic.h" /* CUBIC_STRUCT, CUBIC_COEFF */
#include "emcmotcfg.h" /* EMCMOT_MAX_JOINTS */
#include "kinematics.h"
+#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
@@ -742,6 +743,8 @@ Suggestion: Split this in to an Error and a Status flag
register..
/* error ring buffer access functions */
extern int emcmotErrorInit(emcmot_error_t * errlog);
extern int emcmotErrorPut(emcmot_error_t * errlog, const char *error);
+ extern int emcmotErrorPutfv(emcmot_error_t * errlog, const char *fmt,
va_list ap);
+ extern int emcmotErrorPutf(emcmot_error_t * errlog, const char *fmt, ...);
extern int emcmotErrorGet(emcmot_error_t * errlog, char *error);
#ifdef __cplusplus
--------------------------- src/emc/motion/stashf.c ---------------------------
new file mode 100644
index 0000000..dc64617
@@ -0,0 +1,133 @@
+// This is a component of emc
+// Copyright © 2009 Jeff Epler
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#include "stashf.h"
+#include "dbuf.h"
+#include "rtapi_errno.h"
+#include "rtapi_string.h"
+#include <stdarg.h>
+
+#ifdef RTAPI
+#include <linux/kernel.h>
+#define gettext(s) s
+#define alloca __builtin_alloca
+#else
+#include <stdio.h>
+#include <libintl.h>
+#include <alloca.h>
+#endif
+
+static int SET_ERRNO(int value) {
+#ifdef RTAPI
+ return value;
+#else
+ if(value < 0) {
+ errno = value;
+ return -1;
+ } else {
+ return value;
+ }
+#endif
+}
+
+static int get_code(const char **fmt_io, int *modifier_l) {
+ const char *fmt = *fmt_io;
+ *modifier_l = 0;
+ fmt++;
+ for(; *fmt; fmt++) {
+ switch(*fmt) {
+ case 'l':
+ *modifier_l = 1;
+ break;
+ // integers
+ case 'd': case 'i': case 'x': case 'u': case 'X':
+ // doubles
+ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+ // char; string
+ case 'c': case 's':
+ // pointer
+ case 'p':
+ // literal percent
+ case '%': goto format_end;
+ }
+ }
+format_end:
+ *fmt_io = fmt+1;
+ return *fmt;
+}
+
+int vstashf(struct dbuf_iter *o, const char *fmt, va_list ap) {
+ int modifier_l;
+
+ dbuf_put_string(o, fmt);
+
+ while((fmt = strchr(fmt, '%'))) {
+ int code = get_code(&fmt, &modifier_l);
+
+ switch(code) {
+ case '%':
+ break;
+ case 'c': case 'd': case 'i': case 'x': case 'u': case 'X':
+ if(modifier_l) {
+ case 'p':
+ dbuf_put_long(o, va_arg(ap, long));
+ } else {
+ dbuf_put_int(o, va_arg(ap, int));
+ }
+ break;
+ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+ dbuf_put_double(o, va_arg(ap, double));
+ break;
+ case 's':
+ dbuf_put_string(o, va_arg(ap, const char *));
+ break;
+ default:
+ return SET_ERRNO(-EINVAL);
+ break;
+ }
+ }
+ return 0;
+}
+
+int stashf(struct dbuf_iter *o, const char *fmt, ...) {
+ va_list ap;
+ int result;
+
+ va_start(ap, fmt);
+ result = vstashf(o, fmt, ap);
+ va_end(ap);
+
+ return result;
+}
+
+#define PRINT(...) snprintf(buf, n, ## __VA_ARGS__)
+#define EXTRA buf += result; n -= result; if(n<0) n = 0;
+int snprintdbuf(char *buf, int n, struct dbuf_iter *o) {
+#include "stashf_wrap.h"
+}
+
+#ifndef RTAPI
+#define PRINT(...) fprintf(f, ## __VA_ARGS__)
+int fprintdbuf(FILE *f, struct dbuf_iter *o) {
+#include "stashf_wrap.h"
+}
+
+#define PRINT(...) printf(__VA_ARGS__)
+int printdbuf(struct dbuf_iter *o) {
+#include "stashf_wrap.h"
+}
+#endif
--------------------------- src/emc/motion/stashf.h ---------------------------
new file mode 100644
index 0000000..ac86a67
@@ -0,0 +1,42 @@
+// This is a component of emc
+// Copyright © 2009 Jeff Epler
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#ifndef STASHF_H
+#define STASHF_H
+#include <stdarg.h>
+#ifndef RTAPI
+#include <stdio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dbuf_iter;
+
+int vstashf(struct dbuf_iter *o, const char *fmt, va_list ap);
+int stashf(struct dbuf_iter *o, const char *fmt, ...);
+int snprintdbuf(char *buf, int n, struct dbuf_iter *o);
+#ifndef RTAPI
+int printdbuf(struct dbuf_iter *o);
+int fprintdbuf(FILE *f, struct dbuf_iter *o);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
------------------------- src/emc/motion/stashf_wrap.h -------------------------
new file mode 100644
index 0000000..7af3dbf
@@ -0,0 +1,90 @@
+// This is a component of emc
+// Copyright © 2009 Jeff Epler
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#ifndef EXTRA
+#define EXTRA
+#endif
+
+const char *fmt, *efmt;
+ int result;
+ int total=0;
+
+ result = dbuf_get_string(o, &fmt);
+ if(result < 0) return result;
+
+ if(*fmt) fmt = gettext(fmt);
+
+ while((efmt = strchr(fmt, '%'))) {
+ int modifier_l;
+ int code = get_code(&efmt, &modifier_l);
+ int fmt_len = efmt - fmt;
+ char *block = alloca(fmt_len + 1);
+ memcpy(block, fmt, fmt_len);
+ block[fmt_len] = 0;
+
+ switch(code) {
+ case '%':
+ result = PRINT(block);
+ break;
+ case 'c': case 'd': case 'i': case 'x': case 'u': case 'X':
+ if(modifier_l)
+ case 'p':
+ {
+ long l;
+ result = dbuf_get_long(o, &l);
+ if(result < 0) return SET_ERRNO(result);
+ result = PRINT(block, l);
+ } else {
+ int i;
+ result = dbuf_get_int(o, &i);
+ if(result < 0) return SET_ERRNO(result);
+ result = PRINT(block, i);
+ }
+ break;
+ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+ {
+ double d;
+ result = dbuf_get_double(o, &d);
+ if(result < 0) return SET_ERRNO(result);
+ result = PRINT(block, d);
+ }
+ break;
+ case 's':
+ {
+ const char *s;
+ result = dbuf_get_string(o, &s);
+ if(result < 0) return SET_ERRNO(result);
+ if(*s) s = gettext(s);
+ result = PRINT(block, s);
+ }
+ break;
+ }
+ if(result < 0) return SET_ERRNO(result);
+ total += result;
+ EXTRA
+ fmt = efmt;
+ }
+ if(*fmt) {
+ result = PRINT(fmt);
+ if(result < 0) return SET_ERRNO(result);
+ total += result;
+ EXTRA
+ }
+
+ return SET_ERRNO(result);
+#undef PRINT
+#undef EXTRA
------------------------- src/emc/motion/usrmotintf.cc -------------------------
index 83a4554..e1ce1a4 100644
@@ -35,6 +35,9 @@
#include "rtapi.h"
+#include "dbuf.h"
+#include "stashf.h"
+
static int inited = 0; /* flag if inited */
static emcmot_command_t *emcmotCommand = 0;
@@ -186,8 +189,20 @@ int usrmotReadEmcmotError(char *e)
return -1;
}
+ char data[EMCMOT_ERROR_LEN];
+ struct dbuf d;
+ dbuf_init(&d, (unsigned char *)data, EMCMOT_ERROR_LEN);
+
/* returns 0 if something, -1 if not */
- return emcmotErrorGet(emcmotError, e);
+ int result = emcmotErrorGet(emcmotError, data);
+ if(result < 0) return result;
+
+ struct dbuf_iter di;
+ dbuf_iter_init(&di, &d);
+
+ result = snprintdbuf(e, EMCMOT_ERROR_LEN, &di);
+ if(result < 0) return result;
+ return 0;
}
/*
--------------------------- src/emc/task/Submakefile ---------------------------
index b200cc6..5c0d0a5 100644
@@ -16,6 +16,8 @@ MILLTASKSRCS := \
emc/motion/emcmotutil.c \
emc/task/taskintf.cc \
emc/task/iotaskintf.cc \
+ emc/motion/dbuf.c \
+ emc/motion/stashf.c \
$(ULAPISRCS)
USERSRCS += $(MILLTASKSRCS)
------------------------- src/emc/usr_intf/Submakefile -------------------------
index 3bea1f7..3244705 100644
@@ -13,7 +13,9 @@ USRMOTSRCS := \
emc/usr_intf/usrmot.c \
emc/motion/usrmotintf.cc \
emc/motion/emcmotglb.c \
- emc/motion/emcmotutil.c
+ emc/motion/emcmotutil.c \
+ emc/motion/dbuf.c \
+ emc/motion/stashf.c
HALUISRCS := emc/usr_intf/halui.cc
ifeq "$(HAVE_NCURSES)" "yes"
------------------------------ src/po/Submakefile ------------------------------
index d712ade..380a3b3 100644
@@ -48,6 +48,7 @@ po/emc2.pot: hal/utils/meter.c \
hal/utils/scope_disp.c \
hal/utils/scope_files.c \
hal/utils/miscgtk.c
+po/emc2.pot: emc/motion/control.c
po/emc2.pot: $(TCLSRCS)
po/emc2.pot: $(PYI18NSRCS)
---------------------------- src/rtapi/rtai_rtapi.c ----------------------------
index d1f7ef7..4f54efc 100644
@@ -458,8 +458,10 @@ int rtapi_snprintf(char *buf, unsigned long int size,
const char *fmt, ...)
#define BUFFERLEN 1024
-void default_rtapi_msg_handler(msg_level_t level, const char *buffer) {
- rt_printk(buffer);
+void default_rtapi_msg_handler(msg_level_t level, const char *fmt, va_list ap)
{
+ char buf[BUFFERLEN];
+ rtapi_vsnprintf(buf, BUFFERLEN, fmt, ap);
+ rt_printk(buf);
}
static rtapi_msg_handler_t rtapi_msg_handler = default_rtapi_msg_handler;
@@ -478,10 +480,7 @@ void rtapi_print(const char *fmt, ...)
va_list args;
va_start(args, fmt);
- /* call our own vsn_printf(), which is #defined to vsnprintf() if the
- kernel supplied one. */
- vsn_printf(buffer, BUFFERLEN, fmt, args);
- rtapi_msg_handler(RTAPI_MSG_ALL, buffer);
+ rtapi_msg_handler(RTAPI_MSG_ALL, fmt, args);
va_end(args);
}
@@ -493,10 +492,7 @@ void rtapi_print_msg(int level, const char *fmt, ...)
if ((level <= msg_level) && (msg_level != RTAPI_MSG_NONE)) {
va_start(args, fmt);
- /* call our own vsn_printf(), which is #defined to vsnprintf() if the
- kernel supplied one. */
- vsn_printf(buffer, BUFFERLEN, fmt, args);
- rtapi_msg_handler(level, buffer);
+ rtapi_msg_handler(level, fmt, args);
va_end(args);
}
}
------------------------------ src/rtapi/rtapi.h ------------------------------
index 9da4747..d4a7792 100644
@@ -199,7 +199,7 @@ RTAPI_BEGIN_DECLS
'level' is RTAPI_MSG_ALL, a level which should not normally be used
with rtapi_print_msg().
*/
- typedef void(*rtapi_msg_handler_t)(msg_level_t level, const char *msg);
+ typedef void(*rtapi_msg_handler_t)(msg_level_t level, const char *fmt,
va_list ap);
#ifdef RTAPI
extern void rtapi_set_msg_handler(rtapi_msg_handler_t handler);
extern rtapi_msg_handler_t rtapi_get_msg_handler(void);
--------------------------- src/rtapi/rtapi_string.h ---------------------------
index c540533..d88c5f4 100644
@@ -3,6 +3,7 @@
To be sure, see what has been implemented by looking in linux/string.h
and {linux_src_dir}/lib/string.c */
#include <linux/string.h>
+#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
#ifndef __HAVE_ARCH_STRCMP /* This flag will be defined if we do */
#define __HAVE_ARCH_STRCMP /* have strcmp */
---------------------------- src/rtapi/sim_common.h ----------------------------
index 4f8af5b..aa07215 100644
@@ -126,11 +126,11 @@ int rtapi_shmem_delete(int handle, int module_id)
#define BUFFERLEN 1024
-void default_rtapi_msg_handler(msg_level_t level, const char *buffer) {
+void default_rtapi_msg_handler(msg_level_t level, const char *fmt, va_list ap)
{
if(level == RTAPI_MSG_ALL)
- fputs(buffer, stdout);
+ vfprintf(stdout, fmt, ap);
else
- fputs(buffer, stderr);
+ vfprintf(stderr, fmt, ap);
}
static rtapi_msg_handler_t rtapi_msg_handler = default_rtapi_msg_handler;
@@ -146,27 +146,21 @@ void rtapi_set_msg_handler(rtapi_msg_handler_t handler) {
void rtapi_print(const char *fmt, ...)
{
- char buffer[BUFFERLEN + 1];
va_list args;
va_start(args, fmt);
- /* call the normal library vnsprintf() */
- vsnprintf(buffer, BUFFERLEN, fmt, args);
- rtapi_msg_handler(RTAPI_MSG_ALL, buffer);
+ rtapi_msg_handler(RTAPI_MSG_ALL, fmt, args);
va_end(args);
}
void rtapi_print_msg(int level, const char *fmt, ...)
{
- char buffer[BUFFERLEN + 1];
va_list args;
if ((level <= msg_level) && (msg_level != RTAPI_MSG_NONE)) {
va_start(args, fmt);
- /* call the normal library vnsprintf() */
- vsnprintf(buffer, BUFFERLEN, fmt, args);
- rtapi_msg_handler(level, buffer);
+ rtapi_msg_handler(level, fmt, args);
va_end(args);
}
}
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Emc-developers mailing list
Emc-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/emc-developers